Commit 7d68b3cd 7d68b3cd17901190e6030327230df8e124161643 by Sergey Poznyakoff

Imap client: implement starttls.

* include/mailutils/imap.h (mu_imap_starttls): New proto.
* include/mailutils/imapio.h: Use mu_imapio_t instead of struct _mu_imapio *.
* include/mailutils/sys/imap.h (MU_IMAP_CLIENT_STARTTLS_RX): New state.
* libmailutils/imapio/transport.c: New file.
* libmailutils/imapio/Makefile.am (libimapio_la_SOURCES): Add transport.c
* libproto/imap/starttls.c: New file.
* libproto/imap/Makefile.am (libmu_imap_la_SOURCES): Add starttls.c.
* libproto/imap/capability.c (mu_imap_capability): Bugfix: set up
comparator and reclaim function after successful return from mu_list_map.
* libproto/imap/capatst.c (mu_imap_capability_test): Clear MU_IMAP_RESP
bit.
* libproto/imap/err.c (mu_imap_strerror): Return errstr only if
MU_IMAP_RESP is set.
* mu/imap.c: Implement starttls.
1 parent f675ddc7
...@@ -51,6 +51,8 @@ int mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter); ...@@ -51,6 +51,8 @@ int mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter);
51 int mu_imap_capability_test (mu_imap_t imap, const char *name, 51 int mu_imap_capability_test (mu_imap_t imap, const char *name,
52 const char **pret); 52 const char **pret);
53 53
54 int mu_imap_starttls (mu_imap_t imap);
55
54 int mu_imap_login (mu_imap_t imap, const char *user, const char *pass); 56 int mu_imap_login (mu_imap_t imap, const char *user, const char *pass);
55 int mu_imap_logout (mu_imap_t imap); 57 int mu_imap_logout (mu_imap_t imap);
56 58
......
...@@ -38,22 +38,22 @@ int mu_imapio_get_words (mu_imapio_t io, size_t *pwc, char ***pwv); ...@@ -38,22 +38,22 @@ int mu_imapio_get_words (mu_imapio_t io, size_t *pwc, char ***pwv);
38 38
39 int mu_imapio_send (mu_imapio_t io, const char *buf, size_t bytes); 39 int mu_imapio_send (mu_imapio_t io, const char *buf, size_t bytes);
40 int mu_imapio_printf (mu_imapio_t io, const char *fmt, ...); 40 int mu_imapio_printf (mu_imapio_t io, const char *fmt, ...);
41 int mu_imapio_send_literal_string (struct _mu_imapio *io, const char *buffer); 41 int mu_imapio_send_literal_string (mu_imapio_t io, const char *buffer);
42 int mu_imapio_send_literal_stream (struct _mu_imapio *io, mu_stream_t stream, 42 int mu_imapio_send_literal_stream (mu_imapio_t io, mu_stream_t stream,
43 mu_off_t size); 43 mu_off_t size);
44 int mu_imapio_send_qstring (struct _mu_imapio *io, const char *buffer); 44 int mu_imapio_send_qstring (mu_imapio_t io, const char *buffer);
45 int mu_imapio_send_qstring_unfold (struct _mu_imapio *io, const char *buffer, 45 int mu_imapio_send_qstring_unfold (mu_imapio_t io, const char *buffer,
46 int unfold); 46 int unfold);
47 47
48 int mu_imapio_send_command_v (struct _mu_imapio *io, const char *tag, 48 int mu_imapio_send_command_v (mu_imapio_t io, const char *tag,
49 int argc, char const **argv, const char *extra); 49 int argc, char const **argv, const char *extra);
50 int mu_imapio_send_command (struct _mu_imapio *io, const char *tag, 50 int mu_imapio_send_command (mu_imapio_t io, const char *tag,
51 char const *cmd, ...); 51 char const *cmd, ...);
52 int mu_imapio_send_command_e (struct _mu_imapio *io, const char *tag, 52 int mu_imapio_send_command_e (mu_imapio_t io, const char *tag,
53 char const *cmd, ...); 53 char const *cmd, ...);
54 54
55 int mu_imapio_send_flags (struct _mu_imapio *io, int flags); 55 int mu_imapio_send_flags (mu_imapio_t io, int flags);
56 int mu_imapio_send_time (struct _mu_imapio *io, struct tm *tm, 56 int mu_imapio_send_time (mu_imapio_t io, struct tm *tm,
57 struct mu_timezone *tz); 57 struct mu_timezone *tz);
58 58
59 int mu_imapio_trace_enable (mu_imapio_t io); 59 int mu_imapio_trace_enable (mu_imapio_t io);
...@@ -62,12 +62,15 @@ int mu_imapio_get_trace (mu_imapio_t io); ...@@ -62,12 +62,15 @@ int mu_imapio_get_trace (mu_imapio_t io);
62 void mu_imapio_trace_payload (mu_imapio_t io, int val); 62 void mu_imapio_trace_payload (mu_imapio_t io, int val);
63 int mu_imapio_get_trace_payload (mu_imapio_t io); 63 int mu_imapio_get_trace_payload (mu_imapio_t io);
64 64
65 int mu_imapio_get_streams (mu_imapio_t io, mu_stream_t *streams);
66 int mu_imapio_set_streams (mu_imapio_t io, mu_stream_t *streams);
67
65 int mu_imapio_getbuf (mu_imapio_t io, char **pptr, size_t *psize); 68 int mu_imapio_getbuf (mu_imapio_t io, char **pptr, size_t *psize);
66 69
67 int mu_imapio_reply_string (struct _mu_imapio *io, size_t start, char **pbuf); 70 int mu_imapio_reply_string (mu_imapio_t io, size_t start, char **pbuf);
68 71
69 int mu_imapio_last_error (struct _mu_imapio *io); 72 int mu_imapio_last_error (mu_imapio_t io);
70 void mu_imapio_clearerr (struct _mu_imapio *io); 73 void mu_imapio_clearerr (mu_imapio_t io);
71 74
72 int mu_imap_flag_to_attribute (const char *item, int *attr); 75 int mu_imap_flag_to_attribute (const char *item, int *attr);
73 int mu_imap_format_flags (mu_stream_t str, int flags); 76 int mu_imap_format_flags (mu_stream_t str, int flags);
......
...@@ -70,6 +70,7 @@ enum mu_imap_client_state ...@@ -70,6 +70,7 @@ enum mu_imap_client_state
70 MU_IMAP_CLIENT_SUBSCRIBE_RX, 70 MU_IMAP_CLIENT_SUBSCRIBE_RX,
71 MU_IMAP_CLIENT_UNSUBSCRIBE_RX, 71 MU_IMAP_CLIENT_UNSUBSCRIBE_RX,
72 MU_IMAP_CLIENT_LSUB_RX, 72 MU_IMAP_CLIENT_LSUB_RX,
73 MU_IMAP_CLIENT_STARTTLS_RX,
73 MU_IMAP_CLIENT_CLOSING 74 MU_IMAP_CLIENT_CLOSING
74 }; 75 };
75 76
......
...@@ -33,6 +33,7 @@ libimapio_la_SOURCES = \ ...@@ -33,6 +33,7 @@ libimapio_la_SOURCES = \
33 sendcmde.c\ 33 sendcmde.c\
34 time.c\ 34 time.c\
35 trace.c\ 35 trace.c\
36 transport.c\
36 words.c\ 37 words.c\
37 xscript.c 38 xscript.c
38 39
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
3 2009, 2010, 2011 Free Software Foundation, Inc.
4
5 GNU Mailutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 GNU Mailutils is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
17
18 #include <config.h>
19 #include <errno.h>
20 #include <mailutils/types.h>
21 #include <mailutils/stream.h>
22 #include <mailutils/diag.h>
23 #include <mailutils/imapio.h>
24 #include <mailutils/sys/imapio.h>
25
26 int
27 mu_imapio_get_streams (struct _mu_imapio *io, mu_stream_t *streams)
28 {
29 int rc;
30
31 mu_stream_flush (io->_imap_stream);
32 if (io->_imap_transcript)
33 rc = mu_stream_ioctl (io->_imap_stream, MU_IOCTL_SUBSTREAM,
34 MU_IOCTL_OP_GET, streams);
35 else
36 {
37 streams[0] = io->_imap_stream;
38 mu_stream_ref (streams[0]);
39 streams[1] = io->_imap_stream;
40 mu_stream_ref (streams[1]);
41 rc = 0;
42 }
43 return rc;
44 }
45
46 int
47 mu_imapio_set_streams (struct _mu_imapio *io, mu_stream_t *streams)
48 {
49 int rc;
50
51 if (io->_imap_transcript)
52 rc = mu_stream_ioctl (io->_imap_stream, MU_IOCTL_SUBSTREAM,
53 MU_IOCTL_OP_SET, streams);
54 else
55 {
56 mu_stream_t tmp;
57
58 if (streams[0] == streams[1])
59 {
60 tmp = streams[0];
61 mu_stream_ref (tmp);
62 mu_stream_ref (tmp);
63 rc = 0;
64 }
65 else
66 rc = mu_iostream_create (&tmp, streams[0], streams[1]);
67 if (rc == 0)
68 {
69 mu_stream_unref (io->_imap_stream);
70 io->_imap_stream = tmp;
71 }
72 }
73 return rc;
74 }
...@@ -62,6 +62,7 @@ libmu_imap_la_SOURCES = \ ...@@ -62,6 +62,7 @@ libmu_imap_la_SOURCES = \
62 select.c\ 62 select.c\
63 state.c\ 63 state.c\
64 status.c\ 64 status.c\
65 starttls.c\
65 store.c\ 66 store.c\
66 subscribe.c\ 67 subscribe.c\
67 tag.c\ 68 tag.c\
......
...@@ -94,14 +94,7 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter) ...@@ -94,14 +94,7 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter)
94 return 0; 94 return 0;
95 return mu_list_get_iterator (imap->capa, piter); 95 return mu_list_get_iterator (imap->capa, piter);
96 } 96 }
97 mu_list_clear (imap->capa); 97 mu_list_destroy (&imap->capa);
98 }
99 else
100 {
101 status = mu_list_create (&imap->capa);
102 MU_IMAP_CHECK_ERROR (imap, status);
103 mu_list_set_comparator (imap->capa, capa_comp);
104 mu_list_set_destroy_item (imap->capa, mu_list_free_item);
105 } 98 }
106 99
107 switch (imap->client_state) 100 switch (imap->client_state)
...@@ -124,6 +117,9 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter) ...@@ -124,6 +117,9 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter)
124 return MU_ERR_REPLY; 117 return MU_ERR_REPLY;
125 else 118 else
126 { 119 {
120 mu_list_set_comparator (imap->capa, capa_comp);
121 mu_list_set_destroy_item (imap->capa, mu_list_free_item);
122
127 if (piter) 123 if (piter)
128 status = mu_list_get_iterator (imap->capa, piter); 124 status = mu_list_get_iterator (imap->capa, piter);
129 else 125 else
......
...@@ -31,5 +31,6 @@ mu_imap_capability_test (mu_imap_t imap, const char *name, const char **pret) ...@@ -31,5 +31,6 @@ mu_imap_capability_test (mu_imap_t imap, const char *name, const char **pret)
31 rc = mu_imap_capability (imap, 0, NULL); 31 rc = mu_imap_capability (imap, 0, NULL);
32 if (rc) 32 if (rc)
33 return rc; 33 return rc;
34 MU_IMAP_FCLR (imap, MU_IMAP_RESP);
34 return mu_list_locate (imap->capa, (void*) name, (void**)pret); 35 return mu_list_locate (imap->capa, (void*) name, (void**)pret);
35 } 36 }
......
...@@ -62,11 +62,12 @@ mu_imap_strerror (mu_imap_t imap, const char **pstr) ...@@ -62,11 +62,12 @@ mu_imap_strerror (mu_imap_t imap, const char **pstr)
62 *pstr = "(imap not initialized)"; 62 *pstr = "(imap not initialized)";
63 return EINVAL; 63 return EINVAL;
64 } 64 }
65 if (imap->errstr) 65
66 if (MU_IMAP_FISSET (imap, MU_IMAP_RESP))
66 { 67 {
67 *pstr = imap->errstr; 68 *pstr = imap->errstr;
68 return 0; 69 return 0;
69 } 70 }
70 *pstr = "(no error)"; 71 *pstr = "(no recent reply)";
71 return MU_ERR_NOENT; 72 return MU_ERR_NOENT;
72 } 73 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010, 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <mailutils/errno.h>
25 #include <mailutils/stream.h>
26 #include <mailutils/tls.h>
27 #include <mailutils/imap.h>
28 #include <mailutils/sys/imap.h>
29
30 int
31 mu_imap_starttls (mu_imap_t imap)
32 {
33 #ifdef WITH_TLS
34 int status;
35 mu_stream_t tlsstream, streams[2];
36
37 if (imap == NULL)
38 return EINVAL;
39 if (!imap->io)
40 return MU_ERR_NO_TRANSPORT;
41 if (imap->session_state == MU_IMAP_SESSION_INIT)
42 return MU_ERR_SEQ;
43
44 status = mu_imap_capability_test (imap, "STARTTLS", NULL);
45 if (status == MU_ERR_NOENT)
46 return ENOSYS;
47 else if (status)
48 return status;
49
50 switch (imap->client_state)
51 {
52 case MU_IMAP_CLIENT_READY:
53 status = _mu_imap_tag_next (imap);
54 MU_IMAP_CHECK_EAGAIN (imap, status);
55 status = mu_imapio_printf (imap->io, "%s STARTTLS\r\n", imap->tag_str);
56 MU_IMAP_CHECK_ERROR (imap, status);
57 MU_IMAP_FCLR (imap, MU_IMAP_RESP);
58 imap->client_state = MU_IMAP_CLIENT_STARTTLS_RX;
59
60 case MU_IMAP_CLIENT_STARTTLS_RX:
61 status = _mu_imap_response (imap, NULL, NULL);
62 MU_IMAP_CHECK_EAGAIN (imap, status);
63 switch (imap->resp_code)
64 {
65 case MU_IMAP_OK:
66 status = mu_imapio_get_streams (imap->io, streams);
67 MU_IMAP_CHECK_EAGAIN (imap, status);
68 status = mu_tls_client_stream_create (&tlsstream,
69 streams[0], streams[1], 0);
70 mu_stream_unref (streams[0]);
71 mu_stream_unref (streams[1]);
72 MU_IMAP_CHECK_EAGAIN (imap, status);
73 streams[0] = streams[1] = tlsstream;
74 status = mu_imapio_set_streams (imap->io, streams);
75 mu_stream_unref (streams[0]);
76 mu_stream_unref (streams[1]);
77 MU_IMAP_CHECK_EAGAIN (imap, status);
78 /* Invalidate the capability list */
79 mu_list_destroy (&imap->capa);
80 status = 0;
81 break;
82
83 case MU_IMAP_NO:
84 status = MU_ERR_FAILURE;
85 break;
86
87 case MU_IMAP_BAD:
88 status = MU_ERR_BADREPLY;
89 break;
90 }
91
92 imap->client_state = MU_IMAP_CLIENT_READY;
93 break;
94
95 default:
96 status = EINPROGRESS;
97 }
98 return status;
99 #else
100 return ENOSYS;
101 #endif
102 }
103
...@@ -455,6 +455,15 @@ com_connect (int argc, char **argv) ...@@ -455,6 +455,15 @@ com_connect (int argc, char **argv)
455 } 455 }
456 456
457 static int 457 static int
458 com_starttls (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
459 {
460 int status = mu_imap_starttls (imap);
461 if (status)
462 report_failure ("starttls", status);
463 return 0;
464 }
465
466 static int
458 com_logout (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) 467 com_logout (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
459 { 468 {
460 int status = 0; 469 int status = 0;
...@@ -988,6 +997,10 @@ struct mutool_command imap_comtab[] = { ...@@ -988,6 +997,10 @@ struct mutool_command imap_comtab[] = {
988 com_disconnect, 997 com_disconnect,
989 NULL, 998 NULL,
990 N_("close connection") }, 999 N_("close connection") },
1000 { "starttls", 1, 1, 0,
1001 com_starttls,
1002 NULL,
1003 N_("Establish TLS encrypted channel") },
991 { "login", 2, 3, 0, 1004 { "login", 2, 3, 0,
992 com_login, 1005 com_login,
993 N_("USER [PASS]"), 1006 N_("USER [PASS]"),
......