From 0cc409a44cac5ac29d0bd18fa13a4e9f2b2f2b96 Mon Sep 17 00:00:00 2001 From: Pawel Salek Date: Fri, 5 Mar 2010 21:22:15 +0100 Subject: Implement submission to smtps service. * examples/mail-file.c: allow testing submission to smtps service. * libesmtp-private.h: add negotiate_ssl() prototype. * libesmtp.h: add Starttls_OVER_SSL to starttls_option enum. * protocol.h: enable SSL on connection whenever selected. * smtp-tls.c: share negotiate_ssl(). --- ChangeLog | 8 +++++ examples/mail-file.c | 8 ++++- libesmtp-private.h | 2 ++ libesmtp.h | 3 +- protocol.c | 12 ++++++++ smtp-tls.c | 86 +++++++++++++++++++++++++++++++--------------------- 6 files changed, 83 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index fbc8c2e..7244bbe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-03-05 Pawel Salek + + * examples/mail-file.c: allow testing submission to smtps service. + * libesmtp-private.h: add negotiate_ssl() prototype. + * libesmtp.h: add Starttls_OVER_SSL to starttls_option enum. + * protocol.h: enable SSL on connection whenever selected. + * smtp-tls.c: share negotiate_ssl(). + 2005-12-16 Stable Version 1.0.4 released ---------------------------------------- 2005-12-16 Brian Stafford diff --git a/examples/mail-file.c b/examples/mail-file.c index 771ce5a..784410d 100644 --- a/examples/mail-file.c +++ b/examples/mail-file.c @@ -56,6 +56,7 @@ struct option longopts[] = { "mdn", no_argument, NULL, 'd', }, { "subject", required_argument, NULL, 's', }, { "reverse-path", required_argument, NULL, 'f', }, + { "ssl", no_argument, NULL, 'S', }, { "tls", no_argument, NULL, 't', }, { "require-tls", no_argument, NULL, 'T', }, { "noauth", no_argument, NULL, 1, }, @@ -98,7 +99,7 @@ main (int argc, char **argv) session = smtp_create_session (); message = smtp_add_message (session); - while ((c = getopt_long (argc, argv, "dmch:f:s:n:tTv", + while ((c = getopt_long (argc, argv, "dmch:f:s:n:StTv", longopts, NULL)) != EOF) switch (c) { @@ -138,6 +139,10 @@ main (int argc, char **argv) smtp_set_header (message, "Disposition-Notification-To", NULL, NULL); break; + case 'S': + smtp_starttls_enable (session, Starttls_OVER_SSL); + break; + case 't': smtp_starttls_enable (session, Starttls_ENABLED); break; @@ -543,6 +548,7 @@ usage (void) "\t-m,--monitor -- watch the protocol session with the server\n" "\t-c,--crlf -- translate line endings from \\n to CR-LF\n" "\t-t,--tls -- use STARTTLS extension if possible\n" + "\t-S,--ssl -- connect over SSL to smtps service\n" "\t-T,--require-tls -- require use of STARTTLS extension\n" "\t --noauth -- do not attempt to authenticate to the MSA\n" "\t--version -- show version info and exit\n" diff --git a/libesmtp-private.h b/libesmtp-private.h index 7e242f7..a1dcf90 100644 --- a/libesmtp-private.h +++ b/libesmtp-private.h @@ -31,6 +31,7 @@ #include "message-source.h" #include "concatenate.h" #include "auth-client.h" +#include "siobuf.h" /* SMTP Extensions */ @@ -242,6 +243,7 @@ int select_auth_mechanism (smtp_session_t session); /* smtp-tls.c */ int select_starttls (smtp_session_t session); +int negotiate_ssl (siobuf_t conn, smtp_session_t session); void destroy_starttls_context (smtp_session_t session); #endif diff --git a/libesmtp.h b/libesmtp.h index 4fc2692..87ae049 100644 --- a/libesmtp.h +++ b/libesmtp.h @@ -236,7 +236,8 @@ enum starttls_option { Starttls_DISABLED, Starttls_ENABLED, - Starttls_REQUIRED + Starttls_REQUIRED, + Starttls_OVER_SSL }; int smtp_starttls_enable (smtp_session_t session, enum starttls_option how); diff --git a/protocol.c b/protocol.c index 0b44df8..70b80a4 100644 --- a/protocol.c +++ b/protocol.c @@ -303,6 +303,18 @@ do_session (smtp_session_t session) #ifdef USE_TLS session->using_tls = 0; #endif +#if 1 + if (session->starttls_enabled == Starttls_OVER_SSL) + { + if ( !(select_starttls (session) && + negotiate_ssl (conn, session) == 0) ) + continue; + /* Do we handle here negotiate_ssl returning -1? We might + leave a dangling open socket here. */ + } +#endif + printf("%s A %d\n", __func__, session->using_tls); + nresp = 0; session->cmd_state = session->rsp_state = 0; diff --git a/smtp-tls.c b/smtp-tls.c index a42e8f5..f51cfad 100644 --- a/smtp-tls.c +++ b/smtp-tls.c @@ -419,9 +419,11 @@ select_starttls (smtp_session_t session) storage to record this for future sessions. */ /* if (...) session->starttls_enabled = Starttls_REQUIRED; */ - if (!(session->extensions & EXT_STARTTLS)) + if (session->starttls_enabled == Starttls_DISABLED) return 0; - if (!session->starttls_enabled) + if ( (session->starttls_enabled == Starttls_ENABLED || + session->starttls_enabled == Starttls_REQUIRED) && + !(session->extensions & EXT_STARTTLS)) return 0; #ifdef USE_PTHREADS pthread_mutex_lock (&starttls_mutex); @@ -589,9 +591,10 @@ check_acceptable_security (smtp_session_t session, SSL *ssl) if (!ok) { /* Matching by subjectAltName failed, try commonName */ - X509_NAME_get_text_by_NID (X509_get_subject_name (cert), - NID_commonName, buf, sizeof buf); - if (!match_domain (session->host, buf) != 0) + int l = X509_NAME_get_text_by_NID (X509_get_subject_name (cert), + NID_commonName, buf, sizeof buf); + if (l != strlen(buf) || + !match_domain (session->host, buf) != 0) { if (session->event_cb != NULL) (*session->event_cb) (session, SMTP_EV_WRONG_PEER_CERTIFICATE, @@ -605,35 +608,14 @@ check_acceptable_security (smtp_session_t session, SSL *ssl) return ok; } -void -cmd_starttls (siobuf_t conn, smtp_session_t session) -{ - sio_write (conn, "STARTTLS\r\n", -1); - session->cmd_state = -1; -} - -void -rsp_starttls (siobuf_t conn, smtp_session_t session) +int +negotiate_ssl (siobuf_t conn, smtp_session_t session) { - int code; SSL *ssl; X509 *cert; char buf[256]; - code = read_smtp_response (conn, session, &session->mta_status, NULL); - if (code < 0) - { - session->rsp_state = S_quit; - return; - } - - if (code != 2) - { - if (code != 4 && code != 5) - set_error (SMTP_ERR_INVALID_RESPONSE_STATUS); - session->rsp_state = S_quit; - } - else if (sio_set_tlsclient_ssl (conn, (ssl = starttls_create_ssl (session)))) + if (sio_set_tlsclient_ssl (conn, (ssl = starttls_create_ssl (session)))) { session->using_tls = 1; @@ -643,7 +625,7 @@ rsp_starttls (siobuf_t conn, smtp_session_t session) destroy_auth_mechanisms (session); if (!check_acceptable_security (session, ssl)) - session->rsp_state = S_quit; + return -1; else { if (session->event_cb != NULL) @@ -663,16 +645,52 @@ rsp_starttls (siobuf_t conn, smtp_session_t session) if (session->auth_context != NULL) auth_set_external_id (session->auth_context, buf); } - - /* Next state is EHLO */ - session->rsp_state = S_ehlo; + } + return 0; + } else + return -2; +} + +void +cmd_starttls (siobuf_t conn, smtp_session_t session) +{ + sio_write (conn, "STARTTLS\r\n", -1); + session->cmd_state = -1; +} + +void +rsp_starttls (siobuf_t conn, smtp_session_t session) +{ + int code; + + code = read_smtp_response (conn, session, &session->mta_status, NULL); + if (code < 0) + { + session->rsp_state = S_quit; + return; } - else + + if (code != 2) { + if (code != 4 && code != 5) + set_error (SMTP_ERR_INVALID_RESPONSE_STATUS); + session->rsp_state = S_quit; + } + else { + switch (negotiate_ssl (conn, session) ) { + case 0: + /* Next state is EHLO */ + session->rsp_state = S_ehlo; + break; + case -1: + session->rsp_state = S_quit; + break; + default: /* -2 */ set_error (SMTP_ERR_CLIENT_ERROR); session->rsp_state = -1; } + } } #else -- cgit