You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by sf...@apache.org on 2010/12/18 18:11:14 UTC

svn commit: r1050677 - in /httpd/httpd/trunk: CHANGES docs/manual/mod/mod_authz_core.xml modules/aaa/mod_authz_core.c

Author: sf
Date: Sat Dec 18 17:11:14 2010
New Revision: 1050677

URL: http://svn.apache.org/viewvc?rev=1050677&view=rev
Log:
Add new AuthzSendForbiddenOnFailure directive to allow sending '403 FORBIDDEN'
instead of '401 UNAUTHORIZED' if authorization fails for an authenticated user

PR: 40721

Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/docs/manual/mod/mod_authz_core.xml
    httpd/httpd/trunk/modules/aaa/mod_authz_core.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1050677&r1=1050676&r2=1050677&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Sat Dec 18 17:11:14 2010
@@ -2,6 +2,9 @@
 
 Changes with Apache 2.3.11
 
+  *) mod_authz_core: Add AuthzSendForbiddenOnFailure directive to allow
+     sending '403 FORBIDDEN' instead of '401 UNAUTHORIZED' if authorization
+     fails for an authenticated user. PR 40721. [Stefan Fritsch]
 
 Changes with Apache 2.3.10
 

Modified: httpd/httpd/trunk/docs/manual/mod/mod_authz_core.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_authz_core.xml?rev=1050677&r1=1050676&r2=1050677&view=diff
==============================================================================
--- httpd/httpd/trunk/docs/manual/mod/mod_authz_core.xml (original)
+++ httpd/httpd/trunk/docs/manual/mod/mod_authz_core.xml Sat Dec 18 17:11:14 2010
@@ -27,7 +27,7 @@
 <status>Base</status>
 <sourcefile>mod_authz_core.c</sourcefile>
 <identifier>authz_core_module</identifier>
-<compatibility>Available in Apache 2.3 and later</compatibility>
+<compatibility>Available in Apache HTTPD 2.3 and later</compatibility>
 
 <summary>
     <p>This module provides core authorization capabilities so that
@@ -585,4 +585,26 @@ alias</description>
 </usage>
 </directivesynopsis>
 
+<directivesynopsis>
+<name>AuthzSendForbiddenOnFailure</name>
+<description>Send '403 FORBIDDEN' instead of '401 UNAUTHORIZED' if
+authentication succeeds but authorization fails
+</description>
+<syntax>AuthzSendForbiddenOnFailure On|Off</syntax>
+<default>AuthzSendForbiddenOnFailure Off</default>
+<contextlist><context>directory</context><context>.htaccess</context>
+</contextlist>
+<compatibility>Available in Apache HTTPD 2.3.11 and later</compatibility>
+
+<usage>
+    <p>If authentication succeeds but authorization fails, Apache HTTPD will
+    respond with an HTTP response code of '401 UNAUTHORIZED' by default. This
+    usually causes browsers to display the password dialogue to the user
+    again, which is not wanted in all situations.
+    <directive>AuthzSendForbiddenOnFailure</directive> allows to change the
+    response code to '403 FORBIDDEN'.</p>
+</usage>
+</directivesynopsis>
+
+
 </modulesynopsis>

