Mercurial > hg > nginx-quic
changeset 8349:05e0988a6898 quic
Merged with the default branch.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Wed, 10 Mar 2021 15:39:01 +0300 |
parents | d981c7bd1da7 (current diff) 34e76ceabcec (diff) |
children | 6bb924b00e30 |
files | auto/modules src/event/ngx_event.c src/event/ngx_event_openssl.c src/http/modules/ngx_http_ssl_module.c |
diffstat | 30 files changed, 859 insertions(+), 327 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags +++ b/.hgtags @@ -457,3 +457,4 @@ dc0cc425fa63a80315f6efb68697cadb6626cdf2 8e5b068f761cd512d10c9671fbde0b568c1fd08b release-1.19.5 f618488eb769e0ed74ef0d93cd118d2ad79ef94d release-1.19.6 3fa6e2095a7a51acc630517e1c27a7b7ac41f7b3 release-1.19.7 +8c65d21464aaa5923775f80c32474adc7a320068 release-1.19.8
--- a/auto/init +++ b/auto/init @@ -48,4 +48,6 @@ default: build clean: rm -rf Makefile $NGX_OBJS + +.PHONY: default clean END
--- a/auto/install +++ b/auto/install @@ -215,4 +215,6 @@ upgrade: test -f $NGX_PID_PATH.oldbin kill -QUIT \`cat $NGX_PID_PATH.oldbin\` + +.PHONY: build install modules upgrade END
--- a/auto/modules +++ b/auto/modules @@ -1037,6 +1037,12 @@ if [ $MAIL != NO ]; then ngx_module_srcs=src/mail/ngx_mail_proxy_module.c . auto/module + + ngx_module_name=ngx_mail_realip_module + ngx_module_deps= + ngx_module_srcs=src/mail/ngx_mail_realip_module.c + + . auto/module fi
--- a/auto/unix +++ b/auto/unix @@ -727,19 +727,35 @@ ngx_feature_test="char buf[1]; struct io . auto/feature -ngx_feature="sys_nerr" -ngx_feature_name="NGX_SYS_NERR" -ngx_feature_run=value -ngx_feature_incs='#include <errno.h> - #include <stdio.h>' +# strerrordesc_np(), introduced in glibc 2.32 + +ngx_feature="strerrordesc_np()" +ngx_feature_name="NGX_HAVE_STRERRORDESC_NP" +ngx_feature_run=no +ngx_feature_incs='#include <string.h>' ngx_feature_path= ngx_feature_libs= -ngx_feature_test='printf("%d", sys_nerr);' +ngx_feature_test="char *p; p = strerrordesc_np(0); + if (p == NULL) return 1" . auto/feature if [ $ngx_found = no ]; then + ngx_feature="sys_nerr" + ngx_feature_name="NGX_SYS_NERR" + ngx_feature_run=value + ngx_feature_incs='#include <errno.h> + #include <stdio.h>' + ngx_feature_path= + ngx_feature_libs= + ngx_feature_test='printf("%d", sys_nerr);' + . auto/feature +fi + + +if [ $ngx_found = no ]; then + # Cygiwn defines _sys_nerr ngx_feature="_sys_nerr" ngx_feature_name="NGX_SYS_NERR" @@ -753,34 +769,6 @@ if [ $ngx_found = no ]; then fi -if [ $ngx_found = no ]; then - - # Solaris has no sys_nerr - ngx_feature='maximum errno' - ngx_feature_name=NGX_SYS_NERR - ngx_feature_run=value - ngx_feature_incs='#include <errno.h> - #include <string.h> - #include <stdio.h>' - ngx_feature_path= - ngx_feature_libs= - ngx_feature_test='int n; - char *p; - for (n = 1; n < 1000; n++) { - errno = 0; - p = strerror(n); - if (errno == EINVAL - || p == NULL - || strncmp(p, "Unknown error", 13) == 0) - { - break; - } - } - printf("%d", n);' - . auto/feature -fi - - ngx_feature="localtime_r()" ngx_feature_name="NGX_HAVE_LOCALTIME_R" ngx_feature_run=no
--- a/contrib/vim/syntax/nginx.vim +++ b/contrib/vim/syntax/nginx.vim @@ -2414,26 +2414,26 @@ syn keyword ngxDirectiveThirdParty conta " highlight -hi link ngxComment Comment -hi link ngxParamComment Comment -hi link ngxListenComment Comment -hi link ngxVariable Identifier -hi link ngxVariableString PreProc -hi link ngxString String -hi link ngxListenString String +hi def link ngxComment Comment +hi def link ngxParamComment Comment +hi def link ngxListenComment Comment +hi def link ngxVariable Identifier +hi def link ngxVariableString PreProc +hi def link ngxString String +hi def link ngxListenString String -hi link ngxBoolean Boolean -hi link ngxDirectiveBlock Statement -hi link ngxDirectiveImportant Type -hi link ngxDirectiveListen Type -hi link ngxDirectiveControl Keyword -hi link ngxDirectiveError Constant -hi link ngxDirectiveDeprecated Error -hi link ngxDirective Identifier -hi link ngxDirectiveThirdParty Special -hi link ngxDirectiveThirdPartyDeprecated Error +hi def link ngxBoolean Boolean +hi def link ngxDirectiveBlock Statement +hi def link ngxDirectiveImportant Type +hi def link ngxDirectiveListen Type +hi def link ngxDirectiveControl Keyword +hi def link ngxDirectiveError Constant +hi def link ngxDirectiveDeprecated Error +hi def link ngxDirective Identifier +hi def link ngxDirectiveThirdParty Special +hi def link ngxDirectiveThirdPartyDeprecated Error -hi link ngxListenOptions Keyword -hi link ngxListenOptionsDeprecated Error +hi def link ngxListenOptions Keyword +hi def link ngxListenOptionsDeprecated Error let b:current_syntax = "nginx"
--- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,68 @@ <change_log title="nginx"> +<changes ver="1.19.8" date="2021-03-09"> + +<change type="feature"> +<para lang="ru"> +в директиве proxy_cookie_flags теперь +флаги можно задавать с помощью переменных. +</para> +<para lang="en"> +flags in the "proxy_cookie_flags" directive +can now contain variables. +</para> +</change> + +<change type="feature"> +<para lang="ru"> +параметр proxy_protocol в директиве listen, +директивы proxy_protocol и set_real_ip_from +в почтовом прокси-сервере. +</para> +<para lang="en"> +the "proxy_protocol" parameter of the "listen" directive, +the "proxy_protocol" and "set_real_ip_from" directives +in mail proxy. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +HTTP/2-соединения сразу закрывались +при использовании "keepalive_timeout 0"; +ошибка появилась в 1.19.7. +</para> +<para lang="en"> +HTTP/2 connections were immediately closed +when using "keepalive_timeout 0"; +the bug had appeared in 1.19.7. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +некоторые ошибки логгировались как неизвестные, +если nginx был собран с glibc 2.32. +</para> +<para lang="en"> +some errors were logged as unknown +if nginx was built with glibc 2.32. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +в методе обработки соединений eventport. +</para> +<para lang="en"> +in the eventport method. +</para> +</change> + +</changes> + + <changes ver="1.19.7" date="2021-02-16"> <change type="change">
--- a/misc/GNUmakefile +++ b/misc/GNUmakefile @@ -6,7 +6,7 @@ TEMP = tmp CC = cl OBJS = objs.msvc8 -OPENSSL = openssl-1.1.1i +OPENSSL = openssl-1.1.1j ZLIB = zlib-1.2.11 PCRE = pcre-8.44
--- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1019007 -#define NGINX_VERSION "1.19.7" +#define nginx_version 1019008 +#define NGINX_VERSION "1.19.8" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD
--- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -338,7 +338,7 @@ ngx_handle_read_event(ngx_event_t *rev, return NGX_OK; } - if (rev->oneshot && !rev->ready) { + if (rev->oneshot && rev->ready) { if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { return NGX_ERROR; }
--- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -83,7 +83,7 @@ static time_t ngx_ssl_parse_time( #if OPENSSL_VERSION_NUMBER > 0x10100000L const #endif - ASN1_TIME *asn1time); + ASN1_TIME *asn1time, ngx_log_t *log); static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -1014,26 +1014,52 @@ ngx_ssl_verify_callback(int ok, X509_STO c = ngx_ssl_get_connection(ssl_conn); + if (!(c->log->log_level & NGX_LOG_DEBUG_EVENT)) { + return 1; + } + cert = X509_STORE_CTX_get_current_cert(x509_store); err = X509_STORE_CTX_get_error(x509_store); depth = X509_STORE_CTX_get_error_depth(x509_store); sname = X509_get_subject_name(cert); - subject = sname ? X509_NAME_oneline(sname, NULL, 0) : "(none)"; + + if (sname) { + subject = X509_NAME_oneline(sname, NULL, 0); + if (subject == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, + "X509_NAME_oneline() failed"); + } + + } else { + subject = NULL; + } iname = X509_get_issuer_name(cert); - issuer = iname ? X509_NAME_oneline(iname, NULL, 0) : "(none)"; + + if (iname) { + issuer = X509_NAME_oneline(iname, NULL, 0); + if (issuer == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, + "X509_NAME_oneline() failed"); + } + + } else { + issuer = NULL; + } ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0, "verify:%d, error:%d, depth:%d, " "subject:\"%s\", issuer:\"%s\"", - ok, err, depth, subject, issuer); - - if (sname) { + ok, err, depth, + subject ? subject : "(none)", + issuer ? issuer : "(none)"); + + if (subject) { OPENSSL_free(subject); } - if (iname) { + if (issuer) { OPENSSL_free(issuer); } #endif @@ -1948,6 +1974,10 @@ ngx_ssl_handshake_log(ngx_connection_t * #endif SSL_CIPHER *cipher; + if (!(c->log->log_level & NGX_LOG_DEBUG_EVENT)) { + return; + } + cipher = SSL_get_current_cipher(c->ssl->connection); if (cipher) { @@ -4802,11 +4832,13 @@ ngx_ssl_get_subject_dn(ngx_connection_t bio = BIO_new(BIO_s_mem()); if (bio == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed"); X509_free(cert); return NGX_ERROR; } if (X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253) < 0) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_print_ex() failed"); goto failed; } @@ -4854,11 +4886,13 @@ ngx_ssl_get_issuer_dn(ngx_connection_t * bio = BIO_new(BIO_s_mem()); if (bio == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed"); X509_free(cert); return NGX_ERROR; } if (X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253) < 0) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_print_ex() failed"); goto failed; } @@ -4907,6 +4941,11 @@ ngx_ssl_get_subject_dn_legacy(ngx_connec } p = X509_NAME_oneline(name, NULL, 0); + if (p == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_oneline() failed"); + X509_free(cert); + return NGX_ERROR; + } for (len = 0; p[len]; len++) { /* void */ } @@ -4950,6 +4989,11 @@ ngx_ssl_get_issuer_dn_legacy(ngx_connect } p = X509_NAME_oneline(name, NULL, 0); + if (p == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_NAME_oneline() failed"); + X509_free(cert); + return NGX_ERROR; + } for (len = 0; p[len]; len++) { /* void */ } @@ -4986,6 +5030,7 @@ ngx_ssl_get_serial_number(ngx_connection bio = BIO_new(BIO_s_mem()); if (bio == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed"); X509_free(cert); return NGX_ERROR; } @@ -5024,6 +5069,7 @@ ngx_ssl_get_fingerprint(ngx_connection_t } if (!X509_digest(cert, EVP_sha1(), buf, &len)) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_digest() failed"); X509_free(cert); return NGX_ERROR; } @@ -5097,6 +5143,7 @@ ngx_ssl_get_client_v_start(ngx_connectio bio = BIO_new(BIO_s_mem()); if (bio == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed"); X509_free(cert); return NGX_ERROR; } @@ -5141,6 +5188,7 @@ ngx_ssl_get_client_v_end(ngx_connection_ bio = BIO_new(BIO_s_mem()); if (bio == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed"); X509_free(cert); return NGX_ERROR; } @@ -5183,9 +5231,9 @@ ngx_ssl_get_client_v_remain(ngx_connecti } #if OPENSSL_VERSION_NUMBER > 0x10100000L - end = ngx_ssl_parse_time(X509_get0_notAfter(cert)); + end = ngx_ssl_parse_time(X509_get0_notAfter(cert), c->log); #else - end = ngx_ssl_parse_time(X509_get_notAfter(cert)); + end = ngx_ssl_parse_time(X509_get_notAfter(cert), c->log); #endif if (end == (time_t) NGX_ERROR) { @@ -5220,7 +5268,7 @@ ngx_ssl_parse_time( #if OPENSSL_VERSION_NUMBER > 0x10100000L const #endif - ASN1_TIME *asn1time) + ASN1_TIME *asn1time, ngx_log_t *log) { BIO *bio; char *value; @@ -5236,6 +5284,7 @@ ngx_ssl_parse_time( bio = BIO_new(BIO_s_mem()); if (bio == NULL) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, "BIO_new() failed"); return NGX_ERROR; }
--- a/src/http/modules/ngx_http_grpc_module.c +++ b/src/http/modules/ngx_http_grpc_module.c @@ -4841,9 +4841,9 @@ ngx_http_grpc_ssl_conf_command_check(ngx { #ifndef SSL_CONF_FLAG_FILE return "is not supported on this platform"; +#else + return NGX_CONF_OK; #endif - - return NGX_CONF_OK; }
--- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -56,7 +56,7 @@ typedef struct { #endif } cookie; - ngx_uint_t flags; + ngx_array_t flags_values; ngx_uint_t regex; } ngx_http_proxy_cookie_flags_t; @@ -2916,12 +2916,14 @@ static ngx_int_t ngx_http_proxy_rewrite_cookie_flags(ngx_http_request_t *r, ngx_array_t *attrs, ngx_array_t *flags) { - ngx_str_t pattern; + ngx_str_t pattern, value; #if (NGX_PCRE) ngx_int_t rc; #endif - ngx_uint_t i; + ngx_uint_t i, m, f, nelts; ngx_keyval_t *attr; + ngx_conf_bitmask_t *mask; + ngx_http_complex_value_t *flags_values; ngx_http_proxy_cookie_flags_t *pcf; attr = attrs->elts; @@ -2965,7 +2967,47 @@ ngx_http_proxy_rewrite_cookie_flags(ngx_ return NGX_DECLINED; } - return ngx_http_proxy_edit_cookie_flags(r, attrs, pcf[i].flags); + nelts = pcf[i].flags_values.nelts; + flags_values = pcf[i].flags_values.elts; + + mask = ngx_http_proxy_cookie_flags_masks; + f = 0; + + for (i = 0; i < nelts; i++) { + + if (ngx_http_complex_value(r, &flags_values[i], &value) != NGX_OK) { + return NGX_ERROR; + } + + if (value.len == 0) { + continue; + } + + for (m = 0; mask[m].name.len != 0; m++) { + + if (mask[m].name.len != value.len + || ngx_strncasecmp(mask[m].name.data, value.data, value.len) + != 0) + { + continue; + } + + f |= mask[m].mask; + + break; + } + + if (mask[m].name.len == 0) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "invalid proxy_cookie_flags flag \"%V\"", &value); + } + } + + if (f == 0) { + return NGX_DECLINED; + } + + return ngx_http_proxy_edit_cookie_flags(r, attrs, f); } @@ -4514,8 +4556,8 @@ ngx_http_proxy_cookie_flags(ngx_conf_t * ngx_http_proxy_loc_conf_t *plcf = conf; ngx_str_t *value; - ngx_uint_t i, m; - ngx_conf_bitmask_t *mask; + ngx_uint_t i; + ngx_http_complex_value_t *cv; ngx_http_proxy_cookie_flags_t *pcf; ngx_http_compile_complex_value_t ccv; #if (NGX_PCRE) @@ -4599,32 +4641,27 @@ ngx_http_proxy_cookie_flags(ngx_conf_t * } } - mask = ngx_http_proxy_cookie_flags_masks; - pcf->flags = 0; + if (ngx_array_init(&pcf->flags_values, cf->pool, cf->args->nelts - 2, + sizeof(ngx_http_complex_value_t)) + != NGX_OK) + { + return NGX_CONF_ERROR; + } for (i = 2; i < cf->args->nelts; i++) { - for (m = 0; mask[m].name.len != 0; m++) { - - if (mask[m].name.len != value[i].len - || ngx_strcasecmp(mask[m].name.data, value[i].data) != 0) - { - continue; - } - - if (pcf->flags & mask[m].mask) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "duplicate parameter \"%V\"", &value[i]); - return NGX_CONF_ERROR; - } - - pcf->flags |= mask[m].mask; - - break; + + cv = ngx_array_push(&pcf->flags_values); + if (cv == NULL) { + return NGX_CONF_ERROR; } - if (mask[m].name.len == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid parameter \"%V\"", &value[i]); + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[i]; + ccv.complex_value = cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { return NGX_CONF_ERROR; } } @@ -4876,9 +4913,9 @@ ngx_http_proxy_ssl_conf_command_check(ng { #ifndef SSL_CONF_FLAG_FILE return "is not supported on this platform"; +#else + return NGX_CONF_OK; #endif - - return NGX_CONF_OK; }
--- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -1307,9 +1307,9 @@ ngx_http_ssl_conf_command_check(ngx_conf { #ifndef SSL_CONF_FLAG_FILE return "is not supported on this platform"; +#else + return NGX_CONF_OK; #endif - - return NGX_CONF_OK; }
--- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -2398,9 +2398,9 @@ ngx_http_uwsgi_ssl_conf_command_check(ng { #ifndef SSL_CONF_FLAG_FILE return "is not supported on this platform"; +#else + return NGX_CONF_OK; #endif - - return NGX_CONF_OK; }
--- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -238,6 +238,7 @@ ngx_http_v2_init(ngx_event_t *rev) ngx_http_v2_srv_conf_t *h2scf; ngx_http_v2_main_conf_t *h2mcf; ngx_http_v2_connection_t *h2c; + ngx_http_core_srv_conf_t *cscf; c = rev->data; hc = c->data; @@ -325,8 +326,10 @@ ngx_http_v2_init(ngx_event_t *rev) rev->handler = ngx_http_v2_read_handler; c->write->handler = ngx_http_v2_write_handler; - if (c->read->timer_set) { - ngx_del_timer(c->read); + if (!rev->timer_set) { + cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, + ngx_http_core_module); + ngx_add_timer(rev, cscf->client_header_timeout); } c->idle = 1;
--- a/src/mail/ngx_mail.c +++ b/src/mail/ngx_mail.c @@ -405,6 +405,7 @@ ngx_mail_add_addrs(ngx_conf_t *cf, ngx_m #if (NGX_MAIL_SSL) addrs[i].conf.ssl = addr[i].opt.ssl; #endif + addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; addrs[i].conf.addr_text = addr[i].opt.addr_text; } @@ -439,6 +440,7 @@ ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_ #if (NGX_MAIL_SSL) addrs6[i].conf.ssl = addr[i].opt.ssl; #endif + addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; addrs6[i].conf.addr_text = addr[i].opt.addr_text; }
--- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -41,6 +41,7 @@ typedef struct { unsigned ipv6only:1; #endif unsigned so_keepalive:2; + unsigned proxy_protocol:1; #if (NGX_HAVE_KEEPALIVE_TUNABLE) int tcp_keepidle; int tcp_keepintvl; @@ -55,7 +56,8 @@ typedef struct { typedef struct { ngx_mail_conf_ctx_t *ctx; ngx_str_t addr_text; - ngx_uint_t ssl; /* unsigned ssl:1; */ + unsigned ssl:1; + unsigned proxy_protocol:1; } ngx_mail_addr_conf_t; typedef struct { @@ -176,6 +178,7 @@ typedef enum { typedef struct { ngx_peer_connection_t upstream; ngx_buf_t *buffer; + ngx_uint_t proxy_protocol; /* unsigned proxy_protocol:1; */ } ngx_mail_proxy_ctx_t; @@ -197,6 +200,7 @@ typedef struct { ngx_uint_t mail_state; + unsigned ssl:1; unsigned protocol:3; unsigned blocked:1; unsigned quit:1; @@ -405,6 +409,7 @@ char *ngx_mail_capabilities(ngx_conf_t * /* STUB */ void ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer); void ngx_mail_auth_http_init(ngx_mail_session_t *s); +ngx_int_t ngx_mail_realip_handler(ngx_mail_session_t *s); /**/
--- a/src/mail/ngx_mail_auth_http_module.c +++ b/src/mail/ngx_mail_auth_http_module.c @@ -1224,22 +1224,49 @@ ngx_mail_auth_http_create_request(ngx_ma + sizeof("Client-IP: ") - 1 + s->connection->addr_text.len + sizeof(CRLF) - 1 + sizeof("Client-Host: ") - 1 + s->host.len + sizeof(CRLF) - 1 - + sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len + sizeof(CRLF) - 1 - + sizeof("Auth-SMTP-From: ") - 1 + s->smtp_from.len + sizeof(CRLF) - 1 - + sizeof("Auth-SMTP-To: ") - 1 + s->smtp_to.len + sizeof(CRLF) - 1 -#if (NGX_MAIL_SSL) - + sizeof("Auth-SSL: on" CRLF) - 1 - + sizeof("Auth-SSL-Verify: ") - 1 + verify.len + sizeof(CRLF) - 1 - + sizeof("Auth-SSL-Subject: ") - 1 + subject.len + sizeof(CRLF) - 1 - + sizeof("Auth-SSL-Issuer: ") - 1 + issuer.len + sizeof(CRLF) - 1 - + sizeof("Auth-SSL-Serial: ") - 1 + serial.len + sizeof(CRLF) - 1 - + sizeof("Auth-SSL-Fingerprint: ") - 1 + fingerprint.len - + sizeof(CRLF) - 1 - + sizeof("Auth-SSL-Cert: ") - 1 + cert.len + sizeof(CRLF) - 1 -#endif + ahcf->header.len + sizeof(CRLF) - 1; + if (c->proxy_protocol) { + len += sizeof("Proxy-Protocol-Addr: ") - 1 + + c->proxy_protocol->src_addr.len + sizeof(CRLF) - 1 + + sizeof("Proxy-Protocol-Port: ") - 1 + + sizeof("65535") - 1 + sizeof(CRLF) - 1 + + sizeof("Proxy-Protocol-Server-Addr: ") - 1 + + c->proxy_protocol->dst_addr.len + sizeof(CRLF) - 1 + + sizeof("Proxy-Protocol-Server-Port: ") - 1 + + sizeof("65535") - 1 + sizeof(CRLF) - 1; + } + + if (s->auth_method == NGX_MAIL_AUTH_NONE) { + len += sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SMTP-From: ") - 1 + s->smtp_from.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SMTP-To: ") - 1 + s->smtp_to.len + + sizeof(CRLF) - 1; + } + +#if (NGX_MAIL_SSL) + + if (c->ssl) { + len += sizeof("Auth-SSL: on" CRLF) - 1 + + sizeof("Auth-SSL-Verify: ") - 1 + verify.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Subject: ") - 1 + subject.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Issuer: ") - 1 + issuer.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Serial: ") - 1 + serial.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Fingerprint: ") - 1 + fingerprint.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Cert: ") - 1 + cert.len + + sizeof(CRLF) - 1; + } + +#endif + b = ngx_create_temp_buf(pool, len); if (b == NULL) { return NULL; @@ -1298,6 +1325,26 @@ ngx_mail_auth_http_create_request(ngx_ma *b->last++ = CR; *b->last++ = LF; } + if (c->proxy_protocol) { + b->last = ngx_cpymem(b->last, "Proxy-Protocol-Addr: ", + sizeof("Proxy-Protocol-Addr: ") - 1); + b->last = ngx_copy(b->last, c->proxy_protocol->src_addr.data, + c->proxy_protocol->src_addr.len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_sprintf(b->last, "Proxy-Protocol-Port: %d" CRLF, + c->proxy_protocol->src_port); + + b->last = ngx_cpymem(b->last, "Proxy-Protocol-Server-Addr: ", + sizeof("Proxy-Protocol-Server-Addr: ") - 1); + b->last = ngx_copy(b->last, c->proxy_protocol->dst_addr.data, + c->proxy_protocol->dst_addr.len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_sprintf(b->last, "Proxy-Protocol-Server-Port: %d" CRLF, + c->proxy_protocol->dst_port); + } + if (s->auth_method == NGX_MAIL_AUTH_NONE) { /* HELO, MAIL FROM, and RCPT TO can't contain CRLF, no need to escape */
--- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -548,6 +548,11 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx #endif } + if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) { + ls->proxy_protocol = 1; + continue; + } + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the invalid \"%V\" parameter", &value[i]); return NGX_CONF_ERROR;
--- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -11,6 +11,8 @@ #include <ngx_mail.h> +static void ngx_mail_proxy_protocol_handler(ngx_event_t *rev); +static void ngx_mail_init_session_handler(ngx_event_t *rev); static void ngx_mail_init_session(ngx_connection_t *c); #if (NGX_MAIL_SSL) @@ -26,6 +28,7 @@ ngx_mail_init_connection(ngx_connection_ { size_t len; ngx_uint_t i; + ngx_event_t *rev; ngx_mail_port_t *port; struct sockaddr *sa; struct sockaddr_in *sin; @@ -129,6 +132,10 @@ ngx_mail_init_connection(ngx_connection_ s->main_conf = addr_conf->ctx->main_conf; s->srv_conf = addr_conf->ctx->srv_conf; +#if (NGX_MAIL_SSL) + s->ssl = addr_conf->ssl; +#endif + s->addr_text = &addr_conf->addr_text; c->data = s; @@ -159,13 +166,125 @@ ngx_mail_init_connection(ngx_connection_ c->log_error = NGX_ERROR_INFO; + rev = c->read; + rev->handler = ngx_mail_init_session_handler; + + if (addr_conf->proxy_protocol) { + c->log->action = "reading PROXY protocol"; + + rev->handler = ngx_mail_proxy_protocol_handler; + + if (!rev->ready) { + ngx_add_timer(rev, cscf->timeout); + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_mail_close_connection(c); + } + + return; + } + } + + if (ngx_use_accept_mutex) { + ngx_post_event(rev, &ngx_posted_events); + return; + } + + rev->handler(rev); +} + + +static void +ngx_mail_proxy_protocol_handler(ngx_event_t *rev) +{ + u_char *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER]; + size_t size; + ssize_t n; + ngx_err_t err; + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_core_srv_conf_t *cscf; + + c = rev->data; + s = c->data; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, + "mail PROXY protocol handler"); + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + c->timedout = 1; + ngx_mail_close_connection(c); + return; + } + + n = recv(c->fd, (char *) buf, sizeof(buf), MSG_PEEK); + + err = ngx_socket_errno; + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "recv(): %z", n); + + if (n == -1) { + if (err == NGX_EAGAIN) { + rev->ready = 0; + + if (!rev->timer_set) { + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + ngx_add_timer(rev, cscf->timeout); + } + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_mail_close_connection(c); + } + + return; + } + + ngx_connection_error(c, err, "recv() failed"); + + ngx_mail_close_connection(c); + return; + } + + p = ngx_proxy_protocol_read(c, buf, buf + n); + + if (p == NULL) { + ngx_mail_close_connection(c); + return; + } + + size = p - buf; + + if (c->recv(c, buf, size) != (ssize_t) size) { + ngx_mail_close_connection(c); + return; + } + + if (ngx_mail_realip_handler(s) != NGX_OK) { + ngx_mail_close_connection(c); + return; + } + + ngx_mail_init_session_handler(rev); +} + + +static void +ngx_mail_init_session_handler(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + + c = rev->data; + s = c->data; + #if (NGX_MAIL_SSL) { ngx_mail_ssl_conf_t *sslcf; sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); - if (sslcf->enable || addr_conf->ssl) { + if (sslcf->enable || s->ssl) { c->log->action = "SSL handshaking"; ngx_mail_ssl_init_connection(&sslcf->ssl, c); @@ -215,9 +334,10 @@ ngx_mail_ssl_init_connection(ngx_ssl_t * s = c->data; - cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); - - ngx_add_timer(c->read, cscf->timeout); + if (!c->read->timer_set) { + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + ngx_add_timer(c->read, cscf->timeout); + } c->ssl->handler = ngx_mail_ssl_handshake_handler; @@ -338,6 +458,8 @@ ngx_mail_init_session(ngx_connection_t * s = c->data; + c->log->action = "sending client greeting line"; + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); s->protocol = cscf->protocol->type; @@ -722,11 +844,6 @@ ngx_mail_read_command(ngx_mail_session_t } if (n == NGX_AGAIN) { - if (ngx_handle_read_event(c->read, 0) != NGX_OK) { - ngx_mail_session_internal_server_error(s); - return NGX_ERROR; - } - if (s->buffer->pos == s->buffer->last) { return NGX_AGAIN; }
--- a/src/mail/ngx_mail_imap_handler.c +++ b/src/mail/ngx_mail_imap_handler.c @@ -123,6 +123,12 @@ ngx_mail_imap_auth_state(ngx_event_t *re if (s->out.len) { ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap send handler busy"); s->blocked = 1; + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_close_connection(c); + return; + } + return; } @@ -130,7 +136,16 @@ ngx_mail_imap_auth_state(ngx_event_t *re rc = ngx_mail_read_command(s, c); - if (rc == NGX_AGAIN || rc == NGX_ERROR) { + if (rc == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return; + } + + return; + } + + if (rc == NGX_ERROR) { return; } @@ -293,6 +308,11 @@ ngx_mail_imap_auth_state(ngx_event_t *re } } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return; + } + ngx_mail_send(c->write); }
--- a/src/mail/ngx_mail_pop3_handler.c +++ b/src/mail/ngx_mail_pop3_handler.c @@ -138,6 +138,12 @@ ngx_mail_pop3_auth_state(ngx_event_t *re if (s->out.len) { ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "pop3 send handler busy"); s->blocked = 1; + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_close_connection(c); + return; + } + return; } @@ -145,7 +151,16 @@ ngx_mail_pop3_auth_state(ngx_event_t *re rc = ngx_mail_read_command(s, c); - if (rc == NGX_AGAIN || rc == NGX_ERROR) { + if (rc == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return; + } + + return; + } + + if (rc == NGX_ERROR) { return; } @@ -275,6 +290,11 @@ ngx_mail_pop3_auth_state(ngx_event_t *re s->arg_start = s->buffer->start; } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return; + } + ngx_mail_send(c->write); } }
--- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -17,6 +17,7 @@ typedef struct { ngx_flag_t pass_error_message; ngx_flag_t xclient; ngx_flag_t smtp_auth; + ngx_flag_t proxy_protocol; size_t buffer_size; ngx_msec_t timeout; } ngx_mail_proxy_conf_t; @@ -26,7 +27,8 @@ static void ngx_mail_proxy_block_read(ng static void ngx_mail_proxy_pop3_handler(ngx_event_t *rev); static void ngx_mail_proxy_imap_handler(ngx_event_t *rev); static void ngx_mail_proxy_smtp_handler(ngx_event_t *rev); -static void ngx_mail_proxy_dummy_handler(ngx_event_t *ev); +static void ngx_mail_proxy_write_handler(ngx_event_t *wev); +static ngx_int_t ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s); static ngx_int_t ngx_mail_proxy_read_response(ngx_mail_session_t *s, ngx_uint_t state); static void ngx_mail_proxy_handler(ngx_event_t *ev); @@ -82,6 +84,13 @@ static ngx_command_t ngx_mail_proxy_com offsetof(ngx_mail_proxy_conf_t, smtp_auth), NULL }, + { ngx_string("proxy_protocol"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, proxy_protocol), + NULL }, + ngx_null_command }; @@ -156,7 +165,7 @@ ngx_mail_proxy_init(ngx_mail_session_t * p->upstream.connection->pool = s->connection->pool; s->connection->read->handler = ngx_mail_proxy_block_read; - p->upstream.connection->write->handler = ngx_mail_proxy_dummy_handler; + p->upstream.connection->write->handler = ngx_mail_proxy_write_handler; pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); @@ -167,6 +176,8 @@ ngx_mail_proxy_init(ngx_mail_session_t * return; } + s->proxy->proxy_protocol = pcf->proxy_protocol; + s->out.len = 0; switch (s->protocol) { @@ -186,6 +197,12 @@ ngx_mail_proxy_init(ngx_mail_session_t * s->mail_state = ngx_smtp_start; break; } + + if (rc == NGX_AGAIN) { + return; + } + + ngx_mail_proxy_write_handler(p->upstream.connection->write); } @@ -230,9 +247,25 @@ ngx_mail_proxy_pop3_handler(ngx_event_t return; } + if (s->proxy->proxy_protocol) { + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "mail proxy pop3 busy"); + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + return; + } + rc = ngx_mail_proxy_read_response(s, 0); if (rc == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + return; } @@ -314,6 +347,11 @@ ngx_mail_proxy_pop3_handler(ngx_event_t return; } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + s->proxy->buffer->pos = s->proxy->buffer->start; s->proxy->buffer->last = s->proxy->buffer->start; } @@ -343,9 +381,25 @@ ngx_mail_proxy_imap_handler(ngx_event_t return; } + if (s->proxy->proxy_protocol) { + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "mail proxy imap busy"); + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + return; + } + rc = ngx_mail_proxy_read_response(s, s->mail_state); if (rc == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + return; } @@ -448,6 +502,11 @@ ngx_mail_proxy_imap_handler(ngx_event_t return; } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + s->proxy->buffer->pos = s->proxy->buffer->start; s->proxy->buffer->last = s->proxy->buffer->start; } @@ -479,9 +538,25 @@ ngx_mail_proxy_smtp_handler(ngx_event_t return; } + if (s->proxy->proxy_protocol) { + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "mail proxy smtp busy"); + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + return; + } + rc = ngx_mail_proxy_read_response(s, s->mail_state); if (rc == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + return; } @@ -763,25 +838,103 @@ ngx_mail_proxy_smtp_handler(ngx_event_t return; } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return; + } + s->proxy->buffer->pos = s->proxy->buffer->start; s->proxy->buffer->last = s->proxy->buffer->start; } static void -ngx_mail_proxy_dummy_handler(ngx_event_t *wev) +ngx_mail_proxy_write_handler(ngx_event_t *wev) { ngx_connection_t *c; ngx_mail_session_t *s; - ngx_log_debug0(NGX_LOG_DEBUG_MAIL, wev->log, 0, "mail proxy dummy handler"); + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, wev->log, 0, "mail proxy write handler"); + + c = wev->data; + s = c->data; + + if (s->proxy->proxy_protocol) { + if (ngx_mail_proxy_send_proxy_protocol(s) != NGX_OK) { + return; + } + + s->proxy->proxy_protocol = 0; + } if (ngx_handle_write_event(wev, 0) != NGX_OK) { - c = wev->data; - s = c->data; + ngx_mail_proxy_internal_server_error(s); + } + + if (c->read->ready) { + ngx_post_event(c->read, &ngx_posted_events); + } +} + + +static ngx_int_t +ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s) +{ + u_char *p; + ssize_t n, size; + ngx_connection_t *c; + u_char buf[NGX_PROXY_PROTOCOL_MAX_HEADER]; + + s->connection->log->action = "sending PROXY protocol header to upstream"; + + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, + "mail proxy send PROXY protocol header"); + + p = ngx_proxy_protocol_write(s->connection, buf, + buf + NGX_PROXY_PROTOCOL_MAX_HEADER); + if (p == NULL) { + ngx_mail_proxy_internal_server_error(s); + return NGX_ERROR; + } + + c = s->proxy->upstream.connection; + + size = p - buf; - ngx_mail_proxy_close_session(s); + n = c->send(c, buf, size); + + if (n == NGX_AGAIN) { + if (ngx_handle_write_event(c->write, 0) != NGX_OK) { + ngx_mail_proxy_internal_server_error(s); + return NGX_ERROR; + } + + return NGX_AGAIN; + } + + if (n == NGX_ERROR) { + ngx_mail_proxy_internal_server_error(s); + return NGX_ERROR; } + + if (n != size) { + + /* + * PROXY protocol specification: + * The sender must always ensure that the header + * is sent at once, so that the transport layer + * maintains atomicity along the path to the receiver. + */ + + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "could not send PROXY protocol header at once"); + + ngx_mail_proxy_internal_server_error(s); + + return NGX_ERROR; + } + + return NGX_OK; } @@ -1182,6 +1335,7 @@ ngx_mail_proxy_create_conf(ngx_conf_t *c pcf->pass_error_message = NGX_CONF_UNSET; pcf->xclient = NGX_CONF_UNSET; pcf->smtp_auth = NGX_CONF_UNSET; + pcf->proxy_protocol = NGX_CONF_UNSET; pcf->buffer_size = NGX_CONF_UNSET_SIZE; pcf->timeout = NGX_CONF_UNSET_MSEC; @@ -1199,6 +1353,7 @@ ngx_mail_proxy_merge_conf(ngx_conf_t *cf ngx_conf_merge_value(conf->pass_error_message, prev->pass_error_message, 0); ngx_conf_merge_value(conf->xclient, prev->xclient, 1); ngx_conf_merge_value(conf->smtp_auth, prev->smtp_auth, 0); + ngx_conf_merge_value(conf->proxy_protocol, prev->proxy_protocol, 0); ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, (size_t) ngx_pagesize); ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * 60000);
copy from src/stream/ngx_stream_realip_module.c copy to src/mail/ngx_mail_realip_module.c --- a/src/stream/ngx_stream_realip_module.c +++ b/src/mail/ngx_mail_realip_module.c @@ -7,45 +7,29 @@ #include <ngx_config.h> #include <ngx_core.h> -#include <ngx_stream.h> +#include <ngx_mail.h> typedef struct { ngx_array_t *from; /* array of ngx_cidr_t */ -} ngx_stream_realip_srv_conf_t; - - -typedef struct { - struct sockaddr *sockaddr; - socklen_t socklen; - ngx_str_t addr_text; -} ngx_stream_realip_ctx_t; +} ngx_mail_realip_srv_conf_t; -static ngx_int_t ngx_stream_realip_handler(ngx_stream_session_t *s); -static ngx_int_t ngx_stream_realip_set_addr(ngx_stream_session_t *s, +static ngx_int_t ngx_mail_realip_set_addr(ngx_mail_session_t *s, ngx_addr_t *addr); -static char *ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, +static char *ngx_mail_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static void *ngx_stream_realip_create_srv_conf(ngx_conf_t *cf); -static char *ngx_stream_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, +static void *ngx_mail_realip_create_srv_conf(ngx_conf_t *cf); +static char *ngx_mail_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child); -static ngx_int_t ngx_stream_realip_add_variables(ngx_conf_t *cf); -static ngx_int_t ngx_stream_realip_init(ngx_conf_t *cf); -static ngx_int_t ngx_stream_realip_remote_addr_variable(ngx_stream_session_t *s, - ngx_stream_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_stream_realip_remote_port_variable(ngx_stream_session_t *s, - ngx_stream_variable_value_t *v, uintptr_t data); - - -static ngx_command_t ngx_stream_realip_commands[] = { +static ngx_command_t ngx_mail_realip_commands[] = { { ngx_string("set_real_ip_from"), - NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_stream_realip_from, - NGX_STREAM_SRV_CONF_OFFSET, + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_mail_realip_from, + NGX_MAIL_SRV_CONF_OFFSET, 0, NULL }, @@ -53,23 +37,22 @@ static ngx_command_t ngx_stream_realip_ }; -static ngx_stream_module_t ngx_stream_realip_module_ctx = { - ngx_stream_realip_add_variables, /* preconfiguration */ - ngx_stream_realip_init, /* postconfiguration */ +static ngx_mail_module_t ngx_mail_realip_module_ctx = { + NULL, /* protocol */ NULL, /* create main configuration */ NULL, /* init main configuration */ - ngx_stream_realip_create_srv_conf, /* create server configuration */ - ngx_stream_realip_merge_srv_conf /* merge server configuration */ + ngx_mail_realip_create_srv_conf, /* create server configuration */ + ngx_mail_realip_merge_srv_conf /* merge server configuration */ }; -ngx_module_t ngx_stream_realip_module = { +ngx_module_t ngx_mail_realip_module = { NGX_MODULE_V1, - &ngx_stream_realip_module_ctx, /* module context */ - ngx_stream_realip_commands, /* module directives */ - NGX_STREAM_MODULE, /* module type */ + &ngx_mail_realip_module_ctx, /* module context */ + ngx_mail_realip_commands, /* module directives */ + NGX_MAIL_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ @@ -81,70 +64,52 @@ ngx_module_t ngx_stream_realip_module = }; -static ngx_stream_variable_t ngx_stream_realip_vars[] = { - - { ngx_string("realip_remote_addr"), NULL, - ngx_stream_realip_remote_addr_variable, 0, 0, 0 }, - - { ngx_string("realip_remote_port"), NULL, - ngx_stream_realip_remote_port_variable, 0, 0, 0 }, +ngx_int_t +ngx_mail_realip_handler(ngx_mail_session_t *s) +{ + ngx_addr_t addr; + ngx_connection_t *c; + ngx_mail_realip_srv_conf_t *rscf; - ngx_stream_null_variable -}; - - -static ngx_int_t -ngx_stream_realip_handler(ngx_stream_session_t *s) -{ - ngx_addr_t addr; - ngx_connection_t *c; - ngx_stream_realip_srv_conf_t *rscf; - - rscf = ngx_stream_get_module_srv_conf(s, ngx_stream_realip_module); + rscf = ngx_mail_get_module_srv_conf(s, ngx_mail_realip_module); if (rscf->from == NULL) { - return NGX_DECLINED; + return NGX_OK; } c = s->connection; if (c->proxy_protocol == NULL) { - return NGX_DECLINED; + return NGX_OK; } if (ngx_cidr_match(c->sockaddr, rscf->from) != NGX_OK) { - return NGX_DECLINED; + return NGX_OK; } if (ngx_parse_addr(c->pool, &addr, c->proxy_protocol->src_addr.data, c->proxy_protocol->src_addr.len) != NGX_OK) { - return NGX_DECLINED; + return NGX_OK; } ngx_inet_set_port(addr.sockaddr, c->proxy_protocol->src_port); - return ngx_stream_realip_set_addr(s, &addr); + return ngx_mail_realip_set_addr(s, &addr); } static ngx_int_t -ngx_stream_realip_set_addr(ngx_stream_session_t *s, ngx_addr_t *addr) +ngx_mail_realip_set_addr(ngx_mail_session_t *s, ngx_addr_t *addr) { - size_t len; - u_char *p; - u_char text[NGX_SOCKADDR_STRLEN]; - ngx_connection_t *c; - ngx_stream_realip_ctx_t *ctx; + size_t len; + u_char *p; + u_char text[NGX_SOCKADDR_STRLEN]; + ngx_connection_t *c; c = s->connection; - ctx = ngx_palloc(c->pool, sizeof(ngx_stream_realip_ctx_t)); - if (ctx == NULL) { - return NGX_ERROR; - } - len = ngx_sock_ntop(addr->sockaddr, addr->socklen, text, NGX_SOCKADDR_STRLEN, 0); if (len == 0) { @@ -158,25 +123,19 @@ ngx_stream_realip_set_addr(ngx_stream_se ngx_memcpy(p, text, len); - ngx_stream_set_ctx(s, ctx, ngx_stream_realip_module); - - ctx->sockaddr = c->sockaddr; - ctx->socklen = c->socklen; - ctx->addr_text = c->addr_text; - c->sockaddr = addr->sockaddr; c->socklen = addr->socklen; c->addr_text.len = len; c->addr_text.data = p; - return NGX_DECLINED; + return NGX_OK; } static char * -ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +ngx_mail_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_stream_realip_srv_conf_t *rscf = conf; + ngx_mail_realip_srv_conf_t *rscf = conf; ngx_int_t rc; ngx_str_t *value; @@ -277,11 +236,11 @@ ngx_stream_realip_from(ngx_conf_t *cf, n static void * -ngx_stream_realip_create_srv_conf(ngx_conf_t *cf) +ngx_mail_realip_create_srv_conf(ngx_conf_t *cf) { - ngx_stream_realip_srv_conf_t *conf; + ngx_mail_realip_srv_conf_t *conf; - conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_realip_srv_conf_t)); + conf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_realip_srv_conf_t)); if (conf == NULL) { return NULL; } @@ -297,10 +256,10 @@ ngx_stream_realip_create_srv_conf(ngx_co static char * -ngx_stream_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) +ngx_mail_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) { - ngx_stream_realip_srv_conf_t *prev = parent; - ngx_stream_realip_srv_conf_t *conf = child; + ngx_mail_realip_srv_conf_t *prev = parent; + ngx_mail_realip_srv_conf_t *conf = child; if (conf->from == NULL) { conf->from = prev->from; @@ -308,94 +267,3 @@ ngx_stream_realip_merge_srv_conf(ngx_con return NGX_CONF_OK; } - - -static ngx_int_t -ngx_stream_realip_add_variables(ngx_conf_t *cf) -{ - ngx_stream_variable_t *var, *v; - - for (v = ngx_stream_realip_vars; v->name.len; v++) { - var = ngx_stream_add_variable(cf, &v->name, v->flags); - if (var == NULL) { - return NGX_ERROR; - } - - var->get_handler = v->get_handler; - var->data = v->data; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_stream_realip_init(ngx_conf_t *cf) -{ - ngx_stream_handler_pt *h; - ngx_stream_core_main_conf_t *cmcf; - - cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); - - h = ngx_array_push(&cmcf->phases[NGX_STREAM_POST_ACCEPT_PHASE].handlers); - if (h == NULL) { - return NGX_ERROR; - } - - *h = ngx_stream_realip_handler; - - return NGX_OK; -} - - -static ngx_int_t -ngx_stream_realip_remote_addr_variable(ngx_stream_session_t *s, - ngx_stream_variable_value_t *v, uintptr_t data) -{ - ngx_str_t *addr_text; - ngx_stream_realip_ctx_t *ctx; - - ctx = ngx_stream_get_module_ctx(s, ngx_stream_realip_module); - - addr_text = ctx ? &ctx->addr_text : &s->connection->addr_text; - - v->len = addr_text->len; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->data = addr_text->data; - - return NGX_OK; -} - - -static ngx_int_t -ngx_stream_realip_remote_port_variable(ngx_stream_session_t *s, - ngx_stream_variable_value_t *v, uintptr_t data) -{ - ngx_uint_t port; - struct sockaddr *sa; - ngx_stream_realip_ctx_t *ctx; - - ctx = ngx_stream_get_module_ctx(s, ngx_stream_realip_module); - - sa = ctx ? ctx->sockaddr : s->connection->sockaddr; - - v->len = 0; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - - v->data = ngx_pnalloc(s->connection->pool, sizeof("65535") - 1); - if (v->data == NULL) { - return NGX_ERROR; - } - - port = ngx_inet_get_port(sa); - - if (port > 0 && port < 65536) { - v->len = ngx_sprintf(v->data, "%ui", port) - v->data; - } - - return NGX_OK; -}
--- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -449,6 +449,12 @@ ngx_mail_smtp_auth_state(ngx_event_t *re if (s->out.len) { ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp send handler busy"); s->blocked = 1; + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_close_connection(c); + return; + } + return; } @@ -456,7 +462,16 @@ ngx_mail_smtp_auth_state(ngx_event_t *re rc = ngx_mail_read_command(s, c); - if (rc == NGX_AGAIN || rc == NGX_ERROR) { + if (rc == NGX_AGAIN) { + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return; + } + + return; + } + + if (rc == NGX_ERROR) { return; } @@ -568,6 +583,11 @@ ngx_mail_smtp_auth_state(ngx_event_t *re s->arg_start = s->buffer->pos; } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + ngx_mail_session_internal_server_error(s); + return; + } + ngx_mail_send(c->write); } }
--- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -682,7 +682,7 @@ ngx_mail_ssl_conf_command_check(ngx_conf { #ifndef SSL_CONF_FLAG_FILE return "is not supported on this platform"; +#else + return NGX_CONF_OK; #endif - - return NGX_CONF_OK; }
--- a/src/os/unix/ngx_errno.c +++ b/src/os/unix/ngx_errno.c @@ -9,6 +9,49 @@ #include <ngx_core.h> +static ngx_str_t ngx_unknown_error = ngx_string("Unknown error"); + + +#if (NGX_HAVE_STRERRORDESC_NP) + +/* + * The strerrordesc_np() function, introduced in glibc 2.32, is + * async-signal-safe. This makes it possible to use it directly, + * without copying error messages. + */ + + +u_char * +ngx_strerror(ngx_err_t err, u_char *errstr, size_t size) +{ + size_t len; + const char *msg; + + msg = strerrordesc_np(err); + + if (msg == NULL) { + msg = (char *) ngx_unknown_error.data; + len = ngx_unknown_error.len; + + } else { + len = ngx_strlen(msg); + } + + size = ngx_min(size, len); + + return ngx_cpymem(errstr, msg, size); +} + + +ngx_int_t +ngx_strerror_init(void) +{ + return NGX_OK; +} + + +#else + /* * The strerror() messages are copied because: * @@ -26,7 +69,8 @@ static ngx_str_t *ngx_sys_errlist; -static ngx_str_t ngx_unknown_error = ngx_string("Unknown error"); +static ngx_err_t ngx_first_error; +static ngx_err_t ngx_last_error; u_char * @@ -34,8 +78,13 @@ ngx_strerror(ngx_err_t err, u_char *errs { ngx_str_t *msg; - msg = ((ngx_uint_t) err < NGX_SYS_NERR) ? &ngx_sys_errlist[err]: - &ngx_unknown_error; + if (err >= ngx_first_error && err < ngx_last_error) { + msg = &ngx_sys_errlist[err - ngx_first_error]; + + } else { + msg = &ngx_unknown_error; + } + size = ngx_min(size, msg->len); return ngx_cpymem(errstr, msg->data, size); @@ -50,20 +99,92 @@ ngx_strerror_init(void) size_t len; ngx_err_t err; +#if (NGX_SYS_NERR) + ngx_first_error = 0; + ngx_last_error = NGX_SYS_NERR; + +#elif (EPERM > 1000 && EPERM < 0x7fffffff - 1000) + + /* + * If number of errors is not known, and EPERM error code has large + * but reasonable value, guess possible error codes based on the error + * messages returned by strerror(), starting from EPERM. Notably, + * this covers GNU/Hurd, where errors start at 0x40000001. + */ + + for (err = EPERM; err > EPERM - 1000; err--) { + ngx_set_errno(0); + msg = strerror(err); + + if (errno == EINVAL + || msg == NULL + || strncmp(msg, "Unknown error", 13) == 0) + { + continue; + } + + ngx_first_error = err; + } + + for (err = EPERM; err < EPERM + 1000; err++) { + ngx_set_errno(0); + msg = strerror(err); + + if (errno == EINVAL + || msg == NULL + || strncmp(msg, "Unknown error", 13) == 0) + { + continue; + } + + ngx_last_error = err + 1; + } + +#else + + /* + * If number of errors is not known, guess it based on the error + * messages returned by strerror(). + */ + + ngx_first_error = 0; + + for (err = 0; err < 1000; err++) { + ngx_set_errno(0); + msg = strerror(err); + + if (errno == EINVAL + || msg == NULL + || strncmp(msg, "Unknown error", 13) == 0) + { + continue; + } + + ngx_last_error = err + 1; + } + +#endif + /* * ngx_strerror() is not ready to work at this stage, therefore, * malloc() is used and possible errors are logged using strerror(). */ - len = NGX_SYS_NERR * sizeof(ngx_str_t); + len = (ngx_last_error - ngx_first_error) * sizeof(ngx_str_t); ngx_sys_errlist = malloc(len); if (ngx_sys_errlist == NULL) { goto failed; } - for (err = 0; err < NGX_SYS_NERR; err++) { + for (err = ngx_first_error; err < ngx_last_error; err++) { msg = strerror(err); + + if (msg == NULL) { + ngx_sys_errlist[err - ngx_first_error] = ngx_unknown_error; + continue; + } + len = ngx_strlen(msg); p = malloc(len); @@ -72,8 +193,8 @@ ngx_strerror_init(void) } ngx_memcpy(p, msg, len); - ngx_sys_errlist[err].len = len; - ngx_sys_errlist[err].data = p; + ngx_sys_errlist[err - ngx_first_error].len = len; + ngx_sys_errlist[err - ngx_first_error].data = p; } return NGX_OK; @@ -85,3 +206,5 @@ failed: return NGX_ERROR; } + +#endif