# HG changeset patch # User Maxim Dounin # Date 1184727296 0 # Node ID e2d916d7e50f07f94fa4bf0d0e99ba85225ea2fa # Parent 1c0300c3ae887485014bc2adcfce1ad2066ab93d Mail: starttls only support for SMTP. Capabilities tweaks according to starttls settings. diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -93,6 +93,8 @@ typedef struct { ngx_str_t imap_starttls_only_capability; ngx_str_t smtp_capability; + ngx_str_t smtp_starttls_capability; + ngx_str_t smtp_starttls_only_capability; ngx_str_t server_name; ngx_str_t smtp_server_name; diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -278,7 +278,7 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t ngx_mail_core_srv_conf_t *prev = parent; ngx_mail_core_srv_conf_t *conf = child; - u_char *p; + u_char *p, *auth_p; size_t size, stls_only_size; ngx_str_t *c, *d; ngx_uint_t i, m; @@ -582,6 +582,8 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *p++ = CR; *p++ = LF; } + auth_p = p; + *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H'; @@ -598,6 +600,42 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *p++ = CR; *p = LF; + size += sizeof("250 STARTTLS" CRLF) - 1; + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->smtp_starttls_capability.len = size; + conf->smtp_starttls_capability.data = p; + + p = ngx_cpymem(p, conf->smtp_capability.data, + conf->smtp_capability.len); + + p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); + *p++ = CR; *p = LF; + + p = conf->smtp_starttls_capability.data + + (auth_p - conf->smtp_capability.data) + 3; + *p = '-'; + + size = (auth_p - conf->smtp_capability.data) + + sizeof("250 STARTTLS" CRLF) - 1; + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->smtp_starttls_only_capability.len = size; + conf->smtp_starttls_only_capability.data = p; + + p = ngx_cpymem(p, conf->smtp_capability.data, + auth_p - conf->smtp_capability.data); + + p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); + return NGX_CONF_OK; } diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -1311,6 +1311,26 @@ ngx_smtp_auth_state(ngx_event_t *rev) } else { s->esmtp = 1; + +#if (NGX_MAIL_SSL) + + if (c->ssl == NULL) { + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + + if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) { + size = cscf->smtp_starttls_capability.len; + text = cscf->smtp_starttls_capability.data; + break; + } + + if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { + size = cscf->smtp_starttls_only_capability.len; + text = cscf->smtp_starttls_only_capability.data; + break; + } + } +#endif + size = cscf->smtp_capability.len; text = cscf->smtp_capability.data; } @@ -1319,6 +1339,18 @@ ngx_smtp_auth_state(ngx_event_t *rev) case NGX_SMTP_AUTH: +#if (NGX_MAIL_SSL) + + if (c->ssl == NULL) { + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + + if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { + rc = NGX_MAIL_PARSE_INVALID_COMMAND; + break; + } + } +#endif + if (s->args.nelts == 0) { text = smtp_invalid_argument; size = sizeof(smtp_invalid_argument) - 1; @@ -1471,6 +1503,7 @@ ngx_smtp_auth_state(ngx_event_t *rev) break; #if (NGX_MAIL_SSL) + case NGX_SMTP_STARTTLS: if (c->ssl == NULL) { sslcf = ngx_mail_get_module_srv_conf(s,