48 |
#include <mailutils/header.h> |
#include <mailutils/header.h> |
49 |
#include <mailutils/observer.h> |
#include <mailutils/observer.h> |
50 |
#include <mailutils/stream.h> |
#include <mailutils/stream.h> |
51 |
|
#include <mailutils/argcv.h> |
52 |
|
#include <mailutils/tls.h> |
53 |
|
|
54 |
/* For dbg purposes set to one to see different level of traffic. */ |
/* For dbg purposes set to one to see different level of traffic. */ |
55 |
/* Print to stderr the command sent to the IMAP server. */ |
/* Print to stderr the command sent to the IMAP server. */ |
173 |
f_imap_t f_imap = folder->data; |
f_imap_t f_imap = folder->data; |
174 |
if (f_imap->buffer) |
if (f_imap->buffer) |
175 |
free (f_imap->buffer); |
free (f_imap->buffer); |
176 |
if (f_imap->capa) |
if (f_imap->capav) |
177 |
free (f_imap->capa); |
argcv_free (f_imap->capac, f_imap->capav); |
178 |
free (f_imap); |
free (f_imap); |
179 |
folder->data = NULL; |
folder->data = NULL; |
180 |
} |
} |
214 |
return status; |
return status; |
215 |
} |
} |
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 |
|
|
277 |
/* Simple User/pass authentication for imap. */ |
/* Simple User/pass authentication for imap. */ |
278 |
static int |
static int |
279 |
authenticate_imap_login (authority_t auth) |
authenticate_imap_login (authority_t auth) |
548 |
CHECK_EAGAIN (f_imap, status); |
CHECK_EAGAIN (f_imap, status); |
549 |
f_imap->ptr = f_imap->buffer; |
f_imap->ptr = f_imap->buffer; |
550 |
FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer); |
FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer); |
551 |
/* Are they open for business ? The server send an untag response |
/* Are they open for business ? The server send an untagged response |
552 |
for greeting. Thenically it can be OK/PREAUTH/BYE. The BYE is |
for greeting. Tecnically it can be OK/PREAUTH/BYE. The BYE is |
553 |
the one that we do not want, server being unfriendly. */ |
the one that we do not want, server being unfriendly. */ |
554 |
if (strncasecmp (f_imap->buffer, "* PREAUTH", 9) == 0) |
if (strncasecmp (f_imap->buffer, "* PREAUTH", 9) == 0) |
555 |
{ |
{ |
562 |
f_imap->state = IMAP_AUTH; |
f_imap->state = IMAP_AUTH; |
563 |
} |
} |
564 |
} |
} |
565 |
|
tls(folder); |
566 |
|
|
567 |
case IMAP_AUTH: |
case IMAP_AUTH: |
568 |
case IMAP_LOGIN: |
case IMAP_LOGIN: |
569 |
case IMAP_LOGIN_ACK: |
case IMAP_LOGIN_ACK: |
1042 |
} |
} |
1043 |
|
|
1044 |
/* The (len + 1) in the for is to count the strip '\r' by imap_readline. */ |
/* The (len + 1) in the for is to count the strip '\r' by imap_readline. */ |
1045 |
for (len0 = len = total = 0; total < f_imap->string.nleft; total += (len + 1)) |
for (len0 = len = total = 0; total < f_imap->string.nleft; total += len + 1) |
1046 |
{ |
{ |
1047 |
status = imap_readline (f_imap); |
status = imap_readline (f_imap); |
1048 |
if (DEBUG_SHOW_DATA) |
if (DEBUG_SHOW_DATA) |
2011 |
while (f_imap->nl == NULL); |
while (f_imap->nl == NULL); |
2012 |
|
|
2013 |
/* Conversion \r\n --> \n\0 */ |
/* Conversion \r\n --> \n\0 */ |
2014 |
if (f_imap->nl > f_imap->buffer) |
/* FIXME: This should be done transparently by the TCP stream */ |
2015 |
|
if (f_imap->nl > f_imap->buffer && f_imap->nl[-1] == '\r') |
2016 |
{ |
{ |
2017 |
*(f_imap->nl - 1) = '\n'; |
*(f_imap->nl - 1) = '\n'; |
2018 |
*(f_imap->nl) = '\0'; |
*(f_imap->nl) = '\0'; |
2164 |
initial capabilities list. This makes it unnecessary |
initial capabilities list. This makes it unnecessary |
2165 |
for a client to send a separate CAPABILITY command if |
for a client to send a separate CAPABILITY command if |
2166 |
it recognizes this response. */ |
it recognizes this response. */ |
2167 |
if (f_imap->capa) |
parse_capa (f_imap, cruft); |
|
free (f_imap->capa); |
|
|
f_imap->capa = strdup (cruft); |
|
2168 |
} |
} |
2169 |
else if (strcasecmp (subtag, "NEWNAME") == 0) |
else if (strcasecmp (subtag, "NEWNAME") == 0) |
2170 |
{ |
{ |
2284 |
} |
} |
2285 |
else if (strcasecmp (response, "CAPABILITY") == 0) |
else if (strcasecmp (response, "CAPABILITY") == 0) |
2286 |
{ |
{ |
2287 |
if (f_imap->capa) |
parse_capa (f_imap, remainder); |
|
free (f_imap->capa); |
|
|
f_imap->capa = strdup (remainder); |
|
2288 |
} |
} |
2289 |
else if (strcasecmp (remainder, "EXISTS") == 0) |
else if (strcasecmp (remainder, "EXISTS") == 0) |
2290 |
{ |
{ |
2291 |
f_imap->selected->messages_count = strtol (response, NULL, 10); |
f_imap->selected->messages_count = strtol (response, NULL, 10); |
2292 |
} |
} |
2293 |
else if (strcasecmp (remainder, "EXPUNGE") == 0) |
else if (strcasecmp (remainder, "EXPUNGED") == 0) |
2294 |
{ |
{ |
2295 |
unsigned int msgno = strtol (response, NULL, 10); |
unsigned int msgno = strtol (response, NULL, 10); |
2296 |
status = imap_expunge (f_imap, msgno); |
status = imap_expunge (f_imap, msgno); |