From 501435f6cd4e4bbdd5f5c100e60144a9b7c3ca3a Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Tue, 10 Sep 2024 18:27:49 +0200 Subject: [PATCH] mail proxy: allow dynamically deciding whether to use SMTP authentication to the backend Adds a `Auth-Method` as a valid response header for the HTTP authentication server. When set to 'None', the proxy will not attempt to perform SMTP authentication to the backend, even when `proxy_smtp_auth` is `on`. This is useful when some backends require authentication, while others don't allow it. While this has been tested and works, the patch was created with an incomplete understanding of the `proxy_smtp_auth` option, so it might not be the cleanest implementation. Sharing as 'draft' for now until I find the time to set up a better test environment and revise the patch. Any feedback/pointers/etc welcome :) Fixes #155 --- src/mail/ngx_mail.h | 1 + src/mail/ngx_mail_auth_http_module.c | 18 ++++++++++++++++++ src/mail/ngx_mail_handler.c | 2 ++ src/mail/ngx_mail_pop3_handler.c | 1 + src/mail/ngx_mail_proxy_module.c | 24 ++++++++++++++++++------ src/mail/ngx_mail_smtp_handler.c | 1 + 6 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h index e0c62b7ab..70965f2a4 100644 --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -212,6 +212,7 @@ typedef struct { unsigned starttls:1; unsigned esmtp:1; unsigned auth_method:3; + unsigned proxy_auth_method:3; unsigned auth_wait:1; ngx_str_t login; diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c index 27f64b92e..9266a0ee1 100644 --- a/src/mail/ngx_mail_auth_http_module.c +++ b/src/mail/ngx_mail_auth_http_module.c @@ -677,6 +677,23 @@ ngx_mail_auth_http_process_headers(ngx_mail_session_t *s, continue; } + if (len == sizeof("Auth-Method") - 1 + && ngx_strncasecmp(ctx->header_name_start, + (u_char *) "Auth-Method", + sizeof("Auth-Method") - 1) + == 0) + { + int value_len = ctx->header_end - ctx->header_start; + if (value_len == sizeof("none") - 1 + && ngx_strncasecmp(ctx->header_start, + (u_char *) "none", + sizeof("none") - 1) + == 0) + { + s->proxy_auth_method = NGX_MAIL_AUTH_NONE; + } + } + /* ignore other headers */ continue; @@ -883,6 +900,7 @@ ngx_mail_auth_sleep_handler(ngx_event_t *rev) s->mail_state = 0; s->auth_method = NGX_MAIL_AUTH_PLAIN; + s->proxy_auth_method = NGX_MAIL_AUTH_PLAIN; c->log->action = "in auth state"; diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c index 1167df3fb..328cac5ef 100644 --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -714,6 +714,7 @@ ngx_mail_auth_cram_md5(ngx_mail_session_t *s, ngx_connection_t *c) "mail auth cram-md5: \"%V\" \"%V\"", &s->login, &s->passwd); s->auth_method = NGX_MAIL_AUTH_CRAM_MD5; + s->proxy_auth_method = NGX_MAIL_AUTH_CRAM_MD5; return NGX_DONE; } @@ -748,6 +749,7 @@ ngx_mail_auth_external(ngx_mail_session_t *s, ngx_connection_t *c, "mail auth external: \"%V\"", &s->login); s->auth_method = NGX_MAIL_AUTH_EXTERNAL; + s->proxy_auth_method = NGX_MAIL_AUTH_EXTERNAL; return NGX_DONE; } diff --git a/src/mail/ngx_mail_pop3_handler.c b/src/mail/ngx_mail_pop3_handler.c index 226e7419b..8329e7cdd 100644 --- a/src/mail/ngx_mail_pop3_handler.c +++ b/src/mail/ngx_mail_pop3_handler.c @@ -464,6 +464,7 @@ ngx_mail_pop3_apop(ngx_mail_session_t *s, ngx_connection_t *c) "pop3 apop: \"%V\" \"%V\"", &s->login, &s->passwd); s->auth_method = NGX_MAIL_AUTH_APOP; + s->proxy_auth_method = NGX_MAIL_AUTH_APOP; return NGX_DONE; } diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c index efed9ab3e..da1eb7d59 100644 --- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -605,8 +605,12 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev) if (pcf->xclient) { s->mail_state = ngx_smtp_helo_xclient; - } else if (s->auth_method == NGX_MAIL_AUTH_NONE) { - s->mail_state = ngx_smtp_helo_from; + } else if (s->proxy_auth_method == NGX_MAIL_AUTH_NONE) { + if (s->smtp_from.len) { + s->mail_state = ngx_smtp_helo_from; + } else { + s->mail_state = ngx_smtp_helo; + } } else if (pcf->smtp_auth) { s->mail_state = ngx_smtp_helo_auth; @@ -667,8 +671,12 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev) if (s->smtp_helo.len) { s->mail_state = ngx_smtp_xclient_helo; - } else if (s->auth_method == NGX_MAIL_AUTH_NONE) { - s->mail_state = ngx_smtp_xclient_from; + } else if (s->proxy_auth_method == NGX_MAIL_AUTH_NONE) { + if (s->smtp_from.len) { + s->mail_state = ngx_smtp_xclient_from; + } else { + s->mail_state = ngx_smtp_xclient_helo; + } } else if (pcf->smtp_auth) { s->mail_state = ngx_smtp_xclient_auth; @@ -700,8 +708,12 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev) pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); - if (s->auth_method == NGX_MAIL_AUTH_NONE) { - s->mail_state = ngx_smtp_helo_from; + if (s->proxy_auth_method == NGX_MAIL_AUTH_NONE) { + if (s->smtp_from.len) { + s->mail_state = ngx_smtp_helo_from; + } else { + s->mail_state = ngx_smtp_helo; + } } else if (pcf->smtp_auth) { s->mail_state = ngx_smtp_helo_auth; diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c index e68ceedfd..e2f561894 100644 --- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -820,6 +820,7 @@ ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c) "smtp rcpt to:\"%V\"", &s->smtp_to); s->auth_method = NGX_MAIL_AUTH_NONE; + s->proxy_auth_method = NGX_MAIL_AUTH_NONE; return NGX_DONE; }