Added STARTTLS support.
(smtp_parse_ehlo_ack): New function. (smtp_starttls): New function. (stmp_reader, smtp_writer, smtp_stream_ctl): New static functions.
Showing
1 changed file
with
110 additions
and
4 deletions
... | @@ -48,6 +48,7 @@ | ... | @@ -48,6 +48,7 @@ |
48 | #include <mailutils/property.h> | 48 | #include <mailutils/property.h> |
49 | #include <mailutils/stream.h> | 49 | #include <mailutils/stream.h> |
50 | #include <mailutils/url.h> | 50 | #include <mailutils/url.h> |
51 | #include <mailutils/tls.h> | ||
51 | 52 | ||
52 | #include <mailer0.h> | 53 | #include <mailer0.h> |
53 | #include <registrar0.h> | 54 | #include <registrar0.h> |
... | @@ -90,11 +91,12 @@ struct _smtp | ... | @@ -90,11 +91,12 @@ struct _smtp |
90 | SMTP_HELO, SMTP_HELO_ACK, SMTP_QUIT, SMTP_QUIT_ACK, SMTP_ENV_FROM, | 91 | SMTP_HELO, SMTP_HELO_ACK, SMTP_QUIT, SMTP_QUIT_ACK, SMTP_ENV_FROM, |
91 | SMTP_ENV_RCPT, SMTP_MAIL_FROM, SMTP_MAIL_FROM_ACK, SMTP_RCPT_TO, | 92 | SMTP_ENV_RCPT, SMTP_MAIL_FROM, SMTP_MAIL_FROM_ACK, SMTP_RCPT_TO, |
92 | SMTP_RCPT_TO_ACK, SMTP_DATA, SMTP_DATA_ACK, SMTP_SEND, SMTP_SEND_ACK, | 93 | SMTP_RCPT_TO_ACK, SMTP_DATA, SMTP_DATA_ACK, SMTP_SEND, SMTP_SEND_ACK, |
93 | SMTP_SEND_DOT | 94 | SMTP_SEND_DOT, SMTP_STARTTLS, SMTP_STARTTLS_ACK |
94 | } | 95 | } |
95 | state; | 96 | state; |
96 | 97 | ||
97 | int extended; | 98 | int extended; |
99 | unsigned long capa; /* Server capabilities */ | ||
98 | 100 | ||
99 | const char *mail_from; | 101 | const char *mail_from; |
100 | mu_address_t rcpt_to; /* Destroy this if not the same as argto below. */ | 102 | mu_address_t rcpt_to; /* Destroy this if not the same as argto below. */ |
... | @@ -116,6 +118,10 @@ struct _smtp | ... | @@ -116,6 +118,10 @@ struct _smtp |
116 | 118 | ||
117 | typedef struct _smtp *smtp_t; | 119 | typedef struct _smtp *smtp_t; |
118 | 120 | ||
121 | /* ESMTP capabilities */ | ||
122 | #define CAPA_STARTTLS 0x00000001 | ||
123 | #define CAPA_8BITMIME 0x00000002 | ||
124 | |||
119 | static void smtp_destroy (mu_mailer_t); | 125 | static void smtp_destroy (mu_mailer_t); |
120 | static int smtp_open (mu_mailer_t, int); | 126 | static int smtp_open (mu_mailer_t, int); |
121 | static int smtp_close (mu_mailer_t); | 127 | static int smtp_close (mu_mailer_t); |
... | @@ -123,7 +129,9 @@ static int smtp_send_message (mu_mailer_t, mu_message_t, mu_address_t, mu_addres | ... | @@ -123,7 +129,9 @@ static int smtp_send_message (mu_mailer_t, mu_message_t, mu_address_t, mu_addres |
123 | static int smtp_writeline (smtp_t smtp, const char *format, ...); | 129 | static int smtp_writeline (smtp_t smtp, const char *format, ...); |
124 | static int smtp_readline (smtp_t); | 130 | static int smtp_readline (smtp_t); |
125 | static int smtp_read_ack (smtp_t); | 131 | static int smtp_read_ack (smtp_t); |
132 | static int smtp_parse_ehlo_ack (smtp_t); | ||
126 | static int smtp_write (smtp_t); | 133 | static int smtp_write (smtp_t); |
134 | static int smtp_starttls (smtp_t); | ||
127 | 135 | ||
128 | static int _smtp_set_rcpt (smtp_t, mu_message_t, mu_address_t); | 136 | static int _smtp_set_rcpt (smtp_t, mu_message_t, mu_address_t); |
129 | 137 | ||
... | @@ -362,7 +370,7 @@ smtp_open (mu_mailer_t mailer, int flags) | ... | @@ -362,7 +370,7 @@ smtp_open (mu_mailer_t mailer, int flags) |
362 | smtp->state = SMTP_OPEN; | 370 | smtp->state = SMTP_OPEN; |
363 | 371 | ||
364 | case SMTP_OPEN: | 372 | case SMTP_OPEN: |
365 | MAILER_DEBUG2 (mailer, MU_DEBUG_PROT, "smtp_open (host: %s port: %d)\n", | 373 | MAILER_DEBUG2 (mailer, MU_DEBUG_PROT, "smtp_open (host: %s port: %ld)\n", |
366 | smtp->mailhost, port); | 374 | smtp->mailhost, port); |
367 | status = mu_stream_open (mailer->stream); | 375 | status = mu_stream_open (mailer->stream); |
368 | CHECK_EAGAIN (smtp, status); | 376 | CHECK_EAGAIN (smtp, status); |
... | @@ -390,7 +398,7 @@ smtp_open (mu_mailer_t mailer, int flags) | ... | @@ -390,7 +398,7 @@ smtp_open (mu_mailer_t mailer, int flags) |
390 | smtp->state = SMTP_EHLO_ACK; | 398 | smtp->state = SMTP_EHLO_ACK; |
391 | 399 | ||
392 | case SMTP_EHLO_ACK: | 400 | case SMTP_EHLO_ACK: |
393 | status = smtp_read_ack (smtp); | 401 | status = smtp_parse_ehlo_ack (smtp); |
394 | CHECK_EAGAIN (smtp, status); | 402 | CHECK_EAGAIN (smtp, status); |
395 | 403 | ||
396 | if (smtp->buffer[0] != '2') | 404 | if (smtp->buffer[0] != '2') |
... | @@ -403,9 +411,18 @@ smtp_open (mu_mailer_t mailer, int flags) | ... | @@ -403,9 +411,18 @@ smtp_open (mu_mailer_t mailer, int flags) |
403 | else | 411 | else |
404 | { | 412 | { |
405 | smtp->extended = 1; | 413 | smtp->extended = 1; |
406 | break; | 414 | |
415 | if (smtp->capa & CAPA_STARTTLS) | ||
416 | smtp->state = SMTP_STARTTLS; | ||
417 | else | ||
418 | break; | ||
407 | } | 419 | } |
408 | 420 | ||
421 | case SMTP_STARTTLS: | ||
422 | case SMTP_STARTTLS_ACK: | ||
423 | smtp_starttls (smtp); | ||
424 | break; | ||
425 | |||
409 | case SMTP_HELO: | 426 | case SMTP_HELO: |
410 | if (!smtp->extended) /* FIXME: this will always be false! */ | 427 | if (!smtp->extended) /* FIXME: this will always be false! */ |
411 | { | 428 | { |
... | @@ -465,6 +482,69 @@ smtp_close (mu_mailer_t mailer) | ... | @@ -465,6 +482,69 @@ smtp_close (mu_mailer_t mailer) |
465 | return mu_stream_close (mailer->stream); | 482 | return mu_stream_close (mailer->stream); |
466 | } | 483 | } |
467 | 484 | ||
485 | /* | ||
486 | Client side STARTTLS support. | ||
487 | */ | ||
488 | |||
489 | static int | ||
490 | smtp_reader (void *iodata) | ||
491 | { | ||
492 | int status = 0; | ||
493 | smtp_t iop = iodata; | ||
494 | status = smtp_read_ack (iop); | ||
495 | CHECK_EAGAIN (iop, status); | ||
496 | return status; | ||
497 | } | ||
498 | |||
499 | static int | ||
500 | smtp_writer (void *iodata, char *buf) | ||
501 | { | ||
502 | smtp_t iop = iodata; | ||
503 | int status; | ||
504 | if (strncasecmp (buf, "EHLO", 4) == 0) | ||
505 | status = smtp_writeline (iop, "%s %s\r\n", buf, iop->localhost); | ||
506 | else | ||
507 | status = smtp_writeline (iop, "%s\r\n", buf); | ||
508 | CHECK_ERROR (iop, status); | ||
509 | status = smtp_write (iop); | ||
510 | CHECK_EAGAIN (iop, status); | ||
511 | return status; | ||
512 | } | ||
513 | |||
514 | static void | ||
515 | smtp_stream_ctl (void *iodata, mu_stream_t *pold, mu_stream_t new) | ||
516 | { | ||
517 | smtp_t iop = iodata; | ||
518 | if (pold) | ||
519 | *pold = iop->mailer->stream; | ||
520 | if (new) | ||
521 | iop->mailer->stream = new; | ||
522 | } | ||
523 | |||
524 | static int | ||
525 | smtp_starttls (smtp_t smtp) | ||
526 | { | ||
527 | #ifdef WITH_TLS | ||
528 | int status; | ||
529 | mu_mailer_t mailer = smtp->mailer; | ||
530 | char *keywords[] = { "STARTTLS", "EHLO", NULL }; | ||
531 | |||
532 | if (!mu_tls_enable || !(smtp->capa & CAPA_STARTTLS)) | ||
533 | return -1; | ||
534 | |||
535 | smtp->capa = 0; | ||
536 | status = mu_tls_begin (smtp, smtp_reader, smtp_writer, | ||
537 | smtp_stream_ctl, keywords); | ||
538 | |||
539 | MAILER_DEBUG1 (mailer, MU_DEBUG_PROT, "TLS negotiation %s\n", | ||
540 | status == 0 ? "succeeded" : "failed"); | ||
541 | |||
542 | return status; | ||
543 | #else | ||
544 | return -1; | ||
545 | #endif /* WITH_TLS */ | ||
546 | } | ||
547 | |||
468 | static int | 548 | static int |
469 | message_set_header_value (mu_message_t msg, const char *field, const char *value) | 549 | message_set_header_value (mu_message_t msg, const char *field, const char *value) |
470 | { | 550 | { |
... | @@ -1007,6 +1087,32 @@ smtp_read_ack (smtp_t smtp) | ... | @@ -1007,6 +1087,32 @@ smtp_read_ack (smtp_t smtp) |
1007 | return status; | 1087 | return status; |
1008 | } | 1088 | } |
1009 | 1089 | ||
1090 | static int | ||
1091 | smtp_parse_ehlo_ack (smtp_t smtp) | ||
1092 | { | ||
1093 | int status; | ||
1094 | int multi; | ||
1095 | |||
1096 | do | ||
1097 | { | ||
1098 | multi = 0; | ||
1099 | status = smtp_readline (smtp); | ||
1100 | if ((smtp->ptr - smtp->buffer) > 4 && smtp->buffer[3] == '-') | ||
1101 | multi = 1; | ||
1102 | if (status == 0) { | ||
1103 | smtp->ptr = smtp->buffer; | ||
1104 | |||
1105 | if (!strncasecmp (smtp->buffer, "250-STARTTLS", 12)) | ||
1106 | smtp->capa |= CAPA_STARTTLS; | ||
1107 | } | ||
1108 | } | ||
1109 | while (multi && status == 0); | ||
1110 | |||
1111 | if (status == 0) | ||
1112 | smtp->ptr = smtp->buffer; | ||
1113 | return status; | ||
1114 | } | ||
1115 | |||
1010 | /* Read a complete line form the pop server. Transform CRLF to LF, | 1116 | /* Read a complete line form the pop server. Transform CRLF to LF, |
1011 | put a null in the buffer when done. */ | 1117 | put a null in the buffer when done. */ |
1012 | static int | 1118 | static int | ... | ... |
-
Please register or sign in to post a comment