1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010-2021 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
mu_imap_starttls(mu_imap_t imap)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->response)
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
104