mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-05-04 20:46:11 +02:00
MEDIUM: http: ACL and MAP updates through http-(request|response) rules
This patch allows manipulation of ACL and MAP content thanks to any information available in a session: source IP address, HTTP request or response header, etc... It's an update "on the fly" of the content of the map/acls. This means it does not resist to reload or restart of HAProxy.
This commit is contained in:
parent
953f74d1b3
commit
fabcbe0de6
@ -2848,7 +2848,12 @@ http-check send-state
|
||||
http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
|
||||
add-header <name> <fmt> | set-header <name> <fmt> |
|
||||
del-header <name> | set-nice <nice> | set-log-level <level> |
|
||||
set-tos <tos> | set-mark <mark> }
|
||||
set-tos <tos> | set-mark <mark> |
|
||||
add-acl(<file name>) <key fmt> |
|
||||
del-acl(<file name>) <key fmt> |
|
||||
del-map(<file name>) <key fmt> |
|
||||
set-map(<file name>) <key fmt> <value fmt>
|
||||
}
|
||||
[ { if | unless } <condition> ]
|
||||
Access control for Layer 7 requests
|
||||
|
||||
@ -2944,6 +2949,39 @@ http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
|
||||
downloads). This works on Linux kernels 2.6.32 and above and requires
|
||||
admin privileges.
|
||||
|
||||
- "add-acl" is used to add a new entry into an ACL. The ACL must be loaded
|
||||
from a file (even a dummy empty file). The file name of the ACL to be
|
||||
updated is passed between parentheses. It takes one argument: <key fmt>,
|
||||
which follows log-format rules, to collect content of the new entry. It
|
||||
performs a lookup in the ACL before insertion, to avoid duplicated (or
|
||||
more) values. This lookup is done by a linear search and can be expensive
|
||||
with large lists! It is the equivalent of the "add acl" command from the
|
||||
stats socket, but can be triggered by an HTTP request.
|
||||
|
||||
- "del-acl" is used to delete an entry from an ACL. The ACL must be loaded
|
||||
from a file (even a dummy empty file). The file name of the ACL to be
|
||||
updated is passed between parentheses. It takes one argument: <key fmt>,
|
||||
which follows log-format rules, to collect content of the entry to delete.
|
||||
It is the equivalent of the "del acl" command from the stats socket, but
|
||||
can be triggered by an HTTP request.
|
||||
|
||||
- "del-map" is used to delete an entry from a MAP. The MAP must be loaded
|
||||
from a file (even a dummy empty file). The file name of the MAP to be
|
||||
updated is passed between parentheses. It takes one argument: <key fmt>,
|
||||
which follows log-format rules, to collect content of the entry to delete.
|
||||
It takes one argument: "file name" It is the equivalent of the "del map"
|
||||
command from the stats socket, but can be triggered by an HTTP request.
|
||||
|
||||
- "set-map" is used to add a new entry into a MAP. The MAP must be loaded
|
||||
from a file (even a dummy empty file). The file name of the MAP to be
|
||||
updated is passed between parentheses. It takes 2 arguments: <key fmt>,
|
||||
which follows log-format rules, used to collect MAP key, and <value fmt>,
|
||||
which follows log-format rules, used to collect content for the new entry.
|
||||
It performs a lookup in the MAP before insertion, to avoid duplicated (or
|
||||
more) values. This lookup is done by a linear search and can be expensive
|
||||
with large lists! It is the equivalent of the "set map" command from the
|
||||
stats socket, but can be triggered by an HTTP request.
|
||||
|
||||
There is no limit to the number of http-request statements per instance.
|
||||
|
||||
It is important to know that http-request rules are processed very early in
|
||||
@ -2976,12 +3014,37 @@ http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
|
||||
http-request set-header X-SSL-Client-NotBefore %{+Q}[ssl_c_notbefore]
|
||||
http-request set-header X-SSL-Client-NotAfter %{+Q}[ssl_c_notafter]
|
||||
|
||||
Example:
|
||||
acl key req.hdr(X-Add-Acl-Key) -m found
|
||||
acl add path /addacl
|
||||
acl del path /delacl
|
||||
|
||||
acl myhost hdr(Host) -f myhost.lst
|
||||
|
||||
http-request add-acl(myhost.lst) %[req.hdr(X-Add-Acl-Key)] if key add
|
||||
http-request del-acl(myhost.lst) %[req.hdr(X-Add-Acl-Key)] if key del
|
||||
|
||||
Example:
|
||||
acl value req.hdr(X-Value) -m found
|
||||
acl setmap path /setmap
|
||||
acl delmap path /delmap
|
||||
|
||||
use_backend bk_appli if { hdr(Host),map_str(map.lst) -m found }
|
||||
|
||||
http-request set-map(map.lst) %[src] %[req.hdr(X-Value)] if setmap value
|
||||
http-request del-map(map.lst) %[src] if delmap
|
||||
|
||||
See also : "stats http-request", section 3.4 about userlists and section 7
|
||||
about ACL usage.
|
||||
|
||||
http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> |
|
||||
set-header <name> <fmt> | del-header <name> |
|
||||
set-log-level <level> | set-mark <mark> | set-tos <tos> }
|
||||
set-log-level <level> | set-mark <mark> | set-tos <tos> |
|
||||
add-acl(<file name>) <key fmt> |
|
||||
del-acl(<file name>) <key fmt> |
|
||||
del-map(<file name>) <key fmt> |
|
||||
set-map(<file name>) <key fmt> <value fmt>
|
||||
}
|
||||
[ { if | unless } <condition> ]
|
||||
Access control for Layer 7 responses
|
||||
|
||||
@ -3054,6 +3117,39 @@ http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> |
|
||||
downloads). This works on Linux kernels 2.6.32 and above and requires
|
||||
admin privileges.
|
||||
|
||||
- "add-acl" is used to add a new entry into an ACL. The ACL must be loaded
|
||||
from a file (even a dummy empty file). The file name of the ACL to be
|
||||
updated is passed between parentheses. It takes one argument: <key fmt>,
|
||||
which follows log-format rules, to collect content of the new entry. It
|
||||
performs a lookup in the ACL before insertion, to avoid duplicated (or
|
||||
more) values. This lookup is done by a linear search and can be expensive
|
||||
with large lists! It is the equivalent of the "add acl" command from the
|
||||
stats socket, but can be triggered by an HTTP response.
|
||||
|
||||
- "del-acl" is used to delete an entry from an ACL. The ACL must be loaded
|
||||
from a file (even a dummy empty file). The file name of the ACL to be
|
||||
updated is passed between parentheses. It takes one argument: <key fmt>,
|
||||
which follows log-format rules, to collect content of the entry to delete.
|
||||
It is the equivalent of the "del acl" command from the stats socket, but
|
||||
can be triggered by an HTTP response.
|
||||
|
||||
- "del-map" is used to delete an entry from a MAP. The MAP must be loaded
|
||||
from a file (even a dummy empty file). The file name of the MAP to be
|
||||
updated is passed between parentheses. It takes one argument: <key fmt>,
|
||||
which follows log-format rules, to collect content of the entry to delete.
|
||||
It takes one argument: "file name" It is the equivalent of the "del map"
|
||||
command from the stats socket, but can be triggered by an HTTP response.
|
||||
|
||||
- "set-map" is used to add a new entry into a MAP. The MAP must be loaded
|
||||
from a file (even a dummy empty file). The file name of the MAP to be
|
||||
updated is passed between parentheses. It takes 2 arguments: <key fmt>,
|
||||
which follows log-format rules, used to collect MAP key, and <value fmt>,
|
||||
which follows log-format rules, used to collect content for the new entry.
|
||||
It performs a lookup in the MAP before insertion, to avoid duplicated (or
|
||||
more) values. This lookup is done by a linear search and can be expensive
|
||||
with large lists! It is the equivalent of the "set map" command from the
|
||||
stats socket, but can be triggered by an HTTP response.
|
||||
|
||||
There is no limit to the number of http-response statements per instance.
|
||||
|
||||
It is important to know that http-response rules are processed very early in
|
||||
@ -3061,6 +3157,22 @@ http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> |
|
||||
added by "add-header"/"set-header" are visible by almost all further ACL
|
||||
rules.
|
||||
|
||||
Example:
|
||||
acl key_acl res.hdr(X-Acl-Key) -m found
|
||||
|
||||
acl myhost hdr(Host) -f myhost.lst
|
||||
|
||||
http-response add-acl(myhost.lst) %[res.hdr(X-Acl-Key)] if key_acl
|
||||
http-response del-acl(myhost.lst) %[res.hdr(X-Acl-Key)] if key_acl
|
||||
|
||||
Example:
|
||||
acl value res.hdr(X-Value) -m found
|
||||
|
||||
use_backend bk_appli if { hdr(Host),map_str(map.lst) -m found }
|
||||
|
||||
http-response set-map(map.lst) %[src] %[res.hdr(X-Value)] if value
|
||||
http-response del-map(map.lst) %[src] if ! value
|
||||
|
||||
See also : "http-request", section 3.4 about userlists and section 7 about
|
||||
ACL usage.
|
||||
|
||||
|
||||
@ -252,6 +252,10 @@ enum {
|
||||
HTTP_REQ_ACT_SET_LOGL,
|
||||
HTTP_REQ_ACT_SET_TOS,
|
||||
HTTP_REQ_ACT_SET_MARK,
|
||||
HTTP_REQ_ACT_ADD_ACL,
|
||||
HTTP_REQ_ACT_DEL_ACL,
|
||||
HTTP_REQ_ACT_DEL_MAP,
|
||||
HTTP_REQ_ACT_SET_MAP,
|
||||
HTTP_REQ_ACT_MAX /* must always be last */
|
||||
};
|
||||
|
||||
@ -267,6 +271,10 @@ enum {
|
||||
HTTP_RES_ACT_SET_LOGL,
|
||||
HTTP_RES_ACT_SET_TOS,
|
||||
HTTP_RES_ACT_SET_MARK,
|
||||
HTTP_RES_ACT_ADD_ACL,
|
||||
HTTP_RES_ACT_DEL_ACL,
|
||||
HTTP_RES_ACT_DEL_MAP,
|
||||
HTTP_RES_ACT_SET_MAP,
|
||||
HTTP_RES_ACT_MAX /* must always be last */
|
||||
};
|
||||
|
||||
@ -404,6 +412,11 @@ struct http_req_rule {
|
||||
int loglevel; /* log-level value for HTTP_REQ_ACT_SET_LOGL */
|
||||
int tos; /* tos value for HTTP_REQ_ACT_SET_TOS */
|
||||
int mark; /* nfmark value for HTTP_REQ_ACT_SET_MARK */
|
||||
struct {
|
||||
char *ref; /* MAP or ACL file name to update */
|
||||
struct list key; /* pattern to retrieve MAP or ACL key */
|
||||
struct list value; /* pattern to retrieve MAP value */
|
||||
} map;
|
||||
} arg; /* arguments used by some actions */
|
||||
};
|
||||
|
||||
@ -421,6 +434,11 @@ struct http_res_rule {
|
||||
int loglevel; /* log-level value for HTTP_RES_ACT_SET_LOGL */
|
||||
int tos; /* tos value for HTTP_RES_ACT_SET_TOS */
|
||||
int mark; /* nfmark value for HTTP_RES_ACT_SET_MARK */
|
||||
struct {
|
||||
char *ref; /* MAP or ACL file name to update */
|
||||
struct list key; /* pattern to retrieve MAP or ACL key */
|
||||
struct list value; /* pattern to retrieve MAP value */
|
||||
} map;
|
||||
} arg; /* arguments used by some actions */
|
||||
};
|
||||
|
||||
|
||||
410
src/proto_http.c
410
src/proto_http.c
@ -64,6 +64,7 @@
|
||||
#include <proto/session.h>
|
||||
#include <proto/stream_interface.h>
|
||||
#include <proto/task.h>
|
||||
#include <proto/pattern.h>
|
||||
|
||||
const char HTTP_100[] =
|
||||
"HTTP/1.1 100 Continue\r\n\r\n";
|
||||
@ -3204,6 +3205,90 @@ http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct session
|
||||
trash.len += build_logline(s, trash.str + trash.len, trash.size - trash.len, &rule->arg.hdr_add.fmt);
|
||||
http_header_add_tail2(&txn->req, &txn->hdr_idx, trash.str, trash.len);
|
||||
break;
|
||||
|
||||
case HTTP_REQ_ACT_DEL_ACL:
|
||||
case HTTP_REQ_ACT_DEL_MAP: {
|
||||
struct pat_ref *ref;
|
||||
char *key;
|
||||
int len;
|
||||
|
||||
/* collect reference */
|
||||
ref = pat_ref_lookup(rule->arg.map.ref);
|
||||
if (!ref)
|
||||
continue;
|
||||
|
||||
/* collect key */
|
||||
len = build_logline(s, trash.str, trash.size, &rule->arg.map.key);
|
||||
key = trash.str;
|
||||
key[len] = '\0';
|
||||
|
||||
/* perform update */
|
||||
/* returned code: 1=ok, 0=ko */
|
||||
pat_ref_delete(ref, key);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case HTTP_REQ_ACT_ADD_ACL: {
|
||||
struct pat_ref *ref;
|
||||
char *key;
|
||||
struct chunk *trash_key;
|
||||
int len;
|
||||
|
||||
trash_key = get_trash_chunk();
|
||||
|
||||
/* collect reference */
|
||||
ref = pat_ref_lookup(rule->arg.map.ref);
|
||||
if (!ref)
|
||||
continue;
|
||||
|
||||
/* collect key */
|
||||
len = build_logline(s, trash_key->str, trash_key->size, &rule->arg.map.key);
|
||||
key = trash_key->str;
|
||||
key[len] = '\0';
|
||||
|
||||
/* perform update */
|
||||
/* add entry only if it does not already exist */
|
||||
if (pat_ref_find_elt(ref, key) == NULL)
|
||||
pat_ref_add(ref, key, NULL, NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case HTTP_REQ_ACT_SET_MAP: {
|
||||
struct pat_ref *ref;
|
||||
char *key, *value;
|
||||
struct chunk *trash_key, *trash_value;
|
||||
int len;
|
||||
|
||||
trash_key = get_trash_chunk();
|
||||
trash_value = get_trash_chunk();
|
||||
|
||||
/* collect reference */
|
||||
ref = pat_ref_lookup(rule->arg.map.ref);
|
||||
if (!ref)
|
||||
continue;
|
||||
|
||||
/* collect key */
|
||||
len = build_logline(s, trash_key->str, trash_key->size, &rule->arg.map.key);
|
||||
key = trash_key->str;
|
||||
key[len] = '\0';
|
||||
|
||||
/* collect value */
|
||||
len = build_logline(s, trash_value->str, trash_value->size, &rule->arg.map.value);
|
||||
value = trash_value->str;
|
||||
value[len] = '\0';
|
||||
|
||||
/* perform update */
|
||||
if (pat_ref_find_elt(ref, key) != NULL)
|
||||
/* update entry if it exists */
|
||||
pat_ref_set(ref, key, value, NULL);
|
||||
else
|
||||
/* insert a new entry */
|
||||
pat_ref_add(ref, key, value, NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3293,6 +3378,90 @@ http_res_get_intercept_rule(struct proxy *px, struct list *rules, struct session
|
||||
trash.len += build_logline(s, trash.str + trash.len, trash.size - trash.len, &rule->arg.hdr_add.fmt);
|
||||
http_header_add_tail2(&txn->rsp, &txn->hdr_idx, trash.str, trash.len);
|
||||
break;
|
||||
|
||||
case HTTP_RES_ACT_DEL_ACL:
|
||||
case HTTP_RES_ACT_DEL_MAP: {
|
||||
struct pat_ref *ref;
|
||||
char *key;
|
||||
int len;
|
||||
|
||||
/* collect reference */
|
||||
ref = pat_ref_lookup(rule->arg.map.ref);
|
||||
if (!ref)
|
||||
continue;
|
||||
|
||||
/* collect key */
|
||||
len = build_logline(s, trash.str, trash.size, &rule->arg.map.key);
|
||||
key = trash.str;
|
||||
key[len] = '\0';
|
||||
|
||||
/* perform update */
|
||||
/* returned code: 1=ok, 0=ko */
|
||||
pat_ref_delete(ref, key);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case HTTP_RES_ACT_ADD_ACL: {
|
||||
struct pat_ref *ref;
|
||||
char *key;
|
||||
struct chunk *trash_key;
|
||||
int len;
|
||||
|
||||
trash_key = get_trash_chunk();
|
||||
|
||||
/* collect reference */
|
||||
ref = pat_ref_lookup(rule->arg.map.ref);
|
||||
if (!ref)
|
||||
continue;
|
||||
|
||||
/* collect key */
|
||||
len = build_logline(s, trash_key->str, trash_key->size, &rule->arg.map.key);
|
||||
key = trash_key->str;
|
||||
key[len] = '\0';
|
||||
|
||||
/* perform update */
|
||||
/* check if the entry already exists */
|
||||
if (pat_ref_find_elt(ref, key) == NULL)
|
||||
pat_ref_add(ref, key, NULL, NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case HTTP_RES_ACT_SET_MAP: {
|
||||
struct pat_ref *ref;
|
||||
char *key, *value;
|
||||
struct chunk *trash_key, *trash_value;
|
||||
int len;
|
||||
|
||||
trash_key = get_trash_chunk();
|
||||
trash_value = get_trash_chunk();
|
||||
|
||||
/* collect reference */
|
||||
ref = pat_ref_lookup(rule->arg.map.ref);
|
||||
if (!ref)
|
||||
continue;
|
||||
|
||||
/* collect key */
|
||||
len = build_logline(s, trash_key->str, trash_key->size, &rule->arg.map.key);
|
||||
key = trash_key->str;
|
||||
key[len] = '\0';
|
||||
|
||||
/* collect value */
|
||||
len = build_logline(s, trash_value->str, trash_value->size, &rule->arg.map.value);
|
||||
value = trash_value->str;
|
||||
value[len] = '\0';
|
||||
|
||||
/* perform update */
|
||||
if (pat_ref_find_elt(ref, key) != NULL)
|
||||
/* update entry if it exists */
|
||||
pat_ref_set(ref, key, value, NULL);
|
||||
else
|
||||
/* insert a new entry */
|
||||
pat_ref_add(ref, key, value, NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8652,8 +8821,125 @@ struct http_req_rule *parse_http_req_cond(const char **args, const char *file, i
|
||||
redir->cond = NULL;
|
||||
cur_arg = 2;
|
||||
return rule;
|
||||
} else if (strncmp(args[0], "add-acl", 7) == 0) {
|
||||
/* http-request add-acl(<reference (acl name)>) <key pattern> */
|
||||
rule->action = HTTP_REQ_ACT_ADD_ACL;
|
||||
/*
|
||||
* '+ 8' for 'add-acl('
|
||||
* '- 9' for 'add-acl(' + trailing ')'
|
||||
*/
|
||||
rule->arg.map.ref = strndup(args[0] + 8, strlen(args[0]) - 9);
|
||||
|
||||
cur_arg = 1;
|
||||
|
||||
if (!*args[cur_arg] ||
|
||||
(*args[cur_arg+1] && strcmp(args[cur_arg+1], "if") != 0 && strcmp(args[cur_arg+1], "unless") != 0)) {
|
||||
Alert("parsing [%s:%d]: 'http-request %s' expects exactly 1 argument.\n",
|
||||
file, linenum, args[0]);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
LIST_INIT(&rule->arg.map.key);
|
||||
proxy->conf.args.ctx = ARGC_HRQ;
|
||||
parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
|
||||
(proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
|
||||
file, linenum);
|
||||
free(proxy->conf.lfs_file);
|
||||
proxy->conf.lfs_file = strdup(proxy->conf.args.file);
|
||||
proxy->conf.lfs_line = proxy->conf.args.line;
|
||||
cur_arg += 1;
|
||||
} else if (strncmp(args[0], "del-acl", 7) == 0) {
|
||||
/* http-request del-acl(<reference (acl name)>) <key pattern> */
|
||||
rule->action = HTTP_REQ_ACT_DEL_ACL;
|
||||
/*
|
||||
* '+ 8' for 'del-acl('
|
||||
* '- 9' for 'del-acl(' + trailing ')'
|
||||
*/
|
||||
rule->arg.map.ref = strndup(args[0] + 8, strlen(args[0]) - 9);
|
||||
|
||||
cur_arg = 1;
|
||||
|
||||
if (!*args[cur_arg] ||
|
||||
(*args[cur_arg+1] && strcmp(args[cur_arg+1], "if") != 0 && strcmp(args[cur_arg+1], "unless") != 0)) {
|
||||
Alert("parsing [%s:%d]: 'http-request %s' expects exactly 1 argument.\n",
|
||||
file, linenum, args[0]);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
LIST_INIT(&rule->arg.map.key);
|
||||
proxy->conf.args.ctx = ARGC_HRQ;
|
||||
parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
|
||||
(proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
|
||||
file, linenum);
|
||||
free(proxy->conf.lfs_file);
|
||||
proxy->conf.lfs_file = strdup(proxy->conf.args.file);
|
||||
proxy->conf.lfs_line = proxy->conf.args.line;
|
||||
cur_arg += 1;
|
||||
} else if (strncmp(args[0], "del-map", 7) == 0) {
|
||||
/* http-request del-map(<reference (map name)>) <key pattern> */
|
||||
rule->action = HTTP_REQ_ACT_DEL_MAP;
|
||||
/*
|
||||
* '+ 8' for 'del-map('
|
||||
* '- 9' for 'del-map(' + trailing ')'
|
||||
*/
|
||||
rule->arg.map.ref = strndup(args[0] + 8, strlen(args[0]) - 9);
|
||||
|
||||
cur_arg = 1;
|
||||
|
||||
if (!*args[cur_arg] ||
|
||||
(*args[cur_arg+1] && strcmp(args[cur_arg+1], "if") != 0 && strcmp(args[cur_arg+1], "unless") != 0)) {
|
||||
Alert("parsing [%s:%d]: 'http-request %s' expects exactly 1 argument.\n",
|
||||
file, linenum, args[0]);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
LIST_INIT(&rule->arg.map.key);
|
||||
proxy->conf.args.ctx = ARGC_HRQ;
|
||||
parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
|
||||
(proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
|
||||
file, linenum);
|
||||
free(proxy->conf.lfs_file);
|
||||
proxy->conf.lfs_file = strdup(proxy->conf.args.file);
|
||||
proxy->conf.lfs_line = proxy->conf.args.line;
|
||||
cur_arg += 1;
|
||||
} else if (strncmp(args[0], "set-map", 7) == 0) {
|
||||
/* http-request set-map(<reference (map name)>) <key pattern> <value pattern> */
|
||||
rule->action = HTTP_REQ_ACT_SET_MAP;
|
||||
/*
|
||||
* '+ 8' for 'set-map('
|
||||
* '- 9' for 'set-map(' + trailing ')'
|
||||
*/
|
||||
rule->arg.map.ref = strndup(args[0] + 8, strlen(args[0]) - 9);
|
||||
|
||||
cur_arg = 1;
|
||||
|
||||
if (!*args[cur_arg] || !*args[cur_arg+1] ||
|
||||
(*args[cur_arg+2] && strcmp(args[cur_arg+2], "if") != 0 && strcmp(args[cur_arg+2], "unless") != 0)) {
|
||||
Alert("parsing [%s:%d]: 'http-request %s' expects exactly 2 arguments.\n",
|
||||
file, linenum, args[0]);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
LIST_INIT(&rule->arg.map.key);
|
||||
LIST_INIT(&rule->arg.map.value);
|
||||
proxy->conf.args.ctx = ARGC_HRQ;
|
||||
|
||||
/* key pattern */
|
||||
parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
|
||||
(proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
|
||||
file, linenum);
|
||||
|
||||
/* value pattern */
|
||||
parse_logformat_string(args[cur_arg + 1], proxy, &rule->arg.map.value, LOG_OPT_HTTP,
|
||||
(proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
|
||||
file, linenum);
|
||||
free(proxy->conf.lfs_file);
|
||||
proxy->conf.lfs_file = strdup(proxy->conf.args.file);
|
||||
proxy->conf.lfs_line = proxy->conf.args.line;
|
||||
|
||||
cur_arg += 2;
|
||||
} else {
|
||||
Alert("parsing [%s:%d]: 'http-request' expects 'allow', 'deny', 'auth', 'redirect', 'tarpit', 'add-header', 'set-header', 'set-nice', 'set-tos', 'set-mark', 'set-log-level', but got '%s'%s.\n",
|
||||
Alert("parsing [%s:%d]: 'http-request' expects 'allow', 'deny', 'auth', 'redirect', 'tarpit', 'add-header', 'set-header', 'set-nice', 'set-tos', 'set-mark', 'set-log-level', 'add-acl', 'del-acl', 'del-map', 'set-map', but got '%s'%s.\n",
|
||||
file, linenum, args[0], *args[0] ? "" : " (missing argument)");
|
||||
goto out_err;
|
||||
}
|
||||
@ -8824,8 +9110,128 @@ struct http_res_rule *parse_http_res_cond(const char **args, const char *file, i
|
||||
proxy->conf.lfs_file = strdup(proxy->conf.args.file);
|
||||
proxy->conf.lfs_line = proxy->conf.args.line;
|
||||
cur_arg += 1;
|
||||
} else if (strncmp(args[0], "add-acl", 7) == 0) {
|
||||
/* http-request add-acl(<reference (acl name)>) <key pattern> */
|
||||
rule->action = HTTP_RES_ACT_ADD_ACL;
|
||||
/*
|
||||
* '+ 8' for 'add-acl('
|
||||
* '- 9' for 'add-acl(' + trailing ')'
|
||||
*/
|
||||
rule->arg.map.ref = strndup(args[0] + 8, strlen(args[0]) - 9);
|
||||
|
||||
cur_arg = 1;
|
||||
|
||||
if (!*args[cur_arg] ||
|
||||
(*args[cur_arg+1] && strcmp(args[cur_arg+1], "if") != 0 && strcmp(args[cur_arg+1], "unless") != 0)) {
|
||||
Alert("parsing [%s:%d]: 'http-response %s' expects exactly 1 argument.\n",
|
||||
file, linenum, args[0]);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
LIST_INIT(&rule->arg.map.key);
|
||||
proxy->conf.args.ctx = ARGC_HRS;
|
||||
parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
|
||||
(proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
|
||||
file, linenum);
|
||||
free(proxy->conf.lfs_file);
|
||||
proxy->conf.lfs_file = strdup(proxy->conf.args.file);
|
||||
proxy->conf.lfs_line = proxy->conf.args.line;
|
||||
|
||||
cur_arg += 1;
|
||||
} else if (strncmp(args[0], "del-acl", 7) == 0) {
|
||||
/* http-response del-acl(<reference (acl name)>) <key pattern> */
|
||||
rule->action = HTTP_RES_ACT_DEL_ACL;
|
||||
/*
|
||||
* '+ 8' for 'del-acl('
|
||||
* '- 9' for 'del-acl(' + trailing ')'
|
||||
*/
|
||||
rule->arg.map.ref = strndup(args[0] + 8, strlen(args[0]) - 9);
|
||||
|
||||
cur_arg = 1;
|
||||
|
||||
if (!*args[cur_arg] ||
|
||||
(*args[cur_arg+1] && strcmp(args[cur_arg+1], "if") != 0 && strcmp(args[cur_arg+1], "unless") != 0)) {
|
||||
Alert("parsing [%s:%d]: 'http-response %s' expects exactly 1 argument.\n",
|
||||
file, linenum, args[0]);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
LIST_INIT(&rule->arg.map.key);
|
||||
proxy->conf.args.ctx = ARGC_HRS;
|
||||
parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
|
||||
(proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
|
||||
file, linenum);
|
||||
free(proxy->conf.lfs_file);
|
||||
proxy->conf.lfs_file = strdup(proxy->conf.args.file);
|
||||
proxy->conf.lfs_line = proxy->conf.args.line;
|
||||
cur_arg += 1;
|
||||
} else if (strncmp(args[0], "del-map", 7) == 0) {
|
||||
/* http-response del-map(<reference (map name)>) <key pattern> */
|
||||
rule->action = HTTP_RES_ACT_DEL_MAP;
|
||||
/*
|
||||
* '+ 8' for 'del-map('
|
||||
* '- 9' for 'del-map(' + trailing ')'
|
||||
*/
|
||||
rule->arg.map.ref = strndup(args[0] + 8, strlen(args[0]) - 9);
|
||||
|
||||
cur_arg = 1;
|
||||
|
||||
if (!*args[cur_arg] ||
|
||||
(*args[cur_arg+1] && strcmp(args[cur_arg+1], "if") != 0 && strcmp(args[cur_arg+1], "unless") != 0)) {
|
||||
Alert("parsing [%s:%d]: 'http-response %s' expects exactly 1 argument.\n",
|
||||
file, linenum, args[0]);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
LIST_INIT(&rule->arg.map.key);
|
||||
proxy->conf.args.ctx = ARGC_HRS;
|
||||
parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
|
||||
(proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
|
||||
file, linenum);
|
||||
free(proxy->conf.lfs_file);
|
||||
proxy->conf.lfs_file = strdup(proxy->conf.args.file);
|
||||
proxy->conf.lfs_line = proxy->conf.args.line;
|
||||
cur_arg += 1;
|
||||
} else if (strncmp(args[0], "set-map", 7) == 0) {
|
||||
/* http-response set-map(<reference (map name)>) <key pattern> <value pattern> */
|
||||
rule->action = HTTP_RES_ACT_SET_MAP;
|
||||
/*
|
||||
* '+ 8' for 'set-map('
|
||||
* '- 9' for 'set-map(' + trailing ')'
|
||||
*/
|
||||
rule->arg.map.ref = strndup(args[0] + 8, strlen(args[0]) - 9);
|
||||
|
||||
cur_arg = 1;
|
||||
|
||||
if (!*args[cur_arg] || !*args[cur_arg+1] ||
|
||||
(*args[cur_arg+2] && strcmp(args[cur_arg+2], "if") != 0 && strcmp(args[cur_arg+2], "unless") != 0)) {
|
||||
Alert("parsing [%s:%d]: 'http-response %s' expects exactly 2 arguments.\n",
|
||||
file, linenum, args[0]);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
LIST_INIT(&rule->arg.map.key);
|
||||
LIST_INIT(&rule->arg.map.value);
|
||||
|
||||
proxy->conf.args.ctx = ARGC_HRS;
|
||||
|
||||
/* key pattern */
|
||||
parse_logformat_string(args[cur_arg], proxy, &rule->arg.map.key, LOG_OPT_HTTP,
|
||||
(proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
|
||||
file, linenum);
|
||||
|
||||
/* value pattern */
|
||||
parse_logformat_string(args[cur_arg + 1], proxy, &rule->arg.map.value, LOG_OPT_HTTP,
|
||||
(proxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
|
||||
file, linenum);
|
||||
|
||||
free(proxy->conf.lfs_file);
|
||||
proxy->conf.lfs_file = strdup(proxy->conf.args.file);
|
||||
proxy->conf.lfs_line = proxy->conf.args.line;
|
||||
|
||||
cur_arg += 2;
|
||||
} else {
|
||||
Alert("parsing [%s:%d]: 'http-response' expects 'allow', 'deny', 'redirect', 'add-header', 'set-header', 'set-nice', 'set-tos', 'set-mark', 'set-log-level', but got '%s'%s.\n",
|
||||
Alert("parsing [%s:%d]: 'http-response' expects 'allow', 'deny', 'redirect', 'add-header', 'del-header', 'set-header', 'set-nice', 'set-tos', 'set-mark', 'set-log-level', 'del-acl', 'add-acl', 'del-map', 'set-map', but got '%s'%s.\n",
|
||||
file, linenum, args[0], *args[0] ? "" : " (missing argument)");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user