Implemented client side TLS
Showing
1 changed file
with
74 additions
and
14 deletions
... | @@ -48,6 +48,8 @@ | ... | @@ -48,6 +48,8 @@ |
48 | #include <mailutils/header.h> | 48 | #include <mailutils/header.h> |
49 | #include <mailutils/observer.h> | 49 | #include <mailutils/observer.h> |
50 | #include <mailutils/stream.h> | 50 | #include <mailutils/stream.h> |
51 | #include <mailutils/argcv.h> | ||
52 | #include <mailutils/tls.h> | ||
51 | 53 | ||
52 | /* For dbg purposes set to one to see different level of traffic. */ | 54 | /* For dbg purposes set to one to see different level of traffic. */ |
53 | /* Print to stderr the command sent to the IMAP server. */ | 55 | /* Print to stderr the command sent to the IMAP server. */ |
... | @@ -171,8 +173,8 @@ folder_imap_destroy (folder_t folder) | ... | @@ -171,8 +173,8 @@ folder_imap_destroy (folder_t folder) |
171 | f_imap_t f_imap = folder->data; | 173 | f_imap_t f_imap = folder->data; |
172 | if (f_imap->buffer) | 174 | if (f_imap->buffer) |
173 | free (f_imap->buffer); | 175 | free (f_imap->buffer); |
174 | if (f_imap->capa) | 176 | if (f_imap->capav) |
175 | free (f_imap->capa); | 177 | argcv_free (f_imap->capac, f_imap->capav); |
176 | free (f_imap); | 178 | free (f_imap); |
177 | folder->data = NULL; | 179 | folder->data = NULL; |
178 | } | 180 | } |
... | @@ -212,6 +214,66 @@ folder_imap_get_authority (folder_t folder, authority_t *pauth) | ... | @@ -212,6 +214,66 @@ folder_imap_get_authority (folder_t folder, authority_t *pauth) |
212 | return status; | 214 | return status; |
213 | } | 215 | } |
214 | 216 | ||
217 | static int | ||
218 | parse_capa (f_imap_t f_imap, char *str) | ||
219 | { | ||
220 | if (f_imap->capav) | ||
221 | argcv_free (f_imap->capac, f_imap->capav); | ||
222 | return argcv_get (str, "", NULL, &f_imap->capac, &f_imap->capav); | ||
223 | } | ||
224 | |||
225 | static int | ||
226 | check_capa (f_imap_t f_imap, char *capa) | ||
227 | { | ||
228 | int i; | ||
229 | |||
230 | if (!f_imap->capav) | ||
231 | { | ||
232 | int status; | ||
233 | status = imap_writeline (f_imap, "g%u CAPABILITY\r\n", | ||
234 | f_imap->seq++); | ||
235 | status = imap_send (f_imap); | ||
236 | status = imap_parse (f_imap); | ||
237 | } | ||
238 | for (i = 0; i < f_imap->capac; i++) | ||
239 | if (strcasecmp (f_imap->capav[i], capa) == 0) | ||
240 | return 0; | ||
241 | return 1; | ||
242 | } | ||
243 | |||
244 | static int | ||
245 | tls (folder_t folder) | ||
246 | { | ||
247 | #ifdef WITH_TLS | ||
248 | int status; | ||
249 | f_imap_t f_imap = folder->data; | ||
250 | |||
251 | if (!mu_tls_enable || check_capa (f_imap, "STARTTLS")) | ||
252 | return -1; | ||
253 | |||
254 | status = imap_writeline (f_imap, "g%u STARTTLS\r\n", | ||
255 | f_imap->seq, f_imap->user, f_imap->passwd); | ||
256 | CHECK_ERROR (f_imap, status); | ||
257 | status = imap_send (f_imap); | ||
258 | CHECK_ERROR (f_imap, status); | ||
259 | status = imap_parse (f_imap); | ||
260 | if (status == 0) | ||
261 | { | ||
262 | stream_t str; | ||
263 | status = tls_stream_create_client_from_tcp (&str, folder->stream, 0); | ||
264 | CHECK_ERROR (f_imap, status); | ||
265 | status = stream_open (str); | ||
266 | if (status == 0) | ||
267 | folder->stream = str; | ||
268 | FOLDER_DEBUG1 (folder, MU_DEBUG_PROT, "TLS negotiation %s\n", | ||
269 | status == 0 ? "succeeded" : "failed"); | ||
270 | } | ||
271 | return status; | ||
272 | #else | ||
273 | return -1; | ||
274 | #endif | ||
275 | } | ||
276 | |||
215 | /* Simple User/pass authentication for imap. */ | 277 | /* Simple User/pass authentication for imap. */ |
216 | static int | 278 | static int |
217 | authenticate_imap_login (authority_t auth) | 279 | authenticate_imap_login (authority_t auth) |
... | @@ -486,8 +548,8 @@ folder_imap_open (folder_t folder, int flags) | ... | @@ -486,8 +548,8 @@ folder_imap_open (folder_t folder, int flags) |
486 | CHECK_EAGAIN (f_imap, status); | 548 | CHECK_EAGAIN (f_imap, status); |
487 | f_imap->ptr = f_imap->buffer; | 549 | f_imap->ptr = f_imap->buffer; |
488 | FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer); | 550 | FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer); |
489 | /* Are they open for business ? The server send an untag response | 551 | /* Are they open for business ? The server send an untagged response |
490 | for greeting. Thenically it can be OK/PREAUTH/BYE. The BYE is | 552 | for greeting. Tecnically it can be OK/PREAUTH/BYE. The BYE is |
491 | the one that we do not want, server being unfriendly. */ | 553 | the one that we do not want, server being unfriendly. */ |
492 | if (strncasecmp (f_imap->buffer, "* PREAUTH", 9) == 0) | 554 | if (strncasecmp (f_imap->buffer, "* PREAUTH", 9) == 0) |
493 | { | 555 | { |
... | @@ -500,7 +562,8 @@ folder_imap_open (folder_t folder, int flags) | ... | @@ -500,7 +562,8 @@ folder_imap_open (folder_t folder, int flags) |
500 | f_imap->state = IMAP_AUTH; | 562 | f_imap->state = IMAP_AUTH; |
501 | } | 563 | } |
502 | } | 564 | } |
503 | 565 | tls(folder); | |
566 | |||
504 | case IMAP_AUTH: | 567 | case IMAP_AUTH: |
505 | case IMAP_LOGIN: | 568 | case IMAP_LOGIN: |
506 | case IMAP_LOGIN_ACK: | 569 | case IMAP_LOGIN_ACK: |
... | @@ -979,7 +1042,7 @@ imap_literal_string (f_imap_t f_imap, char **ptr) | ... | @@ -979,7 +1042,7 @@ imap_literal_string (f_imap_t f_imap, char **ptr) |
979 | } | 1042 | } |
980 | 1043 | ||
981 | /* The (len + 1) in the for is to count the strip '\r' by imap_readline. */ | 1044 | /* The (len + 1) in the for is to count the strip '\r' by imap_readline. */ |
982 | for (len0 = len = total = 0; total < f_imap->string.nleft; total += (len + 1)) | 1045 | for (len0 = len = total = 0; total < f_imap->string.nleft; total += len + 1) |
983 | { | 1046 | { |
984 | status = imap_readline (f_imap); | 1047 | status = imap_readline (f_imap); |
985 | if (DEBUG_SHOW_DATA) | 1048 | if (DEBUG_SHOW_DATA) |
... | @@ -1948,7 +2011,8 @@ imap_readline (f_imap_t f_imap) | ... | @@ -1948,7 +2011,8 @@ imap_readline (f_imap_t f_imap) |
1948 | while (f_imap->nl == NULL); | 2011 | while (f_imap->nl == NULL); |
1949 | 2012 | ||
1950 | /* Conversion \r\n --> \n\0 */ | 2013 | /* Conversion \r\n --> \n\0 */ |
1951 | if (f_imap->nl > f_imap->buffer) | 2014 | /* FIXME: This should be done transparently by the TCP stream */ |
2015 | if (f_imap->nl > f_imap->buffer && f_imap->nl[-1] == '\r') | ||
1952 | { | 2016 | { |
1953 | *(f_imap->nl - 1) = '\n'; | 2017 | *(f_imap->nl - 1) = '\n'; |
1954 | *(f_imap->nl) = '\0'; | 2018 | *(f_imap->nl) = '\0'; |
... | @@ -2100,9 +2164,7 @@ imap_parse (f_imap_t f_imap) | ... | @@ -2100,9 +2164,7 @@ imap_parse (f_imap_t f_imap) |
2100 | initial capabilities list. This makes it unnecessary | 2164 | initial capabilities list. This makes it unnecessary |
2101 | for a client to send a separate CAPABILITY command if | 2165 | for a client to send a separate CAPABILITY command if |
2102 | it recognizes this response. */ | 2166 | it recognizes this response. */ |
2103 | if (f_imap->capa) | 2167 | parse_capa (f_imap, cruft); |
2104 | free (f_imap->capa); | ||
2105 | f_imap->capa = strdup (cruft); | ||
2106 | } | 2168 | } |
2107 | else if (strcasecmp (subtag, "NEWNAME") == 0) | 2169 | else if (strcasecmp (subtag, "NEWNAME") == 0) |
2108 | { | 2170 | { |
... | @@ -2222,15 +2284,13 @@ imap_parse (f_imap_t f_imap) | ... | @@ -2222,15 +2284,13 @@ imap_parse (f_imap_t f_imap) |
2222 | } | 2284 | } |
2223 | else if (strcasecmp (response, "CAPABILITY") == 0) | 2285 | else if (strcasecmp (response, "CAPABILITY") == 0) |
2224 | { | 2286 | { |
2225 | if (f_imap->capa) | 2287 | parse_capa (f_imap, remainder); |
2226 | free (f_imap->capa); | ||
2227 | f_imap->capa = strdup (remainder); | ||
2228 | } | 2288 | } |
2229 | else if (strcasecmp (remainder, "EXISTS") == 0) | 2289 | else if (strcasecmp (remainder, "EXISTS") == 0) |
2230 | { | 2290 | { |
2231 | f_imap->selected->messages_count = strtol (response, NULL, 10); | 2291 | f_imap->selected->messages_count = strtol (response, NULL, 10); |
2232 | } | 2292 | } |
2233 | else if (strcasecmp (remainder, "EXPUNGE") == 0) | 2293 | else if (strcasecmp (remainder, "EXPUNGED") == 0) |
2234 | { | 2294 | { |
2235 | unsigned int msgno = strtol (response, NULL, 10); | 2295 | unsigned int msgno = strtol (response, NULL, 10); |
2236 | status = imap_expunge (f_imap, msgno); | 2296 | status = imap_expunge (f_imap, msgno); | ... | ... |
-
Please register or sign in to post a comment