Hi, 

enclosed you will find an attached changeset, that allows more than one
authentication challenge - multiple authenticate response-header
[rfc2616 sec14.47].

Implemented for auth_request and http upstream (ex. backends).

If you want to support it in your own authentication module, just call
`ngx_http_upstream_transmit_headers` after setting
`headers_out.www_authenticate` of request, like in both implemented
modules (see changeset attached).
For upstreams simply add a multiple header entries with
www-authentificate challenges, supported from your module.

PS. If someone needs a git version of it:
https://github.com/sebres/nginx/commits/hg-sb-mod [1] 

Regards, 

sebres. 

Links:
------
[1] https://github.com/sebres/nginx/commits/hg-sb-mod
# HG changeset patch
# User Serg G. Brester (sebres) <serg.bres...@sebres.de>
# Date 1430300326 -7200
#      Wed Apr 29 11:38:46 2015 +0200
# Node ID 10c2a7b3420bc03fc31b969a07daa3f354676a0e
# Parent  43135346275c76add5bf953024a3d244f04184ba
Allow more than one challenge - multiple authenticate response-header [rfc2616 sec14.47]: currently implemented for auth_request (and upstream) only;

Header example:
  WWW-Authenticate: NTLM
  WWW-Authenticate: Digest realm="...", qop="", nonce="", opaque=""
  WWW-Authenticate: Basic realm="..."

diff -r 43135346275c -r 10c2a7b3420b src/http/modules/ngx_http_auth_request_module.c
--- a/src/http/modules/ngx_http_auth_request_module.c	Tue Apr 28 15:34:33 2015 +0200
+++ b/src/http/modules/ngx_http_auth_request_module.c	Wed Apr 29 11:38:46 2015 +0200
@@ -156,6 +156,16 @@ ngx_http_auth_request_handler(ngx_http_r
                 *ho = *h;
 
                 r->headers_out.www_authenticate = ho;
+
+                /* transmit all authenticate headers (ex: multiple authenticate
+                 * challenges [rfc2616 sec14.47]): */
+                if (ngx_http_upstream_transmit_headers(r, !sr->upstream ?
+                        &r->headers_in.headers.part : 
+                        &sr->upstream->headers_in.headers.part,
+                        ho) != NGX_OK)
+                {
+                    return NGX_ERROR;
+                }
             }
 
             return ctx->status;
diff -r 43135346275c -r 10c2a7b3420b src/http/ngx_http_upstream.c
--- a/src/http/ngx_http_upstream.c	Tue Apr 28 15:34:33 2015 +0200
+++ b/src/http/ngx_http_upstream.c	Wed Apr 29 11:38:46 2015 +0200
@@ -2293,6 +2293,57 @@ ngx_http_upstream_test_next(ngx_http_req
 }
 
 
+ngx_int_t
+ngx_http_upstream_transmit_headers(ngx_http_request_t *r, 
+    ngx_list_part_t *part, ngx_table_elt_t *filter)
+{
+    ngx_table_elt_t   *h, *ho;
+    ngx_uint_t        i;
+    h = part->elts;
+
+    for (i = 0; /* void */; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+            part = part->next;
+            h = part->elts;
+            i = 0;
+        }
+        if (h[i].hash == 0) {
+            continue;
+        }
+        /* filter same header: */
+        if (&h[i] == filter) {
+            continue;
+        }
+        /* filter by key name: */
+        if (h[i].key.len != filter->key.len || 
+            ngx_strncasecmp(h[i].key.data, filter->key.data,
+                filter->key.len) != 0)
+        {
+            continue;
+        }
+        /* filter same value: */
+        if (h[i].value.len == filter->value.len && 
+            ngx_strncasecmp(h[i].value.data, filter->value.data,
+                filter->value.len) == 0)
+        {
+            continue;
+        }
+        ho = ngx_list_push(&r->headers_out.headers);
+        if (ho == NULL) {
+            return NGX_ERROR;
+        }
+
+        *ho = h[i];
+    }
+
+    return NGX_OK;
+}
+
+
 static ngx_int_t
 ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
     ngx_http_upstream_t *u)
@@ -2339,6 +2390,16 @@ ngx_http_upstream_intercept_errors(ngx_h
                 *h = *u->headers_in.www_authenticate;
 
                 r->headers_out.www_authenticate = h;
+
+                /* transmit all authenticate headers (ex: multiple authenticate
+                 * challenges [rfc2616 sec14.47]): */
+                if (ngx_http_upstream_transmit_headers(r, 
+                        &u->headers_in.headers.part, h) != NGX_OK)
+                {
+                    ngx_http_upstream_finalize_request(r, u,
+                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
+                    return NGX_OK;
+                }
             }
 
 #if (NGX_HTTP_CACHE)
diff -r 43135346275c -r 10c2a7b3420b src/http/ngx_http_upstream.h
--- a/src/http/ngx_http_upstream.h	Tue Apr 28 15:34:33 2015 +0200
+++ b/src/http/ngx_http_upstream.h	Wed Apr 29 11:38:46 2015 +0200
@@ -404,6 +404,8 @@ ngx_int_t ngx_http_upstream_hide_headers
     ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
     ngx_str_t *default_hide_headers, ngx_hash_init_t *hash);
 
+ngx_int_t ngx_http_upstream_transmit_headers(ngx_http_request_t *r,
+    ngx_list_part_t *part, ngx_table_elt_t *filter);
 
 #define ngx_http_conf_upstream_srv_conf(uscf, module)                         \
     uscf->srv_conf[module.ctx_index]
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel

Reply via email to