Modified: httpd/httpd/trunk/modules/aaa/mod_authz_core.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/aaa/mod_authz_core.c?rev=1050677&r1=1050676&r2=1050677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/aaa/mod_authz_core.c (original)
+++ httpd/httpd/trunk/modules/aaa/mod_authz_core.c Sat Dec 18 17:11:14 2010
@@ -59,7 +59,8 @@ typedef struct provider_alias_rec {
 typedef enum {
     AUTHZ_LOGIC_AND,
     AUTHZ_LOGIC_OR,
-    AUTHZ_LOGIC_OFF
+    AUTHZ_LOGIC_OFF,
+    AUTHZ_LOGIC_UNSET
 } authz_logic_op;
 
 typedef struct authz_section_conf authz_section_conf;
@@ -80,10 +81,13 @@ typedef struct authz_core_dir_conf authz
 
 struct authz_core_dir_conf {
     authz_section_conf *section;
-    authz_logic_op op;
     authz_core_dir_conf *next;
+    authz_logic_op op;
+    signed char authz_forbidden_on_fail;
 };
 
+#define UNSET -1
+
 typedef struct authz_core_srv_conf {
     apr_hash_t *alias_rec;
 } authz_core_srv_conf;
@@ -96,7 +100,8 @@ static void *create_authz_core_dir_confi
 {
     authz_core_dir_conf *conf = apr_pcalloc(p, sizeof(*conf));
 
-    conf->op = AUTHZ_LOGIC_OFF;
+    conf->op = AUTHZ_LOGIC_UNSET;
+    conf->authz_forbidden_on_fail = UNSET;
 
     conf->next = authz_core_first_dir_conf;
     authz_core_first_dir_conf = conf;
@@ -111,7 +116,13 @@ static void *merge_authz_core_dir_config
     authz_core_dir_conf *new = (authz_core_dir_conf *)newv;
     authz_core_dir_conf *conf;
 
-    if (new->op == AUTHZ_LOGIC_OFF || !(base->section || new->section)) {
+    if (new->op == AUTHZ_LOGIC_UNSET && !new->section && base->section ) {
+	/* Only authz_forbidden_on_fail has been set in new. Don't treat
+	 * it as a new auth config w.r.t. AuthMerging */
+        conf = apr_pmemdup(p, base, sizeof(*base));
+    }
+    else if (new->op == AUTHZ_LOGIC_OFF || new->op == AUTHZ_LOGIC_UNSET ||
+             !(base->section || new->section)) {
         conf = apr_pmemdup(p, new, sizeof(*new));
     }
     else {
@@ -145,6 +156,11 @@ static void *merge_authz_core_dir_config
         conf->op = new->op;
     }
 
+    if (new->authz_forbidden_on_fail == UNSET)
+        conf->authz_forbidden_on_fail = base->authz_forbidden_on_fail;
+    else
+        conf->authz_forbidden_on_fail = new->authz_forbidden_on_fail;
+
     return (void*)conf;
 }
 
@@ -655,6 +671,12 @@ static const command_rec authz_cmds[] =
                   "controls how a <Directory>, <Location>, or similar "
                   "directive's authorization directives are combined with "
                   "those of its predecessor"),
+    AP_INIT_FLAG("AuthzSendForbiddenOnFailure", ap_set_flag_slot_char,
+                 (void *)APR_OFFSETOF(authz_core_dir_conf, authz_forbidden_on_fail),
+                 OR_AUTHCFG,
+                 "Controls if an authorization failure should result in a "
+                 "'403 FORBIDDEN' response instead of the HTTP-conforming "
+                 "'401 UNAUTHORIZED'"),
     {NULL}
 };
 
@@ -816,20 +838,23 @@ static int authorize_user_core(request_r
             return HTTP_FORBIDDEN;
         }
         else {
-            /* XXX: maybe we want to return FORBIDDEN here, too??? */
             ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r,
                           "user %s: authorization failure for \"%s\": ",
                           r->user, r->uri);
 
-            /*
-             * If we're returning 401 to an authenticated user, tell them to
-             * try again. If unauthenticated, note_auth_failure has already
-             * been called during auth.
-             */
-            if (r->user)
-                ap_note_auth_failure(r);
-
-            return HTTP_UNAUTHORIZED;
+            if (conf->authz_forbidden_on_fail > 0) {
+                return HTTP_FORBIDDEN;
+            }
+            else {
+                /*
+                 * If we're returning 401 to an authenticated user, tell them to
+                 * try again. If unauthenticated, note_auth_failure has already
+                 * been called during auth.
+                 */
+                if (r->user)
+                    ap_note_auth_failure(r);
+                return HTTP_UNAUTHORIZED;
+            }
         }
     }
     else {