mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-24 23:31:40 +02:00
MEDIUM: pattern: add an argument validation callback to pattern descriptors
This is used to validate that arguments are coherent. For instance, payload_lv expects that the last arg (if any) is not more negative than the sum of the first two. The error is reported if any.
This commit is contained in:
parent
9fcb984b17
commit
21d68a6895
@ -65,6 +65,8 @@ struct pattern_conv {
|
||||
int (*process)(const struct arg *arg_p,
|
||||
union pattern_data *data); /* process function */
|
||||
unsigned int arg_mask; /* arguments (ARG*()) */
|
||||
int (*val_args)(struct arg *arg_p,
|
||||
char **err_msg); /* argument validation function */
|
||||
unsigned int in_type; /* input needed pattern type */
|
||||
unsigned int out_type; /* output pattern type */
|
||||
};
|
||||
@ -85,6 +87,8 @@ struct pattern_fetch {
|
||||
int dir, const struct arg *arg_p,
|
||||
union pattern_data *data); /* fetch processing function */
|
||||
unsigned int arg_mask; /* arguments (ARG*()) */
|
||||
int (*val_args)(struct arg *arg_p,
|
||||
char **err_msg); /* argument validation function */
|
||||
unsigned long out_type; /* output pattern type */
|
||||
int dir; /* usable directions */
|
||||
};
|
||||
|
@ -316,6 +316,8 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx, char *err, int err
|
||||
expr->fetch = fetch;
|
||||
|
||||
if (end != endw) {
|
||||
char *err_msg;
|
||||
|
||||
if (!fetch->arg_mask) {
|
||||
p = my_strndup(str[*idx], endw - str[*idx]);
|
||||
if (p) {
|
||||
@ -333,6 +335,16 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx, char *err, int err
|
||||
}
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
if (fetch->val_args && !fetch->val_args(expr->arg_p, &err_msg)) {
|
||||
p = my_strndup(str[*idx], endw - str[*idx]);
|
||||
if (p) {
|
||||
snprintf(err, err_size, "invalid args in fetch method '%s' : %s.", p, err_msg);
|
||||
free(p);
|
||||
}
|
||||
free(err_msg);
|
||||
goto out_error;
|
||||
}
|
||||
}
|
||||
else if (fetch->arg_mask) {
|
||||
p = my_strndup(str[*idx], endw - str[*idx]);
|
||||
@ -393,6 +405,8 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx, char *err, int err
|
||||
conv_expr->conv = conv;
|
||||
|
||||
if (end != endw) {
|
||||
char *err_msg;
|
||||
|
||||
if (!conv->arg_mask) {
|
||||
p = my_strndup(str[*idx], endw - str[*idx]);
|
||||
|
||||
@ -411,6 +425,16 @@ struct pattern_expr *pattern_parse_expr(char **str, int *idx, char *err, int err
|
||||
}
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
if (conv->val_args && !conv->val_args(conv_expr->arg_p, &err_msg)) {
|
||||
p = my_strndup(str[*idx], endw - str[*idx]);
|
||||
if (p) {
|
||||
snprintf(err, err_size, "invalid args in conv method '%s' : %s.", p, err_msg);
|
||||
free(p);
|
||||
}
|
||||
free(err_msg);
|
||||
goto out_error;
|
||||
}
|
||||
}
|
||||
else if (conv->arg_mask) {
|
||||
p = my_strndup(str[*idx], endw - str[*idx]);
|
||||
@ -505,9 +529,9 @@ static int pattern_conv_ipmask(const struct arg *arg_p, union pattern_data *data
|
||||
|
||||
/* Note: must not be declared <const> as its list will be overwritten */
|
||||
static struct pattern_conv_kw_list pattern_conv_kws = {{ },{
|
||||
{ "upper", pattern_conv_str2upper, 0, PATTERN_TYPE_STRING, PATTERN_TYPE_STRING },
|
||||
{ "lower", pattern_conv_str2lower, 0, PATTERN_TYPE_STRING, PATTERN_TYPE_STRING },
|
||||
{ "ipmask", pattern_conv_ipmask, ARG1(1,MSK4), PATTERN_TYPE_IP, PATTERN_TYPE_IP },
|
||||
{ "upper", pattern_conv_str2upper, 0, NULL, PATTERN_TYPE_STRING, PATTERN_TYPE_STRING },
|
||||
{ "lower", pattern_conv_str2lower, 0, NULL, PATTERN_TYPE_STRING, PATTERN_TYPE_STRING },
|
||||
{ "ipmask", pattern_conv_ipmask, ARG1(1,MSK4), NULL, PATTERN_TYPE_IP, PATTERN_TYPE_IP },
|
||||
{ NULL, NULL, 0, 0, 0 },
|
||||
}};
|
||||
|
||||
|
@ -8533,16 +8533,15 @@ pattern_fetch_set_cookie(struct proxy *px, struct session *l4, void *l7, int dir
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* All supported keywords must be declared here. */
|
||||
/************************************************************************/
|
||||
/* Note: must not be declared <const> as its list will be overwritten */
|
||||
static struct pattern_fetch_kw_list pattern_fetch_keywords = {{ },{
|
||||
{ "hdr", pattern_fetch_hdr, ARG1(1,STR), PATTERN_TYPE_STRING, PATTERN_FETCH_REQ },
|
||||
{ "url_param", pattern_fetch_url_param, ARG1(1,STR), PATTERN_TYPE_STRING, PATTERN_FETCH_REQ },
|
||||
{ "cookie", pattern_fetch_cookie, ARG1(1,STR), PATTERN_TYPE_STRING, PATTERN_FETCH_REQ },
|
||||
{ "set-cookie", pattern_fetch_set_cookie, ARG1(1,STR), PATTERN_TYPE_STRING, PATTERN_FETCH_RTR },
|
||||
{ "hdr", pattern_fetch_hdr, ARG1(1,STR), NULL, PATTERN_TYPE_STRING, PATTERN_FETCH_REQ },
|
||||
{ "url_param", pattern_fetch_url_param, ARG1(1,STR), NULL, PATTERN_TYPE_STRING, PATTERN_FETCH_REQ },
|
||||
{ "cookie", pattern_fetch_cookie, ARG1(1,STR), NULL, PATTERN_TYPE_STRING, PATTERN_FETCH_REQ },
|
||||
{ "set-cookie", pattern_fetch_set_cookie, ARG1(1,STR), NULL, PATTERN_TYPE_STRING, PATTERN_FETCH_RTR },
|
||||
{ NULL, NULL, 0, 0, 0 },
|
||||
}};
|
||||
|
||||
|
@ -1493,6 +1493,50 @@ pattern_fetch_rdp_cookie(struct proxy *px, struct session *l4, void *l7, int dir
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function is used to validate the arguments passed to a "payload" fetch
|
||||
* keyword. This keyword expects two positive integers, with the second one
|
||||
* being strictly positive. It is assumed that the types are already the correct
|
||||
* ones. Returns 0 on error, non-zero if OK. If <err_msg> is not NULL, it will be
|
||||
* filled with a pointer to an error message in case of error, that the caller
|
||||
* is responsible for freeing. The initial location must either be freeable or
|
||||
* NULL.
|
||||
*/
|
||||
static int val_payload(struct arg *arg, char **err_msg)
|
||||
{
|
||||
if (!arg[1].data.uint) {
|
||||
if (err_msg)
|
||||
memprintf(err_msg, "payload length must be > 0");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function is used to validate the arguments passed to a "payload_lv" fetch
|
||||
* keyword. This keyword allows two positive integers and an optional signed one,
|
||||
* with the second one being strictly positive and the third one being greater than
|
||||
* the opposite of the two others if negative. It is assumed that the types are
|
||||
* already the correct ones. Returns 0 on error, non-zero if OK. If <err_msg> is
|
||||
* not NULL, it will be filled with a pointer to an error message in case of
|
||||
* error, that the caller is responsible for freeing. The initial location must
|
||||
* either be freeable or NULL.
|
||||
*/
|
||||
static int val_payload_lv(struct arg *arg, char **err_msg)
|
||||
{
|
||||
if (!arg[1].data.uint) {
|
||||
if (err_msg)
|
||||
memprintf(err_msg, "payload length must be > 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (arg[2].type == ARGT_SINT &&
|
||||
(int)(arg[0].data.uint + arg[1].data.uint + arg[2].data.sint) < 0) {
|
||||
if (err_msg)
|
||||
memprintf(err_msg, "payload offset too negative");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct cfg_kw_list cfg_kws = {{ },{
|
||||
{ CFG_LISTEN, "tcp-request", tcp_parse_tcp_req },
|
||||
{ CFG_LISTEN, "tcp-response", tcp_parse_tcp_rep },
|
||||
@ -1512,14 +1556,14 @@ static struct acl_kw_list acl_kws = {{ },{
|
||||
|
||||
/* Note: must not be declared <const> as its list will be overwritten */
|
||||
static struct pattern_fetch_kw_list pattern_fetch_keywords = {{ },{
|
||||
{ "src", pattern_fetch_src, 0, PATTERN_TYPE_IP, PATTERN_FETCH_REQ },
|
||||
{ "src6", pattern_fetch_src6, 0, PATTERN_TYPE_IPV6, PATTERN_FETCH_REQ },
|
||||
{ "dst", pattern_fetch_dst, 0, PATTERN_TYPE_IP, PATTERN_FETCH_REQ },
|
||||
{ "dst6", pattern_fetch_dst6, 0, PATTERN_TYPE_IPV6, PATTERN_FETCH_REQ },
|
||||
{ "dst_port", pattern_fetch_dport, 0, PATTERN_TYPE_INTEGER, PATTERN_FETCH_REQ },
|
||||
{ "payload", pattern_fetch_payload, ARG2(2,UINT,UINT), PATTERN_TYPE_CONSTDATA, PATTERN_FETCH_REQ|PATTERN_FETCH_RTR },
|
||||
{ "payload_lv", pattern_fetch_payloadlv, ARG3(2,UINT,UINT,SINT), PATTERN_TYPE_CONSTDATA, PATTERN_FETCH_REQ|PATTERN_FETCH_RTR },
|
||||
{ "rdp_cookie", pattern_fetch_rdp_cookie, ARG1(1,STR), PATTERN_TYPE_CONSTSTRING, PATTERN_FETCH_REQ },
|
||||
{ "src", pattern_fetch_src, 0, NULL, PATTERN_TYPE_IP, PATTERN_FETCH_REQ },
|
||||
{ "src6", pattern_fetch_src6, 0, NULL, PATTERN_TYPE_IPV6, PATTERN_FETCH_REQ },
|
||||
{ "dst", pattern_fetch_dst, 0, NULL, PATTERN_TYPE_IP, PATTERN_FETCH_REQ },
|
||||
{ "dst6", pattern_fetch_dst6, 0, NULL, PATTERN_TYPE_IPV6, PATTERN_FETCH_REQ },
|
||||
{ "dst_port", pattern_fetch_dport, 0, NULL, PATTERN_TYPE_INTEGER, PATTERN_FETCH_REQ },
|
||||
{ "payload", pattern_fetch_payload, ARG2(2,UINT,UINT), val_payload, PATTERN_TYPE_CONSTDATA, PATTERN_FETCH_REQ|PATTERN_FETCH_RTR },
|
||||
{ "payload_lv", pattern_fetch_payloadlv, ARG3(2,UINT,UINT,SINT), val_payload_lv, PATTERN_TYPE_CONSTDATA, PATTERN_FETCH_REQ|PATTERN_FETCH_RTR },
|
||||
{ "rdp_cookie", pattern_fetch_rdp_cookie, ARG1(1,STR), NULL, PATTERN_TYPE_CONSTSTRING, PATTERN_FETCH_REQ },
|
||||
{ NULL, NULL, 0, 0, 0 },
|
||||
}};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user