From 4e9289e51a898e190ee33b00d035e285d8298828 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Thu, 16 Apr 2026 20:57:24 +0400 Subject: [PATCH] Proxy authentication for CONNECT requests Notably, ngx_http_auth_basic_module uses Proxy-Authorization input header, Proxy-Authenticate output header and HTTP code 407 instead of Authorization, WWW-Authenticate and 401 respectively. --- src/http/modules/ngx_http_auth_basic_module.c | 32 ++++++++++++------- src/http/ngx_http_core_module.c | 17 +++++++--- src/http/ngx_http_request.h | 4 ++- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c index 69e8d2161..fd95e2ead 100644 --- a/src/http/modules/ngx_http_auth_basic_module.c +++ b/src/http/modules/ngx_http_auth_basic_module.c @@ -318,11 +318,12 @@ ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r, ngx_str_t *passwd, static ngx_int_t ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm) { - size_t len; - u_char *basic, *p; + size_t len; + u_char *basic, *p; + ngx_table_elt_t *h; - r->headers_out.www_authenticate = ngx_list_push(&r->headers_out.headers); - if (r->headers_out.www_authenticate == NULL) { + h = ngx_list_push(&r->headers_out.headers); + if (h == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -330,8 +331,7 @@ ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm) basic = ngx_pnalloc(r->pool, len); if (basic == NULL) { - r->headers_out.www_authenticate->hash = 0; - r->headers_out.www_authenticate = NULL; + h->hash = 0; return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -339,13 +339,21 @@ ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm) p = ngx_cpymem(p, realm->data, realm->len); *p = '"'; - r->headers_out.www_authenticate->hash = 1; - r->headers_out.www_authenticate->next = NULL; - ngx_str_set(&r->headers_out.www_authenticate->key, "WWW-Authenticate"); - r->headers_out.www_authenticate->value.data = basic; - r->headers_out.www_authenticate->value.len = len; + h->hash = 1; + h->next = NULL; + h->value.data = basic; + h->value.len = len; + + if (ngx_http_proxy_auth(r)) { + r->headers_out.proxy_authenticate = h; + ngx_str_set(&h->key, "Proxy-Authenticate"); + return NGX_HTTP_PROXY_AUTH_REQUIRED; - return NGX_HTTP_UNAUTHORIZED; + } else { + r->headers_out.www_authenticate = h; + ngx_str_set(&h->key, "WWW-Authenticate"); + return NGX_HTTP_UNAUTHORIZED; + } } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 53ddf39bb..4c51f7edf 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1144,7 +1144,10 @@ ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) if (rc == NGX_OK) { r->access_code = 0; - for (h = r->headers_out.www_authenticate; h; h = h->next) { + h = ngx_http_proxy_auth(r) ? r->headers_out.proxy_authenticate + : r->headers_out.www_authenticate; + + for ( /* void */ ; h; h = h->next) { h->hash = 0; } @@ -2001,19 +2004,23 @@ ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path, ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r) { - ngx_str_t auth, encoded; - ngx_uint_t len; + ngx_str_t auth, encoded; + ngx_uint_t len; + ngx_table_elt_t *h; if (r->headers_in.user.len == 0 && r->headers_in.user.data != NULL) { return NGX_DECLINED; } - if (r->headers_in.authorization == NULL) { + h = ngx_http_proxy_auth(r) ? r->headers_in.proxy_authorization + : r->headers_in.authorization; + + if (h == NULL) { r->headers_in.user.data = (u_char *) ""; return NGX_DECLINED; } - encoded = r->headers_in.authorization->value; + encoded = h->value; if (encoded.len < sizeof("Basic ") - 1 || ngx_strncasecmp(encoded.data, (u_char *) "Basic ", diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 48eb43eb0..6d18cc3c6 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -618,7 +618,9 @@ typedef struct { } ngx_http_ephemeral_t; -#define ngx_http_ephemeral(r) (void *) (&r->uri_start) +#define ngx_http_ephemeral(r) (void *) (&r->uri_start) + +#define ngx_http_proxy_auth(r) ((r)->method == NGX_HTTP_CONNECT) extern ngx_http_header_t ngx_http_headers_in[]; -- 2.47.3