MINOR: checks: add rbinary expect match type
The rbinary match works similarly to the rstring match type, however the
received data is rewritten as hex-string before the match operation is
done.
This allows using regexes on binary content even with the POSIX regex
engine.
[Cf: I slightly updated the patch. mem2hex function was removed and dump_binary
is used instead.]
diff --git a/doc/configuration.txt b/doc/configuration.txt
index df09280..09f4b66 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -9865,8 +9865,8 @@
the evaluation result is always conclusive.
<match> is a keyword indicating how to look for a specific pattern in the
- response. The keyword may be one of "string", "rstring" or
- binary.
+ response. The keyword may be one of "string", "rstring", "binary" or
+ "rbinary".
The keyword may be preceded by an exclamation mark ("!") to negate
the match. Spaces are allowed between the exclamation mark and the
keyword. See below for more details on the supported keywords.
@@ -9904,6 +9904,15 @@
this exact hexadecimal string.
Purpose is to match data on binary protocols.
+ rbinary <regex> : test a regular expression on the response buffer, like
+ "rstring". However, the response buffer is transformed
+ into its hexadecimal form, including NUL-bytes. This
+ allows using all regex engines to match any binary
+ content. The hexadecimal transformation takes twice the
+ size of the original response. As such, the expected
+ pattern should work on at-most half the response buffer
+ size.
+
It is important to note that the responses will be limited to a certain size
defined by the global "tune.chksize" option, which defaults to 16384 bytes.
Thus, too large responses may not contain the mandatory pattern when using
diff --git a/include/types/checks.h b/include/types/checks.h
index 36b22fe..d798ae2 100644
--- a/include/types/checks.h
+++ b/include/types/checks.h
@@ -215,6 +215,7 @@
TCPCHK_EXPECT_UNDEF = 0, /* Match is not used. */
TCPCHK_EXPECT_STRING, /* Matches a string. */
TCPCHK_EXPECT_REGEX, /* Matches a regular pattern. */
+ TCPCHK_EXPECT_REGEX_BINARY, /* Matches a regular pattern on a hex-encoded text. */
TCPCHK_EXPECT_BINARY, /* Matches a binary sequence. */
};
diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c
index 6c1d986..13ce19c 100644
--- a/src/cfgparse-listen.c
+++ b/src/cfgparse-listen.c
@@ -3282,7 +3282,8 @@
expect->string = strdup(args[cur_arg + 1]);
expect->length = strlen(expect->string);
}
- else if (strcmp(ptr_arg, "rstring") == 0) {
+ else if (strcmp(ptr_arg, "rstring") == 0 ||
+ strcmp(ptr_arg, "rbinary") == 0) {
if (!*(args[cur_arg + 1])) {
ha_alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
file, linenum, args[0], args[1], ptr_arg);
@@ -3290,8 +3291,7 @@
goto out;
}
- expect->type = TCPCHK_EXPECT_REGEX;
-
+ expect->type = ((strcmp(ptr_arg, "rbinary") == 0) ? TCPCHK_EXPECT_REGEX_BINARY : TCPCHK_EXPECT_REGEX);
error = NULL;
if (!(expect->regex = regex_comp(args[cur_arg + 1], 1, 1, &error))) {
ha_alert("parsing [%s:%d] : '%s %s %s' : regular expression '%s': %s.\n",
@@ -3302,7 +3302,7 @@
}
}
else {
- ha_alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
+ ha_alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', 'rbinary', found '%s'.\n",
file, linenum, args[0], args[1], ptr_arg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
diff --git a/src/checks.c b/src/checks.c
index 54055cb..5e77ca6 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -652,6 +652,9 @@
case TCPCHK_EXPECT_REGEX:
chunk_appendf(chk, " (expect regex)");
break;
+ case TCPCHK_EXPECT_REGEX_BINARY:
+ chunk_appendf(chk, " (expect binary regex)");
+ break;
case TCPCHK_EXPECT_UNDEF:
chunk_appendf(chk, " (undefined expect!)");
break;
@@ -2775,7 +2778,6 @@
*/
static int tcpcheck_main(struct check *check)
{
- char *comment;
struct tcpcheck_rule *next;
int done = 0, ret = 0, step = 0;
struct conn_stream *cs = check->cs;
@@ -2784,6 +2786,7 @@
struct proxy *proxy = check->proxy;
struct task *t = check->task;
struct list *head = check->tcpcheck_rules;
+ char *comment;
int retcode = 0;
/* here, we know that the check is complete or that it failed */
@@ -3064,8 +3067,7 @@
check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
/* bypass all comment rules */
- while (&check->current_step->list != head &&
- check->current_step->action == TCPCHK_ACT_COMMENT)
+ while (&check->current_step->list != head && check->current_step->action == TCPCHK_ACT_COMMENT)
check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
if (&check->current_step->list == head)
@@ -3189,6 +3191,12 @@
case TCPCHK_EXPECT_REGEX:
match = regex_exec2(expect->regex, b_head(&check->bi), MIN(b_data(&check->bi), b_size(&check->bi)-1));
break;
+
+ case TCPCHK_EXPECT_REGEX_BINARY:
+ chunk_reset(&trash);
+ dump_binary(&trash, b_head(&check->bi), b_data(&check->bi));
+ match = regex_exec2(expect->regex, b_head(&trash), MIN(b_data(&trash), b_size(&trash)-1));
+ break;
case TCPCHK_EXPECT_UNDEF:
/* Should never happen. */
retcode = -1;
@@ -3239,6 +3247,10 @@
chunk_printf(&trash, "TCPCHK %s (regex) at step %d",
diag, step);
break;
+ case TCPCHK_EXPECT_REGEX_BINARY:
+ chunk_printf(&trash, "TCPCHK %s (binary regex) at step %d",
+ diag, step);
+ break;
case TCPCHK_EXPECT_UNDEF:
/* Should never happen. */
retcode = -1;
@@ -3356,6 +3368,7 @@
free(rule->expect.string);
break;
case TCPCHK_EXPECT_REGEX:
+ case TCPCHK_EXPECT_REGEX_BINARY:
regex_free(rule->expect.regex);
break;
case TCPCHK_EXPECT_UNDEF: