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.
Showing
11 changed files
with
218 additions
and
22 deletions
... | @@ -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 | ... | ... |
libmailutils/imapio/transport.c
0 → 100644
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 | } |
... | @@ -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 | } | ... | ... |
libproto/imap/starttls.c
0 → 100644
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]"), | ... | ... |
-
Please register or sign in to post a comment