[prev in list] [next in list] [prev in thread] [next in thread] 

List:       apache-cvs
Subject:    svn commit: r1128564 - in /httpd/httpd/trunk: CHANGES docs/manual/expr.xml
From:       sf () apache ! org
Date:       2011-05-28 7:01:48
Message-ID: 20110528070148.2B789238896F () eris ! apache ! org
[Download RAW message or body]

Author: sf
Date: Sat May 28 07:01:47 2011
New Revision: 1128564

URL: http://svn.apache.org/viewvc?rev=1128564&view=rev
Log:
Add some features to ap_expr for use by mod_include:
 * a restricted mode that does not allow to bypass request access restrictions
 * new variables DOCUMENT_URI (alias for REQUEST_URI), LAST_MODIFIED
 * -A as an alias for -U
 * an additional data entry in ap_expr_eval_ctx_t for use by the consumer
 * an extensible ap_expr_exec_ctx() API that allows to use that data entry

Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/docs/manual/expr.xml
    httpd/httpd/trunk/include/ap_expr.h
    httpd/httpd/trunk/include/ap_mmn.h
    httpd/httpd/trunk/server/util_expr_eval.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1128564&r1=1128563&r2=1128564&view=diff
 ==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Sat May 28 07:01:47 2011
@@ -2,6 +2,13 @@
 
 Changes with Apache 2.3.13
 
+  *) core: Add some features to ap_expr for use by mod_include: a restricted
+     mode that does not allow to bypass request access restrictions; new
+     variables DOCUMENT_URI (alias for REQUEST_URI), LAST_MODIFIED; -A as an
+     alias for -U; an additional data entry in ap_expr_eval_ctx_t for use by
+     the consumer; an extensible ap_expr_exec_ctx() API that allows to use that
+     data entry. [Stefan Fritsch]
+
   *) mod_include: Merge directory configs instead of one SSI* config directive
      causing all other per-directory SSI* config directives to be reset.
      [Stefan Fritsch]

Modified: httpd/httpd/trunk/docs/manual/expr.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/expr.xml?rev=1128564&r1=1128563&r2=1128564&view=diff
 ==============================================================================
--- httpd/httpd/trunk/docs/manual/expr.xml (original)
+++ httpd/httpd/trunk/docs/manual/expr.xml Sat May 28 07:01:47 2011
@@ -158,6 +158,8 @@ listfunction ::= listfuncname "<strong>(
         <td>The scheme part of the request's URI</td></tr>
     <tr><td><code>REQUEST_URI</code></td>
         <td>The URI of the request</td></tr>
+    <tr><td><code>DOCUMENT_URI</code></td>
+        <td>Same as REQUEST_URI</td></tr>
     <tr><td><code>REQUEST_FILENAME</code></td>
         <td>The full local filesystem path to the file or script matching the
             request, if this has already been determined by the server at the
@@ -166,6 +168,11 @@ listfunction ::= listfuncname "<strong>(
             <code>REQUEST_URI</code> </td></tr>
     <tr><td><code>SCRIPT_FILENAME</code></td>
         <td>Same as <code>REQUEST_FILENAME</code></td></tr>
+    <tr><td><code>LAST_MODIFIED</code></td>
+        <td>The date and time of last modification of the file in the format
+            <code>20101231235959</code>, if this has already been determined by
+            the server at the time <code>LAST_MODIFIED</code> is referenced.
+            </td></tr>
     <tr><td><code>SCRIPT_USER</code></td>
         <td>The user name of the owner of the script.</td></tr>
     <tr><td><code>SCRIPT_GROUP</code></td>
@@ -374,6 +381,8 @@ listfunction ::= listfuncname "<strong>(
             currently-configured access controls for that path. This uses an
             internal subrequest to do the check, so use it with care - it can
             impact your server's performance!</td></tr>
+    <tr><td><code>-A</code></td>
+        <td>Alias for <code>-U</code></td></tr>
     <tr><td><code>-n</code></td>
         <td>True if string is not empty</td></tr>
     <tr><td><code>-z</code></td>

