Return-Path: Delivered-To: apmail-httpd-cvs-archive@www.apache.org Received: (qmail 82297 invoked from network); 1 Sep 2007 21:27:49 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 1 Sep 2007 21:27:49 -0000 Received: (qmail 76530 invoked by uid 500); 1 Sep 2007 21:27:44 -0000 Delivered-To: apmail-httpd-cvs-archive@httpd.apache.org Received: (qmail 76483 invoked by uid 500); 1 Sep 2007 21:27:44 -0000 Mailing-List: contact cvs-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@httpd.apache.org Received: (qmail 76471 invoked by uid 99); 1 Sep 2007 21:27:44 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 01 Sep 2007 14:27:44 -0700 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 01 Sep 2007 21:27:48 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id DF8D91A9832; Sat, 1 Sep 2007 14:27:27 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r571872 - in /httpd/httpd/trunk: CHANGES docs/manual/mod/mod_include.xml modules/filters/mod_include.c modules/filters/mod_include.h Date: Sat, 01 Sep 2007 21:27:27 -0000 To: cvs@httpd.apache.org From: minfrin@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20070901212727.DF8D91A9832@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: minfrin Date: Sat Sep 1 14:27:26 2007 New Revision: 571872 URL: http://svn.apache.org/viewvc?rev=571872&view=rev Log: mod_include: Add an "if" directive syntax to test whether an URL is accessible, and if so, conditionally display content. This allows a webmaster to hide a link to a private page when the user has no access to that page. Modified: httpd/httpd/trunk/CHANGES httpd/httpd/trunk/docs/manual/mod/mod_include.xml httpd/httpd/trunk/modules/filters/mod_include.c httpd/httpd/trunk/modules/filters/mod_include.h Modified: httpd/httpd/trunk/CHANGES URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=571872&r1=571871&r2=571872&view=diff ============================================================================== --- httpd/httpd/trunk/CHANGES [utf-8] (original) +++ httpd/httpd/trunk/CHANGES [utf-8] Sat Sep 1 14:27:26 2007 @@ -2,6 +2,11 @@ Changes with Apache 2.3.0 [ When backported to 2.2.x, remove entry from this file ] + *) mod_include: Add an "if" directive syntax to test whether an URL + is accessible, and if so, conditionally display content. This + allows a webmaster to hide a link to a private page when the user + has no access to that page. [Graham Leggett] + *) mod_authnz_ldap, mod_authn_dbd: Tidy up the code to expose authn parameters to the environment. Improve portability to EBCDIC machines by using apr_toupper(). [Martin Kraemer] Modified: httpd/httpd/trunk/docs/manual/mod/mod_include.xml URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_include.xml?rev=571872&r1=571871&r2=571872&view=diff ============================================================================== --- httpd/httpd/trunk/docs/manual/mod/mod_include.xml (original) +++ httpd/httpd/trunk/docs/manual/mod/mod_include.xml Sat Sep 1 14:27:26 2007 @@ -501,6 +501,25 @@
string
true if string is not empty
+
-A string
+

true if the URL represented by the string is accessible by + configuration, false otherwise. This test only has an effect if + SSIEnableAccess is on. This is useful + where content on a page is to be hidden from users who are not + authorized to view the URL, such as a link to that URL. Note + that the URL is only tested for whether access would be granted, + not whether the URL exists.

+ + Example + <!--#if expr="-A /private" -->
+ + Click <a href="/private">here</a> to access private + information.
+
+ <!--#endif --> +
+
+
string1 = string2
string1 == string2
string1 != string2
@@ -745,6 +764,34 @@ +SSIEnableAccess +Enable the -A flag during conditional flow control processing. +SSIEnableAccess on|off +SSIEnableAccess off +directorylocation + + +

The SSIEnableAccess directive controls whether + the -A test is enabled during conditional flow control processing. + SSIEnableAccess can take on the following values:

+ +
+ +
off
+
<!--#if expr="-A /foo"--> will be interpreted as a series + of string and regular expression tokens, the -A has no special + meaning.
+ +
on
+
<!--#if expr="-A /foo"--> will evaluate to false if the + URL /foo is inaccessible by configuration, or true otherwise.
+ +
+ +
+
+ + XBitHack Parse SSI directives in files with the execute bit set @@ -785,7 +832,7 @@ - + Modified: httpd/httpd/trunk/modules/filters/mod_include.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/filters/mod_include.c?rev=571872&r1=571871&r2=571872&view=diff ============================================================================== --- httpd/httpd/trunk/modules/filters/mod_include.c (original) +++ httpd/httpd/trunk/modules/filters/mod_include.c Sat Sep 1 14:27:26 2007 @@ -80,7 +80,8 @@ TOKEN_GE, TOKEN_LE, TOKEN_GT, - TOKEN_LT + TOKEN_LT, + TOKEN_ACCESS } token_type_t; typedef struct { @@ -114,6 +115,7 @@ const char *default_time_fmt; const char *undefined_echo; xbithack_t xbithack; + const int accessenable; } include_dir_config; typedef struct { @@ -941,7 +943,7 @@ return rc; } -static int get_ptoken(apr_pool_t *pool, const char **parse, token_t *token) +static int get_ptoken(include_ctx_t *ctx, const char **parse, token_t *token, token_t *previous) { const char *p; apr_size_t shift; @@ -990,6 +992,10 @@ unmatched = '\''; break; case '/': + /* if last token was ACCESS, this token is STRING */ + if (previous != NULL && TOKEN_ACCESS == previous->type) { + break; + } TYPE_TOKEN(token, TOKEN_RE); unmatched = '/'; break; @@ -1023,6 +1029,13 @@ } TYPE_TOKEN(token, TOKEN_LT); return 0; + case '-': + if (**parse == 'A' && (ctx->accessenable)) { + TYPE_TOKEN(token, TOKEN_ACCESS); + ++*parse; + return 0; + } + break; } /* It's a string or regex token @@ -1079,11 +1092,11 @@ } if (unmatched) { - token->value = apr_pstrdup(pool, ""); + token->value = apr_pstrdup(ctx->dpool, ""); } else { apr_size_t len = p - token->value - shift; - char *c = apr_palloc(pool, len + 1); + char *c = apr_palloc(ctx->dpool, len + 1); p = token->value; token->value = c; @@ -1111,6 +1124,7 @@ { parse_node_t *new, *root = NULL, *current = NULL; request_rec *r = ctx->intern->r; + request_rec *rr = NULL; const char *error = "Invalid expression \"%s\" in file %s"; const char *parse = expr; int was_unmatched = 0; @@ -1130,7 +1144,8 @@ */ CREATE_NODE(ctx, new); - was_unmatched = get_ptoken(ctx->dpool, &parse, &new->token); + was_unmatched = get_ptoken(ctx, &parse, &new->token, + (current != NULL ? ¤t->token : NULL)); if (!parse) { break; } @@ -1142,6 +1157,7 @@ switch (new->token.type) { case TOKEN_STRING: case TOKEN_NOT: + case TOKEN_ACCESS: case TOKEN_LBRACE: root = current = new; continue; @@ -1276,6 +1292,7 @@ break; case TOKEN_NOT: + case TOKEN_ACCESS: case TOKEN_LBRACE: switch (current->token.type) { case TOKEN_STRING: @@ -1462,6 +1479,34 @@ } break; + case TOKEN_ACCESS: + if (current->left || !current->right || + (current->right->token.type != TOKEN_STRING && + current->right->token.type != TOKEN_RE)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid expression \"%s\" in file %s: Token '-A' must be followed by a URI string.", + expr, r->filename); + *was_error = 1; + return 0; + } + current->right->token.value = + ap_ssi_parse_string(ctx, current->right->token.value, NULL, 0, + SSI_EXPAND_DROP_NAME); + rr = ap_sub_req_lookup_uri(current->right->token.value, r, NULL); + /* 400 and higher are considered access denied */ + if (rr->status < HTTP_BAD_REQUEST) { + current->value = 1; + } + else { + current->value = 0; + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rr->status, r, + "mod_include: The tested " + "subrequest -A \"%s\" returned an error code.", + current->right->token.value); + } + ap_destroy_sub_req(rr); + break; + case TOKEN_RE: if (!error) { error = "No operator before regex in expr \"%s\" in file %s"; @@ -3526,6 +3571,7 @@ if (ap_allow_options(r) & OPT_INCNOEXEC) { ctx->flags |= SSI_FLAG_NO_EXEC; } + ctx->accessenable = conf->accessenable; ctx->if_nesting_level = 0; intern->re = NULL; @@ -3808,6 +3854,9 @@ "SSI End String Tag"), AP_INIT_TAKE1("SSIUndefinedEcho", set_undefined_echo, NULL, OR_ALL, "String to be displayed if an echoed variable is undefined"), + AP_INIT_FLAG("SSIAccessEnable", ap_set_flag_slot, + (void *)APR_OFFSETOF(include_dir_config, accessenable), + OR_LIMIT, "Whether testing access is enabled. Limited to 'on' or 'off'"), {NULL} }; Modified: httpd/httpd/trunk/modules/filters/mod_include.h URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/filters/mod_include.h?rev=571872&r1=571871&r2=571872&view=diff ============================================================================== --- httpd/httpd/trunk/modules/filters/mod_include.h (original) +++ httpd/httpd/trunk/modules/filters/mod_include.h Sat Sep 1 14:27:26 2007 @@ -96,6 +96,9 @@ /* pointer to internal (non-public) data, don't touch */ struct ssi_internal_ctx *intern; + + /* is using the access tests allowed? */ + int accessenable; } include_ctx_t; typedef apr_status_t (include_handler_fn_t)(include_ctx_t *, ap_filter_t *,