On Tue, Feb 21, 2017 at 5:43 PM, Andrei Ivanov <andrei.iva...@gmail.com> wrote:
> On Tue, Feb 21, 2017 at 6:32 PM, Yann Ylavic <ylavic....@gmail.com> wrote:
>>
>> On Tue, Feb 21, 2017 at 4:50 PM, Andrei Ivanov <andrei.iva...@gmail.com>
>> 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-unsubscr...@httpd.apache.org
For additional commands, e-mail: users-h...@httpd.apache.org

Reply via email to