]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Allow <Limit> and <LimitExcept> directives to nest, and
authorChris Darroch <chrisd@apache.org>
Fri, 31 Oct 2008 20:10:07 +0000 (20:10 +0000)
committerChris Darroch <chrisd@apache.org>
Fri, 31 Oct 2008 20:10:07 +0000 (20:10 +0000)
constrain their use to conform with that of other access control
and authorization directives.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@709551 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/manual/mod/core.xml
server/core.c

diff --git a/CHANGES b/CHANGES
index 2635bc0c0d21726e545513a405c2e774c35fc856..1d1746d225ceaea26f2e5593ea05665ae44fb33a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,10 @@
 Changes with Apache 2.3.0
 [ When backported to 2.2.x, remove entry from this file ]
 
+  *) core: Allow <Limit> and <LimitExcept> directives to nest, and
+     constrain their use to conform with that of other access control
+     and authorization directives.  [Chris Darroch]
+
   *) unixd: turn existing code into a module, and turn the set user/group
      and chroot into a child_init function. [Nick Kew]
 
index fa2975257cf1f5ad80997015d169bb5db0d30965..f7bf8d10099febdeaceb36fa4b83b93ee5dadb90 100644 (file)
@@ -1586,10 +1586,9 @@ requests on a persistent connection</description>
 methods</description>
 <syntax>&lt;Limit <var>method</var> [<var>method</var>] ... &gt; ...
     &lt;/Limit&gt;</syntax>
-<contextlist><context>server config</context><context>virtual host</context>
-<context>directory</context><context>.htaccess</context>
+<contextlist><context>directory</context><context>.htaccess</context>
 </contextlist>
-<override>All</override>
+<override>AuthConfig, Limit</override>
 
 <usage>
     <p>Access controls are normally effective for
@@ -1623,17 +1622,48 @@ methods</description>
     <code>LOCK</code>, and <code>UNLOCK</code>. <strong>The method name is
     case-sensitive.</strong> If <code>GET</code> is used it will also
     restrict <code>HEAD</code> requests. The <code>TRACE</code> method
-    cannot be limited (see <directive type="section" module="core"
+    cannot be limited (see <directive module="core"
     >TraceEnable</directive>).</p>
 
     <note type="warning">A <directive type="section"
     module="core">LimitExcept</directive> section should always be
-    used in preference to a <directive type="section"
-    module="core">Limit</directive> section when restricting access,
-    since a <directive type="section"
+    used in preference to a <directive type="section">Limit</directive>
+    section when restricting access, since a <directive type="section"
     module="core">LimitExcept</directive> section provides protection
     against arbitrary methods.</note>
 
+    <p>The <directive type="section">Limit</directive> and
+    <directive type="section" module="core">LimitExcept</directive>
+    directives may be nested.  In this case, each successive level of
+    <directive type="section">Limit</directive> or <directive
+    type="section" module="core">LimitExcept</directive> directives must
+    further restrict the set of methods to which access controls apply.</p>
+
+    <note type="warning">When using
+    <directive type="section">Limit</directive> or
+    <directive type="section">LimitExcept</directive> directives with
+    the <directive module="mod_authz_core">Require</directive> directive,
+    note that the first <directive module="mod_authz_core">Require</directive>
+    to succeed authorizes the request, regardless of the presence of other
+    <directive module="mod_authz_core">Require</directive> directives.</note>
+
+    <p>For example, given the following configuration, all users will
+    be authorized for <code>POST</code> requests, and the
+    <code>Require group editors</code> directive will be ignored
+    in all cases:</p>
+
+    <example>
+      &lt;LimitExcept GET&gt;
+      <indent>
+        Require valid-user
+      </indent> 
+      &lt;/LimitExcept&gt;<br />
+      &lt;Limit POST&gt;
+      <indent>
+        Require group editors
+      </indent> 
+      &lt;/Limit&gt;
+    </example>
 </usage>
 </directivesynopsis>
 
@@ -1643,10 +1673,9 @@ methods</description>
 except the named ones</description>
 <syntax>&lt;LimitExcept <var>method</var> [<var>method</var>] ... &gt; ...
     &lt;/LimitExcept&gt;</syntax>
-<contextlist><context>server config</context><context>virtual host</context>
-<context>directory</context><context>.htaccess</context>
+<contextlist><context>directory</context><context>.htaccess</context>
 </contextlist>
-<override>All</override>
+<override>AuthConfig, Limit</override>
 
 <usage>
     <p><directive type="section">LimitExcept</directive> and
index a1c7c6dd6542a690ed65575565bb47121a4342b3..79067fedbd7e15ff58ea78ef1def87d53fc452f3 100644 (file)
@@ -646,7 +646,7 @@ AP_DECLARE(int) ap_allow_overrides(request_rec *r)
 }
 
 /*
- * Optional function coming from mod_authn_core, used for 
+ * Optional function coming from mod_authn_core, used for
  * retrieving the type of autorization
  */
 static APR_OPTIONAL_FN_TYPE(authn_ap_auth_type) *authn_ap_auth_type;
