From 844a7e76d2557364e6d34d00027f2fa514b9d855 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 31 Jan 2010 21:46:18 +0100 Subject: [PATCH] [MEDIUM] http: add support for proxy authentication We're already able to know if a request is a proxy request or a normal one, and we have an option "http-use-proxy-header" which states that proxy headers must be checked. So let's switch to use the proxy authentication headers and responses when this option is set and we're facing a proxy request. That allows haproxy to enforce auth in front of a proxy. --- doc/configuration.txt | 5 +++++ src/proto_http.c | 22 ++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 2ef3639ea..48c90c763 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -2691,6 +2691,11 @@ option http-use-proxy-header that this option can only be specified in a frontend and will affect the request along its whole life. + Also, when this option is set, a request which requires authentication will + automatically switch to use proxy authentication headers if it is itself a + proxied request. That makes it possible to check or enforce authentication in + front of an existing proxy. + This option should normally never be used, except in front of a proxy. See also : "option httpclose", "option forceclose" and "option diff --git a/src/proto_http.c b/src/proto_http.c index 4ac53b38d..1b59c68f5 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -111,6 +111,15 @@ const char *HTTP_401_fmt = "\r\n" "

401 Unauthorized

\nYou need a valid user and password to access this content.\n\n"; +const char *HTTP_407_fmt = + "HTTP/1.0 407 Unauthorized\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "Proxy-Authenticate: Basic realm=\"%s\"\r\n" + "\r\n" + "

401 Unauthorized

\nYou need a valid user and password to access this content.\n\n"; + const int http_err_codes[HTTP_ERR_SIZE] = { [HTTP_ERR_400] = 400, @@ -1507,7 +1516,16 @@ get_http_auth(struct session *s) txn->auth.method = HTTP_AUTH_WRONG; ctx.idx = 0; - if (!http_find_header("Authorization", txn->req.sol, &txn->hdr_idx, &ctx)) + + if (txn->flags & TX_USE_PX_CONN) { + h = "Proxy-Authorization"; + len = strlen(h); + } else { + h = "Authorization"; + len = strlen(h); + } + + if (!http_find_header2(h, len, txn->req.sol, &txn->hdr_idx, &ctx)) return 0; h = ctx.line + ctx.val; @@ -2969,7 +2987,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s if (!realm) realm = do_stats?STATS_DEFAULT_REALM:px->id; - sprintf(trash, HTTP_401_fmt, realm); + sprintf(trash, (txn->flags & TX_USE_PX_CONN) ? HTTP_407_fmt : HTTP_401_fmt, realm); chunk_initlen(&msg, trash, sizeof(trash), strlen(trash)); txn->status = 401; stream_int_retnclose(req->prod, &msg);