diff options
author | Vladimir Homutov <vl@nginx.com> | 2021-10-20 09:45:34 +0300 |
---|---|---|
committer | Vladimir Homutov <vl@nginx.com> | 2021-10-20 09:45:34 +0300 |
commit | 1fecec0cbf1554c0473d5cca0fb55f8dc006e4ba (patch) | |
tree | 286ac8a4015910f9d0816fe28dcd398a36021022 | |
parent | ebb6f7d6563f51ae8325e3c0f10e9c5a91004fda (diff) | |
download | nginx-1fecec0cbf1554c0473d5cca0fb55f8dc006e4ba.tar.gz |
Mail: connections with wrong ALPN protocols are now rejected.
This is a recommended behavior by RFC 7301 and is useful
for mitigation of protocol confusion attacks [1].
For POP3 and IMAP protocols IANA-assigned ALPN IDs are used [2].
For the SMTP protocol "smtp" is used.
[1] https://alpaca-attack.com/
[2] https://www.iana.org/assignments/tls-extensiontype-values/
-rw-r--r-- | src/mail/ngx_mail.h | 1 | ||||
-rw-r--r-- | src/mail/ngx_mail_imap_module.c | 1 | ||||
-rw-r--r-- | src/mail/ngx_mail_pop3_module.c | 1 | ||||
-rw-r--r-- | src/mail/ngx_mail_smtp_module.c | 1 | ||||
-rw-r--r-- | src/mail/ngx_mail_ssl_module.c | 58 |
5 files changed, 62 insertions, 0 deletions
diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h index 21178c3e2..e0c62b7ab 100644 --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -324,6 +324,7 @@ typedef ngx_int_t (*ngx_mail_parse_command_pt)(ngx_mail_session_t *s); struct ngx_mail_protocol_s { ngx_str_t name; + ngx_str_t alpn; in_port_t port[4]; ngx_uint_t type; diff --git a/src/mail/ngx_mail_imap_module.c b/src/mail/ngx_mail_imap_module.c index 1f187fdee..02c684cd4 100644 --- a/src/mail/ngx_mail_imap_module.c +++ b/src/mail/ngx_mail_imap_module.c @@ -46,6 +46,7 @@ static ngx_str_t ngx_mail_imap_auth_methods_names[] = { static ngx_mail_protocol_t ngx_mail_imap_protocol = { ngx_string("imap"), + ngx_string("\x04imap"), { 143, 993, 0, 0 }, NGX_MAIL_IMAP_PROTOCOL, diff --git a/src/mail/ngx_mail_pop3_module.c b/src/mail/ngx_mail_pop3_module.c index a67307073..a257b5a70 100644 --- a/src/mail/ngx_mail_pop3_module.c +++ b/src/mail/ngx_mail_pop3_module.c @@ -46,6 +46,7 @@ static ngx_str_t ngx_mail_pop3_auth_methods_names[] = { static ngx_mail_protocol_t ngx_mail_pop3_protocol = { ngx_string("pop3"), + ngx_string("\x04pop3"), { 110, 995, 0, 0 }, NGX_MAIL_POP3_PROTOCOL, diff --git a/src/mail/ngx_mail_smtp_module.c b/src/mail/ngx_mail_smtp_module.c index 3b5a2d8f3..0e05fdc03 100644 --- a/src/mail/ngx_mail_smtp_module.c +++ b/src/mail/ngx_mail_smtp_module.c @@ -39,6 +39,7 @@ static ngx_str_t ngx_mail_smtp_auth_methods_names[] = { static ngx_mail_protocol_t ngx_mail_smtp_protocol = { ngx_string("smtp"), + ngx_string("\x04smtp"), { 25, 465, 587, 0 }, NGX_MAIL_SMTP_PROTOCOL, diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c index 09cc425d6..2a1043e66 100644 --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -14,6 +14,12 @@ #define NGX_DEFAULT_ECDH_CURVE "auto" +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation +static int ngx_mail_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, + const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg); +#endif + static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf); static char *ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child); @@ -244,6 +250,54 @@ ngx_module_t ngx_mail_ssl_module = { static ngx_str_t ngx_mail_ssl_sess_id_ctx = ngx_string("MAIL"); +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + +static int +ngx_mail_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, + unsigned char *outlen, const unsigned char *in, unsigned int inlen, + void *arg) +{ + unsigned int srvlen; + unsigned char *srv; + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_core_srv_conf_t *cscf; +#if (NGX_DEBUG) + unsigned int i; +#endif + + c = ngx_ssl_get_connection(ssl_conn); + s = c->data; + +#if (NGX_DEBUG) + for (i = 0; i < inlen; i += in[i] + 1) { + ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, + "SSL ALPN supported by client: %*s", + (size_t) in[i], &in[i + 1]); + } +#endif + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + srv = cscf->protocol->alpn.data; + srvlen = cscf->protocol->alpn.len; + + if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen, + in, inlen) + != OPENSSL_NPN_NEGOTIATED) + { + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, + "SSL ALPN selected: %*s", (size_t) *outlen, *out); + + return SSL_TLSEXT_ERR_OK; +} + +#endif + + static void * ngx_mail_ssl_create_conf(ngx_conf_t *cf) { @@ -394,6 +448,10 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_mail_ssl_alpn_select, NULL); +#endif + if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, conf->prefer_server_ciphers) != NGX_OK) |