Modified: httpd/httpd/trunk/include/ap_expr.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_expr.h?rev=1128564&r1=1128563&r2=1128564&view=diff
 ==============================================================================
--- httpd/httpd/trunk/include/ap_expr.h (original)
+++ httpd/httpd/trunk/include/ap_expr.h Sat May 28 07:01:47 2011
@@ -59,6 +59,11 @@ typedef struct {
 #define AP_EXPR_FLAGS_SSL_EXPR_COMPAT       1
 /** Don't add siginificant request headers to the Vary response header */
 #define AP_EXPR_FLAGS_DONT_VARY             2
+/** Don't allow functions/vars that bypass the current request's access
+ *  restrictions or would otherwise leak confidential information.
+ *  Used by e.g. mod_include.
+ */
+#define AP_EXPR_FLAGS_RESTRICTED            4
 
 
 /**
@@ -119,8 +124,20 @@ typedef struct {
      * interested in this information.
      */
     const char **vary_this;
+    /** Arbitrary context data provided by the caller for custom functions */
+    void *data;
 } ap_expr_eval_ctx_t;
 
+/**
+ * Evaluate a parse tree, full featured version
+ * @param ctx The evaluation context with all data filled in
+ * @return > 0 if expression evaluates to true, == 0 if false, < 0 on error
+ * @note *ctx->err will be set to NULL on success, or to an error message on
+ *       error
+ * @note request headers used during evaluation will be added to the Vary:
+ *       response header if ctx->vary_this is set.
+ */
+AP_DECLARE(int) ap_expr_exec_ctx(ap_expr_eval_ctx_t *ctx);
 
 /**
  * The parser can be extended with variable lookup, functions, and

Modified: httpd/httpd/trunk/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_mmn.h?rev=1128564&r1=1128563&r2=1128564&view=diff
 ==============================================================================
--- httpd/httpd/trunk/include/ap_mmn.h (original)
+++ httpd/httpd/trunk/include/ap_mmn.h Sat May 28 07:01:47 2011
@@ -323,6 +323,8 @@
  * 20110329.3 (2.3.12-dev) Add format field to ap_errorlog_info.
  * 20110329.4 (2.3.13-dev) bgrowth and max_balancers to proxy_server_conf.
  * 20110329.5 (2.3.13-dev) Add ap_regexec_len()
+ * 20110329.6 (2.3.13-dev) Add AP_EXPR_FLAGS_RESTRICTED, ap_expr_eval_ctx_t->data,
+ *                         ap_expr_exec_ctx()
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -330,7 +332,7 @@
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20110329
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 5                    /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 6                    /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a

Modified: httpd/httpd/trunk/server/util_expr_eval.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_expr_eval.c?rev=1128564&r1=1128563&r2=1128564&view=diff
 ==============================================================================
--- httpd/httpd/trunk/server/util_expr_eval.c (original)
+++ httpd/httpd/trunk/server/util_expr_eval.c Sat May 28 07:01:47 2011
@@ -384,7 +384,7 @@ static ap_expr_t *ap_expr_info_make(int 
     ap_expr_t *info = apr_palloc(ctx->pool, sizeof(ap_expr_t));
     ap_expr_lookup_parms parms;
     parms.type  = type;
-    parms.flags = 0;
+    parms.flags = ctx->flags;
     parms.pool  = ctx->pool;
     parms.ptemp = ctx->ptemp;
     parms.name  = name;
@@ -691,12 +691,47 @@ AP_DECLARE(int) ap_expr_exec(request_rec
     return ap_expr_exec_re(r, info, 0, NULL, NULL, err);
 }
 
+AP_DECLARE(int) ap_expr_exec_ctx(ap_expr_eval_ctx_t *ctx)
+{
+    int rc;
+
+    AP_DEBUG_ASSERT(ctx->p != NULL);
+    /* XXX: allow r, c == NULL */
+    AP_DEBUG_ASSERT(ctx->r != NULL);
+    AP_DEBUG_ASSERT(ctx->c != NULL);
+    AP_DEBUG_ASSERT(ctx->s != NULL);
+    AP_DEBUG_ASSERT(ctx->err != NULL);
+    AP_DEBUG_ASSERT(ctx->info != NULL);
+    if (ctx->re_pmatch) {
+        AP_DEBUG_ASSERT(ctx->re_source != NULL);
+        AP_DEBUG_ASSERT(ctx->re_nmatch > 0);
+    }
+
+    *ctx->err = NULL;
+    rc = ap_expr_eval(ctx, ctx->info->root_node);
+    if (*ctx->err != NULL) {
+        ap_log_rerror(LOG_MARK(ctx->info), APLOG_ERR, 0, ctx->r,
+                      "Evaluation of expression from %s:%d failed: %s",
+                      ctx->info->filename, ctx->info->line_number, *ctx->err);
+        return -1;
+    } else {
+        rc = rc ? 1 : 0;
+        ap_log_rerror(LOG_MARK(ctx->info), APLOG_TRACE4, 0, ctx->r,
+                      "Evaluation of expression from %s:%d gave: %d",
+                      ctx->info->filename, ctx->info->line_number, rc);
+
+        if (ctx->vary_this)
+            apr_table_merge(ctx->r->headers_out, "Vary", *ctx->vary_this);
+
+        return rc;
+    }
+}
+
 AP_DECLARE(int) ap_expr_exec_re(request_rec *r, const ap_expr_info_t *info,
                                 apr_size_t nmatch, ap_regmatch_t *pmatch,
                                 const char **source, const char **err)
 {
     ap_expr_eval_ctx_t ctx;
-    int rc;
     int dont_vary = (info->flags & AP_EXPR_FLAGS_DONT_VARY);
     const char *tmp_source = NULL, *vary_this = NULL;
     ap_regmatch_t tmp_pmatch[10];
@@ -711,35 +746,15 @@ AP_DECLARE(int) ap_expr_exec_re(request_
     ctx.re_pmatch = pmatch;
     ctx.re_source = source;
     ctx.vary_this = dont_vary ? NULL : &vary_this;
+    ctx.data = NULL;
 
     if (!pmatch) {
         ctx.re_nmatch = 10;
         ctx.re_pmatch = tmp_pmatch;
         ctx.re_source = &tmp_source;
     }
-    else {
-        AP_DEBUG_ASSERT(source != NULL);
-        AP_DEBUG_ASSERT(nmatch > 0);
-    }
-
-    *err = NULL;
-    rc = ap_expr_eval(&ctx, info->root_node);
-    if (*err != NULL) {
-        ap_log_rerror(LOG_MARK(info), APLOG_ERR, 0, r,
-                      "Evaluation of expression from %s:%d failed: %s",
-                      info->filename, info->line_number, *err);
-        return -1;
-    } else {
-        rc = rc ? 1 : 0;
-        ap_log_rerror(LOG_MARK(info), APLOG_TRACE4, 0, r,
-                      "Evaluation of expression from %s:%d gave: %d",
-                      info->filename, info->line_number, rc);
-
-        if (vary_this)
-            apr_table_merge(r->headers_out, "Vary", vary_this);
 
-        return rc;
-    }
+    return ap_expr_exec_ctx(&ctx);
 }
 
 static void add_vary(ap_expr_eval_ctx_t *ctx, const char *name)
@@ -911,12 +926,12 @@ static int op_file_min(ap_expr_eval_ctx_
     apr_finfo_t sb;
     const char *name = (const char *)data;
     if (apr_stat(&sb, arg, APR_FINFO_MIN, ctx->p) != APR_SUCCESS)
-        return 0;
+        return FALSE;
     switch (name[0]) {
     case 'd':
         return (sb.filetype == APR_DIR);
     case 'e':
-        return 1;
+        return TRUE;
     case 'f':
         return (sb.filetype == APR_REG);
     case 's':
@@ -924,7 +939,7 @@ static int op_file_min(ap_expr_eval_ctx_
     default:
         ap_assert(0);
     }
-    return 0;
+    return FALSE;
 }
 
 static int op_file_link(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
@@ -933,10 +948,10 @@ static int op_file_link(ap_expr_eval_ctx
 #if !defined(OS2)
     if (apr_stat(&sb, arg, APR_FINFO_MIN | APR_FINFO_LINK, ctx->p) == APR_SUCCESS
         && sb.filetype == APR_LNK) {
-        return 1;
+        return TRUE;
     }
 #endif
-    return 0;
+    return FALSE;
 }
 
 static int op_file_xbit(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
@@ -944,24 +959,24 @@ static int op_file_xbit(ap_expr_eval_ctx
     apr_finfo_t sb;
     if (apr_stat(&sb, arg, APR_FINFO_PROT| APR_FINFO_LINK, ctx->p) == APR_SUCCESS
         && (sb.protection & (APR_UEXECUTE | APR_GEXECUTE | APR_WEXECUTE))) {
-        return 1;
+        return TRUE;
     }
-    return 0;
+    return FALSE;
 }
 
 static int op_url_subr(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
 {
-    int rc = 0;
+    int rc = FALSE;
     request_rec  *rsub, *r = ctx->r;
     if (!r)
-        return 0;
+        return FALSE;
     /* avoid some infinite recursions */
     if (r->main && r->main->uri && r->uri && strcmp(r->main->uri, r->uri) == 0)
-        return 0;
+        return FALSE;
 
     rsub = ap_sub_req_lookup_uri(arg, r, NULL);
     if (rsub->status < 400) {
-            rc = 1;
+            rc = TRUE;
     }
     ap_log_rerror(LOG_MARK(ctx->info), APLOG_TRACE5, 0, r,
                   "Subrequest for -U %s at %s:%d gave status: %d",
@@ -973,16 +988,16 @@ static int op_url_subr(ap_expr_eval_ctx_
 
 static int op_file_subr(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
 {
-    int rc = 0;
+    int rc = FALSE;
     apr_finfo_t sb;
     request_rec *rsub, *r = ctx->r;
     if (!r)
-        return 0;
+        return FALSE;
     rsub = ap_sub_req_lookup_file(arg, r, NULL);
     if (rsub->status < 300 &&
         /* double-check that file exists since default result is 200 */
         apr_stat(&sb, rsub->filename, APR_FINFO_MIN, ctx->p) == APR_SUCCESS) {
-        rc = 1;
+        rc = TRUE;
     }
     ap_log_rerror(LOG_MARK(ctx->info), APLOG_TRACE5, 0, r,
                   "Subrequest for -F %s at %s:%d gave status: %d",
@@ -1064,6 +1079,8 @@ static const char *request_var_names[] =
     "REQUEST_LOG_ID",           /* 20 */
     "SCRIPT_USER",              /* 21 */
     "SCRIPT_GROUP",             /* 22 */
+    "DOCUMENT_URI",             /* 23 */
+    "LAST_MODIFIED",            /* 24 */
     NULL
 };
 
@@ -1132,6 +1149,17 @@ static const char *request_var_fn(ap_exp
                 apr_gid_name_get(&result, r->finfo.group, ctx->p);
             return result;
         }
+    case 23:
+        return r->uri;
+    case 24:
+        {
+            apr_time_exp_t tm;
+            apr_time_exp_lt(&tm, r->mtime);
+            return apr_psprintf(ctx->p, "%02d%02d%02d%02d%02d%02d%02d",
+                                (tm.tm_year / 100) + 19, (tm.tm_year % 100),
+                                tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min,
+                                tm.tm_sec);
+        }
     default:
         ap_assert(0);
         return NULL;
@@ -1326,6 +1354,7 @@ struct expr_provider_single {
     const void *func;
     const char *name;
     ap_expr_lookup_fn_t *arg_parsing_func;
+    int restricted;
 };
 
 struct expr_provider_multi {
@@ -1342,46 +1371,47 @@ static const struct expr_provider_multi 
 };
 
 static const struct expr_provider_single string_func_providers[] = {
-    { osenv_func,           "osenv",          NULL },
-    { env_func,             "env",            NULL },
-    { req_table_func,       "resp",           NULL },
-    { req_table_func,       "req",            NULL },
+    { osenv_func,           "osenv",          NULL, 0 },
+    { env_func,             "env",            NULL, 0 },
+    { req_table_func,       "resp",           NULL, 0 },
+    { req_table_func,       "req",            NULL, 0 },
     /* 'http' as alias for 'req' for compatibility with ssl_expr */
-    { req_table_func,       "http",           NULL },
-    { req_table_func,       "note",           NULL },
-    { req_table_func,       "reqenv",         NULL },
-    { tolower_func,         "tolower",        NULL },
-    { toupper_func,         "toupper",        NULL },
-    { escape_func,          "escape",         NULL },
-    { unescape_func,        "unescape",       NULL },
-    { file_func,            "file",           NULL },
-    { filesize_func,        "filesize",       NULL },
+    { req_table_func,       "http",           NULL, 0 },
+    { req_table_func,       "note",           NULL, 0 },
+    { req_table_func,       "reqenv",         NULL, 0 },
+    { tolower_func,         "tolower",        NULL, 0 },
+    { toupper_func,         "toupper",        NULL, 0 },
+    { escape_func,          "escape",         NULL, 0 },
+    { unescape_func,        "unescape",       NULL, 0 },
+    { file_func,            "file",           NULL, 1 },
+    { filesize_func,        "filesize",       NULL, 1 },
     { NULL, NULL, NULL}
 };
 /* XXX: base64 encode/decode ? */
 
 static const struct expr_provider_single unary_op_providers[] = {
-    { op_nz,        "n", NULL },
-    { op_nz,        "z", NULL },
-    { op_R,         "R", subnet_parse_arg },
-    { op_T,         "T", NULL },
-    { op_file_min,  "d", NULL },
-    { op_file_min,  "e", NULL },
-    { op_file_min,  "f", NULL },
-    { op_file_min,  "s", NULL },
-    { op_file_link, "L", NULL },
-    { op_file_link, "h", NULL },
-    { op_file_xbit, "x", NULL },
-    { op_file_subr, "F", NULL },
-    { op_url_subr,  "U", NULL },
+    { op_nz,        "n", NULL,             0 },
+    { op_nz,        "z", NULL,             0 },
+    { op_R,         "R", subnet_parse_arg, 0 },
+    { op_T,         "T", NULL,             0 },
+    { op_file_min,  "d", NULL,             1 },
+    { op_file_min,  "e", NULL,             1 },
+    { op_file_min,  "f", NULL,             1 },
+    { op_file_min,  "s", NULL,             1 },
+    { op_file_link, "L", NULL,             1 },
+    { op_file_link, "h", NULL,             1 },
+    { op_file_xbit, "x", NULL,             1 },
+    { op_file_subr, "F", NULL,             0 },
+    { op_url_subr,  "U", NULL,             0 },
+    { op_url_subr,  "A", NULL,             0 },
     { NULL, NULL, NULL }
 };
 
 static const struct expr_provider_single binary_op_providers[] = {
-    { op_ipmatch,   "ipmatch",      subnet_parse_arg },
-    { op_fnmatch,   "fnmatch",      NULL },
-    { op_strmatch,  "strmatch",     NULL },
-    { op_strcmatch, "strcmatch",    NULL },
+    { op_ipmatch,   "ipmatch",      subnet_parse_arg, 0 },
+    { op_fnmatch,   "fnmatch",      NULL,             0 },
+    { op_strmatch,  "strmatch",     NULL,             0 },
+    { op_strcmatch, "strcmatch",    NULL,             0 },
     { NULL, NULL, NULL }
 };
 
@@ -1423,6 +1453,15 @@ static int core_expr_lookup(ap_expr_look
             }
             while (prov->func) {
                 if (strcasecmp(prov->name, parms->name) == 0) {
+                    if ((parms->flags & AP_EXPR_FLAGS_RESTRICTED)
+                        && prov->restricted) {
+                        *parms->err =
+                            apr_psprintf(parms->ptemp,
+                                         "%s%s not available in restricted context",
+                                         (parms->type == AP_EXPR_FUNC_STRING) ? "" : \
"-", +                                         prov->name);
+                        return !OK;
+                    }
                     *parms->func = prov->func;
                     if (prov->arg_parsing_func) {
                         return prov->arg_parsing_func(parms);


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic