[PATCH 2 of 5] Mail: added missing event handling in auth http code
Maxim Dounin
mdounin at mdounin.ru
Wed Mar 18 12:47:57 UTC 2026
# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1773836277 -10800
# Wed Mar 18 15:17:57 2026 +0300
# Node ID d3607b79bfd01cbb4a42f54766118876cf410731
# Parent ead30bfe050fc52c6327701e67b59566fb5c9318
Mail: added missing event handling in auth http code.
If we need to be notified about further events, ngx_handle_read_event()
(or ngx_handle_write_event()) needs to be called after an event is
processed. Without this, an event can be removed from the kernel and
won't be reported again, notably when using oneshot event methods, such
as eventport on Solaris.
While here, ngx_mail_auth_http_read_handler() was also modified to properly
detect and report premature connection close.
To do so, ngx_mail_auth_http_read_handler() is modified to use a loop
around ngx_recv(), ctx->handler() now reports if there was an error or
we are waiting for additional data, and ngx_handle_read_event() is called
when ngx_recv() reports NGX_AGAIN. The code is now similar to
ngx_ssl_ocsp_read_handler() (which in turn was originally based on the
auth http code).
Similarly, ngx_mail_auth_http_write_handler() is modified to call
ngx_handle_write_event() when the request is not fully sent to the
socket.
diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -31,7 +31,7 @@ typedef struct {
typedef struct ngx_mail_auth_http_ctx_s ngx_mail_auth_http_ctx_t;
-typedef void (*ngx_mail_auth_http_handler_pt)(ngx_mail_session_t *s,
+typedef ngx_int_t (*ngx_mail_auth_http_handler_pt)(ngx_mail_session_t *s,
ngx_mail_auth_http_ctx_t *ctx);
struct ngx_mail_auth_http_ctx_s {
@@ -65,9 +65,9 @@ struct ngx_mail_auth_http_ctx_s {
static void ngx_mail_auth_http_write_handler(ngx_event_t *wev);
static void ngx_mail_auth_http_read_handler(ngx_event_t *rev);
-static void ngx_mail_auth_http_ignore_status_line(ngx_mail_session_t *s,
+static ngx_int_t ngx_mail_auth_http_ignore_status_line(ngx_mail_session_t *s,
ngx_mail_auth_http_ctx_t *ctx);
-static void ngx_mail_auth_http_process_headers(ngx_mail_session_t *s,
+static ngx_int_t ngx_mail_auth_http_process_headers(ngx_mail_session_t *s,
ngx_mail_auth_http_ctx_t *ctx);
static void ngx_mail_auth_sleep_handler(ngx_event_t *rev);
static void ngx_mail_auth_send_error(ngx_mail_session_t *s);
@@ -307,13 +307,20 @@ ngx_mail_auth_http_write_handler(ngx_eve
ahcf = ngx_mail_get_module_srv_conf(s, ngx_mail_auth_http_module);
ngx_add_timer(wev, ahcf->timeout);
}
+
+ if (ngx_handle_write_event(wev, 0) != NGX_OK) {
+ ngx_close_connection(c);
+ ngx_destroy_pool(ctx->pool);
+ ngx_mail_session_internal_server_error(s);
+ }
}
static void
ngx_mail_auth_http_read_handler(ngx_event_t *rev)
{
- ssize_t n, size;
+ ssize_t n, size;
+ ngx_int_t rc;
ngx_connection_t *c;
ngx_mail_session_t *s;
ngx_mail_auth_http_ctx_t *ctx;
@@ -345,19 +352,41 @@ ngx_mail_auth_http_read_handler(ngx_even
}
}
- size = ctx->response->end - ctx->response->last;
+ for ( ;; ) {
+
+ size = ctx->response->end - ctx->response->last;
+
+ n = ngx_recv(c, ctx->response->pos, size);
- n = ngx_recv(c, ctx->response->pos, size);
+ if (n > 0) {
+ ctx->response->last += n;
+
+ rc = ctx->handler(s, ctx);
+
+ if (rc == NGX_ERROR || rc == NGX_DONE) {
+ return;
+ }
- if (n > 0) {
- ctx->response->last += n;
+ continue;
+ }
- ctx->handler(s, ctx);
- return;
+ if (n == NGX_AGAIN) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
+ ngx_close_connection(c);
+ ngx_destroy_pool(ctx->pool);
+ ngx_mail_session_internal_server_error(s);
+ }
+
+ return;
+ }
+
+ break;
}
- if (n == NGX_AGAIN) {
- return;
+ if (n == 0) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "auth http server %V prematurely closed connection",
+ ctx->peer.name);
}
ngx_close_connection(c);
@@ -366,7 +395,7 @@ ngx_mail_auth_http_read_handler(ngx_even
}
-static void
+static ngx_int_t
ngx_mail_auth_http_ignore_status_line(ngx_mail_session_t *s,
ngx_mail_auth_http_ctx_t *ctx)
{
@@ -448,17 +477,19 @@ ngx_mail_auth_http_ignore_status_line(ng
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"auth http server %V sent invalid response",
ctx->peer.name);
+
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+
+ return NGX_ERROR;
}
}
ctx->response->pos = p;
ctx->state = state;
- return;
+ return NGX_AGAIN;
next:
@@ -469,11 +500,11 @@ done:
ctx->response->pos = p + 1;
ctx->state = 0;
ctx->handler = ngx_mail_auth_http_process_headers;
- ctx->handler(s, ctx);
+ return ctx->handler(s, ctx);
}
-static void
+static ngx_int_t
ngx_mail_auth_http_process_headers(ngx_mail_session_t *s,
ngx_mail_auth_http_ctx_t *ctx)
{
@@ -499,7 +530,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
h->key.len = ctx->header_name_end - ctx->header_name_start;
@@ -562,7 +593,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ctx->err.data = p;
@@ -627,7 +658,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ngx_memcpy(s->login.data, ctx->header_start, s->login.len);
@@ -649,7 +680,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ngx_memcpy(s->passwd.data, ctx->header_start, s->passwd.len);
@@ -687,7 +718,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ngx_memcpy(ctx->errcode.data, ctx->header_start,
@@ -722,7 +753,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ctx->errsasl.len = size;
@@ -770,7 +801,7 @@ ngx_mail_auth_http_process_headers(ngx_m
if (p == NULL) {
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ctx->err.data = p;
@@ -790,14 +821,14 @@ ngx_mail_auth_http_process_headers(ngx_m
if (timer == 0) {
s->auth_quit = 1;
ngx_mail_auth_send_error(s);
- return;
+ return NGX_DONE;
}
ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000));
s->connection->read->handler = ngx_mail_auth_sleep_handler;
- return;
+ return NGX_DONE;
}
if (s->auth_wait) {
@@ -807,14 +838,14 @@ ngx_mail_auth_http_process_headers(ngx_m
if (timer == 0) {
ngx_mail_auth_http_init(s);
- return;
+ return NGX_DONE;
}
ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000));
s->connection->read->handler = ngx_mail_auth_sleep_handler;
- return;
+ return NGX_DONE;
}
if (ctx->addr.len == 0 || ctx->port.len == 0) {
@@ -823,7 +854,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ctx->peer.name);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
if (s->passwd.data == NULL
@@ -834,14 +865,14 @@ ngx_mail_auth_http_process_headers(ngx_m
ctx->peer.name);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
peer = ngx_pcalloc(s->connection->pool, sizeof(ngx_addr_t));
if (peer == NULL) {
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
rc = ngx_parse_addr(s->connection->pool, peer,
@@ -861,7 +892,7 @@ ngx_mail_auth_http_process_headers(ngx_m
default:
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
port = ngx_atoi(ctx->port.data, ctx->port.len);
@@ -872,7 +903,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ctx->peer.name, &ctx->port);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ngx_inet_set_port(peer->sockaddr, (in_port_t) port);
@@ -885,7 +916,7 @@ ngx_mail_auth_http_process_headers(ngx_m
if (peer->name.data == NULL) {
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
len = ctx->addr.len;
@@ -900,17 +931,17 @@ ngx_mail_auth_http_process_headers(ngx_m
if (ngx_mail_limit_conn_handler(s) != NGX_OK) {
ngx_destroy_pool(ctx->pool);
- return;
+ return NGX_ERROR;
}
ngx_destroy_pool(ctx->pool);
ngx_mail_proxy_init(s, peer);
- return;
+ return NGX_DONE;
}
if (rc == NGX_AGAIN ) {
- return;
+ return NGX_AGAIN;
}
/* rc == NGX_ERROR */
@@ -918,12 +949,15 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"auth http server %V sent invalid header in response",
ctx->peer.name);
+
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
+
+ /* not reached */
}
More information about the nginx-devel
mailing list