Le 26/05/2020 à 10:22, Christopher Faulet a écrit :

In HAProxy 2.2, I guess 401/407 responses may be generated using an http-request
return rule, making http-request auth rule more or less deprecated. The only
mess is to handle 2 different responses depending on the request path when the
http-use-proxy-header option is used. In addition, http_reply_40x_unauthorized()
is also called for the stats page authentication. This part cannot be replaced
by an http-request return rule. So maybe a good solution is to use error files
(customizable since 2.2). And just add the realm at the right place, as Willy
said. I will investigate.

For HTTP_30X templates, you're right, they should be removed. And HTTP_10X too.


Here are patches to handle customizable 401/407 messages. In fact, only the second patch is really meaningful. There is no change for the http-request auth rule from the configuration point of view. Internally, we rely on the proxy's error messages. It means 401 and 407 status codes are allowed on "errorfile" and "http-error" lines.

The other patches are just cosmetic changes. The last one removes unused HTTP_XXX templates.

Any comments ?

--
Christopher Faulet
>From 5eb45f6a374c920cff241e38e4e1010c593af403 Mon Sep 17 00:00:00 2001
From: Christopher Faulet <[email protected]>
Date: Wed, 27 May 2020 15:24:22 +0200
Subject: [PATCH 1/4] MINOR: http-ana: Make the function http_reply_to_htx()
 public

This function may be used from anywhere to convert an HTTP reply to an HTX
message.
---
 include/proto/http_ana.h | 1 +
 src/http_ana.c           | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/proto/http_ana.h b/include/proto/http_ana.h
