summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPawel Salek <pawsa@fedorapeople.org>2010-03-05 21:22:15 +0100
committerPawel Salek <pawsa@fedorapeople.org>2010-03-05 21:22:15 +0100
commit0cc409a44cac5ac29d0bd18fa13a4e9f2b2f2b96 (patch)
tree5a54b7a2e3f0d767cbf587212c95897b8310a28b
parent5d3cf8a33ced580af0d3e30b8fbd3cf9a5aa315a (diff)
downloadlibesmtp-0cc409a44cac5ac29d0bd18fa13a4e9f2b2f2b96.tar.gz
libesmtp-0cc409a44cac5ac29d0bd18fa13a4e9f2b2f2b96.tar.xz
libesmtp-0cc409a44cac5ac29d0bd18fa13a4e9f2b2f2b96.zip
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().
-rw-r--r--ChangeLog8
-rw-r--r--examples/mail-file.c8
-rw-r--r--libesmtp-private.h2
-rw-r--r--libesmtp.h3
-rw-r--r--protocol.c12
-rw-r--r--smtp-tls.c86
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 <pawsa@fedorapeople.org>
+
+ * 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 <brian@stafford.uklinux.net>
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