On Tue, Feb 21, 2017 at 5:43 PM, Andrei Ivanov <[email protected]> wrote:
> On Tue, Feb 21, 2017 at 6:32 PM, Yann Ylavic <[email protected]> wrote:
>>
>> On Tue, Feb 21, 2017 at 4:50 PM, Andrei Ivanov <[email protected]>
>> wrote:
>> >>>
>> >>> Header set Client-SAN "%{PeerExtList('2.5.29.17')}s"
>>
>> The syntax may be rather:
>>
>> Header set Client-SAN "expr=%{PeerExtList:2.5.29.17}"
>>
>> Does it work better?
>
>
> Uf, no :-(
I've got it to work in (in 2.4.25), with a patch (attached), and for
me it outputs:
Client-SAN: DNS:www1.domain.tld, DNS:www2.domain.tld,
DNS:www3.domain.tld, IP Address:192.168.150.80, IP
Address:192.168.150.145, IP Address:172.25.25.100
So I guess something like:
Require expr "('IP Address:' . %{REMOTE_ADDR}) -in PeerExtList('2.5.29.17')"
should work (at least with 2.4.5).
Regards,
Yann.
Index: server/util_expr_eval.c
===================================================================
--- server/util_expr_eval.c (revision 1783852)
+++ server/util_expr_eval.c (working copy)
@@ -50,6 +50,9 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(int, expr_lookup, (ap_
static const char *ap_expr_eval_string_func(ap_expr_eval_ctx_t *ctx,
const ap_expr_t *info,
const ap_expr_t *args);
+static apr_array_header_t *ap_expr_eval_list_func(ap_expr_eval_ctx_t *ctx,
+ const ap_expr_t *info,
+ const ap_expr_t *args);
static const char *ap_expr_eval_re_backref(ap_expr_eval_ctx_t *ctx,
unsigned int n);
static const char *ap_expr_eval_var(ap_expr_eval_ctx_t *ctx,
@@ -80,6 +83,8 @@ static int inc_rec(ap_expr_eval_ctx_t *ctx)
return 1;
}
+#define AP_EXPR_MAX_LIST_STRINGS 500
+
static const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
const ap_expr_t *node)
{
@@ -161,6 +166,35 @@ static const char *ap_expr_eval_word(ap_expr_eval_
result = ap_expr_eval_string_func(ctx, info, args);
break;
}
+ case op_ListFuncCall: {
+ const ap_expr_t *info = node->node_arg1;
+ const ap_expr_t *args = node->node_arg2;
+ apr_array_header_t *array = ap_expr_eval_list_func(ctx, info, args);
+ if (array && array->nelts > 0) {
+ struct iovec *vec;
+ int n = array->nelts, i = 0;
+ /* sanity check */
+ if (n > AP_EXPR_MAX_LIST_STRINGS) {
+ n = AP_EXPR_MAX_LIST_STRINGS;
+ }
+ /* all entries (but last) separated by ", " */
+ n = (n * 2) - 1;
+ vec = apr_palloc(ctx->p, n * sizeof(struct iovec));
+ for (;;) {
+ const char *s = APR_ARRAY_IDX(array, i, const char *);
+ vec[i].iov_base = (void *)s;
+ vec[i].iov_len = strlen(s);
+ if (++i >= n) {
+ break;
+ }
+ vec[i].iov_base = (void *)", ";
+ vec[i].iov_len = 2;
+ ++i;
+ }
+ result = apr_pstrcatv(ctx->p, vec, n, NULL);
+ }
+ break;
+ }
case op_RegexBackref: {
const unsigned int *np = node->node_arg1;
result = ap_expr_eval_re_backref(ctx, *np);
@@ -213,6 +247,19 @@ static const char *ap_expr_eval_string_func(ap_exp
return (*func)(ctx, data, ap_expr_eval_word(ctx, arg));
}
+static apr_array_header_t *ap_expr_eval_list_func(ap_expr_eval_ctx_t *ctx,
+ const ap_expr_t *info,
+ const ap_expr_t *arg)
+{
+ ap_expr_list_func_t *func = (ap_expr_list_func_t *)info->node_arg1;
+ const void *data = info->node_arg2;
+
+ AP_DEBUG_ASSERT(info->node_op == op_ListFuncInfo);
+ AP_DEBUG_ASSERT(func != NULL);
+ AP_DEBUG_ASSERT(data != NULL);
+ return (*func)(ctx, data, ap_expr_eval_word(ctx, arg));
+}
+
static int intstrcmp(const char *s1, const char *s2)
{
apr_int64_t i1 = apr_atoi64(s1);
@@ -268,13 +315,8 @@ static int ap_expr_eval_comp(ap_expr_eval_ctx_t *c
}
else if (e2->node_op == op_ListFuncCall) {
const ap_expr_t *info = e2->node_arg1;
- const ap_expr_t *arg = e2->node_arg2;
- ap_expr_list_func_t *func = (ap_expr_list_func_t *)info->node_arg1;
- apr_array_header_t *haystack;
-
- AP_DEBUG_ASSERT(func != NULL);
- AP_DEBUG_ASSERT(info->node_op == op_ListFuncInfo);
- haystack = (*func)(ctx, info->node_arg2, ap_expr_eval_word(ctx, arg));
+ const ap_expr_t *args = e2->node_arg2;
+ apr_array_header_t *haystack = ap_expr_eval_list_func(ctx, info, args);
if (haystack == NULL) {
return 0;
}
@@ -474,8 +516,19 @@ ap_expr_t *ap_expr_str_func_make(const char *name,
ap_expr_parse_ctx_t *ctx)
{
ap_expr_t *info = ap_expr_info_make(AP_EXPR_FUNC_STRING, name, ctx, arg);
- if (!info)
- return NULL;
+ if (!info) {
+ /* We know how to make a string result from a list, so if no string
+ * function is found, try to find a list function.
+ */
+ const char *saved_error = ctx->error2;
+ ctx->error2 = NULL;
+ info = ap_expr_list_func_make(name, arg, ctx);
+ if (!info) {
+ /* Didn't work, restore previous error */
+ ctx->error2 = saved_error;
+ }
+ return info;
+ }
info->node_op = op_StringFuncInfo;
return ap_expr_make(op_StringFuncCall, info, arg, ctx);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]