On Tue, Feb 21, 2017 at 5:43 PM, Andrei Ivanov <andrei.ivanov@xxxxxxxxx> wrote: > On Tue, Feb 21, 2017 at 6:32 PM, Yann Ylavic <ylavic.dev@xxxxxxxxx> wrote: >> >> On Tue, Feb 21, 2017 at 4:50 PM, Andrei Ivanov <andrei.ivanov@xxxxxxxxx> >> 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: users-unsubscribe@xxxxxxxxxxxxxxxx For additional commands, e-mail: users-help@xxxxxxxxxxxxxxxx