Mercurial > hg > nginx
comparison src/mail/ngx_mail_smtp_handler.c @ 7546:fcd92ad76b7b
Mail: fixed duplicate resolving.
When using SMTP with SSL and resolver, read events might be enabled
during address resolving, leading to duplicate ngx_mail_ssl_handshake_handler()
calls if something arrives from the client, and duplicate session
initialization - including starting another resolving. This can lead
to a segmentation fault if the session is closed after first resolving
finished. Fix is to block read events while resolving.
Reported by Robert Norris,
http://mailman.nginx.org/pipermail/nginx/2019-July/058204.html.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 01 Aug 2019 13:50:07 +0300 |
parents | b2915d99ee8d |
children | ab6257dac2a8 |
comparison
equal
deleted
inserted
replaced
7545:0ef2bc0ec9c9 | 7546:fcd92ad76b7b |
---|---|
13 | 13 |
14 | 14 |
15 static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx); | 15 static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx); |
16 static void ngx_mail_smtp_resolve_name(ngx_event_t *rev); | 16 static void ngx_mail_smtp_resolve_name(ngx_event_t *rev); |
17 static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx); | 17 static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx); |
18 static void ngx_mail_smtp_block_reading(ngx_event_t *rev); | |
18 static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c); | 19 static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c); |
19 static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev); | 20 static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev); |
20 static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s, | 21 static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s, |
21 ngx_connection_t *c); | 22 ngx_connection_t *c); |
22 | 23 |
86 ctx->addr.socklen = c->socklen; | 87 ctx->addr.socklen = c->socklen; |
87 ctx->handler = ngx_mail_smtp_resolve_addr_handler; | 88 ctx->handler = ngx_mail_smtp_resolve_addr_handler; |
88 ctx->data = s; | 89 ctx->data = s; |
89 ctx->timeout = cscf->resolver_timeout; | 90 ctx->timeout = cscf->resolver_timeout; |
90 | 91 |
92 s->resolver_ctx = ctx; | |
93 c->read->handler = ngx_mail_smtp_block_reading; | |
94 | |
91 if (ngx_resolve_addr(ctx) != NGX_OK) { | 95 if (ngx_resolve_addr(ctx) != NGX_OK) { |
92 ngx_mail_close_connection(c); | 96 ngx_mail_close_connection(c); |
93 } | 97 } |
94 } | 98 } |
95 | 99 |
166 | 170 |
167 ctx->name = s->host; | 171 ctx->name = s->host; |
168 ctx->handler = ngx_mail_smtp_resolve_name_handler; | 172 ctx->handler = ngx_mail_smtp_resolve_name_handler; |
169 ctx->data = s; | 173 ctx->data = s; |
170 ctx->timeout = cscf->resolver_timeout; | 174 ctx->timeout = cscf->resolver_timeout; |
175 | |
176 s->resolver_ctx = ctx; | |
177 c->read->handler = ngx_mail_smtp_block_reading; | |
171 | 178 |
172 if (ngx_resolve_name(ctx) != NGX_OK) { | 179 if (ngx_resolve_name(ctx) != NGX_OK) { |
173 ngx_mail_close_connection(c); | 180 ngx_mail_close_connection(c); |
174 } | 181 } |
175 } | 182 } |
237 ngx_mail_smtp_greeting(s, c); | 244 ngx_mail_smtp_greeting(s, c); |
238 } | 245 } |
239 | 246 |
240 | 247 |
241 static void | 248 static void |
249 ngx_mail_smtp_block_reading(ngx_event_t *rev) | |
250 { | |
251 ngx_connection_t *c; | |
252 ngx_mail_session_t *s; | |
253 ngx_resolver_ctx_t *ctx; | |
254 | |
255 c = rev->data; | |
256 s = c->data; | |
257 | |
258 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp reading blocked"); | |
259 | |
260 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | |
261 | |
262 if (s->resolver_ctx) { | |
263 ctx = s->resolver_ctx; | |
264 | |
265 if (ctx->handler == ngx_mail_smtp_resolve_addr_handler) { | |
266 ngx_resolve_addr_done(ctx); | |
267 | |
268 } else if (ctx->handler == ngx_mail_smtp_resolve_name_handler) { | |
269 ngx_resolve_name_done(ctx); | |
270 } | |
271 | |
272 s->resolver_ctx = NULL; | |
273 } | |
274 | |
275 ngx_mail_close_connection(c); | |
276 } | |
277 } | |
278 | |
279 | |
280 static void | |
242 ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c) | 281 ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c) |
243 { | 282 { |
244 ngx_msec_t timeout; | 283 ngx_msec_t timeout; |
245 ngx_mail_core_srv_conf_t *cscf; | 284 ngx_mail_core_srv_conf_t *cscf; |
246 ngx_mail_smtp_srv_conf_t *sscf; | 285 ngx_mail_smtp_srv_conf_t *sscf; |
254 timeout = sscf->greeting_delay ? sscf->greeting_delay : cscf->timeout; | 293 timeout = sscf->greeting_delay ? sscf->greeting_delay : cscf->timeout; |
255 ngx_add_timer(c->read, timeout); | 294 ngx_add_timer(c->read, timeout); |
256 | 295 |
257 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { | 296 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { |
258 ngx_mail_close_connection(c); | 297 ngx_mail_close_connection(c); |
298 } | |
299 | |
300 if (c->read->ready) { | |
301 ngx_post_event(c->read, &ngx_posted_events); | |
259 } | 302 } |
260 | 303 |
261 if (sscf->greeting_delay) { | 304 if (sscf->greeting_delay) { |
262 c->read->handler = ngx_mail_smtp_invalid_pipelining; | 305 c->read->handler = ngx_mail_smtp_invalid_pipelining; |
263 return; | 306 return; |