MINOR: http-act: emit a warning when a header field name contains forbidden chars

As found in issue #2089, it's easy to mistakenly paste a colon in a
header name, or other chars (e.g. spaces) when quotes are in use, and
this causes all sort of trouble in field because such chars are rejected
by the peer.

Better try to detect these upfront. That's what we're doing here during
the parsing of the add-header/set-header/early-hint actions, where a
warning is emitted if a non-token character is found in a header name.
A special case is made for the colon at the beginning so that it remains
possible to place any future pseudo-headers that may appear. E.g:

  [WARNING]  (14388) : config : parsing [badchar.cfg:23] : header name 'X-Content-Type-Options:' contains forbidden character ':'.

This should be backported to 2.7, and ideally it should be turned to an
error in future versions.
This commit is contained in:
Willy Tarreau 2023-04-04 05:25:16 +02:00
parent c877bd4ea5
commit db12c0dd10

View File

@ -1484,6 +1484,7 @@ static enum act_parse_ret parse_http_set_header(const char **args, int *orig_arg
struct act_rule *rule, char **err)
{
int cap = 0, cur_arg;
const char *p;
if (args[*orig_arg-1][0] == 'e') {
rule->action = ACT_CUSTOM;
@ -1533,6 +1534,23 @@ static enum act_parse_ret parse_http_set_header(const char **args, int *orig_arg
px->conf.lfs_file = strdup(px->conf.args.file);
px->conf.lfs_line = px->conf.args.line;
/* some characters are totally forbidden in header names and
* may happen by accident when writing configs, causing strange
* failures in field. Better catch these ones early, nobody will
* miss them. In particular, a colon at the end (or anywhere
* after the first char) or a space/cr anywhere due to misplaced
* quotes are hard to spot.
*/
for (p = istptr(rule->arg.http.str); p < istend(rule->arg.http.str); p++) {
if (HTTP_IS_TOKEN(*p))
continue;
if (p == istptr(rule->arg.http.str) && *p == ':')
continue;
/* we only report this as-is but it will not cause an error */
memprintf(err, "header name '%s' contains forbidden character '%c'", istptr(rule->arg.http.str), *p);
break;
}
*orig_arg = cur_arg + 1;
return ACT_RET_PRS_OK;
}