@@ -660,7 +660,7 @@ AP_DECLARE(const char *) ap_auth_type(request_rec *r)
 }
 
 /*
- * Optional function coming from mod_authn_core, used for 
+ * Optional function coming from mod_authn_core, used for
  * retrieving the authorization realm
  */
 static APR_OPTIONAL_FN_TYPE(authn_ap_auth_name) *authn_ap_auth_name;
@@ -1042,9 +1042,11 @@ AP_DECLARE(const char *) ap_check_cmd_context(cmd_parms *cmd,
                            " cannot occur within <VirtualHost> section", NULL);
     }
 
-    if ((forbidden & NOT_IN_LIMIT) && cmd->limited != -1) {
+    if ((forbidden & (NOT_IN_LIMIT | NOT_IN_DIR_LOC_FILE))
+        && cmd->limited != -1) {
         return apr_pstrcat(cmd->pool, cmd->cmd->name, gt,
-                           " cannot occur within <Limit> section", NULL);
+                           " cannot occur within <Limit> or <LimitExcept> "
+                           "section", NULL);
     }
 
     if ((forbidden & NOT_IN_DIR_LOC_FILE) == NOT_IN_DIR_LOC_FILE) {
@@ -1656,13 +1658,9 @@ AP_CORE_DECLARE_NONSTD(const char *) ap_limit_section(cmd_parms *cmd,
     const char *limited_methods;
     void *tog = cmd->cmd->cmd_data;
     apr_int64_t limited = 0;
+    apr_int64_t old_limited = cmd->limited;
     const char *errmsg;
 
-    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
-    if (err != NULL) {
-        return err;
-    }
-
     if (endp == NULL) {
         return unclosed_directive(cmd);
     }
@@ -1696,11 +1694,23 @@ AP_CORE_DECLARE_NONSTD(const char *) ap_limit_section(cmd_parms *cmd,
     /* Killing two features with one function,
      * if (tog == NULL) <Limit>, else <LimitExcept>
      */
-    cmd->limited = tog ? ~limited : limited;
+    limited = tog ? ~limited : limited;
+
+    if (!(old_limited & limited)) {
+        return apr_pstrcat(cmd->pool, cmd->cmd->name,
+                           "> directive excludes all methods", NULL);
+    }
+    else if ((old_limited & limited) == old_limited) {
+        return apr_pstrcat(cmd->pool, cmd->cmd->name,
+                           "> directive specifies methods already excluded",
+                           NULL);
+    }
+
+    cmd->limited &= limited;
 
     errmsg = ap_walk_config(cmd->directive->first_child, cmd, cmd->context);
 
-    cmd->limited = -1;
+    cmd->limited = old_limited;
 
     return errmsg;
 }
@@ -1899,7 +1909,8 @@ static const char *filesection(cmd_parms *cmd, void *mconfig, const char *arg)
     const command_rec *thiscmd = cmd->cmd;
     core_dir_config *c = mconfig;
     ap_conf_vector_t *new_file_conf = ap_create_per_dir_config(cmd->pool);
-    const char *err = ap_check_cmd_context(cmd, NOT_IN_LOCATION);
+    const char *err = ap_check_cmd_context(cmd,
+                                           NOT_IN_LOCATION | NOT_IN_LIMIT);
 
     if (err != NULL) {
         return err;
@@ -1979,7 +1990,8 @@ static const char *ifsection(cmd_parms *cmd, void *mconfig, const char *arg)
     const command_rec *thiscmd = cmd->cmd;
     core_dir_config *c = mconfig;
     ap_conf_vector_t *new_file_conf = ap_create_per_dir_config(cmd->pool);
-    const char *err = ap_check_cmd_context(cmd, NOT_IN_LOCATION);
+    const char *err = ap_check_cmd_context(cmd,
+                                           NOT_IN_LOCATION | NOT_IN_LIMIT);
     const char *condition;
     int expr_err = 0;
 
@@ -3174,10 +3186,11 @@ AP_INIT_RAW_ARGS("<VirtualHost", virtualhost_section, NULL, RSRC_CONF,
   "more host addresses"),
 AP_INIT_RAW_ARGS("<Files", filesection, NULL, OR_ALL,
   "Container for directives affecting files matching specified patterns"),
-AP_INIT_RAW_ARGS("<Limit", ap_limit_section, NULL, OR_ALL,
+AP_INIT_RAW_ARGS("<Limit", ap_limit_section, NULL, OR_LIMIT | OR_AUTHCFG,
   "Container for authentication directives when accessed using specified HTTP "
   "methods"),
-AP_INIT_RAW_ARGS("<LimitExcept", ap_limit_section, (void*)1, OR_ALL,
+AP_INIT_RAW_ARGS("<LimitExcept", ap_limit_section, (void*)1,
+                 OR_LIMIT | OR_AUTHCFG,
   "Container for authentication directives to be applied when any HTTP "
   "method other than those specified is used to access the resource"),
 AP_INIT_TAKE1("<IfModule", start_ifmod, NULL, EXEC_ON_READ | OR_ALL,