index c226b1254..894357688 100644
--- a/include/proto/http_ana.h
+++ b/include/proto/http_ana.h
@@ -52,6 +52,7 @@ void http_server_error(struct stream *s, struct stream_interface *si, int err, i
 void http_reply_and_close(struct stream *s, short status, struct http_reply *msg);
 void http_return_srv_error(struct stream *s, struct stream_interface *si);
 struct http_reply *http_error_message(struct stream *s);
+int http_reply_to_htx(struct stream *s, struct htx *htx, struct http_reply *reply);
 int http_reply_message(struct stream *s, struct http_reply *reply);
 int http_forward_proxy_resp(struct stream *s, int final);
 
diff --git a/src/http_ana.c b/src/http_ana.c
index f5add7d98..f7da26821 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -4658,7 +4658,7 @@ struct http_reply *http_error_message(struct stream *s)
  * errorfile, an raw file or a log-format string is used. On success, it returns
  * 0. If an error occurs -1 is returned.
  */
-static int http_reply_to_htx(struct stream *s, struct htx *htx, struct http_reply *reply)
+int http_reply_to_htx(struct stream *s, struct htx *htx, struct http_reply *reply)
 {
 	struct buffer *errmsg;
 	struct htx_sl *sl;
-- 
2.26.2

>From 686f4e1d19ba569890f6c91a6c2b189aeeb03c34 Mon Sep 17 00:00:00 2001
From: Christopher Faulet <[email protected]>
Date: Wed, 27 May 2020 09:57:28 +0200
Subject: [PATCH 2/4] MINOR: http-ana: Use proxy's error replies to emit
 401/407 responses

There is no reason to not use proxy's error replies to emit 401/407
responses. The function http_reply_40x_unauthorized(), responsible to emit those
responses, is not really complex. It only adds a
WWW-Authenticate/Proxy-Authenticate header to a generic message.

So now, error replies can be defined for 401 and 407 status codes, using
errorfile or http-error directives. When an http-request auth rule is evaluated,
the corresponding error reply is used. For 401 responses, all occurrences of the
WWW-Authenticate header are removed and replaced by a new one with a basic
authentication challenge for the configured realm. For 407 responses, the same
is done on the Proxy-Authenticate header. If the error reply must not be
altered, "http-request return" rule must be used instead.
---
 doc/configuration.txt | 32 +++++++++++--------
 include/common/http.h |  2 ++
 src/http.c            | 24 +++++++++++++++
 src/http_ana.c        | 71 +++++++++++++++++++------------------------
 4 files changed, 78 insertions(+), 51 deletions(-)

diff --git a/doc/configuration.txt b/doc/configuration.txt
index 674acd2fd..8a67f4d12 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -2522,8 +2522,8 @@ errorfile <code> <file>
 
   Arguments :
     <code>    is the HTTP status code. Currently, HAProxy is capable of
-              generating codes 200, 400, 403, 404, 405, 408, 410, 425, 429,
-              500, 502, 503, and 504.
+              generating codes 200, 400, 401, 403, 404, 405, 407, 408, 410,
+              425, 429, 500, 502, 503, and 504.
 
     <file>    designates a file containing the full HTTP response. It is
               recommended to follow the common practice of appending ".http" to
@@ -3859,8 +3859,8 @@ errorfile <code> <file>
                                  yes   |    yes   |   yes  |   yes
   Arguments :
     <code>    is the HTTP status code. Currently, HAProxy is capable of
-              generating codes 200, 400, 403, 404, 405, 408, 410, 425, 429, 500,
-              502, 503, and 504.
+              generating codes 200, 400, 401, 403, 404, 405, 407, 408, 410,
+              425, 429, 500, 502, 503, and 504.
 
     <file>    designates a file containing the full HTTP response. It is
               recommended to follow the common practice of appending ".http" to
@@ -3908,8 +3908,8 @@ errorfiles <name> [<code> ...]
     <name>  is the name of an existing http-errors section.
 
     <code>  is a HTTP status code. Several status code may be listed.
-            Currently, HAProxy is capable of generating codes 200, 400, 403,
-            404, 405, 408, 410, 425, 429, 500, 502, 503, and 504.
+            Currently, HAProxy is capable of generating codes 200, 400, 401,
+            403, 404, 405, 407, 408, 410, 425, 429, 500, 502, 503, and 504.
 
   Errors defined in the http-errors section with the name <name> are imported
   in the current proxy. If no status code is specified, all error files of the
@@ -3934,8 +3934,8 @@ errorloc302 <code> <url>
                                  yes   |    yes   |   yes  |   yes
   Arguments :
     <code>    is the HTTP status code. Currently, HAProxy is capable of
-              generating codes 200, 400, 403, 404, 405, 408, 410, 425, 429, 500,
-              502, 503, and 504.
+              generating codes 200, 400, 401, 403, 404, 405, 407, 408, 410,
+              425, 429, 500, 502, 503, and 504.
 
     <url>     it is the exact contents of the "Location" header. It may contain
               either a relative URI to an error page hosted on the same site,
@@ -3966,8 +3966,8 @@ errorloc303 <code> <url>
                                  yes   |    yes   |   yes  |   yes
   Arguments :
     <code>    is the HTTP status code. Currently, HAProxy is capable of
-              generating codes 200, 400, 403, 404, 405, 408, 410, 425, 429, 500,
-              502, 503, and 504.
+              generating codes 200, 400, 401, 403, 404, 405, 407, 408, 410,
+              425, 429, 500, 502, 503, and 504.
 
     <url>     it is the exact contents of the "Location" header. It may contain
               either a relative URI to an error page hosted on the same site,
@@ -4942,8 +4942,8 @@ http-error status <code> [content-type <type>]
   Arguments :
     staus <code>         is the HTTP status code. It must be specified.
                          Currently, HAProxy is capable of generating codes
-                         200, 400, 403, 404, 405, 408, 410, 425, 429, 500,
-                         502, 503, and 504.
+                         200, 400, 401, 403, 404, 405, 407, 408, 410, 425, 429,
+                         500, 502, 503, and 504.
 
     content-type <type>  is the response content type, for instance
                          "text/plain". This parameter is ignored and should be
@@ -5095,6 +5095,14 @@ http-request auth [realm <realm>] [ { if | unless } <condition> ]
   "realm" parameter is supported, it sets the authentication realm that is
   returned with the response (typically the application's name).
 
+  The corresponding proxy's error message is used. It may be customized using
+  an "errorfile" or an "http-error" directive. For 401 responses, all
+  occurrences of the WWW-Authenticate header are removed and replaced by a new
+  one with a basic authentication challenge for realm "<realm>". For 407
+  responses, the same is done on the Proxy-Authenticate header. If the error
+  message must not be altered, consider to use "http-request return" rule
+  instead.
+
   Example:
         acl auth_ok http_auth_group(L1) G1
         http-request auth unless auth_ok
diff --git a/include/common/http.h b/include/common/http.h
index 6f083d435..d31f5e915 100644
--- a/include/common/http.h
+++ b/include/common/http.h
@@ -82,9 +82,11 @@ enum ht_auth_m {
 enum {
 	HTTP_ERR_200 = 0,
 	HTTP_ERR_400,
+	HTTP_ERR_401,
 	HTTP_ERR_403,
 	HTTP_ERR_404,
 	HTTP_ERR_405,
+	HTTP_ERR_407,
 	HTTP_ERR_408,
 	HTTP_ERR_410,
 	HTTP_ERR_421,
diff --git a/src/http.c b/src/http.c
index ec6b4a282..326a08b86 100644
--- a/src/http.c
+++ b/src/http.c
@@ -215,9 +215,11 @@ const char *HTTP_407_fmt =
 const int http_err_codes[HTTP_ERR_SIZE] = {
 	[HTTP_ERR_200] = 200,  /* used by "monitor-uri" */
 	[HTTP_ERR_400] = 400,
+	[HTTP_ERR_401] = 401,
 	[HTTP_ERR_403] = 403,
 	[HTTP_ERR_404] = 404,
 	[HTTP_ERR_405] = 405,
+	[HTTP_ERR_407] = 407,
 	[HTTP_ERR_408] = 408,
 	[HTTP_ERR_410] = 410,
 	[HTTP_ERR_421] = 421,
@@ -248,6 +250,16 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = {
 	"\r\n"
 	"<html><body><h1>400 Bad request</h1>\nYour browser sent an invalid request.\n</body></html>\n",
 
+	[HTTP_ERR_401] =
+	"HTTP/1.1 401 Unauthorized\r\n"
+	"Content-length: 112\r\n"
+	"Cache-Control: no-cache\r\n"
+	"Connection: close\r\n"
+	"Content-Type: text/html\r\n"
+	"WWW-Authenticate: Basic realm=\"\"\r\n"
+	"\r\n"
+	"<html><body><h1>401 Unauthorized</h1>\nYou need a valid user and password to access this content.\n</body></html>\n",
+
 	[HTTP_ERR_403] =
 	"HTTP/1.1 403 Forbidden\r\n"
 	"Content-length: 93\r\n"
@@ -275,6 +287,16 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = {
 	"\r\n"
 	"<html><body><h1>405 Method Not Allowed</h1>\nA request was made of a resource using a request method not supported by that resource\n</body></html>\n",
 
+	[HTTP_ERR_407] =
+	"HTTP/1.1 407 Unauthorized\r\n"
+	"Content-length: 112\r\n"
+	"Cache-Control: no-cache\r\n"
+	"Connection: close\r\n"
+	"Content-Type: text/html\r\n"
+	"Proxy-Authenticate: Basic realm=\"\"\r\n"
+	"\r\n"
+	"<html><body><h1>407 Unauthorized</h1>\nYou need a valid user and password to access this content.\n</body></html>\n",
+
 	[HTTP_ERR_408] =
 	"HTTP/1.1 408 Request Time-out\r\n"
 	"Content-length: 110\r\n"
@@ -396,9 +418,11 @@ int http_get_status_idx(unsigned int status)
 	switch (status) {
 	case 200: return HTTP_ERR_200;
 	case 400: return HTTP_ERR_400;
+	case 401: return HTTP_ERR_401;
 	case 403: return HTTP_ERR_403;
 	case 404: return HTTP_ERR_404;
 	case 405: return HTTP_ERR_405;
+	case 407: return HTTP_ERR_407;
 	case 408: return HTTP_ERR_408;
 	case 410: return HTTP_ERR_410;
 	case 421: return HTTP_ERR_421;
diff --git a/src/http_ana.c b/src/http_ana.c
index f7da26821..e239f7c31 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -4910,61 +4910,54 @@ static int http_reply_40x_unauthorized(struct stream *s, const char *auth_realm)
 {
 	struct channel *res = &s->res;
 	struct htx *htx = htx_from_buf(&res->buf);
-	struct htx_sl *sl;
-	struct ist code, body;
-	int status;
-	unsigned int flags = (HTX_SL_F_IS_RESP|HTX_SL_F_VER_11);
+	struct http_reply *reply;
+	struct http_hdr_ctx ctx;
+	struct ist hdr;
 
 	if (!(s->txn->flags & TX_USE_PX_CONN)) {
-		status = 401;
-		code = ist("401");
-		body = ist("<html><body><h1>401 Unauthorized</h1>\n"
-			   "You need a valid user and password to access this content.\n"
-			   "</body></html>\n");
+		s->txn->status = 401;
+		hdr = ist("WWW-Authenticate");
 	}
 	else {
-		status = 407;
-		code = ist("407");
-		body = ist("<html><body><h1>407 Unauthorized</h1>\n"
-			   "You need a valid user and password to access this content.\n"
-			   "</body></html>\n");
+		s->txn->status = 407;
+		hdr = ist("Proxy-Authenticate");
 	}
-
-	sl = htx_add_stline(htx, HTX_BLK_RES_SL, flags,
-			    ist("HTTP/1.1"), code, ist("Unauthorized"));
-	if (!sl)
-		goto fail;
-	sl->info.res.status = status;
-	s->txn->status = status;
+	reply = http_error_message(s);
+	channel_htx_truncate(res, htx);
 
 	if (chunk_printf(&trash, "Basic realm=\"%s\"", auth_realm) == -1)
 		goto fail;
 
-        if (!htx_add_header(htx, ist("Content-length"), ist("112")) ||
-	    !htx_add_header(htx, ist("Cache-Control"), ist("no-cache")) ||
-	    !htx_add_header(htx, ist("Connection"), ist("close")) ||
-	    !htx_add_header(htx, ist("Content-Type"), ist("text/html")))
-		goto fail;
-	if (status == 401 && !htx_add_header(htx, ist("WWW-Authenticate"), ist2(trash.area, trash.data)))
-		goto fail;
-	if (status == 407 && !htx_add_header(htx, ist("Proxy-Authenticate"), ist2(trash.area, trash.data)))
-		goto fail;
-	if (!htx_add_endof(htx, HTX_BLK_EOH))
+	/* Write the generic 40x message */
+	if (http_reply_to_htx(s, htx, reply) == -1)
 		goto fail;
 
-	while (body.len) {
-		size_t sent = htx_add_data(htx, body);
-		if (!sent)
-			goto fail;
-		body.ptr += sent;
-		body.len -= sent;
-	}
+	/* Remove all existing occurrences of the XXX-Authenticate header */
+	ctx.blk = NULL;
+	while (http_find_header(htx, hdr, &ctx, 1))
+		http_remove_header(htx, &ctx);
 
-	if (!htx_add_endof(htx, HTX_BLK_EOM))
+	/* Now a the right XXX-Authenticate header */
+	if (!http_add_header(htx, hdr, ist2(b_orig(&trash), b_data(&trash))))
 		goto fail;
 
+	/* Finally forward the reply */
+	htx_to_buf(htx, &res->buf);
 	if (!http_forward_proxy_resp(s, 1))
 		goto fail;
+
+	/* Note: Only eval on the request */
+	s->logs.tv_request = now;
+	s->req.analysers &= AN_REQ_FLT_END;
+
+	if (s->sess->fe == s->be) /* report it if the request was intercepted by the frontend */
+		_HA_ATOMIC_ADD(&s->sess->fe->fe_counters.intercepted_req, 1);
+
+	if (!(s->flags & SF_ERR_MASK))
+		s->flags |= SF_ERR_LOCAL;
+	if (!(s->flags & SF_FINST_MASK))
+		s->flags |= SF_FINST_R;
+
 	return 0;
 
   fail:
-- 
2.26.2

>From deb506552d0feb6483cd628513a047093d369e59 Mon Sep 17 00:00:00 2001
From: Christopher Faulet <[email protected]>
Date: Wed, 27 May 2020 15:26:43 +0200
Subject: [PATCH 3/4] MINOR: http-rules: Use an action function to eval
 http-request auth rules

Now http-request auth rules are evaluated in a dedicated function and no longer
handled "in place" during the HTTP rules evaluation. Thus the action name
ACT_HTTP_REQ_AUTH is removed. In additionn, http_reply_40x_unauthorized() is
also removed. This part is now handled in the new action_ptr callback function.
---
 include/types/action.h |  1 -
 src/http_act.c         | 83 +++++++++++++++++++++++++++++++++++++++-
 src/http_ana.c         | 86 ------------------------------------------
 3 files changed, 82 insertions(+), 88 deletions(-)

diff --git a/include/types/action.h b/include/types/action.h
index b01380c3a..00c37fa6a 100644
--- a/include/types/action.h
+++ b/include/types/action.h
@@ -89,7 +89,6 @@ enum act_name {
 
 	/* http request actions. */
 	ACT_HTTP_REQ_TARPIT,
-	ACT_HTTP_REQ_AUTH,
 
 	/* tcp actions */
 	ACT_TCP_EXPECT_PX,
diff --git a/src/http_act.c b/src/http_act.c
index ab4a8bb94..b18da6164 100644
--- a/src/http_act.c
+++ b/src/http_act.c
@@ -25,6 +25,7 @@
 #include <common/initcall.h>
 #include <common/memory.h>
 #include <common/standard.h>
+#include <common/uri_auth.h>
 #include <common/version.h>
 
 #include <types/capture.h>
@@ -884,6 +885,85 @@ static enum act_parse_ret parse_http_deny(const char **args, int *orig_arg, stru
 	return ACT_RET_PRS_OK;
 }
 
+
+/* This function executes a auth action. It builds an 401/407 HTX message using
+ * the corresponding proxy's error message. On success, it returns
+ * ACT_RET_ABRT. If an error occurs ACT_RET_ERR is returned.
+ */
+static enum act_return http_action_auth(struct act_rule *rule, struct proxy *px,
+					struct session *sess, struct stream *s, int flags)
+{
+	struct channel *req = &s->req;
+	struct channel *res = &s->res;
+	struct htx *htx = htx_from_buf(&res->buf);
+	struct http_reply *reply;
+	const char *auth_realm;
+	struct http_hdr_ctx ctx;
+	struct ist hdr;
+
+	/* Auth might be performed on regular http-req rules as well as on stats */
+	auth_realm = rule->arg.http.str.ptr;
+	if (!auth_realm) {
+		if (px->uri_auth && s->current_rule_list == &px->uri_auth->http_req_rules)
+			auth_realm = STATS_DEFAULT_REALM;
+		else
+			auth_realm = px->id;
+	}
+
+	if (!(s->txn->flags & TX_USE_PX_CONN)) {
+		s->txn->status = 401;
+		hdr = ist("WWW-Authenticate");
+	}
+	else {
+		s->txn->status = 407;
+		hdr = ist("Proxy-Authenticate");
+	}
+	reply = http_error_message(s);
+	channel_htx_truncate(res, htx);
+
+	if (chunk_printf(&trash, "Basic realm=\"%s\"", auth_realm) == -1)
+		goto fail;
+
+	/* Write the generic 40x message */
+	if (http_reply_to_htx(s, htx, reply) == -1)
+		goto fail;
+
+	/* Remove all existing occurrences of the XXX-Authenticate header */
+	ctx.blk = NULL;
+	while (http_find_header(htx, hdr, &ctx, 1))
+		http_remove_header(htx, &ctx);
+
+	/* Now a the right XXX-Authenticate header */
+	if (!http_add_header(htx, hdr, ist2(b_orig(&trash), b_data(&trash))))
+		goto fail;
+
+	/* Finally forward the reply */
+	htx_to_buf(htx, &res->buf);
+	if (!http_forward_proxy_resp(s, 1))
+		goto fail;
+
+	/* Note: Only eval on the request */
+	s->logs.tv_request = now;
+	req->analysers &= AN_REQ_FLT_END;
+
+	if (s->sess->fe == s->be) /* report it if the request was intercepted by the frontend */
+		_HA_ATOMIC_ADD(&s->sess->fe->fe_counters.intercepted_req, 1);
+
+	if (!(s->flags & SF_ERR_MASK))
+		s->flags |= SF_ERR_LOCAL;
+	if (!(s->flags & SF_FINST_MASK))
+		s->flags |= SF_FINST_R;
+
+	stream_inc_http_err_ctr(s);
+	return ACT_RET_ABRT;
+
+  fail:
+	/* If an error occurred, remove the incomplete HTTP response from the
+	 * buffer */
+	channel_htx_truncate(res, htx);
+	return ACT_RET_ERR;
+}
+
 /* Parse a "auth" action. It may take 2 optional arguments to define a "realm"
  * parameter. It returns ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error.
  */
@@ -892,8 +972,9 @@ static enum act_parse_ret parse_http_auth(const char **args, int *orig_arg, stru
 {
 	int cur_arg;
 
-	rule->action = ACT_HTTP_REQ_AUTH;
+	rule->action = ACT_CUSTOM;
 	rule->flags |= ACT_FLAG_FINAL;
+	rule->action_ptr = http_action_auth;
 	rule->release_ptr = release_http_action;
 
 	cur_arg = *orig_arg;
diff --git a/src/http_ana.c b/src/http_ana.c
index e239f7c31..cf9570c3b 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -63,7 +63,6 @@ static int http_handle_stats(struct stream *s, struct channel *req);
 
 static int http_handle_expect_hdr(struct stream *s, struct htx *htx, struct http_msg *msg);
 static int http_reply_100_continue(struct stream *s);
-static int http_reply_40x_unauthorized(struct stream *s, const char *auth_realm);
 
 /* This stream analyser waits for a complete HTTP request. It returns 1 if the
  * processing can continue on next analysers, or zero if it either needs more
@@ -2824,7 +2823,6 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
 	struct htx *htx;
 	struct act_rule *rule;
 	struct http_hdr_ctx ctx;
-	const char *auth_realm;
 	enum rule_result rule_ret = HTTP_RULE_RES_CONT;
 	int act_opts = 0;
 
@@ -2920,25 +2918,6 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
 				rule_ret = HTTP_RULE_RES_DENY;
 				goto end;
 
-			case ACT_HTTP_REQ_AUTH:
-				/* Auth might be performed on regular http-req rules as well as on stats */
-				auth_realm = rule->arg.http.str.ptr;
-				if (!auth_realm) {
-					if (px->uri_auth && rules == &px->uri_auth->http_req_rules)
-						auth_realm = STATS_DEFAULT_REALM;
-					else
-						auth_realm = px->id;
-				}
-				/* send 401/407 depending on whether we use a proxy or not. We still
-				 * count one error, because normal browsing won't significantly
-				 * increase the counter but brute force attempts will.
-				 */
-				rule_ret = HTTP_RULE_RES_ABRT;
-				if (http_reply_40x_unauthorized(s, auth_realm) == -1)
-					rule_ret = HTTP_RULE_RES_ERROR;
-				stream_inc_http_err_ctr(s);
-				goto end;
-
 			case ACT_HTTP_REDIR:
 				rule_ret = HTTP_RULE_RES_ABRT;
 				if (!http_apply_redirect_rule(rule->arg.redir, s, txn))
@@ -4902,71 +4881,6 @@ static int http_reply_100_continue(struct stream *s)
 }
 
 
-/* Send a 401-Unauthorized or 407-Unauthorized response to the client, depending
- * ont whether we use a proxy or not. It returns 0 on success and -1 on
- * error. The response channel is updated accordingly.
- */
-static int http_reply_40x_unauthorized(struct stream *s, const char *auth_realm)
-{
-	struct channel *res = &s->res;
-	struct htx *htx = htx_from_buf(&res->buf);
-	struct http_reply *reply;
-	struct http_hdr_ctx ctx;
-	struct ist hdr;
-
-	if (!(s->txn->flags & TX_USE_PX_CONN)) {
-		s->txn->status = 401;
-		hdr = ist("WWW-Authenticate");
-	}
-	else {
-		s->txn->status = 407;
-		hdr = ist("Proxy-Authenticate");
-	}
-	reply = http_error_message(s);
-	channel_htx_truncate(res, htx);
-
-	if (chunk_printf(&trash, "Basic realm=\"%s\"", auth_realm) == -1)
-		goto fail;
-
-	/* Write the generic 40x message */
-	if (http_reply_to_htx(s, htx, reply) == -1)
-		goto fail;
-
-	/* Remove all existing occurrences of the XXX-Authenticate header */
-	ctx.blk = NULL;
-	while (http_find_header(htx, hdr, &ctx, 1))
-		http_remove_header(htx, &ctx);
-
-	/* Now a the right XXX-Authenticate header */
-	if (!http_add_header(htx, hdr, ist2(b_orig(&trash), b_data(&trash))))
-		goto fail;
-
-	/* Finally forward the reply */
-	htx_to_buf(htx, &res->buf);
-	if (!http_forward_proxy_resp(s, 1))
-		goto fail;
-
-	/* Note: Only eval on the request */
-	s->logs.tv_request = now;
-	s->req.analysers &= AN_REQ_FLT_END;
-
-	if (s->sess->fe == s->be) /* report it if the request was intercepted by the frontend */
-		_HA_ATOMIC_ADD(&s->sess->fe->fe_counters.intercepted_req, 1);
-
-	if (!(s->flags & SF_ERR_MASK))
-		s->flags |= SF_ERR_LOCAL;
-	if (!(s->flags & SF_FINST_MASK))
-		s->flags |= SF_FINST_R;
-
-	return 0;
-
-  fail:
-	/* If an error occurred, remove the incomplete HTTP response from the
-	 * buffer */
-	channel_htx_truncate(res, htx);
-	return -1;
-}
-
 /*
  * Capture headers from message <htx> according to header list <cap_hdr>, and
  * fill the <cap> pointers appropriately.
-- 
2.26.2

>From 2a72cca178803f60d9b52edb5862ed6be4565eec Mon Sep 17 00:00:00 2001
From: Christopher Faulet <[email protected]>
Date: Wed, 27 May 2020 10:11:59 +0200
Subject: [PATCH 4/4] CLEANUP: http: Remove unused HTTP message templates

HTTP_1XX, HTTP_3XX and HTTP_4XX message templates are no longer used. Only
HTTP_302 and HTTP_303 are used during configuration parsing by "errorloc" family
directives. So these templates are removed from the generic http code. And
HTTP_302 and HTTP_303 templates are moved as static strings in the function
parsing "errorloc" directives.
---
 include/common/http.h | 10 --------
 src/http.c            | 57 -------------------------------------------
 src/http_htx.c        | 11 +++++++++
 3 files changed, 11 insertions(+), 67 deletions(-)

diff --git a/include/common/http.h b/include/common/http.h
index d31f5e915..acf19903f 100644
--- a/include/common/http.h
+++ b/include/common/http.h
@@ -127,16 +127,6 @@ extern const char *http_err_msgs[HTTP_ERR_SIZE];
 extern const struct ist http_known_methods[HTTP_METH_OTHER];
 extern const uint8_t http_char_classes[256];
 
-extern const struct ist HTTP_100;
-extern const struct ist HTTP_103;
-extern const char *HTTP_301;
-extern const char *HTTP_302;
-extern const char *HTTP_303;
-extern const char *HTTP_307;
-extern const char *HTTP_308;
-extern const char *HTTP_401_fmt;
-extern const char *HTTP_407_fmt;
-
 enum http_meth_t find_http_meth(const char *str, const int len);
 int http_get_status_idx(unsigned int status);
 const char *http_get_reason(unsigned int status);
diff --git a/src/http.c b/src/http.c
index 326a08b86..431f60b3b 100644
--- a/src/http.c
+++ b/src/http.c
@@ -155,63 +155,6 @@ const unsigned char http_char_classes[256] = {
 	[127] = HTTP_FLG_CTL,
 };
 
-const struct ist HTTP_100 = IST("HTTP/1.1 100 Continue\r\n\r\n");
-
-const struct ist HTTP_103 = IST("HTTP/1.1 103 Early Hints\r\n");
-
-/* Warning: no "connection" header is provided with the 3xx messages below */
-const char *HTTP_301 =
-	"HTTP/1.1 301 Moved Permanently\r\n"
-	"Content-length: 0\r\n"
-	"Location: "; /* not terminated since it will be concatenated with the URL */
-
-const char *HTTP_302 =
-	"HTTP/1.1 302 Found\r\n"
-	"Cache-Control: no-cache\r\n"
-	"Content-length: 0\r\n"
-	"Location: "; /* not terminated since it will be concatenated with the URL */
-
-/* same as 302 except that the browser MUST retry with the GET method */
-const char *HTTP_303 =
-	"HTTP/1.1 303 See Other\r\n"
-	"Cache-Control: no-cache\r\n"
-	"Content-length: 0\r\n"
-	"Location: "; /* not terminated since it will be concatenated with the URL */
-
-/* same as 302 except that the browser MUST retry with the same method */
-const char *HTTP_307 =
-	"HTTP/1.1 307 Temporary Redirect\r\n"
-	"Cache-Control: no-cache\r\n"
-	"Content-length: 0\r\n"
-	"Location: "; /* not terminated since it will be concatenated with the URL */
-
-/* same as 301 except that the browser MUST retry with the same method */
-const char *HTTP_308 =
-	"HTTP/1.1 308 Permanent Redirect\r\n"
-	"Content-length: 0\r\n"
-	"Location: "; /* not terminated since it will be concatenated with the URL */
-
-/* Warning: this one is an sprintf() fmt string, with <realm> as its only argument */
-const char *HTTP_401_fmt =
-	"HTTP/1.1 401 Unauthorized\r\n"
-	"Content-length: 112\r\n"
-	"Cache-Control: no-cache\r\n"
-	"Connection: close\r\n"
-	"Content-Type: text/html\r\n"
-	"WWW-Authenticate: Basic realm=\"%s\"\r\n"
-	"\r\n"
-	"<html><body><h1>401 Unauthorized</h1>\nYou need a valid user and password to access this content.\n</body></html>\n";
-
-const char *HTTP_407_fmt =
-	"HTTP/1.1 407 Unauthorized\r\n"
-	"Content-length: 112\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"
-	"<html><body><h1>407 Unauthorized</h1>\nYou need a valid user and password to access this content.\n</body></html>\n";
-
 const int http_err_codes[HTTP_ERR_SIZE] = {
 	[HTTP_ERR_200] = 200,  /* used by "monitor-uri" */
 	[HTTP_ERR_400] = 400,
diff --git a/src/http_htx.c b/src/http_htx.c
index 3137fbebb..7211a4de1 100644
--- a/src/http_htx.c
+++ b/src/http_htx.c
@@ -1223,6 +1223,17 @@ struct buffer *http_parse_errorfile(int status, const char *file, char **errmsg)
  */
 struct buffer *http_parse_errorloc(int errloc, int status, const char *url, char **errmsg)
 {
+	static const char *HTTP_302 =
+		"HTTP/1.1 302 Found\r\n"
+		"Cache-Control: no-cache\r\n"
+		"Content-length: 0\r\n"
+		"Location: "; /* not terminated since it will be concatenated with the URL */
+	static const char *HTTP_303 =
+		"HTTP/1.1 303 See Other\r\n"
+		"Cache-Control: no-cache\r\n"
+		"Content-length: 0\r\n"
+		"Location: "; /* not terminated since it will be concatenated with the URL */
+
 	struct buffer *buf = NULL;
 	const char *msg;
 	char *key = NULL, *err = NULL;
-- 
2.26.2

Reply via email to