Merged with the default branch.

This commit is contained in:
Sergey Kandaurov 2021-03-10 15:39:01 +03:00
commit 02b52e4c0b
30 changed files with 1083 additions and 150 deletions

View File

@ -457,3 +457,4 @@ dc0cc425fa63a80315f6efb68697cadb6626cdf2 release-1.19.4
8e5b068f761cd512d10c9671fbde0b568c1fd08b release-1.19.5
f618488eb769e0ed74ef0d93cd118d2ad79ef94d release-1.19.6
3fa6e2095a7a51acc630517e1c27a7b7ac41f7b3 release-1.19.7
8c65d21464aaa5923775f80c32474adc7a320068 release-1.19.8

View File

@ -48,4 +48,6 @@ default: build
clean:
rm -rf Makefile $NGX_OBJS
.PHONY: default clean
END

View File

@ -215,4 +215,6 @@ upgrade:
test -f $NGX_PID_PATH.oldbin
kill -QUIT \`cat $NGX_PID_PATH.oldbin\`
.PHONY: build install modules upgrade
END

View File

@ -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

View File

@ -727,17 +727,33 @@ ngx_feature_test="char buf[1]; struct iovec vec[1]; ssize_t n;
. 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
@ -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

View File

@ -2414,26 +2414,26 @@ syn keyword ngxDirectiveThirdParty contained ip2proxy_usage_type
" 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"

View File

@ -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">

View File

@ -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

View File

@ -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

View File

@ -338,7 +338,7 @@ ngx_handle_read_event(ngx_event_t *rev, ngx_uint_t flags)
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;
}

View File

@ -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_STORE_CTX *x509_store)
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);
ok, err, depth,
subject ? subject : "(none)",
issuer ? issuer : "(none)");
if (sname) {
if (subject) {
OPENSSL_free(subject);
}
if (iname) {
if (issuer) {
OPENSSL_free(issuer);
}
#endif
@ -1948,6 +1974,10 @@ ngx_ssl_handshake_log(ngx_connection_t *c)
#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 *c, ngx_pool_t *pool, ngx_str_t *s)
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 *c, ngx_pool_t *pool, ngx_str_t *s)
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_connection_t *c, ngx_pool_t *pool,
}
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_connection_t *c, ngx_pool_t *pool,
}
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_t *c, ngx_pool_t *pool, ngx_str_t *s)
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 *c, ngx_pool_t *pool, ngx_str_t *s)
}
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_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
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_t *c, ngx_pool_t *pool, ngx_str_t *s)
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_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
}
#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;
}

View File

@ -4841,9 +4841,9 @@ ngx_http_grpc_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#endif
#else
return NGX_CONF_OK;
#endif
}

View File

@ -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_http_request_t *r, ngx_array_t *attrs,
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 *cf, ngx_command_t *cmd, void *conf)
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 *cf, ngx_command_t *cmd, void *conf)
}
}
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(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#endif
#else
return NGX_CONF_OK;
#endif
}

View File

@ -1307,9 +1307,9 @@ ngx_http_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#endif
#else
return NGX_CONF_OK;
#endif
}

View File

@ -2398,9 +2398,9 @@ ngx_http_uwsgi_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#endif
#else
return NGX_CONF_OK;
#endif
}

View File

@ -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;

View File

@ -405,6 +405,7 @@ ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport,
#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_mail_port_t *mport,
#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;
}

View File

@ -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 *cf, ngx_command_t *cmd, void *conf);
/* 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);
/**/

View File

@ -1224,22 +1224,49 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool,
+ 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_mail_session_t *s, ngx_pool_t *pool,
*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 */

View File

@ -548,6 +548,11 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#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;

View File

@ -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_t *c)
{
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_t *c)
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_t *c)
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 *ssl, ngx_connection_t *c)
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 *c)
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 *s, ngx_connection_t *c)
}
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;
}

View File

@ -123,6 +123,12 @@ ngx_mail_imap_auth_state(ngx_event_t *rev)
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 *rev)
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 *rev)
}
}
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_session_internal_server_error(s);
return;
}
ngx_mail_send(c->write);
}

View File

@ -138,6 +138,12 @@ ngx_mail_pop3_auth_state(ngx_event_t *rev)
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 *rev)
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 *rev)
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);
}
}

View File

@ -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(ngx_event_t *rev);
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_commands[] = {
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 *s, ngx_addr_t *peer)
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 *s, ngx_addr_t *peer)
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, ngx_addr_t *peer)
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 *rev)
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 *rev)
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 *rev)
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 *rev)
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 *rev)
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 *rev)
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_close_session(s);
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;
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 *cf)
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, void *parent, void *child)
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);

View File

@ -0,0 +1,269 @@
/*
* Copyright (C) Igor Sysoev
* Copyright (C) Nginx, Inc.
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_mail.h>
typedef struct {
ngx_array_t *from; /* array of ngx_cidr_t */
} ngx_mail_realip_srv_conf_t;
static ngx_int_t ngx_mail_realip_set_addr(ngx_mail_session_t *s,
ngx_addr_t *addr);
static char *ngx_mail_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
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_command_t ngx_mail_realip_commands[] = {
{ ngx_string("set_real_ip_from"),
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
ngx_mail_realip_from,
NGX_MAIL_SRV_CONF_OFFSET,
0,
NULL },
ngx_null_command
};
static ngx_mail_module_t ngx_mail_realip_module_ctx = {
NULL, /* protocol */
NULL, /* create main configuration */
NULL, /* init main configuration */
ngx_mail_realip_create_srv_conf, /* create server configuration */
ngx_mail_realip_merge_srv_conf /* merge server configuration */
};
ngx_module_t ngx_mail_realip_module = {
NGX_MODULE_V1,
&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 */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
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;
rscf = ngx_mail_get_module_srv_conf(s, ngx_mail_realip_module);
if (rscf->from == NULL) {
return NGX_OK;
}
c = s->connection;
if (c->proxy_protocol == NULL) {
return NGX_OK;
}
if (ngx_cidr_match(c->sockaddr, rscf->from) != NGX_OK) {
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_OK;
}
ngx_inet_set_port(addr.sockaddr, c->proxy_protocol->src_port);
return ngx_mail_realip_set_addr(s, &addr);
}
static ngx_int_t
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;
c = s->connection;
len = ngx_sock_ntop(addr->sockaddr, addr->socklen, text,
NGX_SOCKADDR_STRLEN, 0);
if (len == 0) {
return NGX_ERROR;
}
p = ngx_pnalloc(c->pool, len);
if (p == NULL) {
return NGX_ERROR;
}
ngx_memcpy(p, text, len);
c->sockaddr = addr->sockaddr;
c->socklen = addr->socklen;
c->addr_text.len = len;
c->addr_text.data = p;
return NGX_OK;
}
static char *
ngx_mail_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_mail_realip_srv_conf_t *rscf = conf;
ngx_int_t rc;
ngx_str_t *value;
ngx_url_t u;
ngx_cidr_t c, *cidr;
ngx_uint_t i;
struct sockaddr_in *sin;
#if (NGX_HAVE_INET6)
struct sockaddr_in6 *sin6;
#endif
value = cf->args->elts;
if (rscf->from == NULL) {
rscf->from = ngx_array_create(cf->pool, 2,
sizeof(ngx_cidr_t));
if (rscf->from == NULL) {
return NGX_CONF_ERROR;
}
}
#if (NGX_HAVE_UNIX_DOMAIN)
if (ngx_strcmp(value[1].data, "unix:") == 0) {
cidr = ngx_array_push(rscf->from);
if (cidr == NULL) {
return NGX_CONF_ERROR;
}
cidr->family = AF_UNIX;
return NGX_CONF_OK;
}
#endif
rc = ngx_ptocidr(&value[1], &c);
if (rc != NGX_ERROR) {
if (rc == NGX_DONE) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"low address bits of %V are meaningless",
&value[1]);
}
cidr = ngx_array_push(rscf->from);
if (cidr == NULL) {
return NGX_CONF_ERROR;
}
*cidr = c;
return NGX_CONF_OK;
}
ngx_memzero(&u, sizeof(ngx_url_t));
u.host = value[1];
if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
if (u.err) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"%s in set_real_ip_from \"%V\"",
u.err, &u.host);
}
return NGX_CONF_ERROR;
}
cidr = ngx_array_push_n(rscf->from, u.naddrs);
if (cidr == NULL) {
return NGX_CONF_ERROR;
}
ngx_memzero(cidr, u.naddrs * sizeof(ngx_cidr_t));
for (i = 0; i < u.naddrs; i++) {
cidr[i].family = u.addrs[i].sockaddr->sa_family;
switch (cidr[i].family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr;
cidr[i].u.in6.addr = sin6->sin6_addr;
ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16);
break;
#endif
default: /* AF_INET */
sin = (struct sockaddr_in *) u.addrs[i].sockaddr;
cidr[i].u.in.addr = sin->sin_addr.s_addr;
cidr[i].u.in.mask = 0xffffffff;
break;
}
}
return NGX_CONF_OK;
}
static void *
ngx_mail_realip_create_srv_conf(ngx_conf_t *cf)
{
ngx_mail_realip_srv_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_realip_srv_conf_t));
if (conf == NULL) {
return NULL;
}
/*
* set by ngx_pcalloc():
*
* conf->from = NULL;
*/
return conf;
}
static char *
ngx_mail_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *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;
}
return NGX_CONF_OK;
}

View File

@ -449,6 +449,12 @@ ngx_mail_smtp_auth_state(ngx_event_t *rev)
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 *rev)
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 *rev)
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);
}
}

View File

@ -682,7 +682,7 @@ ngx_mail_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#endif
#else
return NGX_CONF_OK;
#endif
}

View File

@ -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 *errstr, size_t size)
{
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

View File

@ -1026,9 +1026,9 @@ ngx_stream_proxy_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#endif
#else
return NGX_CONF_OK;
#endif
}

View File

@ -1061,9 +1061,9 @@ ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
{
#ifndef SSL_CONF_FLAG_FILE
return "is not supported on this platform";
#endif
#else
return NGX_CONF_OK;
#endif
}