]> granicus.if.org Git - apache/commitdiff
Authz refactoring
authorBradley Nicholes <bnicholes@apache.org>
Wed, 11 Jan 2006 14:30:28 +0000 (14:30 +0000)
committerBradley Nicholes <bnicholes@apache.org>
Wed, 11 Jan 2006 14:30:28 +0000 (14:30 +0000)
Merge from branches/authz-dev

Basically here is a list of what has been done:
- Convert all of the authz modules from hook based to provider based
- Remove the ap_requires field from the core_dir_config structure
- Remove the function ap_requires() since its functionality is no
longer supported or necessary in the refactoring
- Remove the calls to ap_some_auth_required() in the core request
handling to allow the  hooks to be called in all cases.
- Add the new module mod_authz_core which will act as the authorization
provider vector and contain common authz directives such as 'Require',
'Reject' and  '<RequireAlias>'
- Add the new module mod_authn_core which will contain common
authentication directives such as 'AuthType', 'AuthName' and
'<AuthnProviderAlias>'
- Move the check for METHOD_MASK out of the authz providers and into
the authz_core provider vector
- Define the status codes that can be returned by the authz providers
as AUTHZ_DENIED,  AUTHZ_GRANTED and AUTHZ_GENERAL_ERROR
- Remove the 'Satisfy' directive
- Implement the '<RequireAll>', '<RequireOne>' block directives  to
handle the 'and' and 'or' logic for authorization.
- Remove the 'AuthzXXXAuthoritative' directives from all of the authz
providers
- Implement the 'Reject' directive that will deny authorization if the
argument is true
- Fold the 'Reject' directive into the '<RequireAll>', '<RequireOne>'
logic
- Reimplement the host based authorization functionality provided by
'allow', 'deny' and 'order' as authz providers
- Remove the 'allow', 'deny' and 'order' directives
- Merge mod_authn_alias into mod_authn_core
- Add '<RequireAlias>' functionality which is similar to
'<AuthnProviderAlias>' but specific to authorization aliasing
- Remove all of the references to the 'authzxxxAuthoritative'
directives from the documentation
- Remove the 'Satisfy' directive from the documentation
- Remove 'Allow', 'Deny', 'Order' directives from the documentation
- Document '<RequireAll>', '<RequireOne>', 'Reject' directives
- Reimplement the APIs ap_auth_type(), ap_auth_name() as optional
functions and move the  actual implementation into mod_authn_core
- Reimplement the API ap_some_auth_required() as an optional function
and move the  actual implementation into mod_authz_core

Major Changes:
- Added the directives <RequireAll>, <RequireOne>, <RequireAlias>,
Reject
- Expanded the functionality of the directive 'Require' to handle all
authorization and access control
- Added the new authz providers 'env', 'ip', 'host', 'all' to handle
host-based access control
- Removed the directives 'Allow', 'Deny', 'Order', 'Satisfy',
'AuthzXXXAuthoritative'
- Removed the ap_require() API
- Moved the directives 'AuthType', 'AuthName' out of mod_core and into
mod_authn_core
- Moved the directive 'Require' out of mod_core and into
mod_authz_core
- Merged mod_authn_alias into mod_authn_core
- Renamed mod_authz_dbm authz providers from 'group' and 'file-group'
to 'dbm-group' and 'dbm-file-group'

Benefits:
- All authorization and access control is now handle through two
directives, 'Require' and 'Reject'
- Authorization has been expanded to allow for complex 'AND/OR' control
logic through the directives '<RequireAll>' and '<RequireOne>'
- Configuration is now much simpler and consistent across the board
- Other modules like mod_ssl and mod_proxy should be able to plug into
and take advantage of  the same provider based authorization mechanism
by implementing their own providers

Issues:
- Backwards compatibility between 2.2 and 2.3 configurations will be
broken in the area  of authorization and access control due to the fact
that the directives 'allow', 'deny',  'order' and 'satisfy' have been
removed.  When moving from 2.2 to 2.3 these directives  will have to be
changed to 'Require all granted', 'Require all denied' or some variation
 of the authz host-based providers.
- Existing third party authorization modules will have to adapt to the
new structure.

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

45 files changed:
docs/conf/extra/httpd-autoindex.conf.in
docs/conf/extra/httpd-dav.conf.in
docs/conf/extra/httpd-info.conf.in
docs/conf/extra/httpd-manual.conf.in
docs/conf/extra/httpd-multilang-errordoc.conf.in
docs/conf/extra/httpd-userdir.conf.in
docs/conf/httpd.conf.in
docs/manual/developer/request.xml
docs/manual/mod/allmodules.xml
docs/manual/mod/core.xml
docs/manual/mod/mod_auth_digest.xml
docs/manual/mod/mod_authn_alias.xml
docs/manual/mod/mod_authn_core.xml [new file with mode: 0644]
docs/manual/mod/mod_authn_core.xml.meta [new file with mode: 0644]
docs/manual/mod/mod_authnz_ldap.xml
docs/manual/mod/mod_authz_core.xml [new file with mode: 0644]
docs/manual/mod/mod_authz_core.xml.meta [new file with mode: 0644]
docs/manual/mod/mod_authz_dbd.xml
docs/manual/mod/mod_authz_dbm.xml
docs/manual/mod/mod_authz_groupfile.xml
docs/manual/mod/mod_authz_host.xml
docs/manual/mod/mod_authz_owner.xml
docs/manual/mod/mod_authz_user.xml
docs/manual/mod/mod_ldap.xml
include/ap_mmn.h
include/http_core.h
modules/aaa/NWGNUauthncore [new file with mode: 0644]
modules/aaa/NWGNUauthzcore [new file with mode: 0644]
modules/aaa/NWGNUmakefile
modules/aaa/config.m4
modules/aaa/mod_auth.h
modules/aaa/mod_auth_basic.c
modules/aaa/mod_authn_core.c [new file with mode: 0644]
modules/aaa/mod_authn_default.c
modules/aaa/mod_authnz_ldap.c
modules/aaa/mod_authz_core.c [new file with mode: 0644]
modules/aaa/mod_authz_dbd.c
modules/aaa/mod_authz_dbm.c
modules/aaa/mod_authz_default.c
modules/aaa/mod_authz_groupfile.c
modules/aaa/mod_authz_host.c
modules/aaa/mod_authz_owner.c
modules/aaa/mod_authz_user.c
server/core.c
server/request.c

index 13b400d1ad3306f85ad372ab7e9867b203b7124f..91ddb534c5b5918a09e892894e2bfc7ba20eb7c2 100644 (file)
@@ -22,8 +22,7 @@ Alias /icons/ "@exp_iconsdir@/"
 <Directory "@exp_iconsdir@">
     Options Indexes MultiViews
     AllowOverride None
-    Order allow,deny
-    Allow from all
+    Require all granted
 </Directory>
 
 #
index 56a1a819aba45614913a788176e186c7a47fa181..ec8a5e59b648650c0a88ab3ab24c406a5c612934 100644 (file)
@@ -24,6 +24,7 @@ Alias /uploads "@@ServerRoot@@/uploads"
     # You can use the htdigest program to create the password database:
     #   htdigest -c "@@ServerRoot@@/user.passwd" DAV-upload admin
     AuthUserFile "@@ServerRoot@@/user.passwd"
+    AuthDigestProvider file
 
     # Allow universal read-access, but writes are restricted
     # to the admin user.
index db316c032e11dcc77c608f4ecc0bb26842748fb4..261f096d7e1112625174e19d8d5ad84c2447d802 100644 (file)
@@ -12,9 +12,7 @@
 
 <Location /server-status>
     SetHandler server-status
-    Order deny,allow
-    Deny from all
-    Allow from .example.com
+    Require host .example.com
 </Location>
 
 #
@@ -31,7 +29,5 @@
 #
 <Location /server-info>
     SetHandler server-info
-    Order deny,allow
-    Deny from all
-    Allow from .example.com
+    Require host .example.com
 </Location>
index 874b0933ec4711be777bb995e1c35b3cf752a7f1..fc9e61694469889ba5b97c9320959e35be65f273 100644 (file)
@@ -12,8 +12,7 @@ AliasMatch ^/manual(?:/(?:de|en|es|fr|ja|ko|pt-br|ru))?(/.*)?$ "@exp_manualdir@$
 <Directory "@exp_manualdir@">
     Options Indexes
     AllowOverride None
-    Order allow,deny
-    Allow from all
+    Require all granted
 
     <Files *.html>
         SetHandler type-map
index d3192508b5ad850e3f4cd9fe24318e2d68f32692..617f5f607f83d37e93a2efa47c17a1056986d04f 100644 (file)
@@ -26,8 +26,7 @@ Alias /error/ "@exp_errordir@/"
     Options IncludesNoExec
     AddOutputFilter Includes html
     AddHandler type-map var
-    Order allow,deny
-    Allow from all
+    Require all granted
     LanguagePriority en cs de es fr it ja ko nl pl pt-br ro sv tr
     ForceLanguagePriority Prefer Fallback
 </Directory>
index f424dd437d8ed257603838b0e6f02ce90d078530..210fba0a71d12468f38e4c194c9356664a566d39 100644 (file)
@@ -17,12 +17,10 @@ UserDir public_html
     AllowOverride FileInfo AuthConfig Limit Indexes
     Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
     <Limit GET POST OPTIONS>
-        Order allow,deny
-        Allow from all
+        Require all granted
     </Limit>
     <LimitExcept GET POST OPTIONS>
-        Order deny,allow
-        Deny from all
+        Require all denied
     </LimitExcept>
 </Directory>
 
index e493562a1513b3b78c236413fe854224d659b8dd..a165e575125dfa5255a35b58ad57e0bd75a10617 100644 (file)
@@ -112,8 +112,7 @@ DocumentRoot "@exp_htdocsdir@"
 <Directory />
     Options FollowSymLinks
     AllowOverride None
-    Order deny,allow
-    Deny from all
+    Require all denied
 </Directory>
 
 #
@@ -151,8 +150,7 @@ DocumentRoot "@exp_htdocsdir@"
     #
     # Controls who can get stuff from this server.
     #
-    Order allow,deny
-    Allow from all
+    Require all granted
 
 </Directory>
 
@@ -169,9 +167,7 @@ DocumentRoot "@exp_htdocsdir@"
 # viewed by Web clients. 
 #
 <FilesMatch "^\.ht">
-    Order allow,deny
-    Deny from all
-    Satisfy All
+    Require all denied
 </FilesMatch>
 
 #
@@ -265,8 +261,7 @@ LogLevel warn
 <Directory "@exp_cgidir@">
     AllowOverride None
     Options None
-    Order allow,deny
-    Allow from all
+    Require all granted
 </Directory>
 
 #
index 72d5cf68b01b7866b2e36c15f6c924161ab286c0..7bb768927411532370b98a742e9c34431c4bb40a 100644 (file)
     <p>Needs Documentation. Code is:</p>
 
     <example><pre>
-switch (ap_satisfies(r)) {
-case SATISFY_ALL:
-case SATISFY_NOSPEC:
-    if ((access_status = ap_run_access_checker(r)) != 0) {
-        return decl_die(access_status, "check access", r);
-    }
-
-    if (ap_some_auth_required(r)) {
-        if (((access_status = ap_run_check_user_id(r)) != 0)
-            || !ap_auth_type(r)) {
-            return decl_die(access_status, ap_auth_type(r)
-                          ? "check user.  No user file?"
-                          : "perform authentication. AuthType not set!",
-                          r);
-        }
-
-        if (((access_status = ap_run_auth_checker(r)) != 0)
-            || !ap_auth_type(r)) {
-            return decl_die(access_status, ap_auth_type(r)
-                          ? "check access.  No groups file?"
-                          : "perform authentication. AuthType not set!",
-                          r);
-        }
-    }
-    break;
-
-case SATISFY_ANY:
-    if (((access_status = ap_run_access_checker(r)) != 0)) {
-        if (!ap_some_auth_required(r)) {
+        if ((access_status = ap_run_access_checker(r)) != 0) {
             return decl_die(access_status, "check access", r);
         }
 
-        if (((access_status = ap_run_check_user_id(r)) != 0)
-            || !ap_auth_type(r)) {
-            return decl_die(access_status, ap_auth_type(r)
-                          ? "check user.  No user file?"
-                          : "perform authentication. AuthType not set!",
-                          r);
+        if ((access_status = ap_run_check_user_id(r)) != 0) {
+            return decl_die(access_status, "check user", r);
         }
 
-        if (((access_status = ap_run_auth_checker(r)) != 0)
-            || !ap_auth_type(r)) {
-            return decl_die(access_status, ap_auth_type(r)
-                          ? "check access.  No groups file?"
-                          : "perform authentication. AuthType not set!",
-                          r);
+        if ((access_status = ap_run_auth_checker(r)) != 0) {
+            return decl_die(access_status, "check authorization", r);
         }
-    }
-    break;
-}</pre>
+    </pre>
     </example>
 </section>
 
index 0bac66e23c6cc871d1a5d4fa9e66531c873d91f2..d76e4b8507fc4311c7011a40fb7c345083a5221b 100644 (file)
@@ -9,11 +9,13 @@
   <modulefile>mod_auth_digest.xml</modulefile>
   <modulefile>mod_authn_alias.xml</modulefile>
   <modulefile>mod_authn_anon.xml</modulefile>
+  <modulefile>mod_authn_core.xml</modulefile>
   <modulefile>mod_authn_dbd.xml</modulefile>
   <modulefile>mod_authn_dbm.xml</modulefile>
   <modulefile>mod_authn_default.xml</modulefile>
   <modulefile>mod_authn_file.xml</modulefile>
   <modulefile>mod_authnz_ldap.xml</modulefile>
+  <modulefile>mod_authz_core.xml</modulefile>
   <modulefile>mod_authz_dbd.xml</modulefile>
   <modulefile>mod_authz_dbm.xml</modulefile>
   <modulefile>mod_authz_default.xml</modulefile>
index 3d9447e70f1b7d0fca31140fbbfe64957f32c505..d5402df6c4fe27d996bd18a07b9d36a506793d46 100644 (file)
@@ -469,69 +469,6 @@ be passed through</description>
 <seealso><a href="../howto/htaccess.html">.htaccess Files</a></seealso>
 </directivesynopsis>
 
-<directivesynopsis>
-<name>AuthName</name>
-<description>Authorization realm for use in HTTP
-authentication</description>
-<syntax>AuthName <var>auth-domain</var></syntax>
-<contextlist><context>directory</context><context>.htaccess</context>
-</contextlist>
-<override>AuthConfig</override>
-
-<usage>
-    <p>This directive sets the name of the authorization realm for a
-    directory. This realm is given to the client so that the user
-    knows which username and password to send.
-    <directive>AuthName</directive> takes a single argument; if the
-    realm name contains spaces, it must be enclosed in quotation
-    marks.  It must be accompanied by <directive
-    module="core">AuthType</directive> and <directive
-    module="core">Require</directive> directives, and directives such
-    as <directive module="mod_authn_file">AuthUserFile</directive> and
-    <directive module="mod_authz_groupfile">AuthGroupFile</directive> to
-    work.</p>
-
-   <p>For example:</p>
-
-   <example>
-     AuthName "Top Secret"
-   </example>
-
-    <p>The string provided for the <code>AuthName</code> is what will
-    appear in the password dialog provided by most browsers.</p>
-</usage>
-<seealso><a
-    href="../howto/auth.html">Authentication, Authorization, and
-    Access Control</a></seealso>
-</directivesynopsis>
-
-<directivesynopsis>
-<name>AuthType</name>
-<description>Type of user authentication</description>
-<syntax>AuthType Basic|Digest</syntax>
-<contextlist><context>directory</context><context>.htaccess</context>
-</contextlist>
-<override>AuthConfig</override>
-
-<usage>
-    <p>This directive selects the type of user authentication for a
-    directory. The authentication types available are
-    <code>Basic</code> (implemented by
-    <module>mod_auth_basic</module>) and <code>Digest</code>
-    (implemented by <module>mod_auth_digest</module>).</p>
-
-    <p>To implement authentication, you must also use the <directive
-    module="core">AuthName</directive> and <directive
-    module="core">Require</directive> directives.  In addition, the
-    server must have an authentication-provider module such as
-    <module>mod_authn_file</module> and an authorization module such
-    as <module>mod_authz_user</module>.</p>
-</usage> 
-
-<seealso><a href="../howto/auth.html">Authentication, Authorization,
-    and Access Control</a></seealso> 
-</directivesynopsis>
-
 <directivesynopsis>
 <name>CGIMapExtension</name>
 <description>Technique for locating the interpreter for CGI
@@ -2391,101 +2328,6 @@ directory</description>
 </usage>
 </directivesynopsis>
 
-<directivesynopsis>
-<name>Require</name>
-<description>Selects which authenticated users can access
-a resource</description>
-<syntax>Require <var>entity-name</var> [<var>entity-name</var>] ...</syntax>
-<contextlist><context>directory</context><context>.htaccess</context>
-</contextlist>
-<override>AuthConfig</override>
-
-<usage>
-    <p>This directive selects which authenticated users can access a
-    resource.  The restrictions are processed by authorization
-    modules.  Some of the allowed syntaxes provided by
-    <module>mod_authz_user</module> and
-    <module>mod_authz_groupfile</module> are:</p>
-
-    <dl>
-      <dt><code>Require user <var>userid</var> [<var>userid</var>]
-      ...</code></dt>
-      <dd>Only the named users can access the resource.</dd>
-
-      <dt><code>Require group <var>group-name</var> [<var>group-name</var>]
-      ...</code></dt>
-      <dd>Only users in the named groups can access the resource.</dd>
-
-      <dt><code>Require valid-user</code></dt>
-      <dd>All valid users can access the resource.</dd>
-    </dl>
-
-    <p>Other authorization modules that implement require options
-    include <module>mod_authnz_ldap</module>,
-    <module>mod_authz_dbm</module>, and
-    <module>mod_authz_owner</module>.</p>
-
-    <p><directive>Require</directive> must be accompanied by
-    <directive module="core">AuthName</directive> and <directive
-    module="core">AuthType</directive> directives, and directives such
-    as <directive module="mod_authn_file">AuthUserFile</directive>
-    and <directive module="mod_authz_groupfile">AuthGroupFile</directive> (to
-    define users and groups) in order to work correctly. Example:</p>
-
-    <example>
-       AuthType Basic<br />
-       AuthName "Restricted Resource"<br />
-       AuthUserFile /web/users<br />
-       AuthGroupFile /web/groups<br />
-       Require group admin
-    </example>
-
-    <p>Access controls which are applied in this way are effective for
-    <strong>all</strong> methods. <strong>This is what is normally
-    desired.</strong> If you wish to apply access controls only to
-    specific methods, while leaving other methods unprotected, then
-    place the <directive>Require</directive> statement into a
-    <directive module="core" type="section">Limit</directive>
-    section.</p>
-    <p>If <directive>Require</directive> is used together with 
-    the <directive module="mod_authz_host">Allow</directive> or
-    <directive module="mod_authz_host">Deny</directive> directives,
-    then the interaction of these restrictions is controlled by
-    the <directive module="core">Satisfy</directive> directive.</p>
-
-    <note><title>Removing controls in subdirectories</title>
-    <p>The following example shows how to use the <directive
-    module="core">Satisfy</directive> directive to disable access
-    controls in a subdirectory of a protected directory.  This
-    technique should be used with caution, because it will also
-    disable any access controls imposed by
-    <module>mod_authz_host</module>.</p>
-    <example>
-      &lt;Directory /path/to/protected/&gt;<br />
-        <indent>
-        Require user david<br />
-        </indent>
-      &lt;/Directory&gt;<br />
-      &lt;Directory /path/to/protected/unprotected&gt;<br />
-        <indent>
-        # All access controls and authentication are disabled<br />
-        # in this directory<br />
-        Satisfy Any<br />
-        Allow from all<br />
-        </indent>
-      &lt;/Directory&gt;<br />
-    </example>
-    </note>
-      
-</usage>
-
-<seealso><a href="../howto/auth.html">Authentication, Authorization,
-    and Access Control</a></seealso> 
-<seealso><directive module="core">Satisfy</directive></seealso>
-<seealso><module>mod_authz_host</module></seealso>
-</directivesynopsis>
-
 <directivesynopsis>
 <name>RLimitCPU</name>
 <description>Limits the CPU consumption of processes launched
@@ -2593,55 +2435,6 @@ processes launched by Apache children</description>
 <seealso><directive module="core">RLimitCPU</directive></seealso>
 </directivesynopsis>
 
-<directivesynopsis>
-<name>Satisfy</name>
-<description>Interaction between host-level access control and
-user authentication</description>
-<syntax>Satisfy Any|All</syntax>
-<default>Satisfy All</default>
-<contextlist><context>directory</context><context>.htaccess</context>
-</contextlist>
-<override>AuthConfig</override>
-<compatibility>Influenced by <directive module="core" type="section"
->Limit</directive> and <directive module="core"
-type="section">LimitExcept</directive> in version 2.0.51 and
-later</compatibility>
-
-<usage>
-    <p>Access policy if both <directive
-    module="mod_authz_host">Allow</directive> and <directive
-    module="core">Require</directive> used. The parameter can be
-    either <code>All</code> or <code>Any</code>. This directive is only
-    useful if access to a particular area is being restricted by both
-    username/password <em>and</em> client host address. In this case
-    the default behavior (<code>All</code>) is to require that the client
-    passes the address access restriction <em>and</em> enters a valid
-    username and password. With the <code>Any</code> option the client will be
-    granted access if they either pass the host restriction or enter a
-    valid username and password. This can be used to password restrict
-    an area, but to let clients from particular addresses in without
-    prompting for a password.</p>
-
-    <p>For example, if you wanted to let people on your network have
-    unrestricted access to a portion of your website, but require that
-    people outside of your network provide a password, you could use a
-    configuration similar to the following:</p>
-
-    <example>
-      Require valid-user<br />
-      Allow from 192.168.1<br />
-      Satisfy Any
-    </example>
-
-    <p>Since version 2.0.51 <directive>Satisfy</directive> directives can
-    be restricted to particular methods by <directive module="core"
-    type="section">Limit</directive> and <directive module="core" type="section"
-    >LimitExcept</directive> sections.</p>
-</usage>
-   <seealso><directive module="mod_authz_host">Allow</directive></seealso>
-   <seealso><directive module="core">Require</directive></seealso>
-</directivesynopsis>
-
 <directivesynopsis>
 <name>ScriptInterpreterSource</name>
 <description>Technique for locating the interpreter for CGI
index 283a4196fb3e9073da67f98b310adb4153475f07..cf65d1a4e7e1070baa58e59a1ec19c6218ca0d7e 100644 (file)
@@ -38,7 +38,6 @@
 <seealso><directive module="core">AuthName</directive></seealso>
 <seealso><directive module="core">AuthType</directive></seealso>
 <seealso><directive module="core">Require</directive></seealso>
-<seealso><directive module="core">Satisfy</directive></seealso>
 <seealso><a href="../howto/auth.html">Authentication howto</a></seealso>
 
 <section id="using"><title>Using Digest Authentication</title>
index 6ba51d0c1b068a4ec27a27f3d7573c72e689d7b9..9bf23c09cacf42e7de64dcb458f76b9471865273 100644 (file)
@@ -76,7 +76,6 @@
     
          AuthType Basic<br />
          AuthName LDAP_Protected_Place<br />
-         AuthzLDAPAuthoritative off<br />
          require valid-user<br />
       </indent>
       &lt;/Directory&gt;<br />
diff --git a/docs/manual/mod/mod_authn_core.xml b/docs/manual/mod/mod_authn_core.xml
new file mode 100644 (file)
index 0000000..4fcf0b2
--- /dev/null
@@ -0,0 +1,103 @@
+<?xml version="1.0"?>\r
+<!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">\r
+<?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>\r
+<!-- $LastChangedRevision: 151408 $ -->\r
+\r
+<!--\r
+ Copyright 2002-2005 The Apache Software Foundation or its licensors, as\r
+ applicable.\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+     http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+-->\r
+\r
+<modulesynopsis metafile="mod_authn_core.xml.meta">\r
+\r
+<name>mod_authn_core</name> \r
+<description>Core Authentication</description>\r
+<status>Base</status>\r
+<sourcefile>mod_authn_core.c</sourcefile>\r
+<identifier>authn_core_module</identifier>\r
+<compatibility>Available in Apache 2.3 and later</compatibility>\r
+\r
+<summary>\r
+    <p>This module provides core authentication capabilities to \r
+    allow or deny access to portions of the web site. \r
+    <module>mod_authn_core</module> provides directives that are \r
+    common to all authentication providers.</p>\r
+</summary>\r
+\r
+<directivesynopsis>\r
+<name>AuthName</name>\r
+<description>Authorization realm for use in HTTP\r
+authentication</description>\r
+<syntax>AuthName <var>auth-domain</var></syntax>\r
+<contextlist><context>directory</context><context>.htaccess</context>\r
+</contextlist>\r
+<override>AuthConfig</override>\r
+\r
+<usage>\r
+    <p>This directive sets the name of the authorization realm for a\r
+    directory. This realm is given to the client so that the user\r
+    knows which username and password to send.\r
+    <directive>AuthName</directive> takes a single argument; if the\r
+    realm name contains spaces, it must be enclosed in quotation\r
+    marks.  It must be accompanied by <directive\r
+    module="mod_authn_core">AuthType</directive> and <directive\r
+    module="mod_authz_core">Require</directive> directives, and directives such\r
+    as <directive module="mod_authn_file">AuthUserFile</directive> and\r
+    <directive module="mod_authz_groupfile">AuthGroupFile</directive> to\r
+    work.</p>\r
+\r
+   <p>For example:</p>\r
+\r
+   <example>\r
+     AuthName "Top Secret"\r
+   </example>\r
+\r
+    <p>The string provided for the <code>AuthName</code> is what will\r
+    appear in the password dialog provided by most browsers.</p>\r
+</usage>\r
+<seealso><a\r
+    href="../howto/auth.html">Authentication, Authorization, and\r
+    Access Control</a></seealso>\r
+</directivesynopsis>\r
+\r
+<directivesynopsis>\r
+<name>AuthType</name>\r
+<description>Type of user authentication</description>\r
+<syntax>AuthType Basic|Digest</syntax>\r
+<contextlist><context>directory</context><context>.htaccess</context>\r
+</contextlist>\r
+<override>AuthConfig</override>\r
+\r
+<usage>\r
+    <p>This directive selects the type of user authentication for a\r
+    directory. The authentication types available are\r
+    <code>Basic</code> (implemented by\r
+    <module>mod_auth_basic</module>) and <code>Digest</code>\r
+    (implemented by <module>mod_auth_digest</module>).</p>\r
+\r
+    <p>To implement authentication, you must also use the <directive\r
+    module="mod_authn_core">AuthName</directive> and <directive\r
+    module="mod_authz_core">Require</directive> directives.  In addition, the\r
+    server must have an authentication-provider module such as\r
+    <module>mod_authn_file</module> and an authorization module such\r
+    as <module>mod_authz_user</module>.</p>\r
+</usage> \r
+\r
+<seealso><a href="../howto/auth.html">Authentication, Authorization,\r
+    and Access Control</a></seealso> \r
+</directivesynopsis>\r
+\r
+\r
+</modulesynopsis>\r
diff --git a/docs/manual/mod/mod_authn_core.xml.meta b/docs/manual/mod/mod_authn_core.xml.meta
new file mode 100644 (file)
index 0000000..5161d87
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" ?>\r
+\r
+<metafile>\r
+  <basename>mod_authn_core</basename>\r
+  <path>/mod/</path>\r
+  <relpath>..</relpath>\r
+\r
+  <variants>\r
+    <variant>en</variant>\r
+  </variants>\r
+</metafile>\r
index 526de29f98c5356b74ca17bb8fb0c79c9c904a71..f9f25dd4bf435afa669f6ca9720a2708f7b178a1 100644 (file)
@@ -301,9 +301,7 @@ for HTTP Basic authentication.</description>
     <p>If this directive exists, <module>mod_authnz_ldap</module> grants
     access to any user that has successfully authenticated during the
     search/bind phase.  Requires that <module>mod_authz_user</module> be 
-    loaded and that the 
-    <directive module="mod_authnz_ldap">AuthzLDAPAuthoritative</directive>
-    directive be set to off.</p>
+    loaded.</p>
 </section>
 
 <section id="requser"><title>require ldap-user</title>
@@ -573,17 +571,10 @@ require valid-user
     that gets created in the web</p>
 <example><pre>
 AuthLDAPURL            "the url"
-AuthzLDAPAuthoritative off
 AuthGroupFile <em>mygroupfile</em>
 require group <em>mygroupfile</em>
 </pre></example>
 
-    <p><directive module="mod_authnz_ldap">AuthzLDAPAuthoritative</directive> 
-    must be off to allow <module>mod_authnz_ldap</module> to decline group
-    authentication so that Apache will fall back to file
-    authentication for checking group membership. This allows the
-    FrontPage-managed group file to be used.</p>
-
 <section id="howitworks"><title>How It Works</title>
 
     <p>FrontPage restricts access to a web by adding the <code>require
@@ -643,25 +634,6 @@ require group <em>mygroupfile</em>
 </section>
 </section>
 
-<directivesynopsis>
-<name>AuthzLDAPAuthoritative</name>
-<description>Prevent other authentication modules from
-authenticating the user if this one fails</description>
-<syntax>AuthzLDAPAuthoritative on|off</syntax>
-<default>AuthzLDAPAuthoritative on</default>
-<contextlist><context>directory</context><context>.htaccess</context>
-</contextlist>
-<override>AuthConfig</override>
-
-<usage>
-    <p>Set to <code>off</code> if this module should let other
-    authentication modules attempt to authenticate the user, should
-    authentication with this module fail. Control is only passed on
-    to lower modules if there is no DN or rule that matches the
-    supplied user name (as passed by the client).</p>
-</usage>
-</directivesynopsis>
-
 <directivesynopsis>
 <name>AuthLDAPBindDN</name>
 <description>Optional DN to use in binding to the LDAP server</description>
diff --git a/docs/manual/mod/mod_authz_core.xml b/docs/manual/mod/mod_authz_core.xml
new file mode 100644 (file)
index 0000000..9faac24
--- /dev/null
@@ -0,0 +1,222 @@
+<?xml version="1.0"?>\r
+<!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">\r
+<?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>\r
+<!-- $LastChangedRevision: 151408 $ -->\r
+\r
+<!--\r
+ Copyright 2002-2005 The Apache Software Foundation or its licensors, as\r
+ applicable.\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+     http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+-->\r
+\r
+<modulesynopsis metafile="mod_authz_core.xml.meta">\r
+\r
+<name>mod_authz_core</name> \r
+<description>Core Authorization</description>\r
+<status>Base</status>\r
+<sourcefile>mod_authz_core.c</sourcefile>\r
+<identifier>authz_core_module</identifier>\r
+<compatibility>Available in Apache 2.3 and later</compatibility>\r
+\r
+<summary>\r
+    <p>This module provides core authorization capabilities so that\r
+    authenticated users can be allowed or denied access to portions\r
+    of the web site. <module>mod_authz_core</module> provides the \r
+    functionality to register various authorization providers. It is\r
+    usually used in conjunction with an authentication\r
+    provider module such as <module>mod_authn_file</module> and an \r
+    authorization module such as <module>mod_authz_user</module>. It\r
+    also allows for "AND" and "OR" logic to be applied to the \r
+    authorization processing.</p>\r
+</summary>\r
+\r
+<directivesynopsis>\r
+<name>Require</name>\r
+<description>Selects which authenticated users can access\r
+a resource</description>\r
+<syntax>Require <var>entity-name</var> [<var>entity-name</var>] ...</syntax>\r
+<contextlist><context>directory</context><context>.htaccess</context>\r
+</contextlist>\r
+<override>AuthConfig</override>\r
+\r
+<usage>\r
+    <p>This directive selects which authenticated users can access a\r
+    resource.  The restrictions are processed by authorization\r
+    modules.  Some of the allowed syntaxes provided by\r
+    <module>mod_authz_user</module> and\r
+    <module>mod_authz_groupfile</module> are:</p>\r
+\r
+    <dl>\r
+      <dt><code>Require user <var>userid</var> [<var>userid</var>]\r
+      ...</code></dt>\r
+      <dd>Only the named users can access the resource.</dd>\r
+\r
+      <dt><code>Require group <var>group-name</var> [<var>group-name</var>]\r
+      ...</code></dt>\r
+      <dd>Only users in the named groups can access the resource.</dd>\r
+\r
+      <dt><code>Require valid-user</code></dt>\r
+      <dd>All valid users can access the resource.</dd>\r
+    </dl>\r
+\r
+    <p>Other authorization modules that implement require options\r
+    include <module>mod_authnz_ldap</module>,\r
+    <module>mod_authz_dbm</module>, <module>mod_authz_dbd</module>, \r
+    <module>mod_authz_host</module>, and\r
+    <module>mod_authz_owner</module>.</p>\r
+\r
+    <p>For a complete authentication and authorization configuration, \r
+    <directive>Require</directive> must be accompanied by\r
+    <directive module="mod_authn_core">AuthName</directive>, <directive\r
+    module="mod_authn_core">AuthType</directive> and \r
+    <directive module="mod_auth_basic">AuthBasicProvider</directive> \r
+    directives, and directives such as \r
+    <directive module="mod_authn_file">AuthUserFile</directive>\r
+    and <directive module="mod_authz_groupfile">AuthGroupFile</directive> (to\r
+    define users and groups) in order to work correctly. Example:</p>\r
+\r
+    <example>\r
+       AuthType Basic<br />\r
+       AuthName "Restricted Resource"<br />\r
+       AuthBasicProvider file<br />\r
+       AuthUserFile /web/users<br />\r
+       AuthGroupFile /web/groups<br />\r
+       Require group admin\r
+    </example>\r
+\r
+    <p>Access controls which are applied in this way are effective for\r
+    <strong>all</strong> methods. <strong>This is what is normally\r
+    desired.</strong> If you wish to apply access controls only to\r
+    specific methods, while leaving other methods unprotected, then\r
+    place the <directive>Require</directive> statement into a\r
+    <directive module="core" type="section">Limit</directive>\r
+    section.</p>\r
\r
+</usage>\r
+\r
+<seealso><a href="../howto/auth.html">Authentication, Authorization,\r
+    and Access Control</a></seealso> \r
+<seealso><module>mod_authz_host</module></seealso>\r
+</directivesynopsis>\r
+\r
+<directivesynopsis>\r
+<name>Reject</name>\r
+<description>Rejects which authenticated users can access\r
+a resource</description>\r
+<syntax>Reject <var>entity-name</var> [<var>entity-name</var>] ...</syntax>\r
+<contextlist><context>directory</context><context>.htaccess</context>\r
+</contextlist>\r
+<override>AuthConfig</override>\r
+\r
+<usage>\r
+    <p>This directive is similar to the \r
+    <directive module="mod_authz_core">Require</directive> directive however\r
+    it rejects which authenticated users can access a resource.  The \r
+    restrictions are processed by authorization modules.  See the \r
+    <directive module="mod_authz_core">Require</directive> directive for details \r
+    about usage.</p>\r
+</usage>\r
+\r
+<seealso><a href="../howto/auth.html">Authentication, Authorization,\r
+    and Access Control</a></seealso> \r
+<seealso><module>mod_authz_host</module></seealso>\r
+</directivesynopsis>\r
+\r
+<directivesynopsis type="section">\r
+<name>SatisfyAll</name>\r
+<description>Enclose a group of authorization directives that must all\r
+be satisfied in order to grant access to a resource.  This block allows\r
+for 'AND' logic to be applied to various authorization providers.</description>\r
+<syntax>&lt;SatisfyAll&gt;\r
+... &lt;/SatisfyAll&gt;</syntax>\r
+<contextlist><context>directory</context><context>.htaccess</context>\r
+</contextlist>\r
+<override>AuthConfig</override>\r
+\r
+<usage>\r
+    <p><directive type="section">SatisfyAll</directive> and\r
+    <code>&lt;/SatisfyAll&gt;</code> are used to enclose a group of\r
+    authorization directives that must all be satisfied in order to \r
+    grant access to a resource.</p>\r
+\r
+    <p>The <directive module="mod_authz_core">\r
+    &lt;SatisfyAll&gt;</directive> block as well as the \r
+    <directive module="mod_authz_core">&lt;SatisfyOne&gt;</directive> block \r
+    allow you to apply "AND" and "OR" logic to the authorization processing. \r
+    For example the following authorization block would apply the logic:</p>\r
+\r
+    <p><var>\r
+    if ((user == "John") || <br />\r
+    &nbsp;&nbsp;&nbsp;((Group == "admin") &amp;&amp; (ldap-group &lt;ldap-object&gt; contains auth'ed_user) &amp;&amp;<br />\r
+    &nbsp;&nbsp;&nbsp;&nbsp;((ldap-attribute dept == "sales") || \r
+    (file-group contains contains auth'ed_user))))<br />\r
+    then<br />\r
+    &nbsp;&nbsp;auth_granted<br />\r
+    else<br />\r
+    &nbsp;&nbsp;auth_denied<br />\r
+    </var></p>\r
+\r
+    <example>\r
+    &lt;Directory /www/mydocs&gt;<br />\r
+    &nbsp;  Authname ...<br />\r
+    &nbsp;  AuthBasicProvider ...<br />\r
+    &nbsp;  ...<br />\r
+    &nbsp;  Require user John<br />\r
+    &nbsp;  &lt;SatisfyAll&gt;<br />\r
+    &nbsp;&nbsp;    Require Group admins<br />\r
+    &nbsp;&nbsp;    Require ldap-group cn=mygroup,o=foo<br />\r
+    &nbsp;&nbsp;    &lt;SatisfyOne&gt;<br />\r
+    &nbsp;&nbsp;&nbsp;      Require ldap-attribute dept="sales"<br />\r
+    &nbsp;&nbsp;&nbsp;      Require file-group<br />\r
+    &nbsp;&nbsp;    &lt;/SatisfyOne&gt;<br />\r
+    &nbsp;  &lt;/SatisfyAll&gt;<br />\r
+    &lt;/Directory&gt;<br />\r
+    </example>\r
+\r
+</usage>\r
+\r
+<seealso><a href="../howto/auth.html">Authentication, Authorization,\r
+    and Access Control</a></seealso> \r
+\r
+</directivesynopsis>\r
+\r
+<directivesynopsis type="section">\r
+<name>SatisfyOne</name>\r
+<description>Enclose a group of authorization directives that must \r
+satisfy at least one in order to grant access to a resource.  This \r
+block allows for 'OR' logic to be applied to various authorization \r
+providers.</description>\r
+<syntax>&lt;SatisfyOne&gt;\r
+... &lt;/SatisfyOne&gt;</syntax>\r
+<contextlist><context>directory</context><context>.htaccess</context>\r
+</contextlist>\r
+<override>AuthConfig</override>\r
+\r
+<usage>\r
+    <p><directive type="section">SatisfyOne</directive> and\r
+    <code>&lt;/SatisfyOne&gt;</code> are used to enclose a group of\r
+    authorization directives that must satisfy at least one in order to \r
+    grant access to a resource.</p>\r
+\r
+    <p>See the <directive module="mod_authz_core">\r
+    &lt;SatisfyAll&gt;</directive> directive for a usage example.</p>\r
+\r
+</usage>\r
+\r
+<seealso><a href="../howto/auth.html">Authentication, Authorization,\r
+    and Access Control</a></seealso> \r
+\r
+</directivesynopsis>\r
+\r
+</modulesynopsis>\r
diff --git a/docs/manual/mod/mod_authz_core.xml.meta b/docs/manual/mod/mod_authz_core.xml.meta
new file mode 100644 (file)
index 0000000..b2bef72
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" ?>\r
+\r
+<metafile>\r
+  <basename>mod_authz_core</basename>\r
+  <path>/mod/</path>\r
+  <relpath>..</relpath>\r
+\r
+  <variants>\r
+    <variant>en</variant>\r
+  </variants>\r
+</metafile>\r
index 6002c86aee5097f5599680e82bb71613130b68d0..03cf4ba910d4b234a1816dc727efb97073cfaedd 100644 (file)
@@ -38,7 +38,6 @@
 </summary>
 
 <seealso><directive module="core">Require</directive></seealso>
-<seealso><directive module="core">Satisfy</directive></seealso>
 <seealso><directive module="mod_dbd">DBDriver</directive></seealso>
 <seealso><directive module="mod_dbd">DBDParams</directive></seealso>
 
@@ -182,40 +181,4 @@ header is present</description>
 </usage>
 </directivesynopsis>
 
-<directivesynopsis>
-<name>AuthzDBDAuthoritative</name>
-<description>Sets whether authorization will be passed on to lower level
-modules</description>
-<syntax>AuthzDBDAuthoritative On|Off</syntax>
-<default>AuthzDBDAuthoritative On</default>
-<contextlist><context>directory</context></contextlist>
-
-<usage>
-    <p>Setting the <directive>AuthzDBDAuthoritative</directive>
-    directive explicitly to <code>Off</code> allows group authorization
-    to be handled by another authz module if the userID is not
-    in any authorized dbd-group. If there are any groups
-    specified, the usual checks will be applied and a failure will
-    give an Authentication Required reply.</p>
-
-    <p>So if a userID appears in the database of more than one module;
-    or if a valid <directive module="core">Require</directive>
-    directive applies to more than one module; then the first module
-    will verify the credentials; and no access is passed on;
-    regardless of the <directive>AuthAuthoritative</directive> setting.</p>
-
-    <p>A common use for this is in conjunction with one of the
-    auth providers; such or
-    <module>mod_authn_file</module>. Whereas this DBD module supplies
-    the bulk of the user credential checking; a few (administrator) related
-    accesses fall through to a lower level with a well protected
-    <code>.htpasswd</code> file.</p>
-
-    <p>By default, control is not passed on and an unknown group
-    will result in an Authentication Required reply. Not
-    setting it thus keeps the system secure and forces an NCSA
-    compliant behaviour.</p>
-</usage>
-</directivesynopsis>
-
 </modulesynopsis>
index 6d6ca04ff3616b6927d67d6547301fd5573f5c8b..f53029c623543d2fe028181535d1ab3c79d3bc4a 100644 (file)
@@ -37,7 +37,6 @@
 </summary>
 
 <seealso><directive module="core">Require</directive></seealso>
-<seealso><directive module="core">Satisfy</directive></seealso>
 
 <directivesynopsis>
 <name>AuthDBMGroupFile</name>
@@ -119,51 +118,4 @@ store list of user groups</description>
 </usage>
 </directivesynopsis>
 
-<directivesynopsis>
-<name>AuthzDBMAuthoritative</name>
-<description>Sets whether authorization will be passed on to lower level
-modules</description>
-<syntax>AuthzDBMAuthoritative On|Off</syntax>
-<default>AuthzDBMAuthoritative On</default>
-<contextlist><context>directory</context><context>.htaccess</context>
-</contextlist>
-<override>AuthConfig</override>
-
-<usage>
-    <p>Setting the <directive>AuthzDBMAuthoritative</directive>
-    directive explicitly to <code>Off</code> allows group authorization
-    to be passed on to lower level modules (as defined in the
-    <code>modules.c</code> file) if there is no group found
-    for the the supplied userID. If there are any groups
-    specified, the usual checks will be applied and a failure will
-    give an Authentication Required reply.</p>
-
-    <p>So if a userID appears in the database of more than one module;
-    or if a valid <directive module="core">Require</directive>
-    directive applies to more than one module; then the first module
-    will verify the credentials; and no access is passed on;
-    regardless of the <directive>AuthAuthoritative</directive> setting.</p>
-
-    <p>A common use for this is in conjunction with one of the
-    auth providers; such as <module>mod_authn_dbm</module> or
-    <module>mod_authn_file</module>. Whereas this DBM module supplies
-    the bulk of the user credential checking; a few (administrator) related
-    accesses fall through to a lower level with a well protected
-    <code>.htpasswd</code> file.</p>
-
-    <p>By default, control is not passed on and an unknown group
-    will result in an Authentication Required reply. Not
-    setting it thus keeps the system secure and forces an NCSA
-    compliant behaviour.</p>
-
-    <note type="warning"><title>Security</title>
-      <p>Do consider the implications of allowing a user to
-      allow fall-through in his .htaccess file; and verify that this
-      is really what you want; Generally it is easier to just secure
-      a single <code>.htpasswd</code> file, than it is to secure a
-      database which might have more access interfaces.</p>
-    </note>
-</usage>
-</directivesynopsis>
-
 </modulesynopsis>
index d3aed88d6649a493354f897226752e607cd7b697..b590113a628997640409182e577bfafb3513a749 100644 (file)
@@ -37,7 +37,6 @@
 </summary>
 
 <seealso><directive module="core">Require</directive></seealso>
-<seealso><directive module="core">Satisfy</directive></seealso>
 
 <directivesynopsis>
 <name>AuthGroupFile</name>
@@ -75,36 +74,4 @@ of user groups for authorization</description>
 </usage>
 </directivesynopsis>
 
-<directivesynopsis>
-<name>AuthzGroupFileAuthoritative</name>
-<description>Sets whether authorization will be passed on to lower level
-modules</description>
-<syntax>AuthzGroupFileAuthoritative On|Off</syntax>
-<default>AuthzGroupFileAuthoritative On</default>
-<contextlist><context>directory</context><context>.htaccess</context>
-</contextlist>
-<override>AuthConfig</override>
-
-<usage>
-    <p>Setting the <directive>AuthzGroupFileAuthoritative</directive>
-    directive explicitly to <code>Off</code> allows for
-    group authorization to be passed on to lower level modules (as defined
-    in the <code>modules.c</code> files) if there is <strong>no
-    group</strong> matching the supplied userID.</p>
-
-    <p>By default, control is not passed on and an unknown group
-    will result in an Authentication Required reply. Not
-    setting it thus keeps the system secure and forces an NCSA
-    compliant behaviour.</p>
-
-    <note type="warning"><title>Security</title>
-      <p>Do consider the implications of allowing a user to
-      allow fall-through in his <code>.htaccess</code> file; and verify
-      that this is really what you want; Generally it is easier to just
-      secure a single <code>.htpasswd</code> file, than it is to secure
-      a database which might have more access interfaces.</p>
-    </note>
-</usage>
-</directivesynopsis>
-
 </modulesynopsis>
index 915aaecc6a8a494bbe406885311320aa9c6b5fe1..89f332bfbcf5ed9eb1e83eb01a8be51a81b30071 100644 (file)
@@ -28,31 +28,21 @@ address)</description>
 <status>Base</status>
 <sourcefile>mod_authz_host.c</sourcefile>
 <identifier>authz_host_module</identifier>
-<compatibility>Available in Apache 2.1 and later</compatibility>
+<compatibility>Available in Apache 2.3 and later</compatibility>
 
 <summary>
-    <p>The directives provided by <module>mod_authz_host</module> are
-    used in <directive module="core" type="section">Directory</directive>,
-    <directive module="core" type="section">Files</directive>, and
-    <directive module="core" type="section">Location</directive> sections
+    <p>The authorization providers implemented by <module>mod_authz_host</module> are
+    registered using the <directive module="mod_authz_core">Require</directive> or
+    <directive module="mod_authz_core">Reject</directive> directives.  These 
+    directives can be referenced within a 
+    <directive module="core" type="section">Directory</directive>,
+    <directive module="core" type="section">Files</directive>, 
+    or <directive module="core" type="section">Location</directive> section
     as well as <code><a href="core.html#accessfilename">.htaccess</a>
     </code> files to control access to particular parts of the server.
     Access can be controlled based on the client hostname, IP address, or
     other characteristics of the client request, as captured in <a
-    href="../env.html">environment variables</a>. The <directive
-    module="mod_authz_host">Allow</directive> and <directive
-    module="mod_authz_host">Deny</directive> directives are used to
-    specify which clients are or are not allowed access to the server,
-    while the <directive module="mod_authz_host">Order</directive>
-    directive sets the default access state, and configures how the
-    <directive module="mod_authz_host">Allow</directive> and <directive
-    module="mod_authz_host">Deny</directive> directives interact with each
-    other.</p>
-
-    <p>Both host-based access restrictions and password-based
-    authentication may be implemented simultaneously. In that case,
-    the <directive module="core">Satisfy</directive> directive is used
-    to determine how the two sets of restrictions interact.</p>
+    href="../env.html">environment variables</a>.</p>
 
     <p>In general, access restriction directives apply to all
     access methods (<code>GET</code>, <code>PUT</code>,
@@ -62,111 +52,33 @@ address)</description>
     in a <directive module="core" type="section">Limit</directive> section.</p>
 </summary>
 
-<seealso><directive module="core">Satisfy</directive></seealso>
-<seealso><directive module="core">Require</directive></seealso>
-
-<directivesynopsis>
-<name>Allow</name>
-<description>Controls which hosts can access an area of the
-server</description>
-<syntax> Allow from all|<var>host</var>|env=<var>env-variable</var>
-[<var>host</var>|env=<var>env-variable</var>] ...</syntax>
-<contextlist><context>directory</context><context>.htaccess</context>
-</contextlist>
-<override>Limit</override>
-
-<usage>
-    <p>The <directive>Allow</directive> directive affects which hosts can
+<seealso><a href="../howto/auth.html">Authentication, Authorization,
+    and Access Control</a></seealso> 
+<seealso><directive module="mod_authz_core">Require</directive></seealso>
+<seealso><directive module="mod_authz_core">Reject</directive></seealso>
+
+<section id="requiredirectives"><title>The require Directives</title>
+
+    <p>Apache's <directive module="mod_authz_core">Require</directive> and 
+    <directive module="mod_authz_core">Reject</directive> directives are 
+    used during the authorization phase to ensure that a user is allowed or
+    denied access to a resource.  mod_authz_host extends the 
+    authorization types with <code>env</code>, <code>ip</code>, 
+    <code>host</code> and <code>all</code>.  Other authorization types may also be 
+    used but may require that additional authorization modules be loaded.</p>
+
+    <p>These authorization providers affect which hosts can
     access an area of the server. Access can be controlled by
     hostname, IP Address, IP Address range, or by other
     characteristics of the client request captured in environment
     variables.</p>
 
-    <p>The first argument to this directive is always
-    <code>from</code>. The subsequent arguments can take three
-    different forms. If <code>Allow from all</code> is specified, then
-    all hosts are allowed access, subject to the configuration of the
-    <directive module="mod_authz_host">Deny</directive> and <directive
-    module="mod_authz_host">Order</directive> directives as discussed
-    below. To allow only particular hosts or groups of hosts to access
-    the server, the <em>host</em> can be specified in any of the
-    following formats:</p>
-
-    <dl>
-      <dt>A (partial) domain-name</dt>
-
-      <dd>
-      <example><title>Example:</title>
-        Allow from apache.org<br />
-        Allow from .net example.edu
-      </example>
-      <p>Hosts whose names match, or end in, this string are allowed
-      access. Only complete components are matched, so the above
-      example will match <code>foo.apache.org</code> but it will not
-      match <code>fooapache.org</code>. This configuration will cause
-      Apache to perform a double reverse DNS lookup on the client IP
-      address, regardless of the setting of the <directive
-      module="core">HostnameLookups</directive> directive.  It will do
-      a reverse DNS lookup on the IP address to find the associated
-      hostname, and then do a forward lookup on the hostname to assure
-      that it matches the original IP address.  Only if the forward
-      and reverse DNS are consistent and the hostname matches will
-      access be allowed.</p></dd>
-
-      <dt>A full IP address</dt>
-
-      <dd>
-      <example><title>Example:</title>
-        Allow from 10.1.2.3<br />
-        Allow from 192.168.1.104 192.168.1.205
-      </example>
-      <p>An IP address of a host allowed access</p></dd>
-
-      <dt>A partial IP address</dt>
-
-      <dd>
-      <example><title>Example:</title>
-        Allow from 10.1<br />
-        Allow from 10 172.20 192.168.2
-      </example>
-      <p>The first 1 to 3 bytes of an IP address, for subnet
-      restriction.</p></dd>
-
-      <dt>A network/netmask pair</dt>
-
-      <dd>
-      <example><title>Example:</title>
-        Allow from 10.1.0.0/255.255.0.0
-      </example>
-      <p>A network a.b.c.d, and a netmask w.x.y.z. For more
-      fine-grained subnet restriction.</p></dd>
-
-      <dt>A network/nnn CIDR specification</dt>
-
-      <dd>
-      <example><title>Example:</title>
-        Allow from 10.1.0.0/16
-      </example>
-      <p>Similar to the previous case, except the netmask consists of
-      nnn high-order 1 bits.</p></dd>
-    </dl>
-
-    <p>Note that the last three examples above match exactly the
-    same set of hosts.</p>
+<section id="reqenv"><title>require env</title>
 
-    <p>IPv6 addresses and IPv6 subnets can be specified as shown
-    below:</p>
-
-    <example>
-       Allow from 2001:db8::a00:20ff:fea7:ccea<br />
-       Allow from 2001:db8::a00:20ff:fea7:ccea/10
-    </example>
-
-    <p>The third format of the arguments to the
-    <directive>Allow</directive> directive allows access to the server
+    <p>The <code>env</code> provider allows access to the server
     to be controlled based on the existence of an <a
-    href="../env.html">environment variable</a>. When <code>Allow from
-    env=<var>env-variable</var></code> is specified, then the request is
+    href="../env.html">environment variable</a>. When <code>Require 
+    env <var>env-variable</var></code> is specified, then the request is
     allowed access if the environment variable <var>env-variable</var>
     exists. The server provides the ability to set environment
     variables in a flexible way based on characteristics of the client
@@ -175,162 +87,126 @@ server</description>
     used to allow access based on such factors as the clients
     <code>User-Agent</code> (browser type), <code>Referer</code>, or
     other HTTP request header fields.</p>
-
+    
     <example><title>Example:</title>
       SetEnvIf User-Agent ^KnockKnock/2\.0 let_me_in<br />
       &lt;Directory /docroot&gt;<br />
       <indent>
-        Order Deny,Allow<br />
-        Deny from all<br />
-        Allow from env=let_me_in<br />
+        Require env let_me_in<br />
       </indent>
       &lt;/Directory&gt;
     </example>
-
+    
     <p>In this case, browsers with a user-agent string beginning
     with <code>KnockKnock/2.0</code> will be allowed access, and all
     others will be denied.</p>
-</usage>
-</directivesynopsis>
-
-<directivesynopsis>
-<name>Deny</name>
-<description>Controls which hosts are denied access to the
-server</description>
-<syntax> Deny from all|<var>host</var>|env=<var>env-variable</var>
-[<var>host</var>|env=<var>env-variable</var>] ...</syntax>
-<contextlist><context>directory</context><context>.htaccess</context>
-</contextlist>
-<override>Limit</override>
-
-<usage>
-    <p>This directive allows access to the server to be restricted
-    based on hostname, IP address, or environment variables. The
-    arguments for the <directive>Deny</directive> directive are
-    identical to the arguments for the <directive
-    module="mod_authz_host">Allow</directive> directive.</p>
-</usage>
-</directivesynopsis>
-
-<directivesynopsis>
-<name>Order</name>
-<description>Controls the default access state and the order in which
-<directive>Allow</directive> and <directive>Deny</directive> are
-evaluated.</description>
-<syntax> Order <var>ordering</var></syntax>
-<default>Order Deny,Allow</default>
-<contextlist><context>directory</context><context>.htaccess</context>
-</contextlist>
-<override>Limit</override>
-
-<usage>
-    <p>The <directive>Order</directive> directive controls the default
-    access state and the order in which <directive
-    module="mod_authz_host">Allow</directive> and <directive
-    module="mod_authz_host">Deny</directive> directives are evaluated.
-    <var>Ordering</var> is one of</p>
-
-    <dl>
-      <dt><code>Deny,Allow</code></dt>
-
-      <dd>The <directive module="mod_authz_host">Deny</directive> directives
-      are evaluated before the <directive
-      module="mod_authz_host">Allow</directive> directives. Access is
-      allowed by default. Any client which does not match a
-      <directive module="mod_authz_host">Deny</directive> directive or does
-      match an <directive module="mod_authz_host">Allow</directive>
-      directive will be allowed access to the server.</dd>
-
-      <dt><code>Allow,Deny</code></dt>
-
-      <dd>The <directive module="mod_authz_host">Allow</directive>
-      directives are evaluated before the <directive
-      module="mod_authz_host">Deny</directive> directives. Access is denied
-      by default. Any client which does not match an <directive
-      module="mod_authz_host">Allow</directive> directive or does match a
-      <directive module="mod_authz_host">Deny</directive> directive will be
-      denied access to the server.</dd>
-
-      <dt><code>Mutual-failure</code></dt>
-
-      <dd>Only those hosts which appear on the <directive
-      module="mod_authz_host">Allow</directive> list and do not appear on
-      the <directive module="mod_authz_host">Deny</directive> list are
-      granted access. This ordering has the same effect as <code>Order
-      Allow,Deny</code> and is deprecated in favor of that
-      configuration.</dd>
-    </dl>
-
-    <p>Keywords may only be separated by a comma; <em>no whitespace</em> is
-    allowed between them. Note that in all cases every <directive
-    module="mod_authz_host">Allow</directive> and <directive
-    module="mod_authz_host">Deny</directive> statement is evaluated.</p>
-
-    <p>In the following example, all hosts in the apache.org domain
-    are allowed access; all other hosts are denied access.</p>
 
+</section>
+
+<section id="reqip"><title>require ip</title>
+
+    <p>The <code>ip</code> provider allows access to the server
+    to be controlled based on the IP address of the remote client. 
+    When <code>Require ip <var>ip-address</var></code> is specified, 
+    then the request is allowed access if the IP address matches.</p>
+
+    <p>A full IP address:</p>
+    
     <example>
-      Order Deny,Allow<br />
-      Deny from all<br />
-      Allow from apache.org
+      Require ip 10.1.2.3<br />
+      Require ip 192.168.1.104 192.168.1.205
     </example>
 
-    <p>In the next example, all hosts in the apache.org domain are
-    allowed access, except for the hosts which are in the
-    foo.apache.org subdomain, who are denied access. All hosts not
-    in the apache.org domain are denied access because the default
-    state is to deny access to the server.</p>
+    <p>An IP address of a host allowed access</p>
+    
+    <p>A partial IP address:</p>
+    
+    <example>
+      Require ip 10.1<br />
+      Require ip 10 172.20 192.168.2
+    </example>
+    <p>The first 1 to 3 bytes of an IP address, for subnet
+    restriction.</p>
+    
+    <p>A network/netmask pair:</p>
+    
+    <example>
+      Require ip 10.1.0.0/255.255.0.0
+    </example>
+    <p>A network a.b.c.d, and a netmask w.x.y.z. For more
+    fine-grained subnet restriction.</p>
+    
+    <p>A network/nnn CIDR specification:</p>
+    
+    <example>
+      Require ip 10.1.0.0/16
+    </example>
+    <p>Similar to the previous case, except the netmask consists of
+    nnn high-order 1 bits.</p>
+    
+    <p>Note that the last three examples above match exactly the
+    same set of hosts.</p>
+    
+    <p>IPv6 addresses and IPv6 subnets can be specified as shown
+    below:</p>
+    
+    <example>
+     Require ip 2001:db8::a00:20ff:fea7:ccea<br />
+     Require ip 2001:db8::a00:20ff:fea7:ccea/10
+    </example>
+
+
+</section>
 
+<section id="reqhost"><title>require host</title>
+
+    <p>The <code>host</code> provider allows access to the server
+    to be controlled based on the host name of the remote client. 
+    When <code>Require host <var>host-name</var></code> is specified, 
+    then the request is allowed access if the host name matches.</p>
+
+    <p>A (partial) domain-name</p>
+    
     <example>
-      Order Allow,Deny<br />
-      Allow from apache.org<br />
-      Deny from foo.apache.org
+    Require host apache.org<br />
+    Require host .net example.edu
     </example>
+    
+    <p>Hosts whose names match, or end in, this string are allowed
+    access. Only complete components are matched, so the above
+    example will match <code>foo.apache.org</code> but it will not
+    match <code>fooapache.org</code>. This configuration will cause
+    Apache to perform a double reverse DNS lookup on the client IP
+    address, regardless of the setting of the <directive
+    module="core">HostnameLookups</directive> directive.  It will do
+    a reverse DNS lookup on the IP address to find the associated
+    hostname, and then do a forward lookup on the hostname to assure
+    that it matches the original IP address.  Only if the forward
+    and reverse DNS are consistent and the hostname matches will
+    access be allowed.</p>
+
+</section>
+
+<section id="reqall"><title>require all</title>
+
+    <p>The <code>all</code> provider mimics the functionality the
+    was previously provided by the 'Allow from all' and 'Deny from all'
+    directives.  This provider can take one of two arguments which are 
+    'granted' or 'denied'.  The following examples will grant or deny 
+    access to all requests.</p>
 
-    <p>On the other hand, if the <directive>Order</directive> in the last
-    example is changed to <code>Deny,Allow</code>, all hosts will
-    be allowed access. This happens because, regardless of the
-    actual ordering of the directives in the configuration file,
-    the <code>Allow from apache.org</code> will be evaluated last
-    and will override the <code>Deny from foo.apache.org</code>.
-    All hosts not in the <code>apache.org</code> domain will also
-    be allowed access because the default state will change to
-    <em>allow</em>.</p>
-
-    <p>The presence of an <directive>Order</directive> directive can affect
-    access to a part of the server even in the absence of accompanying
-    <directive module="mod_authz_host">Allow</directive> and <directive
-    module="mod_authz_host">Deny</directive> directives because of its effect
-    on the default access state. For example,</p>
+    <example>
+    Require all granted<br />
+    </example>
 
     <example>
-      &lt;Directory /www&gt;<br />
-      <indent>
-        Order Allow,Deny<br />
-      </indent>
-      &lt;/Directory&gt;
+    Require all denied<br />
     </example>
 
-    <p>will deny all access to the <code>/www</code> directory
-    because the default access state will be set to
-    <em>deny</em>.</p>
-
-    <p>The <directive>Order</directive> directive controls the order of access
-    directive processing only within each phase of the server's
-    configuration processing. This implies, for example, that an
-    <directive module="mod_authz_host">Allow</directive> or <directive
-    module="mod_authz_host">Deny</directive> directive occurring in a
-    <directive module="core" type="section">Location</directive> section will
-    always be evaluated after an <directive
-    module="mod_authz_host">Allow</directive> or <directive
-    module="mod_authz_host">Deny</directive> directive occurring in a
-    <directive module="core" type="section">Directory</directive> section or
-    <code>.htaccess</code> file, regardless of the setting of the
-    <directive>Order</directive> directive. For details on the merging
-    of configuration sections, see the documentation on <a
-    href="../sections.html">How Directory, Location and Files sections
-    work</a>.</p>
-</usage>
-</directivesynopsis>
+</section>
+
+
+</section>
+
 
 </modulesynopsis>
index 66e68954fe6acc024a8d838f87ba5032712d6c65..bff20aff2255cae40145a796cb271eb2dbcfd254 100644 (file)
@@ -70,7 +70,6 @@
     </note>
 </summary>
 <seealso><directive module="core">Require</directive></seealso>
-<seealso><directive module="core">Satisfy</directive></seealso>
 
 <section id="examples"><title>Configuration Examples</title>
 
@@ -93,7 +92,6 @@
           AuthName MyPrivateFiles<br />
           AuthBasicProvider dbm<br />
           AuthDBMUserFile /usr/local/apache2/etc/.htdbm-all<br />
-          Satisfy All<br />
           Require file-owner<br />
         </indent>
         &lt;/Directory&gt;
     </section>
 </section>
 
-<directivesynopsis>
-<name>AuthzOwnerAuthoritative</name>
-<description>Sets whether authorization will be passed on to lower level
-modules</description>
-<syntax>AuthzOwnerAuthoritative On|Off</syntax>
-<default>AuthzOwnerAuthoritative On</default>
-<contextlist><context>directory</context><context>.htaccess</context>
-</contextlist>
-<override>AuthConfig</override>
-
-<usage>
-    <p>Setting the <directive>AuthzOwnerAuthoritative</directive>
-    directive explicitly to <code>Off</code> allows for
-    user authorization to be passed on to lower level modules (as defined
-    in the <code>modules.c</code> files) if:</p>
-
-    <ul>
-    <li>in the case of <code>file-owner</code> the file-system owner does not
-    match the supplied web-username or could not be determined, or</li>
-
-    <li>in the case of <code>file-group</code> the file-system group does not
-    contain the supplied web-username or could not be determined.</li>
-    </ul>
-
-    <p>Note that setting the value to <code>Off</code> also allows the
-    combination of <code>file-owner</code> and <code>file-group</code>, so
-    access will be allowed if either one or the other (or both) match.</p>
-
-    <p>By default, control is not passed on and an authorization failure
-    will result in an "Authentication Required" reply. Not
-    setting it to <code>Off</code> thus keeps the system secure and forces
-    an NCSA compliant behaviour.</p>
-</usage>
-</directivesynopsis>
-
 </modulesynopsis>
index c9d006971b6dfab987c582848ff4d8ca5e939b5e..35703b6f8be3661cd8a39aae11bc5febbb4e3123 100644 (file)
     grant access to all successfully authenticated users.</p>
 </summary>
 <seealso><directive module="core">Require</directive></seealso>
-<seealso><directive module="core">Satisfy</directive></seealso>
-
-<directivesynopsis>
-<name>AuthzUserAuthoritative</name>
-<description>Sets whether authorization will be passed on to lower level
-modules</description>
-<syntax>AuthzUserAuthoritative On|Off</syntax>
-<default>AuthzUserAuthoritative On</default>
-<contextlist><context>directory</context><context>.htaccess</context>
-</contextlist>
-<override>AuthConfig</override>
-
-<usage>
-    <p>Setting the <directive>AuthzUserAuthoritative</directive>
-    directive explicitly to <code>Off</code> allows for
-    user authorization to be passed on to lower level modules (as defined
-    in the <code>modules.c</code> files) if there is <strong>no
-    user</strong> matching the supplied userID.</p>
-
-    <p>By default, control is not passed on and an unknown user
-    will result in an Authentication Required reply. Not
-    setting it to <code>Off</code> thus keeps the system secure and forces
-    an NCSA compliant behaviour.</p>
-</usage>
-</directivesynopsis>
 
 </modulesynopsis>
index a432341de14e1bb48cb1f5cb4d1a186c2f0647d4..b22cadb228b134195897827dfec96d646226c42b 100644 (file)
@@ -81,7 +81,6 @@ by other LDAP modules</description>
         Allow from yourdomain.example.com<br />
         AuthLDAPEnabled on<br />
         AuthLDAPURL ldap://127.0.0.1/dc=example,dc=com?uid?one<br />
-        AuthLDAPAuthoritative on<br />
         require valid-user<br />
       </indent>
       &lt;/Location&gt;
@@ -212,7 +211,6 @@ by other LDAP modules</description>
         Allow from yourdomain.example.com<br />
         AuthLDAPEnabled on<br />
         AuthLDAPURL ldaps://127.0.0.1/dc=example,dc=com?uid?one<br />
-        AuthLDAPAuthoritative on<br />
         require valid-user<br />
       </indent>
       &lt;/Location&gt;
@@ -234,7 +232,6 @@ by other LDAP modules</description>
         AuthLDAPEnabled on<br />
         LDAPTrustedMode TLS
         AuthLDAPURL ldap://127.0.0.1/dc=example,dc=com?uid?one<br />
-        AuthLDAPAuthoritative on<br />
         require valid-user<br />
       </indent>
       &lt;/Location&gt;
@@ -287,7 +284,6 @@ by other LDAP modules</description>
                 AuthLDAPEnabled on<br />
                 LDAPTrustedClientCert CERT_NICKNAME &lt;nickname&gt; [password]<br />
                 AuthLDAPURL ldaps://127.0.0.1/dc=example,dc=com?uid?one<br />
-                AuthLDAPAuthoritative on<br />
                 require valid-user<br />
             </indent>
             &lt;/Location&gt;
@@ -355,7 +351,6 @@ by other LDAP modules</description>
                 LDAPTrustedClientCert CERT_BASE64 /certs/cert1.pem<br />
                 LDAPTrustedClientCert KEY_BASE64 /certs/key1.pem<br />
                 AuthLDAPURL ldaps://127.0.0.1/dc=example,dc=com?uid?one<br />
-                AuthLDAPAuthoritative on<br />
                 require valid-user<br />
             </indent>
             &lt;/Location&gt;
index 2c6bf7fa5799d759256187edfc071fc16da7a1b6..e6ca34309e6bf3037b0b3850377e85b363347768 100644 (file)
  * 20051115.0 (2.3.0-dev) Added use_canonical_phys_port to core_dir_config
  * 20051231.0 (2.3.0-dev) Added num_blank_lines, pending_header_line, and
  *                        pending_header_size to request_rec
+ * 20060110.0 (2.3.0-dev) Conversion of Authz to be provider based 
+                          addition of <SatisfyAll><SatisfyOne>
+                          removal of Satisfy, Allow, Deny, Order
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
 
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
-#define MODULE_MAGIC_NUMBER_MAJOR 20051231
+#define MODULE_MAGIC_NUMBER_MAJOR 20060110
 #endif
 #define MODULE_MAGIC_NUMBER_MINOR 0                     /* 0...n */
 
index 62f9e95e4093d327fb4c85edd8a28706c6855d43..44f2410a1423bdff5e5b314687b1a580b8c1cdc8 100644 (file)
@@ -114,13 +114,6 @@ extern "C" {
 
 /** @} // get_remote_host */
 
-/** all of the requirements must be met */
-#define SATISFY_ALL 0
-/**  any of the requirements must be met */
-#define SATISFY_ANY 1
-/** There are no applicable satisfy lines */
-#define SATISFY_NOSPEC 2
-
 /** Make sure we don't write less than 8000 bytes at any one time.
  */
 #define AP_MIN_BYTES_TO_WRITE  8000
@@ -294,25 +287,6 @@ AP_DECLARE(const char *) ap_auth_type(request_rec *r);
  */
 AP_DECLARE(const char *) ap_auth_name(request_rec *r);     
 
-/**
- * How the requires lines must be met.
- * @param r The current request
- * @return How the requirements must be met.  One of:
- * <pre>
- *      SATISFY_ANY    -- any of the requirements must be met.
- *      SATISFY_ALL    -- all of the requirements must be met.
- *      SATISFY_NOSPEC -- There are no applicable satisfy lines
- * </pre>
- */
-AP_DECLARE(int) ap_satisfies(request_rec *r);
-
-/**
- * Retrieve information about all of the requires directives for this request
- * @param r The current request
- * @return An array of all requires directives for this request
- */
-AP_DECLARE(const apr_array_header_t *) ap_requires(request_rec *r);    
-
 #ifdef CORE_PRIVATE
 
 /**
@@ -451,13 +425,6 @@ typedef struct {
     
     char *ap_default_type;
   
-    /* Authentication stuff.  Groan... */
-    
-    int *satisfy; /* for every method one */
-    char *ap_auth_type;
-    char *ap_auth_name;
-    apr_array_header_t *ap_requires;
-
     /* Custom response config. These can contain text or a URL to redirect to.
      * if response_code_strings is NULL then there are none in the config,
      * if it's not null then it's allocated to sizeof(char*)*RESPONSE_CODES.
@@ -680,6 +647,15 @@ APR_DECLARE_OPTIONAL_FN(void, ap_logio_add_bytes_out,
 APR_DECLARE_OPTIONAL_FN(const char *, ap_ident_lookup,
                         (request_rec *r));
 
+/* ----------------------------------------------------------------------
+ *
+ * authorization values with mod_authz_host
+ */
+
+APR_DECLARE_OPTIONAL_FN(int, authz_some_auth_required, (request_rec *r));
+APR_DECLARE_OPTIONAL_FN(const char *, authn_ap_auth_type, (request_rec *r));
+APR_DECLARE_OPTIONAL_FN(const char *, authn_ap_auth_name, (request_rec *r));
+
 /* ---------------------------------------------------------------------- */
 
 #ifdef __cplusplus
diff --git a/modules/aaa/NWGNUauthncore b/modules/aaa/NWGNUauthncore
new file mode 100644 (file)
index 0000000..e86b694
--- /dev/null
@@ -0,0 +1,250 @@
+#\r
+# Make sure all needed macro's are defined\r
+#\r
+\r
+#\r
+# Get the 'head' of the build environment if necessary.  This includes default\r
+# targets and paths to tools\r
+#\r
+\r
+ifndef EnvironmentDefined\r
+include $(AP_WORK)\build\NWGNUhead.inc\r
+endif\r
+\r
+#\r
+# These directories will be at the beginning of the include list, followed by\r
+# INCDIRS\r
+#\r
+XINCDIRS       += \\r
+                       $(AP_WORK)/include \\r
+                       $(NWOS) \\r
+                       $(AP_WORK)/modules/arch/netware \\r
+                       $(APR)/include \\r
+                       $(APRUTIL)/include \\r
+                       $(APR) \\r
+                       $(EOLIST)\r
+\r
+#\r
+# These flags will come after CFLAGS\r
+#\r
+XCFLAGS                += \\r
+                       -prefix pre_nw.h \\r
+                       $(EOLIST)\r
+\r
+#\r
+# These defines will come after DEFINES\r
+#\r
+XDEFINES       += \\r
+                       $(EOLIST)\r
+\r
+#\r
+# These flags will be added to the link.opt file\r
+#\r
+XLFLAGS                += \\r
+                       $(EOLIST)\r
+\r
+#\r
+# These values will be appended to the correct variables based on the value of\r
+# RELEASE\r
+#\r
+ifeq "$(RELEASE)" "debug"\r
+XINCDIRS       += \\r
+                       $(EOLIST)\r
+\r
+XCFLAGS                += \\r
+                       $(EOLIST)\r
+\r
+XDEFINES       += \\r
+                       $(EOLIST)\r
+\r
+XLFLAGS                += \\r
+                       $(EOLIST)\r
+endif\r
+\r
+ifeq "$(RELEASE)" "noopt"\r
+XINCDIRS       += \\r
+                       $(EOLIST)\r
+\r
+XCFLAGS                += \\r
+                       $(EOLIST)\r
+\r
+XDEFINES       += \\r
+                       $(EOLIST)\r
+\r
+XLFLAGS                += \\r
+                       $(EOLIST)\r
+endif\r
+\r
+ifeq "$(RELEASE)" "release"\r
+XINCDIRS       += \\r
+                       $(EOLIST)\r
+\r
+XCFLAGS                += \\r
+                       $(EOLIST)\r
+\r
+XDEFINES       += \\r
+                       $(EOLIST)\r
+\r
+XLFLAGS                += \\r
+                       $(EOLIST)\r
+endif\r
+\r
+#\r
+# These are used by the link target if an NLM is being generated\r
+# This is used by the link 'name' directive to name the nlm.  If left blank\r
+# TARGET_nlm (see below) will be used.\r
+#\r
+NLM_NAME               = authncore\r
+\r
+#\r
+# This is used by the link '-desc ' directive. \r
+# If left blank, NLM_NAME will be used.\r
+#\r
+NLM_DESCRIPTION        = Apache $(VERSION_STR) Authentication Core Module\r
+\r
+#\r
+# This is used by the '-threadname' directive.  If left blank,\r
+# NLM_NAME Thread will be used.\r
+#\r
+NLM_THREAD_NAME        = AuthnCore Module\r
+\r
+#\r
+# If this is specified, it will override VERSION value in \r
+# $(AP_WORK)\build\NWGNUenvironment.inc\r
+#\r
+NLM_VERSION            =\r
+\r
+#\r
+# If this is specified, it will override the default of 64K\r
+#\r
+NLM_STACK_SIZE = 8192\r
+\r
+\r
+#\r
+# If this is specified it will be used by the link '-entry' directive\r
+#\r
+NLM_ENTRY_SYM  = _LibCPrelude\r
+\r
+#\r
+# If this is specified it will be used by the link '-exit' directive\r
+#\r
+NLM_EXIT_SYM   = _LibCPostlude\r
+\r
+#\r
+# If this is specified it will be used by the link '-check' directive\r
+#\r
+NLM_CHECK_SYM  =\r
+\r
+#\r
+# If these are specified it will be used by the link '-flags' directive\r
+#\r
+NLM_FLAGS              =  AUTOUNLOAD, PSEUDOPREEMPTION\r
+\r
+#\r
+# If this is specified it will be linked in with the XDCData option in the def \r
+# file instead of the default of $(NWOS)/apache.xdc.  XDCData can be disabled\r
+# by setting APACHE_UNIPROC in the environment\r
+#\r
+XDCDATA         = \r
+\r
+#\r
+# If there is an NLM target, put it here\r
+#\r
+TARGET_nlm = \\r
+       $(OBJDIR)/authncore.nlm \\r
+       $(EOLIST)\r
+\r
+#\r
+# If there is an LIB target, put it here\r
+#\r
+TARGET_lib = \\r
+       $(EOLIST)\r
+\r
+#\r
+# These are the OBJ files needed to create the NLM target above.\r
+# Paths must all use the '/' character\r
+#\r
+FILES_nlm_objs = \\r
+       $(OBJDIR)/mod_authn_core.o \\r
+       $(EOLIST)\r
+\r
+#\r
+# These are the LIB files needed to create the NLM target above.\r
+# These will be added as a library command in the link.opt file.\r
+#\r
+FILES_nlm_libs = \\r
+       libcpre.o \\r
+       $(EOLIST)\r
+\r
+#\r
+# These are the modules that the above NLM target depends on to load.\r
+# These will be added as a module command in the link.opt file.\r
+#\r
+FILES_nlm_modules = \\r
+       aprlib \\r
+       libc \\r
+       $(EOLIST)\r
+\r
+#\r
+# If the nlm has a msg file, put it's path here\r
+#\r
+FILE_nlm_msg =\r
\r
+#\r
+# If the nlm has a hlp file put it's path here\r
+#\r
+FILE_nlm_hlp =\r
+\r
+#\r
+# If this is specified, it will override $(NWOS)\copyright.txt.\r
+#\r
+FILE_nlm_copyright =\r
+\r
+#\r
+# Any additional imports go here\r
+#\r
+FILES_nlm_Ximports = \\r
+       @$(APR)/aprlib.imp \\r
+       @$(NWOS)/httpd.imp \\r
+       @libc.imp \\r
+       $(EOLIST)\r
\r
+#   \r
+# Any symbols exported to here\r
+#\r
+FILES_nlm_exports = \\r
+       authn_core_module \\r
+       $(EOLIST)\r
+       \r
+#   \r
+# These are the OBJ files needed to create the LIB target above.\r
+# Paths must all use the '/' character\r
+#\r
+FILES_lib_objs = \\r
+               $(EOLIST)\r
+\r
+#\r
+# implement targets and dependancies (leave this section alone)\r
+#\r
+\r
+libs :: $(OBJDIR) $(TARGET_lib)\r
+\r
+nlms :: libs $(TARGET_nlm)\r
+\r
+#\r
+# Updated this target to create necessary directories and copy files to the \r
+# correct place.  (See $(AP_WORK)\build\NWGNUhead.inc for examples)\r
+#\r
+install :: nlms FORCE\r
+\r
+#\r
+# Any specialized rules here\r
+#\r
+\r
+#\r
+# Include the 'tail' makefile that has targets that depend on variables defined\r
+# in this makefile\r
+#\r
+\r
+include $(AP_WORK)\build\NWGNUtail.inc\r
+\r
diff --git a/modules/aaa/NWGNUauthzcore b/modules/aaa/NWGNUauthzcore
new file mode 100644 (file)
index 0000000..01056f2
--- /dev/null
@@ -0,0 +1,250 @@
+#\r
+# Make sure all needed macro's are defined\r
+#\r
+\r
+#\r
+# Get the 'head' of the build environment if necessary.  This includes default\r
+# targets and paths to tools\r
+#\r
+\r
+ifndef EnvironmentDefined\r
+include $(AP_WORK)\build\NWGNUhead.inc\r
+endif\r
+\r
+#\r
+# These directories will be at the beginning of the include list, followed by\r
+# INCDIRS\r
+#\r
+XINCDIRS       += \\r
+                       $(AP_WORK)/include \\r
+                       $(NWOS) \\r
+                       $(AP_WORK)/modules/arch/netware \\r
+                       $(APR)/include \\r
+                       $(APRUTIL)/include \\r
+                       $(APR) \\r
+                       $(EOLIST)\r
+\r
+#\r
+# These flags will come after CFLAGS\r
+#\r
+XCFLAGS                += \\r
+                       -prefix pre_nw.h \\r
+                       $(EOLIST)\r
+\r
+#\r
+# These defines will come after DEFINES\r
+#\r
+XDEFINES       += \\r
+                       $(EOLIST)\r
+\r
+#\r
+# These flags will be added to the link.opt file\r
+#\r
+XLFLAGS                += \\r
+                       $(EOLIST)\r
+\r
+#\r
+# These values will be appended to the correct variables based on the value of\r
+# RELEASE\r
+#\r
+ifeq "$(RELEASE)" "debug"\r
+XINCDIRS       += \\r
+                       $(EOLIST)\r
+\r
+XCFLAGS                += \\r
+                       $(EOLIST)\r
+\r
+XDEFINES       += \\r
+                       $(EOLIST)\r
+\r
+XLFLAGS                += \\r
+                       $(EOLIST)\r
+endif\r
+\r
+ifeq "$(RELEASE)" "noopt"\r
+XINCDIRS       += \\r
+                       $(EOLIST)\r
+\r
+XCFLAGS                += \\r
+                       $(EOLIST)\r
+\r
+XDEFINES       += \\r
+                       $(EOLIST)\r
+\r
+XLFLAGS                += \\r
+                       $(EOLIST)\r
+endif\r
+\r
+ifeq "$(RELEASE)" "release"\r
+XINCDIRS       += \\r
+                       $(EOLIST)\r
+\r
+XCFLAGS                += \\r
+                       $(EOLIST)\r
+\r
+XDEFINES       += \\r
+                       $(EOLIST)\r
+\r
+XLFLAGS                += \\r
+                       $(EOLIST)\r
+endif\r
+\r
+#\r
+# These are used by the link target if an NLM is being generated\r
+# This is used by the link 'name' directive to name the nlm.  If left blank\r
+# TARGET_nlm (see below) will be used.\r
+#\r
+NLM_NAME               = authzcore\r
+\r
+#\r
+# This is used by the link '-desc ' directive. \r
+# If left blank, NLM_NAME will be used.\r
+#\r
+NLM_DESCRIPTION        = Apache $(VERSION_STR) Authorization Core Module\r
+\r
+#\r
+# This is used by the '-threadname' directive.  If left blank,\r
+# NLM_NAME Thread will be used.\r
+#\r
+NLM_THREAD_NAME        = AuthzCore Module\r
+\r
+#\r
+# If this is specified, it will override VERSION value in \r
+# $(AP_WORK)\build\NWGNUenvironment.inc\r
+#\r
+NLM_VERSION            =\r
+\r
+#\r
+# If this is specified, it will override the default of 64K\r
+#\r
+NLM_STACK_SIZE = 8192\r
+\r
+\r
+#\r
+# If this is specified it will be used by the link '-entry' directive\r
+#\r
+NLM_ENTRY_SYM  = _LibCPrelude\r
+\r
+#\r
+# If this is specified it will be used by the link '-exit' directive\r
+#\r
+NLM_EXIT_SYM   = _LibCPostlude\r
+\r
+#\r
+# If this is specified it will be used by the link '-check' directive\r
+#\r
+NLM_CHECK_SYM  =\r
+\r
+#\r
+# If these are specified it will be used by the link '-flags' directive\r
+#\r
+NLM_FLAGS              =  AUTOUNLOAD, PSEUDOPREEMPTION\r
+\r
+#\r
+# If this is specified it will be linked in with the XDCData option in the def \r
+# file instead of the default of $(NWOS)/apache.xdc.  XDCData can be disabled\r
+# by setting APACHE_UNIPROC in the environment\r
+#\r
+XDCDATA         = \r
+\r
+#\r
+# If there is an NLM target, put it here\r
+#\r
+TARGET_nlm = \\r
+       $(OBJDIR)/authzcore.nlm \\r
+       $(EOLIST)\r
+\r
+#\r
+# If there is an LIB target, put it here\r
+#\r
+TARGET_lib = \\r
+       $(EOLIST)\r
+\r
+#\r
+# These are the OBJ files needed to create the NLM target above.\r
+# Paths must all use the '/' character\r
+#\r
+FILES_nlm_objs = \\r
+       $(OBJDIR)/mod_authz_core.o \\r
+       $(EOLIST)\r
+\r
+#\r
+# These are the LIB files needed to create the NLM target above.\r
+# These will be added as a library command in the link.opt file.\r
+#\r
+FILES_nlm_libs = \\r
+       libcpre.o \\r
+       $(EOLIST)\r
+\r
+#\r
+# These are the modules that the above NLM target depends on to load.\r
+# These will be added as a module command in the link.opt file.\r
+#\r
+FILES_nlm_modules = \\r
+       aprlib \\r
+       libc \\r
+       $(EOLIST)\r
+\r
+#\r
+# If the nlm has a msg file, put it's path here\r
+#\r
+FILE_nlm_msg =\r
\r
+#\r
+# If the nlm has a hlp file put it's path here\r
+#\r
+FILE_nlm_hlp =\r
+\r
+#\r
+# If this is specified, it will override $(NWOS)\copyright.txt.\r
+#\r
+FILE_nlm_copyright =\r
+\r
+#\r
+# Any additional imports go here\r
+#\r
+FILES_nlm_Ximports = \\r
+       @$(APR)/aprlib.imp \\r
+       @$(NWOS)/httpd.imp \\r
+       @libc.imp \\r
+       $(EOLIST)\r
\r
+#   \r
+# Any symbols exported to here\r
+#\r
+FILES_nlm_exports = \\r
+       authz_core_module \\r
+       $(EOLIST)\r
+       \r
+#   \r
+# These are the OBJ files needed to create the LIB target above.\r
+# Paths must all use the '/' character\r
+#\r
+FILES_lib_objs = \\r
+               $(EOLIST)\r
+\r
+#\r
+# implement targets and dependancies (leave this section alone)\r
+#\r
+\r
+libs :: $(OBJDIR) $(TARGET_lib)\r
+\r
+nlms :: libs $(TARGET_nlm)\r
+\r
+#\r
+# Updated this target to create necessary directories and copy files to the \r
+# correct place.  (See $(AP_WORK)\build\NWGNUhead.inc for examples)\r
+#\r
+install :: nlms FORCE\r
+\r
+#\r
+# Any specialized rules here\r
+#\r
+\r
+#\r
+# Include the 'tail' makefile that has targets that depend on variables defined\r
+# in this makefile\r
+#\r
+\r
+include $(AP_WORK)\build\NWGNUtail.inc\r
+\r
index 0809983d53424ac2f38bac0290af44b77931c0a5..7756b0f11485bab2d62cede92dfb6d127fcd79d0 100644 (file)
@@ -156,10 +156,12 @@ TARGET_nlm = \
        $(OBJDIR)/authdigt.nlm \
        $(OBJDIR)/authnano.nlm \
        $(OBJDIR)/authnalias.nlm \
+       $(OBJDIR)/authncore.nlm \
        $(OBJDIR)/authndbm.nlm \
        $(OBJDIR)/authndef.nlm \
        $(OBJDIR)/authnfil.nlm \
        $(OBJDIR)/authndbd.nlm \
+       $(OBJDIR)/authzcore.nlm \
        $(OBJDIR)/authzdbm.nlm \
        $(OBJDIR)/authzdef.nlm \
        $(OBJDIR)/authzgrp.nlm \
index 314078736238053a412e9bed719f8cbb7902ce26..f7c01303a40bf1f2bee7851ce1db850ccd627dd3 100644 (file)
@@ -18,8 +18,10 @@ dnl - and just in case all of the above punt; a default handler to
 dnl keep the bad guys out.
 APACHE_MODULE(authn_default, authentication backstopper, , , yes)
 
-dnl Provider alias module.
-APACHE_MODULE(authn_alias, auth provider alias, , , no)
+dnl General Authentication modules; module which implements the 
+dnl non-authn module specific directives.
+dnl
+APACHE_MODULE(authn_core, core authentication module, , , yes)
 
 dnl Authorization modules: modules which verify a certain property such as
 dnl membership of a group, value of the IP address against a list of pre
@@ -33,6 +35,11 @@ APACHE_MODULE(authz_dbm, DBM-based authorization control, , , most)
 APACHE_MODULE(authz_owner, 'require file-owner' authorization control, , , most)
 APACHE_MODULE(authz_dbd, SQL based authorization and Login/Session support, , , most)
 
+dnl General Authorization modules; provider module which implements the 
+dnl non-authz module specific directives.
+dnl
+APACHE_MODULE(authz_core, core authorization provider vector module, , , yes)
+
 dnl LDAP authentication module. This module has both the authn and authz
 dnl modules in one, so as to share the LDAP server config directives.
 APACHE_MODULE(authnz_ldap, LDAP based authentication, , , no)
index ac44a423a31a7bef26a8c0cd8dfcf0c954466c37..0a413946e218ecf64c9921e9714a85c2a0805d64 100644 (file)
@@ -16,7 +16,7 @@
 
 /**
  * @file  mod_auth.h
- * @brief uthentication Extension Module for Apache
+ * @brief Authentication and Authorization Extension for Apache
  *
  * @defgroup MOD_AUTH mod_auth
  * @ingroup  APACHE_MODS
@@ -35,10 +35,13 @@ extern "C" {
 #endif
 
 #define AUTHN_PROVIDER_GROUP "authn"
+#define AUTHZ_PROVIDER_GROUP "authz"
 #define AUTHN_DEFAULT_PROVIDER "file"
-    
+#define AUTHZ_DEFAULT_PROVIDER "default"
+
 #define AUTHZ_GROUP_NOTE "authz_group_note"
 #define AUTHN_PROVIDER_NAME_NOTE "authn_provider_name"
+#define AUTHZ_PROVIDER_NAME_NOTE "authz_provider_name"
 
 typedef enum {
     AUTH_DENIED,
@@ -48,12 +51,23 @@ typedef enum {
     AUTH_GENERAL_ERROR
 } authn_status;
 
+typedef enum {
+    AUTHZ_DENIED,
+    AUTHZ_GRANTED,
+    AUTHZ_GENERAL_ERROR
+} authz_status;
+
+typedef enum {
+       AUTHZ_REQSTATE_ONE,
+       AUTHZ_REQSTATE_ALL
+} authz_request_state;
+
 typedef struct {
     /* Given a username and password, expected to return AUTH_GRANTED
      * if we can validate this user/password combination.
      */
     authn_status (*check_password)(request_rec *r, const char *user,
-                                  const char *password);
+                                   const char *password);
 
     /* Given a user and realm, expected to return AUTH_USER_FOUND if we
      * can find a md5 hash of 'user:realm:password'
@@ -72,10 +86,30 @@ struct authn_provider_list {
 };
 
 typedef struct {
-    /* For a given user, return a hash of all groups the user belongs to.  */
-    apr_hash_t * (*get_user_groups)(request_rec *r, const char *user);
+    /* Given a request_rec, expected to return AUTH_GRANTED
+     * if we can authorize user access.
+     */
+    authz_status (*check_authorization)(request_rec *r,
+                                        const char *require_line);
 } authz_provider;
 
+/* A linked-list of authn providers. */
+typedef struct authz_provider_list authz_provider_list;
+
+struct authz_provider_list {
+    const char *provider_name;
+    const authz_provider *provider;
+       authz_provider_list *one_next;
+       authz_provider_list *all_next;
+    /** If a Limit method is in effect, this field will be set */
+    apr_int64_t method_mask;
+       authz_request_state req_state;
+    int req_state_level;
+    /** String following 'require <provider>' from config file */
+    char *requirement;
+    int is_reject;
+};
+
 #ifdef __cplusplus
 }
 #endif
index c009af285506e2032735203b2bb8a2c840873597..b82cee5cfb3a9709d57c7de1632e72dd25bac442 100644 (file)
@@ -195,7 +195,7 @@ static int authenticate_basic_user(request_rec *r)
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    r->ap_auth_type = "Basic";
+    r->ap_auth_type = (char*)current_auth;
 
     res = get_basic_auth(r, &sent_user, &sent_pw);
     if (res) {
diff --git a/modules/aaa/mod_authn_core.c b/modules/aaa/mod_authn_core.c
new file mode 100644 (file)
index 0000000..b8e189e
--- /dev/null
@@ -0,0 +1,314 @@
+/* Copyright 2002-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Security options etc.
+ *
+ * Module derived from code originally written by Rob McCool
+ *
+ */
+
+#include "apr_strings.h"
+#include "apr_network_io.h"
+#define APR_WANT_STRFUNC
+#define APR_WANT_BYTEFUNC
+#include "apr_want.h"
+
+#define CORE_PRIVATE
+#include "ap_config.h"
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_request.h"
+#include "http_protocol.h"
+#include "ap_provider.h"
+
+#include "mod_auth.h"
+
+#if APR_HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+/* TODO List
+
+- Track down all of the references to r->ap_auth_type
+   and change them to ap_auth_type()
+- Remove ap_auth_type and ap_auth_name from the 
+   request_rec   
+
+*/
+
+typedef struct {
+    char *ap_auth_type;
+    char *ap_auth_name;
+} authn_core_dir_conf;
+
+typedef struct provider_alias_rec {
+    char *provider_name;
+    char *provider_alias;
+    ap_conf_vector_t *sec_auth;
+    const authn_provider *provider;
+} provider_alias_rec;
+
+typedef struct authn_alias_srv_conf {
+    apr_hash_t *alias_rec;
+} authn_alias_srv_conf;
+
+
+module AP_MODULE_DECLARE_DATA authn_core_module;
+
+static void *create_authn_core_dir_config(apr_pool_t *p, char *dummy)
+{
+    authn_core_dir_conf *conf =
+            (authn_core_dir_conf *)apr_pcalloc(p, sizeof(authn_core_dir_conf));
+
+    return (void *)conf;
+}
+
+static void *merge_authn_core_dir_config(apr_pool_t *a, void *basev, void *newv)
+{
+    authn_core_dir_conf *base = (authn_core_dir_conf *)basev;
+    authn_core_dir_conf *new = (authn_core_dir_conf *)newv;
+    authn_core_dir_conf *conf;
+
+    /* Create this conf by duplicating the base, replacing elements
+    * (or creating copies for merging) where new-> values exist.
+    */
+    conf = (authn_core_dir_conf *)apr_palloc(a, sizeof(authn_core_dir_conf));
+    memcpy(conf, base, sizeof(authn_core_dir_conf));
+
+    if (new->ap_auth_type) {
+        conf->ap_auth_type = new->ap_auth_type;
+    }
+
+    if (new->ap_auth_name) {
+        conf->ap_auth_name = new->ap_auth_name;
+    }
+
+    return (void*)conf;
+}
+
+static authn_status authn_alias_check_password(request_rec *r, const char *user,
+                                              const char *password)
+{
+    /* Look up the provider alias in the alias list */
+    /* Get the the dir_config and call ap_Merge_per_dir_configs() */
+    /* Call the real provider->check_password() function */
+    /* return the result of the above function call */
+
+    const char *provider_name = apr_table_get(r->notes, AUTHN_PROVIDER_NAME_NOTE);
+    authn_status ret = AUTH_USER_NOT_FOUND;
+    authn_alias_srv_conf *authcfg =
+        (authn_alias_srv_conf *)ap_get_module_config(r->server->module_config,
+                                                     &authn_core_module);
+
+    if (provider_name) {
+        provider_alias_rec *prvdraliasrec = apr_hash_get(authcfg->alias_rec,
+                                                         provider_name, APR_HASH_KEY_STRING);
+        ap_conf_vector_t *orig_dir_config = r->per_dir_config;
+
+        /* If we found the alias provider in the list, then merge the directory
+           configurations and call the real provider */
+        if (prvdraliasrec) {
+            r->per_dir_config = ap_merge_per_dir_configs(r->pool, orig_dir_config,
+                                                         prvdraliasrec->sec_auth);
+            ret = prvdraliasrec->provider->check_password(r,user,password);
+            r->per_dir_config = orig_dir_config;
+        }
+    }
+
+    return ret;
+}
+
+static authn_status authn_alias_get_realm_hash(request_rec *r, const char *user,
+                                               const char *realm, char **rethash)
+{
+    /* Look up the provider alias in the alias list */
+    /* Get the the dir_config and call ap_Merge_per_dir_configs() */
+    /* Call the real provider->get_realm_hash() function */
+    /* return the result of the above function call */
+
+    const char *provider_name = apr_table_get(r->notes, AUTHN_PROVIDER_NAME_NOTE);
+    authn_status ret = AUTH_USER_NOT_FOUND;
+    authn_alias_srv_conf *authcfg =
+        (authn_alias_srv_conf *)ap_get_module_config(r->server->module_config,
+                                                     &authn_core_module);
+
+    if (provider_name) {
+        provider_alias_rec *prvdraliasrec = apr_hash_get(authcfg->alias_rec,
+                                                         provider_name, APR_HASH_KEY_STRING);
+        ap_conf_vector_t *orig_dir_config = r->per_dir_config;
+
+        /* If we found the alias provider in the list, then merge the directory
+           configurations and call the real provider */
+        if (prvdraliasrec) {
+            r->per_dir_config = ap_merge_per_dir_configs(r->pool, orig_dir_config,
+                                                         prvdraliasrec->sec_auth);
+            ret = prvdraliasrec->provider->get_realm_hash(r,user,realm,rethash);
+            r->per_dir_config = orig_dir_config;
+        }
+    }
+
+    return ret;
+}
+
+static void *create_authn_alias_svr_config(apr_pool_t *p, server_rec *s)
+{
+
+    authn_alias_srv_conf *authcfg;
+
+    authcfg = (authn_alias_srv_conf *) apr_pcalloc(p, sizeof(authn_alias_srv_conf));
+    authcfg->alias_rec = apr_hash_make(p);
+
+    return (void *) authcfg;
+}
+
+static const authn_provider authn_alias_provider =
+{
+    &authn_alias_check_password,
+    &authn_alias_get_realm_hash,
+};
+
+static const char *authaliassection(cmd_parms *cmd, void *mconfig, const char *arg)
+{
+    int old_overrides = cmd->override;
+    const char *endp = ap_strrchr_c(arg, '>');
+    const char *args;
+    char *provider_alias;
+    char *provider_name;
+    const char *errmsg;
+    ap_conf_vector_t *new_auth_config = ap_create_per_dir_config(cmd->pool);
+    authn_alias_srv_conf *authcfg =
+        (authn_alias_srv_conf *)ap_get_module_config(cmd->server->module_config,
+                                                     &authn_core_module);
+
+    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+    if (err != NULL) {
+        return err;
+    }
+
+    if (endp == NULL) {
+        return apr_pstrcat(cmd->pool, cmd->cmd->name,
+                           "> directive missing closing '>'", NULL);
+    }
+
+    args = apr_pstrndup(cmd->pool, arg, endp - arg);
+
+    if (!args[0]) {
+        return apr_pstrcat(cmd->pool, cmd->cmd->name,
+                           "> directive requires additional arguments", NULL);
+    }
+
+    /* Pull the real provider name and the alias name from the block header */
+    provider_name = ap_getword_conf(cmd->pool, &args);
+    provider_alias = ap_getword_conf(cmd->pool, &args);
+
+    if (!provider_name[0] || !provider_alias[0]) {
+        return apr_pstrcat(cmd->pool, cmd->cmd->name,
+                           "> directive requires additional arguments", NULL);
+    }
+
+    /* walk the subsection configuration to get the per_dir config that we will
+       merge just before the real provider is called. */
+    cmd->override = OR_ALL|ACCESS_CONF;
+    errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_auth_config);
+
+    if (!errmsg) {
+        provider_alias_rec *prvdraliasrec = apr_pcalloc(cmd->pool, sizeof(provider_alias_rec));
+        const authn_provider *provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP, provider_name,"0");
+
+        /* Save off the new directory config along with the original provider name
+           and function pointer data */
+        prvdraliasrec->sec_auth = new_auth_config;
+        prvdraliasrec->provider_name = provider_name;
+        prvdraliasrec->provider_alias = provider_alias;
+        prvdraliasrec->provider = provider;
+        apr_hash_set(authcfg->alias_rec, provider_alias, APR_HASH_KEY_STRING, prvdraliasrec);
+
+        /* Register the fake provider so that we get called first */
+        ap_register_provider(cmd->pool, AUTHN_PROVIDER_GROUP, provider_alias, "0",
+                             &authn_alias_provider);
+    }
+
+    cmd->override = old_overrides;
+
+    return errmsg;
+}
+
+/*
+ * Load an authorisation realm into our location configuration, applying the
+ * usual rules that apply to realms.
+ */
+static const char *set_authname(cmd_parms *cmd, void *mconfig,
+                                const char *word1)
+{
+    authn_core_dir_conf *aconfig = (authn_core_dir_conf *)mconfig;
+
+    aconfig->ap_auth_name = ap_escape_quotes(cmd->pool, word1);
+    return NULL;
+}
+
+
+static const char *authn_ap_auth_type(request_rec *r)
+{
+    authn_core_dir_conf *conf;
+
+    conf = (authn_core_dir_conf *)ap_get_module_config(r->per_dir_config,
+        &authn_core_module);
+
+    return apr_pstrdup(r->pool, conf->ap_auth_type);
+}
+
+static const char *authn_ap_auth_name(request_rec *r)
+{
+    authn_core_dir_conf *conf;
+
+    conf = (authn_core_dir_conf *)ap_get_module_config(r->per_dir_config,
+        &authn_core_module);
+
+    return apr_pstrdup(r->pool, conf->ap_auth_name);
+}
+
+static const command_rec authn_cmds[] =
+{
+    AP_INIT_TAKE1("AuthType", ap_set_string_slot,
+                  (void*)APR_OFFSETOF(authn_core_dir_conf, ap_auth_type), OR_AUTHCFG,
+                  "An HTTP authorization type (e.g., \"Basic\")"),
+    AP_INIT_TAKE1("AuthName", set_authname, NULL, OR_AUTHCFG,
+                  "The authentication realm (e.g. \"Members Only\")"),
+    AP_INIT_RAW_ARGS("<AuthnProviderAlias", authaliassection, NULL, RSRC_CONF,
+                     "Container for authentication directives grouped under "
+                     "a provider alias"),
+    {NULL}
+};
+
+static void register_hooks(apr_pool_t *p)
+{
+    APR_REGISTER_OPTIONAL_FN(authn_ap_auth_type);
+    APR_REGISTER_OPTIONAL_FN(authn_ap_auth_name);
+}
+
+module AP_MODULE_DECLARE_DATA authn_core_module =
+{
+    STANDARD20_MODULE_STUFF,
+    create_authn_core_dir_config,   /* dir config creater */
+    merge_authn_core_dir_config,    /* dir merger --- default is to override */
+    create_authn_alias_svr_config,  /* server config */
+    NULL,                           /* merge server config */
+    authn_cmds,
+    register_hooks                  /* register hooks */
+};
index f13904a7193f15fc015574c052a9442ea71dd06e..2541f6b5beb075763d2bcb31cabb43a86284d1a4 100644 (file)
@@ -59,8 +59,10 @@ static int authenticate_no_user(request_rec *r)
 
     const char *type;
 
+    /* if there isn't an auth_type, then assume that no authentication
+        is require so return OK */
     if (!(type = ap_auth_type(r))) {
-        return DECLINED;
+        return OK;
     }
 
     /* fill in the r->user field */
index edce66563c4bb95ba8f8fa48470f5d146cacf865..ca21a618e978c7a1348184361e1b7a62471df995 100644 (file)
@@ -17,6 +17,7 @@
 #include "ap_provider.h"
 #include "httpd.h"
 #include "http_config.h"
+#include "ap_provider.h"
 #include "http_core.h"
 #include "http_log.h"
 #include "http_protocol.h"
@@ -45,9 +46,6 @@ typedef struct {
 #if APR_HAS_THREADS
     apr_thread_mutex_t *lock;       /* Lock for this config */
 #endif
-    int auth_authoritative;         /* Is this auth method the one and only? */
-/*    int authz_enabled;              Is ldap authorization enabled in this directory? */
-
 
     /* These parameters are all derived from the AuthLDAPURL directive */
     char *url;                      /* String representation of the URL */
@@ -294,12 +292,6 @@ static void *create_authnz_ldap_dir_config(apr_pool_t *p, char *d)
     sec->bindpw = NULL;
     sec->deref = always;
     sec->group_attrib_is_dn = 1;
-    sec->auth_authoritative = 1;
-
-/*
-    sec->frontpage_hack = 0;
-*/
-
     sec->secure = -1;   /*Initialize to unset*/
 
     sec->user_is_dn = 0;
@@ -448,23 +440,8 @@ start_over:
     return AUTH_GRANTED;
 }
 
-/*
- * Authorisation Phase
- * -------------------
- *
- * After checking whether the username and password are correct, we need
- * to check whether that user is authorised to view this resource. The
- * require directive is used to do this:
- *
- *  require valid-user          Any authenticated is allowed in.
- *  require user <username>     This particular user is allowed in.
- *  require group <groupname>   The user must be a member of this group
- *                              in order to be allowed in.
- *  require dn <dn>             The user must have the following DN in the
- *                              LDAP tree to be let in.
- *
- */
-static int authz_ldap_check_user_access(request_rec *r)
+static authz_status ldapuser_check_authorization(request_rec *r,
+                                             const char *require_args)
 {
     int result = 0;
     authn_ldap_request_t *req =
@@ -473,28 +450,146 @@ static int authz_ldap_check_user_access(request_rec *r)
         (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module);
 
     util_ldap_connection_t *ldc = NULL;
-    int m = r->method_number;
 
-    const apr_array_header_t *reqs_arr = ap_requires(r);
-    require_line *reqs = reqs_arr ? (require_line *)reqs_arr->elts : NULL;
-
-    register int x;
     const char *t;
-    char *w, *value;
-    int method_restricted = 0;
+    char *w;
 
     char filtbuf[FILTER_LENGTH];
     const char *dn = NULL;
     const char **vals = NULL;
 
-/*
-    if (!sec->enabled) {
-        return DECLINED;
+    if (!sec->have_ldap_url) {
+        return AUTHZ_DENIED;
     }
-*/
+
+    if (sec->host) {
+        ldc = util_ldap_connection_find(r, sec->host, sec->port,
+                                       sec->binddn, sec->bindpw, sec->deref,
+                                       sec->secure);
+        apr_pool_cleanup_register(r->pool, ldc,
+                                  authnz_ldap_cleanup_connection_close,
+                                  apr_pool_cleanup_null);
+    }
+    else {
+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                      "[%" APR_PID_T_FMT "] auth_ldap authorize: no sec->host - weird...?", getpid());
+        return AUTHZ_DENIED;
+    }
+
+    /*
+     * If we have been authenticated by some other module than mod_authnz_ldap,
+     * the req structure needed for authorization needs to be created
+     * and populated with the userid and DN of the account in LDAP
+     */
+
+    /* Check that we have a userid to start with */
+    if ((!r->user) || (strlen(r->user) == 0)) {
+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+            "ldap authorize: Userid is blank, AuthType=%s",
+            r->ap_auth_type);
+    }
+
+    if(!req) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+            "ldap authorize: Creating LDAP req structure");
+
+        /* Build the username filter */
+        authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec);
+
+        /* Search for the user DN */
+        result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn,
+             sec->scope, sec->attributes, filtbuf, &dn, &vals);
+
+        /* Search failed, log error and return failure */
+        if(result != LDAP_SUCCESS) {
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                "auth_ldap authorise: User DN not found, %s", ldc->reason);
+            return AUTHZ_DENIED;
+        }
+
+        req = (authn_ldap_request_t *)apr_pcalloc(r->pool,
+            sizeof(authn_ldap_request_t));
+        ap_set_module_config(r->request_config, &authnz_ldap_module, req);
+        req->dn = apr_pstrdup(r->pool, dn);
+        req->user = r->user;
+    }
+
+    if (req->dn == NULL || strlen(req->dn) == 0) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                      "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                      "require user: user's DN has not been defined; failing authorization",
+                      getpid());
+        return AUTHZ_DENIED;
+    }
+
+    /*
+     * First do a whole-line compare, in case it's something like
+     *   require user Babs Jensen
+     */
+    result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, require_args);
+    switch(result) {
+        case LDAP_COMPARE_TRUE: {
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                          "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                          "require user: authorization successful", getpid());
+            return AUTHZ_GRANTED;
+        }
+        default: {
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                          "[%" APR_PID_T_FMT "] auth_ldap authorize: require user: "
+                          "authorization failed [%s][%s]", getpid(),
+                          ldc->reason, ldap_err2string(result));
+        }
+    }
+
+    /*
+     * Now break apart the line and compare each word on it
+     */
+    t = require_args;
+    while ((w = ap_getword_conf(r->pool, &t)) && w[0]) {
+        result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, w);
+        switch(result) {
+            case LDAP_COMPARE_TRUE: {
+                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                              "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                              "require user: authorization successful", getpid());
+                return AUTHZ_GRANTED;
+            }
+            default: {
+                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                              "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                              "require user: authorization failed [%s][%s]",
+                              getpid(), ldc->reason, ldap_err2string(result));
+            }
+        }
+    }
+
+    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                  "[%" APR_PID_T_FMT "] auth_ldap authorize: authorization denied", getpid());
+    return AUTHZ_DENIED;
+}
+
+static authz_status ldapgroup_check_authorization(request_rec *r,
+                                             const char *require_args)
+{
+    int result = 0;
+    authn_ldap_request_t *req =
+        (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module);
+    authn_ldap_config_t *sec =
+        (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module);
+
+    util_ldap_connection_t *ldc = NULL;
+
+    const char *t;
+
+    char filtbuf[FILTER_LENGTH];
+    const char *dn = NULL;
+    const char **vals = NULL;
+    struct mod_auth_ldap_groupattr_entry_t *ent;
+    int i;
 
     if (!sec->have_ldap_url) {
-        return DECLINED;
+        return AUTHZ_DENIED;
     }
 
     if (sec->host) {
@@ -507,8 +602,8 @@ static int authz_ldap_check_user_access(request_rec *r)
     }
     else {
         ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
-                      "[%" APR_PID_T_FMT "] auth_ldap authorise: no sec->host - weird...?", getpid());
-        return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED;
+                      "[%" APR_PID_T_FMT "] auth_ldap authorize: no sec->host - weird...?", getpid());
+        return AUTHZ_DENIED;
     }
 
     /*
@@ -529,12 +624,6 @@ static int authz_ldap_check_user_access(request_rec *r)
 #endif
     }
 
-    if (!reqs_arr) {
-        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                      "[%" APR_PID_T_FMT "] auth_ldap authorise: no requirements array", getpid());
-        return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED;
-    }
-
     /*
      * If we have been authenticated by some other module than mod_auth_ldap,
      * the req structure needed for authorization needs to be created
@@ -563,7 +652,7 @@ static int authz_ldap_check_user_access(request_rec *r)
         if(result != LDAP_SUCCESS) {
             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                 "auth_ldap authorise: User DN not found, %s", ldc->reason);
-            return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED;
+            return AUTHZ_DENIED;
         }
 
         req = (authn_ldap_request_t *)apr_pcalloc(r->pool,
@@ -573,252 +662,416 @@ static int authz_ldap_check_user_access(request_rec *r)
         req->user = r->user;
     }
 
-    /* Loop through the requirements array until there's no elements
-     * left, or something causes a return from inside the loop */
-    for(x=0; x < reqs_arr->nelts; x++) {
-        if (! (reqs[x].method_mask & (APR_INT64_C(1) << m))) {
-            continue;
+    ent = (struct mod_auth_ldap_groupattr_entry_t *) sec->groupattr->elts;
+
+    if (sec->group_attrib_is_dn) {
+        if (req->dn == NULL || strlen(req->dn) == 0) {
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                          "[%" APR_PID_T_FMT "] auth_ldap authorize: require group: "
+                          "user's DN has not been defined; failing authorization",
+                          getpid());
+            return AUTHZ_DENIED;
         }
-        method_restricted = 1;
+    }
+    else {
+        if (req->user == NULL || strlen(req->user) == 0) {
+            /* We weren't called in the authentication phase, so we didn't have a
+             * chance to set the user field. Do so now. */
+            req->user = r->user;
+        }
+    }
+
+    t = require_args;
 
-        t = reqs[x].requirement;
-        w = ap_getword_white(r->pool, &t);
+    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                  "[%" APR_PID_T_FMT "] auth_ldap authorize: require group: "
+                  "testing for group membership in \"%s\"",
+                  getpid(), t);
 
-        if (strcmp(w, "ldap-user") == 0) {
-            if (req->dn == NULL || strlen(req->dn) == 0) {
+    for (i = 0; i < sec->groupattr->nelts; i++) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                      "[%" APR_PID_T_FMT "] auth_ldap authorize: require group: "
+                      "testing for %s: %s (%s)", getpid(),
+                      ent[i].name, sec->group_attrib_is_dn ? req->dn : req->user, t);
+
+        result = util_ldap_cache_compare(r, ldc, sec->url, t, ent[i].name,
+                             sec->group_attrib_is_dn ? req->dn : req->user);
+        switch(result) {
+            case LDAP_COMPARE_TRUE: {
                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                              "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                              "require user: user's DN has not been defined; failing authorisation",
-                              getpid());
-                return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED;
+                              "[%" APR_PID_T_FMT "] auth_ldap authorize: require group: "
+                              "authorization successful (attribute %s) [%s][%s]",
+                              getpid(), ent[i].name, ldc->reason, ldap_err2string(result));
+                return AUTHZ_GRANTED;
             }
-            /*
-             * First do a whole-line compare, in case it's something like
-             *   require user Babs Jensen
-             */
-            result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, t);
-            switch(result) {
-                case LDAP_COMPARE_TRUE: {
-                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                                  "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                                  "require user: authorisation successful", getpid());
-                    return OK;
-                }
-                default: {
-                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                                  "[%" APR_PID_T_FMT "] auth_ldap authorise: require user: "
-                                  "authorisation failed [%s][%s]", getpid(),
-                                  ldc->reason, ldap_err2string(result));
-                }
-            }
-            /*
-             * Now break apart the line and compare each word on it
-             */
-            while (t[0]) {
-                w = ap_getword_conf(r->pool, &t);
-                result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, w);
-                switch(result) {
-                    case LDAP_COMPARE_TRUE: {
-                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                                      "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                                      "require user: authorisation successful", getpid());
-                        return OK;
-                    }
-                    default: {
-                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                                      "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                                      "require user: authorisation failed [%s][%s]",
-                                      getpid(), ldc->reason, ldap_err2string(result));
-                    }
-                }
-            }
-        }
-        else if (strcmp(w, "ldap-dn") == 0) {
-            if (req->dn == NULL || strlen(req->dn) == 0) {
+            default: {
                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                              "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                              "require dn: user's DN has not been defined; failing authorisation",
-                              getpid());
-                return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED;
+                              "[%" APR_PID_T_FMT "] auth_ldap authorize: require group \"%s\": "
+                              "authorization failed [%s][%s]",
+                              getpid(), t, ldc->reason, ldap_err2string(result));
             }
+        }
+    }
 
-            result = util_ldap_cache_comparedn(r, ldc, sec->url, req->dn, t, sec->compare_dn_on_server);
-            switch(result) {
-                case LDAP_COMPARE_TRUE: {
-                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                                  "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                                  "require dn: authorisation successful", getpid());
-                    return OK;
-                }
-                default: {
-                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                                  "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                                  "require dn \"%s\": LDAP error [%s][%s]",
-                                  getpid(), t, ldc->reason, ldap_err2string(result));
-                }
-            }
+    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                  "[%" APR_PID_T_FMT "] auth_ldap authorize: authorization denied", getpid());
+
+    return AUTHZ_DENIED;
+}
+
+static authz_status ldapdn_check_authorization(request_rec *r,
+                                             const char *require_args)
+{
+    int result = 0;
+    authn_ldap_request_t *req =
+        (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module);
+    authn_ldap_config_t *sec =
+        (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module);
+
+    util_ldap_connection_t *ldc = NULL;
+
+    const char *t;
+
+    char filtbuf[FILTER_LENGTH];
+    const char *dn = NULL;
+    const char **vals = NULL;
+
+    if (!sec->have_ldap_url) {
+        return AUTHZ_DENIED;
+    }
+
+    if (sec->host) {
+        ldc = util_ldap_connection_find(r, sec->host, sec->port,
+                                       sec->binddn, sec->bindpw, sec->deref,
+                                       sec->secure);
+        apr_pool_cleanup_register(r->pool, ldc,
+                                  authnz_ldap_cleanup_connection_close,
+                                  apr_pool_cleanup_null);
+    }
+    else {
+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                      "[%" APR_PID_T_FMT "] auth_ldap authorize: no sec->host - weird...?", getpid());
+        return AUTHZ_DENIED;
+    }
+
+    /*
+     * If we have been authenticated by some other module than mod_auth_ldap,
+     * the req structure needed for authorization needs to be created
+     * and populated with the userid and DN of the account in LDAP
+     */
+
+    /* Check that we have a userid to start with */
+    if ((!r->user) || (strlen(r->user) == 0)) {
+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+            "ldap authorize: Userid is blank, AuthType=%s",
+            r->ap_auth_type);
+    }
+
+    if(!req) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+            "ldap authorize: Creating LDAP req structure");
+
+        /* Build the username filter */
+        authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec);
+
+        /* Search for the user DN */
+        result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn,
+             sec->scope, sec->attributes, filtbuf, &dn, &vals);
+
+        /* Search failed, log error and return failure */
+        if(result != LDAP_SUCCESS) {
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                "auth_ldap authorise: User DN not found, %s", ldc->reason);
+            return AUTHZ_DENIED;
         }
-        else if (strcmp(w, "ldap-group") == 0) {
-            struct mod_auth_ldap_groupattr_entry_t *ent = (struct mod_auth_ldap_groupattr_entry_t *) sec->groupattr->elts;
-            int i;
-
-            if (sec->group_attrib_is_dn) {
-                if (req->dn == NULL || strlen(req->dn) == 0) {
-                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                                  "[%" APR_PID_T_FMT "] auth_ldap authorise: require group: "
-                                  "user's DN has not been defined; failing authorisation",
-                                  getpid());
-                    return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED;
-                }
-            }
-            else {
-                if (req->user == NULL || strlen(req->user) == 0) {
-                    /* We weren't called in the authentication phase, so we didn't have a
-                     * chance to set the user field. Do so now. */
-                    req->user = r->user;
-                }
-            }
 
+        req = (authn_ldap_request_t *)apr_pcalloc(r->pool,
+            sizeof(authn_ldap_request_t));
+        ap_set_module_config(r->request_config, &authnz_ldap_module, req);
+        req->dn = apr_pstrdup(r->pool, dn);
+        req->user = r->user;
+    }
+
+    t = require_args;
+
+    if (req->dn == NULL || strlen(req->dn) == 0) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                      "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                      "require dn: user's DN has not been defined; failing authorization",
+                      getpid());
+        return AUTHZ_DENIED;
+    }
+
+    result = util_ldap_cache_comparedn(r, ldc, sec->url, req->dn, t, sec->compare_dn_on_server);
+    switch(result) {
+        case LDAP_COMPARE_TRUE: {
             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                          "[%" APR_PID_T_FMT "] auth_ldap authorise: require group: "
-                          "testing for group membership in \"%s\"",
-                          getpid(), t);
+                          "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                          "require dn: authorization successful", getpid());
+            return AUTHZ_GRANTED;
+        }
+        default: {
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                          "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                          "require dn \"%s\": LDAP error [%s][%s]",
+                          getpid(), t, ldc->reason, ldap_err2string(result));
+        }
+    }
 
-            for (i = 0; i < sec->groupattr->nelts; i++) {
-                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                              "[%" APR_PID_T_FMT "] auth_ldap authorise: require group: "
-                              "testing for %s: %s (%s)", getpid(),
-                              ent[i].name, sec->group_attrib_is_dn ? req->dn : req->user, t);
-
-                result = util_ldap_cache_compare(r, ldc, sec->url, t, ent[i].name,
-                                     sec->group_attrib_is_dn ? req->dn : req->user);
-                switch(result) {
-                    case LDAP_COMPARE_TRUE: {
-                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                                      "[%" APR_PID_T_FMT "] auth_ldap authorise: require group: "
-                                      "authorisation successful (attribute %s) [%s][%s]",
-                                      getpid(), ent[i].name, ldc->reason, ldap_err2string(result));
-                        return OK;
-                    }
-                    default: {
-                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                                      "[%" APR_PID_T_FMT "] auth_ldap authorise: require group \"%s\": "
-                                      "authorisation failed [%s][%s]",
-                                      getpid(), t, ldc->reason, ldap_err2string(result));
-                    }
-                }
-            }
+
+    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                  "[%" APR_PID_T_FMT "] auth_ldap authorise: authorisation denied", getpid());
+
+    return AUTHZ_DENIED;
+}
+
+static authz_status ldapattribute_check_authorization(request_rec *r,
+                                             const char *require_args)
+{
+    int result = 0;
+    authn_ldap_request_t *req =
+        (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module);
+    authn_ldap_config_t *sec =
+        (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module);
+
+    util_ldap_connection_t *ldc = NULL;
+
+    const char *t;
+    char *w, *value;
+
+    char filtbuf[FILTER_LENGTH];
+    const char *dn = NULL;
+    const char **vals = NULL;
+
+    if (!sec->have_ldap_url) {
+        return AUTHZ_DENIED;
+    }
+
+    if (sec->host) {
+        ldc = util_ldap_connection_find(r, sec->host, sec->port,
+                                       sec->binddn, sec->bindpw, sec->deref,
+                                       sec->secure);
+        apr_pool_cleanup_register(r->pool, ldc,
+                                  authnz_ldap_cleanup_connection_close,
+                                  apr_pool_cleanup_null);
+    }
+    else {
+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                      "[%" APR_PID_T_FMT "] auth_ldap authorize: no sec->host - weird...?", getpid());
+        return AUTHZ_DENIED;
+    }
+
+    /*
+     * If we have been authenticated by some other module than mod_auth_ldap,
+     * the req structure needed for authorization needs to be created
+     * and populated with the userid and DN of the account in LDAP
+     */
+
+    /* Check that we have a userid to start with */
+    if ((!r->user) || (strlen(r->user) == 0)) {
+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+            "ldap authorize: Userid is blank, AuthType=%s",
+            r->ap_auth_type);
+    }
+
+    if(!req) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+            "ldap authorize: Creating LDAP req structure");
+
+        /* Build the username filter */
+        authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec);
+
+        /* Search for the user DN */
+        result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn,
+             sec->scope, sec->attributes, filtbuf, &dn, &vals);
+
+        /* Search failed, log error and return failure */
+        if(result != LDAP_SUCCESS) {
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                "auth_ldap authorise: User DN not found, %s", ldc->reason);
+            return AUTHZ_DENIED;
         }
-        else if (strcmp(w, "ldap-attribute") == 0) {
-            if (req->dn == NULL || strlen(req->dn) == 0) {
-                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                              "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                              "require ldap-attribute: user's DN has not been defined; failing authorisation",
+
+        req = (authn_ldap_request_t *)apr_pcalloc(r->pool,
+            sizeof(authn_ldap_request_t));
+        ap_set_module_config(r->request_config, &authnz_ldap_module, req);
+        req->dn = apr_pstrdup(r->pool, dn);
+        req->user = r->user;
+    }
+
+    if (req->dn == NULL || strlen(req->dn) == 0) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                      "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                      "require ldap-attribute: user's DN has not been defined; failing authorization",
+                      getpid());
+        return AUTHZ_DENIED;
+    }
+
+    t = require_args;
+    while (t[0]) {
+        w = ap_getword(r->pool, &t, '=');
+        value = ap_getword_conf(r->pool, &t);
+
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                      "[%" APR_PID_T_FMT "] auth_ldap authorize: checking attribute"
+                      " %s has value %s", getpid(), w, value);
+        result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, w, value);
+        switch(result) {
+            case LDAP_COMPARE_TRUE: {
+                ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
+                              0, r, "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                              "require attribute: authorization successful", 
                               getpid());
-                return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED;
+                return AUTHZ_GRANTED;
             }
-            while (t[0]) {
-                w = ap_getword(r->pool, &t, '=');
-                value = ap_getword_conf(r->pool, &t);
-
-                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                              "[%" APR_PID_T_FMT "] auth_ldap authorise: checking attribute"
-                              " %s has value %s", getpid(), w, value);
-                result = util_ldap_cache_compare(r, ldc, sec->url, req->dn,
-                                                 w, value);
-                switch(result) {
-                    case LDAP_COMPARE_TRUE: {
-                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
-                                      0, r, "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                                      "require attribute: authorisation "
-                                      "successful", getpid());
-                        return OK;
-                    }
-                    default: {
-                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
-                                      0, r, "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                                      "require attribute: authorisation "
-                                      "failed [%s][%s]", getpid(),
-                                      ldc->reason, ldap_err2string(result));
-                    }
-                }
+            default: {
+                ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
+                              0, r, "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                              "require attribute: authorization failed [%s][%s]", 
+                              getpid(), ldc->reason, ldap_err2string(result));
             }
         }
-        else if (strcmp(w, "ldap-filter") == 0) {
-            if (req->dn == NULL || strlen(req->dn) == 0) {
-                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                              "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                              "require ldap-filter: user's DN has not been defined; failing authorisation",
-                              getpid());
-                return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED;
-            }
-            if (t[0]) {
-                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                              "[%" APR_PID_T_FMT "] auth_ldap authorise: checking filter %s",
-                              getpid(), t);
-
-                /* Build the username filter */
-                authn_ldap_build_filter(filtbuf, r, req->user, t, sec);
-
-                /* Search for the user DN */
-                result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn,
-                     sec->scope, sec->attributes, filtbuf, &dn, &vals);
-
-                /* Make sure that the filtered search returned the correct user dn */
-                if (result == LDAP_SUCCESS) {
-                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                                  "[%" APR_PID_T_FMT "] auth_ldap authorise: checking dn match %s",
-                                  getpid(), dn);
-                    result = util_ldap_cache_comparedn(r, ldc, sec->url, req->dn, dn,
-                         sec->compare_dn_on_server);
-                }
+    }
 
-                switch(result) {
-                    case LDAP_COMPARE_TRUE: {
-                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
-                                      0, r, "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                                      "require ldap-filter: authorisation "
-                                      "successful", getpid());
-                        return OK;
-                    }
-                    case LDAP_FILTER_ERROR: {
-                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
-                                      0, r, "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                                      "require ldap-filter: %s authorisation "
-                                      "failed [%s][%s]", getpid(),
-                                      filtbuf, ldc->reason, ldap_err2string(result));
-                        break;
-                    }
-                    default: {
-                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
-                                      0, r, "[%" APR_PID_T_FMT "] auth_ldap authorise: "
-                                      "require ldap-filter: authorisation "
-                                      "failed [%s][%s]", getpid(),
-                                      ldc->reason, ldap_err2string(result));
-                    }
-                }
-            }
+    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                  "[%" APR_PID_T_FMT "] auth_ldap authorise: authorisation denied", getpid());
+
+    return AUTHZ_DENIED;
+}
+
+static authz_status ldapfilter_check_authorization(request_rec *r,
+                                             const char *require_args)
+{
+    int result = 0;
+    authn_ldap_request_t *req =
+        (authn_ldap_request_t *)ap_get_module_config(r->request_config, &authnz_ldap_module);
+    authn_ldap_config_t *sec =
+        (authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module);
+
+    util_ldap_connection_t *ldc = NULL;
+    const char *t;
+
+    char filtbuf[FILTER_LENGTH];
+    const char *dn = NULL;
+    const char **vals = NULL;
+
+    if (!sec->have_ldap_url) {
+        return AUTHZ_DENIED;
+    }
+
+    if (sec->host) {
+        ldc = util_ldap_connection_find(r, sec->host, sec->port,
+                                       sec->binddn, sec->bindpw, sec->deref,
+                                       sec->secure);
+        apr_pool_cleanup_register(r->pool, ldc,
+                                  authnz_ldap_cleanup_connection_close,
+                                  apr_pool_cleanup_null);
+    }
+    else {
+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                      "[%" APR_PID_T_FMT "] auth_ldap authorize: no sec->host - weird...?", getpid());
+        return AUTHZ_DENIED;
+    }
+
+    /*
+     * If we have been authenticated by some other module than mod_auth_ldap,
+     * the req structure needed for authorization needs to be created
+     * and populated with the userid and DN of the account in LDAP
+     */
+
+    /* Check that we have a userid to start with */
+    if ((!r->user) || (strlen(r->user) == 0)) {
+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+            "ldap authorize: Userid is blank, AuthType=%s",
+            r->ap_auth_type);
+    }
+
+    if(!req) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+            "ldap authorize: Creating LDAP req structure");
+
+        /* Build the username filter */
+        authn_ldap_build_filter(filtbuf, r, r->user, NULL, sec);
+
+        /* Search for the user DN */
+        result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn,
+             sec->scope, sec->attributes, filtbuf, &dn, &vals);
+
+        /* Search failed, log error and return failure */
+        if(result != LDAP_SUCCESS) {
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                "auth_ldap authorise: User DN not found, %s", ldc->reason);
+            return AUTHZ_DENIED;
         }
+
+        req = (authn_ldap_request_t *)apr_pcalloc(r->pool,
+            sizeof(authn_ldap_request_t));
+        ap_set_module_config(r->request_config, &authnz_ldap_module, req);
+        req->dn = apr_pstrdup(r->pool, dn);
+        req->user = r->user;
     }
 
-    if (!method_restricted) {
+    if (req->dn == NULL || strlen(req->dn) == 0) {
         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                      "[%" APR_PID_T_FMT "] auth_ldap authorise: agreeing because non-restricted",
+                      "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                      "require ldap-filter: user's DN has not been defined; failing authorization",
                       getpid());
-        return OK;
+        return AUTHZ_DENIED;
     }
 
-    if (!sec->auth_authoritative) {
+    t = require_args;
+
+    if (t[0]) {
         ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                      "[%" APR_PID_T_FMT "] auth_ldap authorise: declining to authorise", getpid());
-        return DECLINED;
+                      "[%" APR_PID_T_FMT "] auth_ldap authorize: checking filter %s",
+                      getpid(), t);
+
+        /* Build the username filter */
+        authn_ldap_build_filter(filtbuf, r, req->user, t, sec);
+
+        /* Search for the user DN */
+        result = util_ldap_cache_getuserdn(r, ldc, sec->url, sec->basedn,
+             sec->scope, sec->attributes, filtbuf, &dn, &vals);
+
+        /* Make sure that the filtered search returned the correct user dn */
+        if (result == LDAP_SUCCESS) {
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                          "[%" APR_PID_T_FMT "] auth_ldap authorize: checking dn match %s",
+                          getpid(), dn);
+            result = util_ldap_cache_comparedn(r, ldc, sec->url, req->dn, dn,
+                 sec->compare_dn_on_server);
+        }
+
+        switch(result) {
+            case LDAP_COMPARE_TRUE: {
+                ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
+                              0, r, "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                              "require ldap-filter: authorization "
+                              "successful", getpid());
+                return AUTHZ_GRANTED;
+            }
+            case LDAP_FILTER_ERROR: {
+                ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
+                              0, r, "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                              "require ldap-filter: %s authorization "
+                              "failed [%s][%s]", getpid(),
+                              filtbuf, ldc->reason, ldap_err2string(result));
+                break;
+            }
+            default: {
+                ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
+                              0, r, "[%" APR_PID_T_FMT "] auth_ldap authorize: "
+                              "require ldap-filter: authorization "
+                              "failed [%s][%s]", getpid(),
+                              ldc->reason, ldap_err2string(result));
+            }
+        }
     }
 
     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-                  "[%" APR_PID_T_FMT "] auth_ldap authorise: authorisation denied", getpid());
-    ap_note_basic_auth_failure (r);
+                  "[%" APR_PID_T_FMT "] auth_ldap authorise: authorization denied", getpid());
 
-    return HTTP_UNAUTHORIZED;
+    return AUTHZ_DENIED;
 }
 
 
@@ -1032,11 +1285,6 @@ static const command_rec authnz_ldap_cmds[] =
                  "DN of the remote user. By default, this is set to off, meaning that "
                  "the REMOTE_USER variable will contain whatever value the remote user sent."),
 
-    AP_INIT_FLAG("AuthzLDAPAuthoritative", ap_set_flag_slot,
-                 (void *)APR_OFFSETOF(authn_ldap_config_t, auth_authoritative), OR_AUTHCFG,
-                 "Set to 'off' to allow access control to be passed along to lower modules if "
-                 "the UserID and/or group is not known to this module"),
-
     AP_INIT_FLAG("AuthLDAPCompareDNOnServer", ap_set_flag_slot,
                  (void *)APR_OFFSETOF(authn_ldap_config_t, compare_dn_on_server), OR_AUTHCFG,
                  "Set to 'on' to force auth_ldap to do DN compares (for the \"require dn\" "
@@ -1059,12 +1307,6 @@ static const command_rec authnz_ldap_cmds[] =
                   "values \"never\", \"searching\", \"finding\", or \"always\". "
                   "Defaults to always."),
 
-/*
-    AP_INIT_FLAG("AuthLDAPAuthzEnabled", ap_set_flag_slot,
-                 (void *)APR_OFFSETOF(authn_ldap_config_t, authz_enabled), OR_AUTHCFG,
-                 "Set to off to disable the LDAP authorization handler, even if it's been enabled in a higher tree"),
-*/
-
     AP_INIT_TAKE1("AuthLDAPCharsetConfig", set_charset_config, NULL, RSRC_CONF,
                   "Character set conversion configuration file. If omitted, character set"
                   "conversion is disabled."),
@@ -1160,6 +1402,30 @@ static const authn_provider authn_ldap_provider =
     &authn_ldap_check_password,
 };
 
+static const authz_provider authz_ldapuser_provider =
+{
+    &ldapuser_check_authorization,
+};
+static const authz_provider authz_ldapgroup_provider =
+{
+    &ldapgroup_check_authorization,
+};
+
+static const authz_provider authz_ldapdn_provider =
+{
+    &ldapdn_check_authorization,
+};
+
+static const authz_provider authz_ldapattribute_provider =
+{
+    &ldapattribute_check_authorization,
+};
+
+static const authz_provider authz_ldapfilter_provider =
+{
+    &ldapfilter_check_authorization,
+};
+
 static void ImportULDAPOptFn(void)
 {
     util_ldap_connection_close  = APR_RETRIEVE_OPTIONAL_FN(uldap_connection_close);
@@ -1173,12 +1439,23 @@ static void ImportULDAPOptFn(void)
 
 static void register_hooks(apr_pool_t *p)
 {
-    static const char * const aszPost[]={ "mod_authz_user.c", NULL };
-
+    /* Register authn provider */
     ap_register_provider(p, AUTHN_PROVIDER_GROUP, "ldap", "0",
                          &authn_ldap_provider);
+
+    /* Register authz providers */
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-user", "0",
+                         &authz_ldapuser_provider);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-group", "0",
+                         &authz_ldapgroup_provider);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-dn", "0",
+                         &authz_ldapdn_provider);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-attribute", "0",
+                         &authz_ldapattribute_provider);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "ldap-filter", "0",
+                         &authz_ldapfilter_provider);
+
     ap_hook_post_config(authnz_ldap_post_config,NULL,NULL,APR_HOOK_MIDDLE);
-    ap_hook_auth_checker(authz_ldap_check_user_access, NULL, aszPost, APR_HOOK_MIDDLE);
 
     ap_hook_optional_fn_retrieve(ImportULDAPOptFn,NULL,NULL,APR_HOOK_MIDDLE);
 }
diff --git a/modules/aaa/mod_authz_core.c b/modules/aaa/mod_authz_core.c
new file mode 100644 (file)
index 0000000..b3493ac
--- /dev/null
@@ -0,0 +1,672 @@
+/* Copyright 2002-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Security options etc.
+ *
+ * Module derived from code originally written by Rob McCool
+ *
+ */
+
+#include "apr_strings.h"
+#include "apr_network_io.h"
+#include "apr_md5.h"
+
+#define APR_WANT_STRFUNC
+#define APR_WANT_BYTEFUNC
+#include "apr_want.h"
+
+#define CORE_PRIVATE
+#include "ap_config.h"
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_request.h"
+#include "http_protocol.h"
+#include "ap_provider.h"
+
+#include "mod_auth.h"
+
+#if APR_HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+/* TODO List
+
+X- Convert all of the authz modules to providers
+X- Remove the ap_requires field from the core_dir_config structure
+X- Remove the ap_requires field from authz_dir_conf   
+X- Remove the function ap_requires() and authz_ap_requires()
+   since their functionality is no longer supported 
+   or necessary in the refactoring
+X- Remove the calls to ap_some_auth_required() in the
+   core request handling to allow the hooks to be called
+   in all cases.  Is this function even necessary
+   anymore?
+- Determine of merge_authz_dir_config is even 
+   necessary and remove if not
+X- Split the authz type from the arguments when the
+   authz provider is registered and store the type
+   in ->provider_name and the arguments in ->requirement
+X- Move the check for METHOD_MASK out of the authz 
+   providers and into the provider vector
+X- Change the status code to AUTHZ_DENIED, AUTHZ_GRANTED
+   and AUTHZ_GENERAL_ERROR   
+- Determine if setting the AUTHZ_PROVIDER_NAME_NOTE note
+   is even necessary.  This was used in authn to support
+   authn_alias.  Is there a need for an authz_alias?
+X- Remove the Satisfy directive functionality and replace it with the
+   <SatisfyAll>, <SatisfyOne> directives
+X- Remove the Satisfy directive 
+X- Implement the <SatisfyAll> <SatisfyOne> block directives
+   to handle the 'and' and 'or' logic for authorization.
+X- Remove the AuthzXXXAuthoritative directives from all of
+   the authz providers
+X- Implement the Reject directive that will deny authorization
+   if the argument is true
+X- Fold the Reject directive into the <SatisfyAll> <SatisfyOne>
+   logic
+X- Reimplement the host based authorization 'allow', 'deny'
+   and 'order' as authz providers   
+X- Remove the 'allow', 'deny' and 'order' directives      
+- Merge mod_authn_alias into mod_authn_core
+X- Remove all of the references to the authzxxxAuthoritative
+   directives from the documentation
+X- Remove the Satisfy directive from the documentation
+*/
+
+typedef struct provider_alias_rec {
+    char *provider_name;
+    char *provider_alias;
+    char *provider_args;
+    ap_conf_vector_t *sec_auth;
+    const authz_provider *provider;
+} provider_alias_rec;
+
+typedef struct {
+    authz_provider_list *providers;
+    authz_request_state req_state;
+    int req_state_level;
+} authz_core_dir_conf;
+
+typedef struct authz_core_srv_conf {
+    apr_hash_t *alias_rec;
+} authz_core_srv_conf;
+
+
+module AP_MODULE_DECLARE_DATA authz_core_module;
+
+static void *create_authz_core_dir_config(apr_pool_t *p, char *dummy)
+{
+    authz_core_dir_conf *conf =
+            (authz_core_dir_conf *)apr_pcalloc(p, sizeof(authz_core_dir_conf));
+
+    conf->req_state = AUTHZ_REQSTATE_ONE;
+    conf->req_state_level = 0;
+    return (void *)conf;
+}
+
+#if 0
+static void *merge_authz_core_dir_config(apr_pool_t *a, void *basev, void *newv)
+{
+    authz_core_dir_conf *base = (authz_core_dir_conf *)basev;
+    authz_core_dir_conf *new = (authz_core_dir_conf *)newv;
+    authz_core_dir_conf *conf;
+
+    /* Create this conf by duplicating the base, replacing elements
+    * (or creating copies for merging) where new-> values exist.
+    */
+    conf = (authz_core_dir_conf *)apr_palloc(a, sizeof(authz_core_dir_conf));
+    memcpy(conf, base, sizeof(authz_core_dir_conf));
+
+    return (void*)conf;
+}
+#endif
+
+static void *create_authz_core_svr_config(apr_pool_t *p, server_rec *s)
+{
+
+    authz_core_srv_conf *authcfg;
+
+    authcfg = (authz_core_srv_conf *) apr_pcalloc(p, sizeof(authz_core_srv_conf));
+    authcfg->alias_rec = apr_hash_make(p);
+
+    return (void *) authcfg;
+}
+
+static const char *add_authz_provider(cmd_parms *cmd, void *config,
+                                      const char *arg)
+{
+    authz_core_dir_conf *conf = (authz_core_dir_conf*)config;
+    authz_provider_list *newp;
+    const char *t, *w;
+
+    newp = apr_pcalloc(cmd->pool, sizeof(authz_provider_list));
+
+    t = arg;
+    w = ap_getword_white(cmd->pool, &t);
+
+    if (w)
+        newp->provider_name = apr_pstrdup(cmd->pool, w);
+    if (t)
+        newp->requirement = apr_pstrdup(cmd->pool, t);
+    newp->method_mask = cmd->limited;
+
+    /* lookup and cache the actual provider now */
+    newp->provider = ap_lookup_provider(AUTHZ_PROVIDER_GROUP,
+                                        newp->provider_name, "0");
+    newp->req_state = conf->req_state;
+    newp->req_state_level = conf->req_state_level;
+    newp->is_reject = (int)cmd->info;
+
+    /* by the time the config file is used, the provider should be loaded
+     * and registered with us.
+     */
+    if (newp->provider == NULL) {
+        return apr_psprintf(cmd->pool,
+                            "Unknown Authz provider: %s",
+                            newp->provider_name);
+    }
+
+    /* if the provider doesn't provide the appropriate function, reject it */
+    if (!newp->provider->check_authorization) {
+        return apr_psprintf(cmd->pool,
+                            "The '%s' Authz provider is not supported by any "
+                            "of the loaded authorization modules ",
+                            newp->provider_name);
+    }
+
+    /* Add it to the list now. */
+    if (!conf->providers) {
+        conf->providers = newp;
+    }
+    else {
+        authz_provider_list *last = conf->providers;
+        int level = conf->req_state_level;
+
+        /* if the level is 0 then take care of the implicit 'or'
+           operation at this level. */
+        if (level == 0) {
+            /* Just run through the Require_one list and add the
+                node */
+            while (last->one_next) {
+                last = last->one_next;
+            }
+            last->one_next = newp;
+        } 
+        else {
+            /* Traverse the list to find the last entry.Each level 
+               indicates a transition in the logic. */
+            for (;level;level--) {
+                /* if we are in a Require_all block then run through
+                    all of the Require_all nodes to the end of the list */
+                if (last->req_state == AUTHZ_REQSTATE_ALL) {
+                    while (last->all_next) {
+                        last = last->all_next;
+                    }
+                    /* If the end of the list contains a node state
+                        change then run through all of the Require_one
+                        nodes to the end of that list */
+                    if (level >= last->req_state_level) {
+                        while (last->one_next) {
+                            last = last->one_next;
+                        }
+                    }
+                    continue;
+                }
+                /* if we are in a Require_one block then run through
+                    all of the Require_one nodes to the end of the list */
+                if (last->req_state == AUTHZ_REQSTATE_ONE) {
+                    while (last->one_next) {
+                        last = last->one_next;
+                    }
+                    /* If the end of the list contains a node state
+                        change then run through all of the Require_all
+                        nodes to the end of that list */
+                    if (level >= last->req_state_level) {
+                        while (last->all_next) {
+                            last = last->all_next;
+                        }
+                    }
+                    continue;
+                }
+            }
+
+            /* The current state flag indicates which way the transition should
+               go.  If ALL then take the all_next path, otherwise one_next */
+            if (last->req_state == AUTHZ_REQSTATE_ALL) {
+                /* If we already have an all_next node, then
+                   we must have dropped back a level so assign
+                   the node to one_next */
+                if (!last->all_next) {
+                    last->all_next = newp;
+                }
+                else
+                    last->one_next = newp;
+            }
+            else {
+                /* If we already have a one_next node, then
+                   we must have dropped back a level so assign
+                   the node to all_next */
+                if (!last->one_next) {
+                    last->one_next = newp;
+                }
+                else
+                    last->all_next = newp;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+/* This is a fake authz provider that really merges various authz alias
+   configurations and then envokes them. */
+static authz_status authz_alias_check_authorization(request_rec *r,
+                                              const char *require_args)
+{
+    /* Look up the provider alias in the alias list */
+    /* Get the the dir_config and call ap_Merge_per_dir_configs() */
+    /* Call the real provider->check_authorization() function */
+    /* return the result of the above function call */
+
+    const char *provider_name = apr_table_get(r->notes, AUTHZ_PROVIDER_NAME_NOTE);
+    authz_status ret = AUTHZ_DENIED;
+    authz_core_srv_conf *authcfg =
+        (authz_core_srv_conf *)ap_get_module_config(r->server->module_config,
+                                                     &authz_core_module);
+
+    if (provider_name) {
+        provider_alias_rec *prvdraliasrec = apr_hash_get(authcfg->alias_rec,
+                                                         provider_name, APR_HASH_KEY_STRING);
+        ap_conf_vector_t *orig_dir_config = r->per_dir_config;
+
+        /* If we found the alias provider in the list, then merge the directory
+           configurations and call the real provider */
+        if (prvdraliasrec) {
+            r->per_dir_config = ap_merge_per_dir_configs(r->pool, orig_dir_config,
+                                                         prvdraliasrec->sec_auth);
+            ret = prvdraliasrec->provider->check_authorization(r, prvdraliasrec->provider_args);
+            r->per_dir_config = orig_dir_config;
+        }
+    }
+
+    return ret;
+}
+
+static const authz_provider authz_alias_provider =
+{
+    &authz_alias_check_authorization,
+};
+
+static const char *authz_require_alias_section(cmd_parms *cmd, void *mconfig, const char *arg)
+{
+    int old_overrides = cmd->override;
+    const char *endp = ap_strrchr_c(arg, '>');
+    const char *args;
+    char *provider_alias;
+    char *provider_name;
+    char *provider_args;
+    const char *errmsg;
+    ap_conf_vector_t *new_authz_config = ap_create_per_dir_config(cmd->pool);
+    authz_core_srv_conf *authcfg = 
+        (authz_core_srv_conf *)ap_get_module_config(cmd->server->module_config,
+                                                     &authz_core_module);
+
+    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+    if (err != NULL) {
+        return err;
+    }
+
+    if (endp == NULL) {
+        return apr_pstrcat(cmd->pool, cmd->cmd->name,
+                           "> directive missing closing '>'", NULL);
+    }
+
+    args = apr_pstrndup(cmd->pool, arg, endp - arg);
+
+    if (!args[0]) {
+        return apr_pstrcat(cmd->pool, cmd->cmd->name,
+                           "> directive requires additional arguments", NULL);
+    }
+
+    /* Pull the real provider name and the alias name from the block header */
+    provider_name = ap_getword_conf(cmd->pool, &args);
+    provider_alias = ap_getword_conf(cmd->pool, &args);
+    provider_args = ap_getword_conf(cmd->pool, &args);
+
+    if (!provider_name[0] || !provider_alias[0]) {
+        return apr_pstrcat(cmd->pool, cmd->cmd->name,
+                           "> directive requires additional arguments", NULL);
+    }
+
+    /* walk the subsection configuration to get the per_dir config that we will
+       merge just before the real provider is called. */
+    cmd->override = OR_ALL|ACCESS_CONF;
+    errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_authz_config);
+
+    if (!errmsg) {
+        provider_alias_rec *prvdraliasrec = apr_pcalloc(cmd->pool, sizeof(provider_alias_rec));
+        const authz_provider *provider = ap_lookup_provider(AUTHZ_PROVIDER_GROUP, provider_name,"0");
+
+        /* Save off the new directory config along with the original provider name
+           and function pointer data */
+        prvdraliasrec->sec_auth = new_authz_config;
+        prvdraliasrec->provider_name = provider_name;
+        prvdraliasrec->provider_alias = provider_alias;
+        prvdraliasrec->provider_args = provider_args;
+        prvdraliasrec->provider = provider;         
+        
+        apr_hash_set(authcfg->alias_rec, provider_alias, APR_HASH_KEY_STRING, prvdraliasrec);
+
+        /* Register the fake provider so that we get called first */
+        ap_register_provider(cmd->pool, AUTHZ_PROVIDER_GROUP, provider_alias, "0",
+                             &authz_alias_provider);
+    }
+
+    cmd->override = old_overrides;
+
+    return errmsg;
+}
+
+static const char *authz_require_section(cmd_parms *cmd, void *mconfig, const char *arg)
+{
+    int old_overrides = cmd->override;
+    const char *endp = ap_strrchr_c(arg, '>');
+    const char *args;
+    const char *errmsg;
+    authz_request_state old_reqstate;
+    authz_core_dir_conf *conf = (authz_core_dir_conf*)mconfig;
+//  authz_core_srv_conf *authcfg = 
+//      (authz_core_srv_conf *)ap_get_module_config(cmd->server->module_config,
+//                                                   &authz_core_module);
+
+    if (endp == NULL) {
+        return apr_pstrcat(cmd->pool, cmd->cmd->name,
+                           "> directive missing closing '>'", NULL);
+    }
+
+    args = apr_pstrndup(cmd->pool, arg, endp - arg);
+
+    if (args[0]) {
+        return apr_pstrcat(cmd->pool, cmd->cmd->name,
+                           "> directive doesn't take additional arguments", NULL);
+    }
+
+    /* Save off the current request state so that we can go back to it after walking
+       the subsection.  Indicate a transition in the logic incrementing the level.
+       After the subsection walk the level will be decremented to indicate the
+       path to follow. As the require directives are read by the configuration
+       the req_state and the level will allow it to traverse the list to find
+       the last element in the provider calling list. */
+    old_reqstate = conf->req_state;
+    if (strcasecmp (cmd->directive->directive, "<SatisfyAll") == 0) {
+        conf->req_state = AUTHZ_REQSTATE_ALL;
+    }
+    else {
+        conf->req_state = AUTHZ_REQSTATE_ONE;
+    }
+    conf->req_state_level++;
+    cmd->override = OR_ALL|ACCESS_CONF;
+
+    /* walk the subsection configuration to get the per_dir config that we will
+       merge just before the real provider is called. */
+    errmsg = ap_walk_config(cmd->directive->first_child, cmd, cmd->context);
+
+    conf->req_state_level--;
+    conf->req_state = old_reqstate;
+    cmd->override = old_overrides;
+
+    return errmsg;
+}
+
+static const command_rec authz_cmds[] =
+{
+    AP_INIT_RAW_ARGS("Require", add_authz_provider, NULL, OR_AUTHCFG,
+                     "Selects which authenticated users or groups may access "
+                     "a protected space"),
+    AP_INIT_RAW_ARGS("Reject", add_authz_provider, (void*)1, OR_AUTHCFG,
+                     "Rejects the specified authenticated users or groups from accessing "
+                     "a protected space"),
+    AP_INIT_RAW_ARGS("<RequireAlias", authz_require_alias_section, NULL, RSRC_CONF,
+                     "Container for authorization directives grouped under "
+                     "an authz provider alias"),
+    AP_INIT_RAW_ARGS("<SatisfyAll", authz_require_section, NULL, OR_AUTHCFG,
+                     "Container for grouping require statements that must all " 
+                     "succeed for authorization to be granted"),
+    AP_INIT_RAW_ARGS("<SatisfyOne", authz_require_section, NULL, OR_AUTHCFG,
+                     "Container for grouping require statements of which one " 
+                     "must succeed for authorization to be granted"),
+    {NULL}
+};
+
+static authz_status check_provider_list (request_rec *r, authz_provider_list *current_provider, int prev_level)
+{
+    authz_status auth_result = AUTHZ_DENIED;
+
+    const authz_provider *provider;
+
+    /* For now, if a provider isn't set, we'll be nice and use the file
+     * provider.
+     */
+    if (!current_provider) {
+        provider = ap_lookup_provider(AUTHZ_PROVIDER_GROUP,
+                                      AUTHZ_DEFAULT_PROVIDER, "0");
+
+        if (!provider || !provider->check_authorization) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                          "No default authz provider configured");
+            auth_result = AUTHZ_GENERAL_ERROR;
+            return auth_result;
+        }
+        apr_table_setn(r->notes, AUTHZ_PROVIDER_NAME_NOTE,
+                       AUTHZ_DEFAULT_PROVIDER);
+    }
+    else {
+        provider = current_provider->provider;
+        apr_table_setn(r->notes, AUTHZ_PROVIDER_NAME_NOTE,
+                       current_provider->provider_name);
+    }
+
+    /* check to make sure that the request method requires
+    authorization before calling the provider */
+    if (!(current_provider->method_mask & 
+        (AP_METHOD_BIT << r->method_number))) {
+        return AUTHZ_DENIED;
+    }
+
+    auth_result = provider->check_authorization(r,
+                    current_provider->requirement);
+
+    if (auth_result == AUTHZ_GENERAL_ERROR) {
+        return auth_result;
+    }
+
+    if (current_provider->is_reject) {
+        auth_result = auth_result == AUTHZ_DENIED ? AUTHZ_GRANTED : AUTHZ_DENIED;
+    }
+
+    apr_table_unset(r->notes, AUTHZ_PROVIDER_NAME_NOTE);
+
+    /* If the current node is a Require_One type */
+    if (current_provider->req_state == AUTHZ_REQSTATE_ONE) {
+        /* if the auth_result of *this* node was GRANTED and we are embedded in a Require_all block
+            then look to see if there is another Require_all node that needs to be satisfied */
+        if (auth_result == AUTHZ_GRANTED) {
+            if ((current_provider->all_next) && 
+                (current_provider->all_next->req_state_level < current_provider->req_state_level)) {
+                auth_result = check_provider_list (r, current_provider->all_next,
+                                                   current_provider->req_state_level);
+            }
+            return auth_result;
+        }
+        one_next:
+
+        /* Traverse forward to the next Require_one node it one exists 
+            otherwise just return the auth_result */
+        if (current_provider->one_next) {
+            auth_result = check_provider_list (r, current_provider->one_next, 
+                                               current_provider->req_state_level);
+        }
+        else
+            return auth_result;
+
+        /* if the *last* auth_result was GRANTED and we are embedded in a Require_all block
+            then look to see if there is another Require_all node that needs to be satisfied */
+        if ((auth_result == AUTHZ_GRANTED) && (current_provider->all_next) &&
+            (current_provider->all_next->req_state_level < current_provider->req_state_level)) {
+            auth_result = check_provider_list (r, current_provider->all_next,
+                                               current_provider->req_state_level);
+        }
+             /* If the *last* auth_result was DENIED and we are inside of a Require_one block
+                 then look to see if there is another Require_one node that can be satisfied */
+        else if ((auth_result == AUTHZ_DENIED) && (current_provider->one_next) &&
+                 (current_provider->one_next->req_state_level < current_provider->req_state_level)) {
+            goto one_next;
+        }
+
+        return auth_result;
+    }
+
+    /* If the current node is a Require_All type */
+    if (current_provider->req_state == AUTHZ_REQSTATE_ALL) {
+        /* if the auth_result of *this* node was DENIED and we are embedded in a Require_one block
+            then look to see if there is another Require_one node that can be satisfied */
+        if (auth_result == AUTHZ_DENIED) {
+            if ((current_provider->one_next) && 
+                (current_provider->one_next->req_state_level < current_provider->req_state_level)) {
+                auth_result = check_provider_list (r, current_provider->one_next,
+                                                   current_provider->req_state_level);
+            }
+            return auth_result;
+        }
+        all_next:
+
+        /* Traverse forward to the next Require_all node it one exists 
+            otherwise just return the auth_result */
+        if (current_provider->all_next) {
+            auth_result = check_provider_list (r, current_provider->all_next,
+                                               current_provider->req_state_level);
+        }
+        else
+            return auth_result;
+
+        /* if the *last* auth_result was DENIED and we are embedded in a Require_one block
+            then look to see if there is another Require_one node that can be satisfied */
+        if ((auth_result == AUTHZ_DENIED) && (current_provider->one_next) &&
+            (current_provider->one_next->req_state_level < current_provider->req_state_level)) {
+            auth_result = check_provider_list (r, current_provider->one_next,
+                                               current_provider->req_state_level);
+        }
+             /* If the *last* auth_result was GRANTED and we are inside of a Require_all block
+                 then look to see if there is another Require_all node that needs to be satisfied */
+        else if ((auth_result == AUTHZ_GRANTED) && (current_provider->all_next) &&
+                 (current_provider->all_next->req_state_level < current_provider->req_state_level)) {
+            goto all_next;
+        }
+    }
+
+    return auth_result;
+}
+
+static int authorize_user(request_rec *r)
+{
+    authz_core_dir_conf *conf = ap_get_module_config(r->per_dir_config,
+            &authz_core_module);
+    authz_status auth_result;
+    authz_provider_list *current_provider;
+
+    /* If we're not really configured for providers, stop now. */
+    if (!conf->providers) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                      "no authorization providers configured");
+        return DECLINED;
+    }
+
+    current_provider = conf->providers;
+
+    auth_result = check_provider_list (r, current_provider, 0);
+
+    if (auth_result != AUTHZ_GRANTED) {
+        int return_code;
+
+        switch (auth_result) {
+            case AUTHZ_DENIED:
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                              "user %s: authorization failure for \"%s\": ",
+                              r->user, r->uri);
+                return_code = HTTP_UNAUTHORIZED;
+                break;
+            case AUTHZ_GENERAL_ERROR:
+            default:
+                /* We'll assume that the module has already said what its
+                 * error was in the logs.
+                 */
+                return_code = HTTP_INTERNAL_SERVER_ERROR;
+                break;
+        }
+
+        /* If we're returning 403, tell them to try again. */
+        if (return_code == HTTP_UNAUTHORIZED) {
+            ap_note_auth_failure (r);
+        }
+        return return_code;
+    }
+
+    return OK;
+}
+
+static int authz_some_auth_required(request_rec *r)
+{
+    authz_core_dir_conf *conf = ap_get_module_config(r->per_dir_config,
+            &authz_core_module);
+    authz_provider_list *current_provider;
+    int req_authz = 0;
+
+    current_provider = conf->providers;
+    while (current_provider) {
+
+        /* Does this provider config apply for this method */
+        if (current_provider->method_mask &
+                (AP_METHOD_BIT << r->method_number)) {
+            req_authz = 1;
+            break;
+        }
+
+        current_provider = current_provider->one_next;
+    }
+
+    return req_authz;
+}
+
+static void register_hooks(apr_pool_t *p)
+{
+    APR_REGISTER_OPTIONAL_FN(authz_some_auth_required);
+
+    ap_hook_auth_checker(authorize_user, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+module AP_MODULE_DECLARE_DATA authz_core_module =
+{
+    STANDARD20_MODULE_STUFF,
+    create_authz_core_dir_config,   /* dir config creater */
+    NULL,                           /* dir merger --- default is to override */
+    create_authz_core_svr_config,   /* server config */
+    NULL,                           /* merge server config */
+    authz_cmds,
+    register_hooks                  /* register hooks */
+};
index 3395b4b588a5eb5757a5068f432bfc13cfd42576..a9f8cc6445e22f07c3a16794d2123c30810bc409 100644 (file)
@@ -17,6 +17,7 @@
 #include "httpd.h"
 #include "http_log.h"
 #include "http_config.h"
+#include "ap_provider.h"
 #include "http_request.h"
 #include "http_protocol.h"
 #include "http_core.h"
@@ -25,6 +26,9 @@
 #include "apr_strings.h"
 #include "mod_authz_dbd.h"
 
+#include "mod_auth.h"
+
+
 module AP_MODULE_DECLARE_DATA authz_dbd_module;
 
 /* Export a hook for modules that manage clientside sessions
@@ -40,7 +44,6 @@ typedef struct {
     const char *query;
     const char *redir_query;
     int redirect;
-    int authoritative;
 } authz_dbd_cfg ;
 
 static ap_dbd_t *(*dbd_handle)(request_rec*) = NULL;
@@ -51,7 +54,7 @@ static const char *const noerror = "???";
 static void *authz_dbd_cr_cfg(apr_pool_t *pool, char *dummy)
 {
     authz_dbd_cfg *ret = apr_pcalloc(pool, sizeof(authz_dbd_cfg));
-    ret->redirect = ret->authoritative = -1;
+    ret->redirect = -1;
     return ret;
 }
 static void *authz_dbd_merge_cfg(apr_pool_t *pool, void *BASE, void *ADD)
@@ -63,8 +66,6 @@ static void *authz_dbd_merge_cfg(apr_pool_t *pool, void *BASE, void *ADD)
     ret->query = (add->query == NULL) ? base->query : add->query;
     ret->redir_query = (add->redir_query == NULL)
                             ? base->redir_query : add->redir_query;
-    ret->authoritative = (add->authoritative == -1)
-                            ? base->authoritative : add->authoritative;
     ret->redirect = (add->redirect == -1) ? base->redirect : add->redirect;
     return ret;
 }
@@ -89,9 +90,6 @@ static const char *authz_dbd_prepare(cmd_parms *cmd, void *cfg,
     return ap_set_string_slot(cmd, cfg, label);
 }
 static const command_rec authz_dbd_cmds[] = {
-    AP_INIT_FLAG("AuthzDBDAuthoritative", ap_set_flag_slot,
-                 (void*)APR_OFFSETOF(authz_dbd_cfg, authoritative), ACCESS_CONF,
-                 "Whether dbd-group is authoritative"),
     AP_INIT_FLAG("AuthzDBDLoginToReferer", ap_set_flag_slot,
                  (void*)APR_OFFSETOF(authz_dbd_cfg, redirect), ACCESS_CONF,
                  "Whether to redirect to referer on successful login"),
@@ -181,6 +179,7 @@ static int authz_dbd_login(request_rec *r, authz_dbd_cfg *cfg,
         }
     }
     if (newuri != NULL) {
+        r->status = HTTP_MOVED_TEMPORARILY;
         apr_table_set(r->err_headers_out, "Location", newuri);
         rv = HTTP_MOVED_TEMPORARILY;
     }
@@ -242,67 +241,82 @@ static int authz_dbd_group_query(request_rec *r, authz_dbd_cfg *cfg,
     }
     return OK;
 }
-static int authz_dbd_check(request_rec *r)
+
+static authz_status dbdgroup_check_authorization(request_rec *r,
+                                              const char *require_args)
 {
-    int i, x, rv;
+    int i, rv;
     const char *w;
-    int m = r->method_number;
-    const apr_array_header_t *reqs_arr = ap_requires(r);
-    require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL;
     apr_array_header_t *groups = NULL;
     const char *t;
     authz_dbd_cfg *cfg = ap_get_module_config(r->per_dir_config,
                                               &authz_dbd_module);
 
-    if (!reqs_arr) {
-        return DECLINED;
-    }
-
-    for (x = 0; x < reqs_arr->nelts; x++) {
-        if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) {
-            continue;
+    if (groups == NULL) {
+        groups = apr_array_make(r->pool, 4, sizeof(const char*));
+        rv = authz_dbd_group_query(r, cfg, groups);
+        if (rv != OK) {
+            return AUTHZ_GENERAL_ERROR;
         }
+    }
 
-        t = reqs[x].requirement;
+    t = require_args;
+    while (t[0]) {
         w = ap_getword_white(r->pool, &t);
-        if (!strcasecmp(w, "dbd-group")) {
-            if (groups == NULL) {
-                groups = apr_array_make(r->pool, 4, sizeof(const char*));
-                rv = authz_dbd_group_query(r, cfg, groups);
-                if (rv != OK) {
-                    return rv;
-                }
+        for (i=0; i < groups->nelts; ++i) {
+            if (!strcmp(w, ((const char**)groups->elts)[i])) {
+                return AUTHZ_GRANTED;
             }
-            while (t[0]) {
-                w = ap_getword_white(r->pool, &t);
-                for (i=0; i < groups->nelts; ++i) {
-                    if (!strcmp(w, ((const char**)groups->elts)[i])) {
-                        return OK;
-                    }
-                }
-            }
-        }
-        else if (!strcasecmp(w, "dbd-login")) {
-            return authz_dbd_login(r, cfg, "login");
-        }
-        else if (!strcasecmp(w, "dbd-logout")) {
-            return authz_dbd_login(r, cfg, "logout");
         }
     }
 
-    if ((groups != NULL) && cfg->authoritative) {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                   "authz_dbd: user %s denied access to %s",
-                   r->user, r->uri);
-        ap_note_auth_failure(r);
-        return HTTP_UNAUTHORIZED;
-    }
-    return DECLINED;
+    return AUTHZ_DENIED;
+}
+
+static authz_status dbdlogin_check_authorization(request_rec *r,
+                                              const char *require_args)
+{
+    authz_dbd_cfg *cfg = ap_get_module_config(r->per_dir_config,
+                                              &authz_dbd_module);
+
+    return (authz_dbd_login(r, cfg, "login") == OK ? AUTHZ_GRANTED : AUTHZ_DENIED);
 }
+
+static authz_status dbdlogout_check_authorization(request_rec *r,
+                                              const char *require_args)
+{
+    authz_dbd_cfg *cfg = ap_get_module_config(r->per_dir_config,
+                                              &authz_dbd_module);
+
+    return (authz_dbd_login(r, cfg, "logout") == OK ? AUTHZ_GRANTED : AUTHZ_DENIED);
+}
+
+static const authz_provider authz_dbdgroup_provider =
+{
+    &dbdgroup_check_authorization,
+};
+
+static const authz_provider authz_dbdlogin_provider =
+{
+    &dbdlogin_check_authorization,
+};
+
+
+static const authz_provider authz_dbdlogout_provider =
+{
+    &dbdlogout_check_authorization,
+};
+
 static void authz_dbd_hooks(apr_pool_t *p)
 {
-    ap_hook_auth_checker(authz_dbd_check, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "dbd-group", "0",
+                         &authz_dbdgroup_provider);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "dbd-login", "0",
+                         &authz_dbdlogin_provider);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "dbd-logout", "0",
+                         &authz_dbdlogout_provider);
 }
+
 module AP_MODULE_DECLARE_DATA authz_dbd_module =
 {
     STANDARD20_MODULE_STUFF,
index a69c747272de3f18de6a005b9348d01910965e60..c3c0aca1379b0e3d00abb267d37fc833eada7b36 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "httpd.h"
 #include "http_config.h"
+#include "ap_provider.h"
 #include "http_core.h"
 #include "http_log.h"
 #include "http_protocol.h"
 typedef struct {
     char *grpfile;
     char *dbmtype;
-    int authoritative;
 } authz_dbm_config_rec;
 
+APR_DECLARE_OPTIONAL_FN(char*, authz_owner_get_file_group, (request_rec *r));
+
+
 /* This should go into APR; perhaps with some nice
  * caching/locking/flocking of the open dbm file.
  */
@@ -62,7 +65,6 @@ static void *create_authz_dbm_dir_config(apr_pool_t *p, char *d)
 
     conf->grpfile = NULL;
     conf->dbmtype = "default";
-    conf->authoritative = 1;  /* fortress is secure by default */
 
     return conf;
 }
@@ -75,11 +77,6 @@ static const command_rec authz_dbm_cmds[] =
     AP_INIT_TAKE1("AuthzDBMType", ap_set_string_slot,
      (void *)APR_OFFSETOF(authz_dbm_config_rec, dbmtype),
      OR_AUTHCFG, "what type of DBM file the group file is"),
-    AP_INIT_FLAG("AuthzDBMAuthoritative", ap_set_flag_slot,
-     (void *)APR_OFFSETOF(authz_dbm_config_rec, authoritative),
-     OR_AUTHCFG, "Set to 'Off' to allow access control to be passed along to "
-     "lower modules, if the group required is not found or empty, or the user "
-     " is not in the required groups. (default is On.)"),
     {NULL}
 };
 
@@ -133,142 +130,152 @@ static apr_status_t get_dbm_grp(request_rec *r, char *key1, char *key2,
     return retval;
 }
 
-/* Checking ID */
-static int dbm_check_auth(request_rec *r)
+static authz_status dbmgroup_check_authorization(request_rec *r,
+                                             const char *require_args)
 {
     authz_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config,
                                                       &authz_dbm_module);
     char *user = r->user;
-    int m = r->method_number;
-    const apr_array_header_t *reqs_arr = ap_requires(r);
-    require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL;
-    register int x;
     const char *t;
     char *w;
-    int required_group = 0;
-    const char *filegroup = NULL;
     const char *orig_groups = NULL;
-    char *reason = NULL;
+    const char *realm = ap_auth_name(r);
+    const char *groups;
+    char *v;
 
     if (!conf->grpfile) {
-        return DECLINED;
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                        "No group file was specified in the configuration");
+        return AUTHZ_DENIED;
     }
 
-    if (!reqs_arr) {
-        return DECLINED;
-    }
+    /* fetch group data from dbm file only once. */
+    if (!orig_groups) {
+        apr_status_t status;
 
-    for (x = 0; x < reqs_arr->nelts; x++) {
+        status = get_dbm_grp(r, apr_pstrcat(r->pool, user, ":", realm, NULL),
+                             user, conf->grpfile, conf->dbmtype, &groups);
 
-        if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) {
-            continue;
+        if (status != APR_SUCCESS) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                          "could not open dbm (type %s) group access "
+                          "file: %s", conf->dbmtype, conf->grpfile);
+            return AUTHZ_GENERAL_ERROR;
         }
 
-        t = reqs[x].requirement;
-        w = ap_getword_white(r->pool, &t);
+        if (groups == NULL) {
+            /* no groups available, so exit immediately */
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                          "Authorization of user %s to access %s failed, reason: "
+                          "user doesn't appear in DBM group file (%s).", 
+                          r->user, r->uri, conf->grpfile);
+            return AUTHZ_DENIED;
+        }
 
-        if (!strcasecmp(w, "file-group")) {
-            filegroup = apr_table_get(r->notes, AUTHZ_GROUP_NOTE);
+        orig_groups = groups;
+    }
 
-            if (!filegroup) {
-                /* mod_authz_owner is not present or not
-                 * authoritative. We are just a helper module for testing
-                 * group membership, so we don't care and decline.
-                 */
-                continue;
+    t = require_args;
+    while ((w = ap_getword_white(r->pool, &t)) && w[0]) {
+        groups = orig_groups;
+        while (groups[0]) {
+            v = ap_getword(r->pool, &groups, ',');
+            if (!strcmp(v, w)) {
+                return AUTHZ_GRANTED;
             }
         }
+    }
 
-        if (!strcasecmp(w, "group") || filegroup) {
-            const char *realm = ap_auth_name(r);
-            const char *groups;
-            char *v;
-
-            /* remember that actually a group is required */
-            required_group = 1;
-
-            /* fetch group data from dbm file only once. */
-            if (!orig_groups) {
-                apr_status_t status;
-
-                status = get_dbm_grp(r, apr_pstrcat(r->pool, user, ":", realm,
-                                                    NULL),
-                                     user,
-                                     conf->grpfile, conf->dbmtype, &groups);
-
-                if (status != APR_SUCCESS) {
-                    ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
-                                  "could not open dbm (type %s) group access "
-                                  "file: %s", conf->dbmtype, conf->grpfile);
-                    return HTTP_INTERNAL_SERVER_ERROR;
-                }
-
-                if (groups == NULL) {
-                    /* no groups available, so exit immediately */
-                    reason = apr_psprintf(r->pool,
-                                          "user doesn't appear in DBM group "
-                                          "file (%s).", conf->grpfile);
-                    break;
-                }
-
-                orig_groups = groups;
-            }
+    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                  "Authorization of user %s to access %s failed, reason: "
+                  "user is not part of the 'require'ed group(s).",
+                  r->user, r->uri);
 
-            if (filegroup) {
-                groups = orig_groups;
-                while (groups[0]) {
-                    v = ap_getword(r->pool, &groups, ',');
-                    if (!strcmp(v, filegroup)) {
-                        return OK;
-                    }
-                }
-
-                if (conf->authoritative) {
-                    reason = apr_psprintf(r->pool,
-                                          "file group '%s' does not match.",
-                                          filegroup);
-                    break;
-                }
-
-                /* now forget the filegroup, thus alternatively require'd
-                   groups get a real chance */
-                filegroup = NULL;
-            }
-            else {
-                while (t[0]) {
-                    w = ap_getword_white(r->pool, &t);
-                    groups = orig_groups;
-                    while (groups[0]) {
-                        v = ap_getword(r->pool, &groups, ',');
-                        if (!strcmp(v, w)) {
-                            return OK;
-                        }
-                    }
-                }
-            }
-        }
+    return AUTHZ_DENIED;
+}
+
+APR_OPTIONAL_FN_TYPE(authz_owner_get_file_group) *authz_owner_get_file_group;
+
+static authz_status dbmfilegroup_check_authorization(request_rec *r,
+                                              const char *require_args)
+{
+    authz_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config,
+                                                      &authz_dbm_module);
+    char *user = r->user;
+    const char *realm = ap_auth_name(r);
+    const char *filegroup = NULL;
+    const char *orig_groups = NULL;
+    apr_status_t status;
+    const char *groups;
+    char *v;
+
+    if (!conf->grpfile) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                        "No group file was specified in the configuration");
+        return AUTHZ_DENIED;
+    }
+
+    /* fetch group data from dbm file. */
+    status = get_dbm_grp(r, apr_pstrcat(r->pool, user, ":", realm, NULL),
+                         user, conf->grpfile, conf->dbmtype, &groups);
+
+    if (status != APR_SUCCESS) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                      "could not open dbm (type %s) group access "
+                      "file: %s", conf->dbmtype, conf->grpfile);
+        return AUTHZ_DENIED;
     }
 
-    /* No applicable "require group" for this method seen */
-    if (!required_group || !conf->authoritative) {
-        return DECLINED;
+    if (groups == NULL) {
+        /* no groups available, so exit immediately */
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                      "Authorization of user %s to access %s failed, reason: "
+                      "user doesn't appear in DBM group file (%s).", 
+                      r->user, r->uri, conf->grpfile);
+        return AUTHZ_DENIED;
+    }
+
+    orig_groups = groups;
+
+    filegroup = authz_owner_get_file_group(r);
+
+    if (filegroup) {
+        groups = orig_groups;
+        while (groups[0]) {
+            v = ap_getword(r->pool, &groups, ',');
+            if (!strcmp(v, filegroup)) {
+                return AUTHZ_GRANTED;
+            }
+        }
     }
 
     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                  "Authorization of user %s to access %s failed, reason: %s",
-                  r->user, r->uri,
-                  reason ? reason : "user is not part of the "
-                                    "'require'ed group(s).");
+                  "Authorization of user %s to access %s failed, reason: "
+                  "user is not part of the 'require'ed group(s).",
+                  r->user, r->uri);
 
-    ap_note_auth_failure(r);
-    return HTTP_UNAUTHORIZED;
+    return AUTHZ_DENIED;
 }
 
+static const authz_provider authz_dbmgroup_provider =
+{
+    &dbmgroup_check_authorization,
+};
+
+static const authz_provider authz_dbmfilegroup_provider =
+{
+    &dbmfilegroup_check_authorization,
+};
+
+
 static void register_hooks(apr_pool_t *p)
 {
-    static const char * const aszPre[]={ "mod_authz_owner.c", NULL };
+    authz_owner_get_file_group = APR_RETRIEVE_OPTIONAL_FN(authz_owner_get_file_group);
 
-    ap_hook_auth_checker(dbm_check_auth, aszPre, NULL, APR_HOOK_MIDDLE);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "dbm-group", "0",
+                         &authz_dbmgroup_provider);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "dbm-file-group", "0",
+                         &authz_dbmfilegroup_provider);
 }
 
 module AP_MODULE_DECLARE_DATA authz_dbm_module =
index 0576a0c24bfca609bcb2854f0026e6340b58fef9..8a4712278b7457ce70f1cf23953c294bb9e9b1e1 100644 (file)
@@ -53,31 +53,6 @@ static int check_user_access(request_rec *r)
 {
     authz_default_config_rec *conf = ap_get_module_config(r->per_dir_config,
                                                  &authz_default_module);
-    int m = r->method_number;
-    int method_restricted = 0;
-    register int x;
-    const apr_array_header_t *reqs_arr = ap_requires(r);
-    require_line *reqs;
-
-    /* BUG FIX: tadc, 11-Nov-1995.  If there is no "requires" directive,
-     * then any user will do.
-     */
-    if (!reqs_arr) {
-        return OK;
-    }
-    reqs = (require_line *)reqs_arr->elts;
-
-    for (x = 0; x < reqs_arr->nelts; x++) {
-        if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) {
-            continue;
-        }
-        method_restricted = 1;
-        break;
-    }
-
-    if (method_restricted == 0) {
-        return OK;
-    }
 
     if (!(conf->authoritative)) {
         return DECLINED;
index 77a63b964484f703cf92ec2ddc5d2c103f425d97..72d55efbb69cc441d90adb2e4f1ab67d738e2b1f 100644 (file)
@@ -38,8 +38,6 @@
  *
  * If there are any 'require group' blocks and we
  * are not in any group - we HTTP_UNAUTHORIZE
- * unless we are non-authoritative; in which
- * case we DECLINED.
  *
  */
 
@@ -47,6 +45,7 @@
 #include "apr_lib.h" /* apr_isspace */
 
 #include "ap_config.h"
+#include "ap_provider.h"
 #include "httpd.h"
 #include "http_config.h"
 #include "http_core.h"
 
 typedef struct {
     char *groupfile;
-    int authoritative;
 } authz_groupfile_config_rec;
 
+APR_DECLARE_OPTIONAL_FN(char*, authz_owner_get_file_group, (request_rec *r));
+
 static void *create_authz_groupfile_dir_config(apr_pool_t *p, char *d)
 {
     authz_groupfile_config_rec *conf = apr_palloc(p, sizeof(*conf));
 
     conf->groupfile = NULL;
-    conf->authoritative = 1; /* keep the fortress secure by default */
     return conf;
 }
 
@@ -86,13 +85,6 @@ static const command_rec authz_groupfile_cmds[] =
                    (void *)APR_OFFSETOF(authz_groupfile_config_rec, groupfile),
                    OR_AUTHCFG,
                    "text file containing group names and member user IDs"),
-    AP_INIT_FLAG("AuthzGroupFileAuthoritative", ap_set_flag_slot,
-                 (void *)APR_OFFSETOF(authz_groupfile_config_rec,
-                                      authoritative),
-                 OR_AUTHCFG,
-                 "Set to 'Off' to allow access control to be passed along to "
-                 "lower modules if the 'require group' fails. (default is "
-                 "On)."),
     {NULL}
 };
 
@@ -145,131 +137,139 @@ static apr_status_t groups_for_user(apr_pool_t *p, char *user, char *grpfile,
     return APR_SUCCESS;
 }
 
-/* Checking ID */
-
-static int check_user_access(request_rec *r)
+static authz_status group_check_authorization(request_rec *r,
+                                             const char *require_args)
 {
     authz_groupfile_config_rec *conf = ap_get_module_config(r->per_dir_config,
-                                                      &authz_groupfile_module);
+            &authz_groupfile_module);
     char *user = r->user;
-    int m = r->method_number;
-    int required_group = 0;
-    register int x;
     const char *t, *w;
     apr_table_t *grpstatus = NULL;
-    const apr_array_header_t *reqs_arr = ap_requires(r);
-    require_line *reqs;
-    const char *filegroup = NULL;
-    char *reason = NULL;
+    apr_status_t status;
 
     /* If there is no group file - then we are not
      * configured. So decline.
      */
     if (!(conf->groupfile)) {
-        return DECLINED;
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                        "No group file was specified in the configuration");
+        return AUTHZ_DENIED;
     }
 
-    if (!reqs_arr) {
-        return DECLINED; /* XXX change from legacy */
-    }
+    status = groups_for_user(r->pool, user, conf->groupfile,
+                                &grpstatus);
 
-    reqs = (require_line *)reqs_arr->elts;
+    if (status != APR_SUCCESS) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                        "Could not open group file: %s",
+                        conf->groupfile);
+        return AUTHZ_DENIED;
+    }
 
-    for (x = 0; x < reqs_arr->nelts; x++) {
+    if (apr_table_elts(grpstatus)->nelts == 0) {
+        /* no groups available, so exit immediately */
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                      "Authorization of user %s to access %s failed, reason: "
+                      "user doesn't appear in group file (%s).",
+                      r->user, r->uri, conf->groupfile);
+        return AUTHZ_DENIED;
+    }
 
-        if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) {
-            continue;
+    t = require_args;
+    while ((w = ap_getword_conf(r->pool, &t)) && w[0]) {
+        if (apr_table_get(grpstatus, w)) {
+            return AUTHZ_GRANTED;
         }
+    }
 
-        t = reqs[x].requirement;
-        w = ap_getword_white(r->pool, &t);
+    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                    "Authorization of user %s to access %s failed, reason: "
+                    "user is not part of the 'require'ed group(s).",
+                    r->user, r->uri);
 
-        /* needs mod_authz_owner to be present */
-        if (!strcasecmp(w, "file-group")) {
-            filegroup = apr_table_get(r->notes, AUTHZ_GROUP_NOTE);
+    return AUTHZ_DENIED;
+}
 
-            if (!filegroup) {
-                /* mod_authz_owner is not present or not
-                 * authoritative. We are just a helper module for testing
-                 * group membership, so we don't care and decline.
-                 */
-                continue;
-            }
-        }
+APR_OPTIONAL_FN_TYPE(authz_owner_get_file_group) *authz_owner_get_file_group;
 
-        if (!strcasecmp(w, "group") || filegroup) {
-            required_group = 1; /* remember the requirement */
-
-            /* create group table only if actually needed. */
-            if (!grpstatus) {
-                apr_status_t status;
-
-                status = groups_for_user(r->pool, user, conf->groupfile,
-                                         &grpstatus);
-
-                if (status != APR_SUCCESS) {
-                    ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
-                                  "Could not open group file: %s",
-                                  conf->groupfile);
-                    return HTTP_INTERNAL_SERVER_ERROR;
-                }
-
-                if (apr_table_elts(grpstatus)->nelts == 0) {
-                    /* no groups available, so exit immediately */
-                    reason = apr_psprintf(r->pool,
-                                          "user doesn't appear in group file "
-                                          "(%s).", conf->groupfile);
-                    break;
-                }
-            }
+static authz_status filegroup_check_authorization(request_rec *r,
+                                              const char *require_args)
+{
+    authz_groupfile_config_rec *conf = ap_get_module_config(r->per_dir_config,
+            &authz_groupfile_module);
+    char *user = r->user;
+    apr_table_t *grpstatus = NULL;
+    apr_status_t status;
+    const char *filegroup = NULL;
 
-            if (filegroup) {
-                if (apr_table_get(grpstatus, filegroup)) {
-                    return OK;
-                }
-
-                if (conf->authoritative) {
-                    reason = apr_psprintf(r->pool,
-                                          "file group '%s' does not match.",
-                                          filegroup);
-                    break;
-                }
-
-                /* now forget the filegroup, thus alternatively require'd
-                   groups get a real chance */
-                filegroup = NULL;
-            }
-            else {
-                while (t[0]) {
-                    w = ap_getword_conf(r->pool, &t);
-                    if (apr_table_get(grpstatus, w)) {
-                        return OK;
-                    }
-                }
-            }
-        }
+    /* If there is no group file - then we are not
+     * configured. So decline.
+     */
+    if (!(conf->groupfile)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                        "No group file was specified in the configuration");
+        return AUTHZ_DENIED;
+    }
+
+    status = groups_for_user(r->pool, user, conf->groupfile,
+                             &grpstatus);
+    if (status != APR_SUCCESS) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                      "Could not open group file: %s",
+                      conf->groupfile);
+        return AUTHZ_DENIED;
+    }
+
+    if (apr_table_elts(grpstatus)->nelts == 0) {
+        /* no groups available, so exit immediately */
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                        "Authorization of user %s to access %s failed, reason: "
+                        "user doesn't appear in group file (%s).",
+                        r->user, r->uri, conf->groupfile);
+        return AUTHZ_DENIED;
     }
 
-    /* No applicable "require group" for this method seen */
-    if (!required_group || !conf->authoritative) {
-        return DECLINED;
+    filegroup = authz_owner_get_file_group(r);
+
+    if (filegroup) {
+        if (apr_table_get(grpstatus, filegroup)) {
+            return AUTHZ_GRANTED;
+        }
+    }
+    else {
+        /* No need to emit a error log entry because the call
+        to authz_owner_get_file_group already did it
+        for us.
+        */
+        return AUTHZ_DENIED;
     }
 
     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                  "Authorization of user %s to access %s failed, reason: %s",
-                  r->user, r->uri,
-                  reason ? reason : "user is not part of the "
-                                    "'require'ed group(s).");
+                  "Authorization of user %s to access %s failed, reason: "
+                  "user is not part of the 'require'ed file group.",
+                  r->user, r->uri);
 
-    ap_note_auth_failure(r);
-    return HTTP_UNAUTHORIZED;
+    return AUTHZ_DENIED;
 }
 
+static const authz_provider authz_group_provider =
+{
+    &group_check_authorization,
+};
+
+static const authz_provider authz_filegroup_provider =
+{
+    &filegroup_check_authorization,
+};
+
 static void register_hooks(apr_pool_t *p)
 {
-    static const char * const aszPre[]={ "mod_authz_owner.c", NULL };
+    authz_owner_get_file_group = APR_RETRIEVE_OPTIONAL_FN(authz_owner_get_file_group);
 
-    ap_hook_auth_checker(check_user_access, aszPre, NULL, APR_HOOK_MIDDLE);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "group", "0",
+                         &authz_group_provider);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "file-group", "0",
+                         &authz_filegroup_provider);
 }
 
 module AP_MODULE_DECLARE_DATA authz_groupfile_module =
index 582f32c7ac3ac7f330bdf7f9134fe2427057c5f7..89ebc023b681fda93911415a36d032f442004fa2 100644 (file)
 #include "apr_want.h"
 
 #include "ap_config.h"
+#include "ap_provider.h"
 #include "httpd.h"
 #include "http_core.h"
 #include "http_config.h"
 #include "http_log.h"
+#include "http_protocol.h"
 #include "http_request.h"
 
+#include "mod_auth.h"
+
 #if APR_HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
 
-enum allowdeny_type {
-    T_ENV,
-    T_ALL,
-    T_IP,
-    T_HOST,
-    T_FAIL
-};
-
 typedef struct {
-    apr_int64_t limited;
-    union {
-        char *from;
-        apr_ipsubnet_t *ip;
-    } x;
-    enum allowdeny_type type;
-} allowdeny;
-
-/* things in the 'order' array */
-#define DENY_THEN_ALLOW 0
-#define ALLOW_THEN_DENY 1
-#define MUTUAL_FAILURE 2
-
-typedef struct {
-    int order[METHODS];
-    apr_array_header_t *allows;
-    apr_array_header_t *denys;
+       int dummy;  /* just here to stop compiler warnings for now. */
 } authz_host_dir_conf;
 
 module AP_MODULE_DECLARE_DATA authz_host_module;
 
 static void *create_authz_host_dir_config(apr_pool_t *p, char *dummy)
 {
-    int i;
     authz_host_dir_conf *conf =
         (authz_host_dir_conf *)apr_pcalloc(p, sizeof(authz_host_dir_conf));
 
-    for (i = 0; i < METHODS; ++i) {
-        conf->order[i] = DENY_THEN_ALLOW;
-    }
-    conf->allows = apr_array_make(p, 1, sizeof(allowdeny));
-    conf->denys = apr_array_make(p, 1, sizeof(allowdeny));
-
     return (void *)conf;
 }
 
-static const char *order(cmd_parms *cmd, void *dv, const char *arg)
-{
-    authz_host_dir_conf *d = (authz_host_dir_conf *) dv;
-    int i, o;
-
-    if (!strcasecmp(arg, "allow,deny"))
-        o = ALLOW_THEN_DENY;
-    else if (!strcasecmp(arg, "deny,allow"))
-        o = DENY_THEN_ALLOW;
-    else if (!strcasecmp(arg, "mutual-failure"))
-        o = MUTUAL_FAILURE;
-    else
-        return "unknown order";
-
-    for (i = 0; i < METHODS; ++i)
-        if (cmd->limited & (AP_METHOD_BIT << i))
-            d->order[i] = o;
-
-    return NULL;
-}
-
-static const char *allow_cmd(cmd_parms *cmd, void *dv, const char *from,
-                             const char *where_c)
-{
-    authz_host_dir_conf *d = (authz_host_dir_conf *) dv;
-    allowdeny *a;
-    char *where = apr_pstrdup(cmd->pool, where_c);
-    char *s;
-    char msgbuf[120];
-    apr_status_t rv;
-
-    if (strcasecmp(from, "from"))
-        return "allow and deny must be followed by 'from'";
-
-    a = (allowdeny *) apr_array_push(cmd->info ? d->allows : d->denys);
-    a->x.from = where;
-    a->limited = cmd->limited;
-
-    if (!strncasecmp(where, "env=", 4)) {
-        a->type = T_ENV;
-        a->x.from += 4;
-
-    }
-    else if (!strcasecmp(where, "all")) {
-        a->type = T_ALL;
-    }
-    else if ((s = ap_strchr(where, '/'))) {
-        *s++ = '\0';
-        rv = apr_ipsubnet_create(&a->x.ip, where, s, cmd->pool);
-        if(APR_STATUS_IS_EINVAL(rv)) {
-            /* looked nothing like an IP address */
-            return "An IP address was expected";
-        }
-        else if (rv != APR_SUCCESS) {
-            apr_strerror(rv, msgbuf, sizeof msgbuf);
-            return apr_pstrdup(cmd->pool, msgbuf);
-        }
-        a->type = T_IP;
-    }
-    else if (!APR_STATUS_IS_EINVAL(rv = apr_ipsubnet_create(&a->x.ip, where,
-                                                            NULL, cmd->pool))) {
-        if (rv != APR_SUCCESS) {
-            apr_strerror(rv, msgbuf, sizeof msgbuf);
-            return apr_pstrdup(cmd->pool, msgbuf);
-        }
-        a->type = T_IP;
-    }
-    else { /* no slash, didn't look like an IP address => must be a host */
-        a->type = T_HOST;
-    }
-
-    return NULL;
-}
-
-static char its_an_allow;
-
 static const command_rec authz_host_cmds[] =
 {
-    AP_INIT_TAKE1("order", order, NULL, OR_LIMIT,
-                  "'allow,deny', 'deny,allow', or 'mutual-failure'"),
-    AP_INIT_ITERATE2("allow", allow_cmd, &its_an_allow, OR_LIMIT,
-                     "'from' followed by hostnames or IP-address wildcards"),
-    AP_INIT_ITERATE2("deny", allow_cmd, NULL, OR_LIMIT,
-                     "'from' followed by hostnames or IP-address wildcards"),
     {NULL}
 };
 
@@ -199,115 +90,168 @@ static int in_domain(const char *domain, const char *what)
     }
 }
 
-static int find_allowdeny(request_rec *r, apr_array_header_t *a, int method)
+static authz_status env_check_authorization(request_rec *r, const char *require_line)
 {
-
-    allowdeny *ap = (allowdeny *) a->elts;
-    apr_int64_t mmask = (AP_METHOD_BIT << method);
-    int i;
-    int gothost = 0;
-    const char *remotehost = NULL;
-
-    for (i = 0; i < a->nelts; ++i) {
-        if (!(mmask & ap[i].limited)) {
-            continue;
+    const char *t, *w;
+
+    /* The 'env' provider will allow the configuration to specify a list of
+        env variables to check rather than a single variable.  This is different
+        from the previous host based syntax. */
+    t = require_line;
+    while ((w = ap_getword_conf(r->pool, &t)) && w[0]) {
+        if (apr_table_get(r->subprocess_env, w)) {
+            return AUTHZ_GRANTED;
         }
+    }
 
-        switch (ap[i].type) {
-        case T_ENV:
-            if (apr_table_get(r->subprocess_env, ap[i].x.from)) {
-                return 1;
-            }
-            break;
+    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                  "access to %s failed, reason: env variable list does not meet "
+                  "'require'ments for user '%s' to be allowed access",
+                  r->uri, r->user);
 
-        case T_ALL:
-            return 1;
+    ap_note_auth_failure(r);
+    return AUTHZ_DENIED;
+}
 
-        case T_IP:
-            if (apr_ipsubnet_test(ap[i].x.ip, r->connection->remote_addr)) {
-                return 1;
+static authz_status ip_check_authorization(request_rec *r, const char *require_line)
+{
+    const char *t, *w;
+
+    /* The 'ip' provider will allow the configuration to specify a list of
+        ip addresses to check rather than a single address.  This is different
+        from the previous host based syntax. */
+    t = require_line;
+    while ((w = ap_getword_conf(r->pool, &t)) && w[0]) {
+        char *where = apr_pstrdup(r->pool, w);
+        char *s;
+        char msgbuf[120];
+        apr_ipsubnet_t *ip;
+        apr_status_t rv;
+        int got_ip = 0;
+
+        if ((s = ap_strchr(where, '/'))) {
+            *s++ = '\0';
+            rv = apr_ipsubnet_create(&ip, where, s, r->pool);
+            if(APR_STATUS_IS_EINVAL(rv)) {
+                /* looked nothing like an IP address */
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                              "an ip address 'require' list appears to be invalid ");
             }
-            break;
-
-        case T_HOST:
-            if (!gothost) {
-                int remotehost_is_ip;
-
-                remotehost = ap_get_remote_host(r->connection,
-                                                r->per_dir_config,
-                                                REMOTE_DOUBLE_REV,
-                                                &remotehost_is_ip);
-
-                if ((remotehost == NULL) || remotehost_is_ip) {
-                    gothost = 1;
-                }
-                else {
-                    gothost = 2;
-                }
+            else if (rv != APR_SUCCESS) {
+                apr_strerror(rv, msgbuf, sizeof msgbuf);
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                              "an ip address 'require' list appears to be invalid; %s ",
+                              msgbuf);
             }
-
-            if ((gothost == 2) && in_domain(ap[i].x.from, remotehost)) {
-                return 1;
+            else
+                got_ip = 1;
+        }
+        else if (!APR_STATUS_IS_EINVAL(rv = apr_ipsubnet_create(&ip, where,
+                                                                NULL, r->pool))) {
+            if (rv != APR_SUCCESS) {
+                apr_strerror(rv, msgbuf, sizeof msgbuf);
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                              "an ip address 'require' list appears to be invalid; %s ",
+                              msgbuf);
             }
-            break;
+            else 
+                got_ip = 1;
+        }
 
-        case T_FAIL:
-            /* do nothing? */
-            break;
+        if (got_ip && apr_ipsubnet_test(ip, r->connection->remote_addr)) {
+            return AUTHZ_GRANTED;
         }
     }
 
-    return 0;
+    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                  "access to %s failed, reason: ip address list does not meet "
+                  "'require'ments for user '%s' to be allowed access",
+                  r->uri, r->user);
+
+    ap_note_auth_failure(r);
+    return AUTHZ_DENIED;
 }
 
-static int check_dir_access(request_rec *r)
+static authz_status host_check_authorization(request_rec *r, const char *require_line)
 {
-    int method = r->method_number;
-    int ret = OK;
-    authz_host_dir_conf *a = (authz_host_dir_conf *)
-        ap_get_module_config(r->per_dir_config, &authz_host_module);
-
-    if (a->order[method] == ALLOW_THEN_DENY) {
-        ret = HTTP_FORBIDDEN;
-        if (find_allowdeny(r, a->allows, method)) {
-            ret = OK;
-        }
-        if (find_allowdeny(r, a->denys, method)) {
-            ret = HTTP_FORBIDDEN;
-        }
-    }
-    else if (a->order[method] == DENY_THEN_ALLOW) {
-        if (find_allowdeny(r, a->denys, method)) {
-            ret = HTTP_FORBIDDEN;
-        }
-        if (find_allowdeny(r, a->allows, method)) {
-            ret = OK;
-        }
+    const char *t, *w;
+    const char *remotehost = NULL;
+    int remotehost_is_ip;
+
+    remotehost = ap_get_remote_host(r->connection,
+                                    r->per_dir_config,
+                                    REMOTE_DOUBLE_REV,
+                                    &remotehost_is_ip);
+
+    if ((remotehost == NULL) || remotehost_is_ip) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                      "access to %s failed, reason: unable to get the "
+                      "remote host name", r->uri);
     }
     else {
-        if (find_allowdeny(r, a->allows, method)
-            && !find_allowdeny(r, a->denys, method)) {
-            ret = OK;
-        }
-        else {
-            ret = HTTP_FORBIDDEN;
+        /* The 'host' provider will allow the configuration to specify a list of
+            host names to check rather than a single name.  This is different
+            from the previous host based syntax. */
+        t = require_line;
+        while ((w = ap_getword_conf(r->pool, &t)) && w[0]) {
+            if (in_domain(w, remotehost)) {
+                return AUTHZ_GRANTED;
+            }
         }
-    }
 
-    if (ret == HTTP_FORBIDDEN
-        && (ap_satisfies(r) != SATISFY_ANY || !ap_some_auth_required(r))) {
         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-            "client denied by server configuration: %s",
-            r->filename);
+                      "access to %s failed, reason: host name list does not meet "
+                      "'require'ments for user '%s' to be allowed access",
+                      r->uri, r->user);
     }
 
-    return ret;
+    ap_note_auth_failure(r);
+    return AUTHZ_DENIED;
+}
+
+static authz_status all_check_authorization(request_rec *r, const char *require_line)
+{
+    /* If the argument to the 'all' provider is 'granted' then just let 
+        everybody in. This would be equivalent to the previous syntax of
+        'allow from all'. If the argument is anything else, this would
+        be equivalent to 'deny from all' Of course the opposite would be 
+        true if the 'all' provider is invoked by the 'reject' directive */
+    if (strcasecmp(require_line, "granted") == 0) {
+        return AUTHZ_GRANTED;
+    }
+    return AUTHZ_DENIED;
 }
 
+static const authz_provider authz_env_provider =
+{
+    &env_check_authorization,
+};
+
+static const authz_provider authz_ip_provider =
+{
+    &ip_check_authorization,
+};
+
+static const authz_provider authz_host_provider =
+{
+    &host_check_authorization,
+};
+
+static const authz_provider authz_all_provider =
+{
+    &all_check_authorization,
+};
+
 static void register_hooks(apr_pool_t *p)
 {
-    /* This can be access checker since we don't require r->user to be set. */
-    ap_hook_access_checker(check_dir_access,NULL,NULL,APR_HOOK_MIDDLE);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "env", "0",
+                         &authz_env_provider);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "ip", "0",
+                         &authz_ip_provider);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "host", "0",
+                         &authz_host_provider);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "all", "0",
+                         &authz_all_provider);
 }
 
 module AP_MODULE_DECLARE_DATA authz_host_module =
index 050860d896e37d575159aaf5d22a574ec2533f58..1f74800379322fcbab1c5f56762f35d6df6cb90e 100644 (file)
@@ -19,6 +19,7 @@
 #include "apr_user.h"
 
 #include "ap_config.h"
+#include "ap_provider.h"
 #include "httpd.h"
 #include "http_config.h"
 #include "http_core.h"
 #include "mod_auth.h"     /* for AUTHZ_GROUP_NOTE */
 
 typedef struct {
-    int authoritative;
 } authz_owner_config_rec;
 
+APR_DECLARE_OPTIONAL_FN(char*, authz_owner_get_file_group, (request_rec *r));
+
 static void *create_authz_owner_dir_config(apr_pool_t *p, char *d)
 {
     authz_owner_config_rec *conf = apr_palloc(p, sizeof(*conf));
 
-    conf->authoritative = 1; /* keep the fortress secure by default */
     return conf;
 }
 
 static const command_rec authz_owner_cmds[] =
 {
-    AP_INIT_FLAG("AuthzOwnerAuthoritative", ap_set_flag_slot,
-                 (void *)APR_OFFSETOF(authz_owner_config_rec, authoritative),
-                 OR_AUTHCFG,
-                 "Set to 'Off' to allow access control to be passed along to "
-                 "lower modules. (default is On.)"),
     {NULL}
 };
 
 module AP_MODULE_DECLARE_DATA authz_owner_module;
 
-static int check_file_owner(request_rec *r)
+static authz_status fileowner_check_authorization(request_rec *r,
+                                             const char *require_args)
 {
-    authz_owner_config_rec *conf = ap_get_module_config(r->per_dir_config,
-                                                        &authz_owner_module);
-    int m = r->method_number;
-    register int x;
-    const char *t, *w;
-    const apr_array_header_t *reqs_arr = ap_requires(r);
-    require_line *reqs;
-    int required_owner = 0;
-    apr_status_t status = 0;
     char *reason = NULL;
+    apr_status_t status = 0;
 
-    if (!reqs_arr) {
-        return DECLINED;
+#if !APR_HAS_USER
+    reason = "'Require file-owner' is not supported on this platform.";
+    ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                  "Authorization of user %s to access %s failed, reason: %s",
+                  r->user, r->uri, reason ? reason : "unknown");
+    return AUTHZ_DENIED;
+#else  /* APR_HAS_USER */
+    char *owner = NULL;
+    apr_finfo_t finfo;
+
+    if (!r->filename) {
+        reason = "no filename available";
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                      "Authorization of user %s to access %s failed, reason: %s",
+                      r->user, r->uri, reason ? reason : "unknown");
+        return AUTHZ_DENIED;
     }
 
-    reqs = (require_line *)reqs_arr->elts;
-    for (x = 0; x < reqs_arr->nelts; x++) {
-
-        /* if authoritative = On then break if a require already failed. */
-        if (reason && conf->authoritative) {
-            break;
-        }
+    status = apr_stat(&finfo, r->filename, APR_FINFO_USER, r->pool);
+    if (status != APR_SUCCESS) {
+        reason = apr_pstrcat(r->pool, "could not stat file ",
+                                r->filename, NULL);
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                      "Authorization of user %s to access %s failed, reason: %s",
+                      r->user, r->uri, reason ? reason : "unknown");
+        return AUTHZ_DENIED;
+    }
 
-        if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) {
-            continue;
-        }
+    if (!(finfo.valid & APR_FINFO_USER)) {
+        reason = "no file owner information available";
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                      "Authorization of user %s to access %s failed, reason: %s",
+                      r->user, r->uri, reason ? reason : "unknown");
+        return AUTHZ_DENIED;
+    }
 
-        t = reqs[x].requirement;
-        w = ap_getword_white(r->pool, &t);
+    status = apr_uid_name_get(&owner, finfo.user, r->pool);
+    if (status != APR_SUCCESS || !owner) {
+        reason = "could not get name of file owner";
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                      "Authorization of user %s to access %s failed, reason: %s",
+                      r->user, r->uri, reason ? reason : "unknown");
+        return AUTHZ_DENIED;
+    }
 
-        if (!strcmp(w, "file-owner")) {
-#if !APR_HAS_USER
-            if ((required_owner & ~1) && conf->authoritative) {
-                break;
-            }
+    if (strcmp(owner, r->user)) {
+        reason = apr_psprintf(r->pool, "file owner %s does not match.",
+                                owner);
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                      "Authorization of user %s to access %s failed, reason: %s",
+                      r->user, r->uri, reason ? reason : "unknown");
+        return AUTHZ_DENIED;
+    }
 
-            required_owner |= 1; /* remember the requirement */
-            reason = "'Require file-owner' is not supported on this platform.";
-            continue;
-#else  /* APR_HAS_USER */
-            char *owner = NULL;
-            apr_finfo_t finfo;
-
-            if ((required_owner & ~1) && conf->authoritative) {
-                break;
-            }
-
-            required_owner |= 1; /* remember the requirement */
-
-            if (!r->filename) {
-                reason = "no filename available";
-                continue;
-            }
-
-            status = apr_stat(&finfo, r->filename, APR_FINFO_USER, r->pool);
-            if (status != APR_SUCCESS) {
-                reason = apr_pstrcat(r->pool, "could not stat file ",
-                                     r->filename, NULL);
-                continue;
-            }
-
-            if (!(finfo.valid & APR_FINFO_USER)) {
-                reason = "no file owner information available";
-                continue;
-            }
-
-            status = apr_uid_name_get(&owner, finfo.user, r->pool);
-            if (status != APR_SUCCESS || !owner) {
-                reason = "could not get name of file owner";
-                continue;
-            }
-
-            if (strcmp(owner, r->user)) {
-                reason = apr_psprintf(r->pool, "file owner %s does not match.",
-                                      owner);
-                continue;
-            }
-
-            /* this user is authorized */
-            return OK;
+    /* this user is authorized */
+    return AUTHZ_GRANTED;
 #endif /* APR_HAS_USER */
-        }
-
-        /* file-group only figures out the file's group and lets
-         * other modules do the actual authorization (against a group file/db).
-         * Thus, these modules have to hook themselves after
-         * mod_authz_owner and of course recognize 'file-group', too.
-         */
-        if (!strcmp(w, "file-group")) {
-#if !APR_HAS_USER
-            if ((required_owner & ~6) && conf->authoritative) {
-                break;
-            }
+}
 
-            required_owner |= 2; /* remember the requirement */
-            reason = "'Require file-group' is not supported on this platform.";
-            continue;
+static char *authz_owner_get_file_group(request_rec *r)
+{
+    char *reason = NULL;
+
+    /* file-group only figures out the file's group and lets
+    * other modules do the actual authorization (against a group file/db).
+    * Thus, these modules have to hook themselves after
+    * mod_authz_owner and of course recognize 'file-group', too.
+    */
+#if !APR_HAS_USER
+    return NULL;
 #else  /* APR_HAS_USER */
-            char *group = NULL;
-            apr_finfo_t finfo;
-
-            if ((required_owner & ~6) && conf->authoritative) {
-                break;
-            }
-
-            required_owner |= 2; /* remember the requirement */
-
-            if (!r->filename) {
-                reason = "no filename available";
-                continue;
-            }
-
-            status = apr_stat(&finfo, r->filename, APR_FINFO_GROUP, r->pool);
-            if (status != APR_SUCCESS) {
-                reason = apr_pstrcat(r->pool, "could not stat file ",
-                                     r->filename, NULL);
-                continue;
-            }
-
-            if (!(finfo.valid & APR_FINFO_GROUP)) {
-                reason = "no file group information available";
-                continue;
-            }
-
-            status = apr_gid_name_get(&group, finfo.group, r->pool);
-            if (status != APR_SUCCESS || !group) {
-                reason = "could not get name of file group";
-                continue;
-            }
-
-            /* store group name in a note and let others decide... */
-            apr_table_setn(r->notes, AUTHZ_GROUP_NOTE, group);
-            required_owner |= 4;
-            continue;
-#endif /* APR_HAS_USER */
-        }
+    char *group = NULL;
+    apr_finfo_t finfo;
+    apr_status_t status = 0;
+
+    if (!r->filename) {
+        reason = "no filename available";
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                      "Authorization of user %s to access %s failed, reason: %s",
+                      r->user, r->uri, reason ? reason : "unknown");
+        return NULL;
     }
 
-    if (!required_owner || !conf->authoritative) {
-        return DECLINED;
+    status = apr_stat(&finfo, r->filename, APR_FINFO_GROUP, r->pool);
+    if (status != APR_SUCCESS) {
+        reason = apr_pstrcat(r->pool, "could not stat file ",
+                                r->filename, NULL);
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                      "Authorization of user %s to access %s failed, reason: %s",
+                      r->user, r->uri, reason ? reason : "unknown");
+        return NULL;
     }
 
-    /* allow file-group passed to group db modules either if this is the
-     * only applicable requirement here or if a file-owner failed but we're
-     * not authoritative.
-     * This allows configurations like:
-     *
-     * AuthzOwnerAuthoritative Off
-     * require file-owner
-     * require file-group
-     *
-     * with the semantical meaning of "either owner or group must match"
-     * (inclusive or)
-     *
-     * [ 6 == 2 | 4; 7 == 1 | 2 | 4 ] should I use #defines instead?
-     */
-    if (required_owner == 6 || (required_owner == 7 && !conf->authoritative)) {
-        return DECLINED;
+    if (!(finfo.valid & APR_FINFO_GROUP)) {
+        reason = "no file group information available";
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                      "Authorization of user %s to access %s failed, reason: %s",
+                      r->user, r->uri, reason ? reason : "unknown");
+        return NULL;
     }
 
-    ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
-                  "Authorization of user %s to access %s failed, reason: %s",
-                  r->user, r->uri, reason ? reason : "unknown");
+    status = apr_gid_name_get(&group, finfo.group, r->pool);
+    if (status != APR_SUCCESS || !group) {
+        reason = "could not get name of file group";
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
+                      "Authorization of user %s to access %s failed, reason: %s",
+                      r->user, r->uri, reason ? reason : "unknown");
+        return NULL;
+    }
 
-    ap_note_auth_failure(r);
-    return HTTP_UNAUTHORIZED;
+    return group;
+#endif /* APR_HAS_USER */
 }
 
+static const authz_provider authz_fileowner_provider =
+{
+    &fileowner_check_authorization,
+};
+
 static void register_hooks(apr_pool_t *p)
 {
-    ap_hook_auth_checker(check_file_owner, NULL, NULL, APR_HOOK_MIDDLE);
+    APR_REGISTER_OPTIONAL_FN(authz_owner_get_file_group);
+
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "file-owner", "0",
+                         &authz_fileowner_provider);
 }
 
 module AP_MODULE_DECLARE_DATA authz_owner_module =
index cc6d808a3eceef445d517b76c9b0dfa5321a984e..0292f841bf72a6ce84f6259b26a766fe5f455992 100644 (file)
@@ -17,6 +17,7 @@
 #include "apr_strings.h"
 
 #include "ap_config.h"
+#include "ap_provider.h"
 #include "httpd.h"
 #include "http_config.h"
 #include "http_core.h"
 #include "http_protocol.h"
 #include "http_request.h"
 
+#include "mod_auth.h"
+
 typedef struct {
-    int authoritative;
+       int dummy;  /* just here to stop compiler warnings for now. */
 } authz_user_config_rec;
 
 static void *create_authz_user_dir_config(apr_pool_t *p, char *d)
 {
     authz_user_config_rec *conf = apr_palloc(p, sizeof(*conf));
 
-    conf->authoritative = 1; /* keep the fortress secure by default */
     return conf;
 }
 
 static const command_rec authz_user_cmds[] =
 {
-    AP_INIT_FLAG("AuthzUserAuthoritative", ap_set_flag_slot,
-                 (void *)APR_OFFSETOF(authz_user_config_rec, authoritative),
-                 OR_AUTHCFG,
-                 "Set to 'Off' to allow access control to be passed along to "
-                 "lower modules if the 'require user' or 'require valid-user' "
-                 "statement is not met. (default: On)."),
     {NULL}
 };
 
 module AP_MODULE_DECLARE_DATA authz_user_module;
 
-static int check_user_access(request_rec *r)
+static authz_status user_check_authorization(request_rec *r,
+                                             const char *require_args)
 {
-    authz_user_config_rec *conf = ap_get_module_config(r->per_dir_config,
-                                                       &authz_user_module);
-    char *user = r->user;
-    int m = r->method_number;
-    int required_user = 0;
-    register int x;
     const char *t, *w;
-    const apr_array_header_t *reqs_arr = ap_requires(r);
-    require_line *reqs;
-
-    /* BUG FIX: tadc, 11-Nov-1995.  If there is no "requires" directive,
-     * then any user will do.
-     */
-    if (!reqs_arr) {
-        return DECLINED;
-    }
-    reqs = (require_line *)reqs_arr->elts;
-
-    for (x = 0; x < reqs_arr->nelts; x++) {
-
-        if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) {
-            continue;
-        }
 
-        t = reqs[x].requirement;
-        w = ap_getword_white(r->pool, &t);
-        if (!strcasecmp(w, "valid-user")) {
-            return OK;
+    t = require_args;
+    while ((w = ap_getword_conf(r->pool, &t)) && w[0]) {
+        if (!strcmp(r->user, w)) {
+            return AUTHZ_GRANTED;
         }
-        if (!strcasecmp(w, "user")) {
-            /* And note that there are applicable requirements
-             * which we consider ourselves the owner of.
-             */
-            required_user = 1;
-            while (t[0]) {
-                w = ap_getword_conf(r->pool, &t);
-                if (!strcmp(user, w)) {
-                    return OK;
-                }
-            }
-        }
-    }
-
-    if (!required_user) {
-        /* no applicable requirements */
-        return DECLINED;
-    }
-
-    if (!conf->authoritative) {
-        return DECLINED;
     }
 
     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                   "access to %s failed, reason: user '%s' does not meet "
-                  "'require'ments for user/valid-user to be allowed access",
-                  r->uri, user);
+                  "'require'ments for user to be allowed access",
+                  r->uri, r->user);
 
     ap_note_auth_failure(r);
-    return HTTP_UNAUTHORIZED;
+    return AUTHZ_DENIED;
 }
 
+static authz_status validuser_check_authorization(request_rec *r, const char *require_line)
+{
+    return AUTHZ_GRANTED;
+}
+
+static const authz_provider authz_user_provider =
+{
+    &user_check_authorization,
+};
+static const authz_provider authz_validuser_provider =
+{
+    &validuser_check_authorization,
+};
+
 static void register_hooks(apr_pool_t *p)
 {
-    ap_hook_auth_checker(check_user_access, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "user", "0",
+                         &authz_user_provider);
+    ap_register_provider(p, AUTHZ_PROVIDER_GROUP, "valid-user", "0",
+                         &authz_validuser_provider);
 }
 
 module AP_MODULE_DECLARE_DATA authz_user_module =
index cd71ce79918dce920a28e5ee6da0fe14d62907e7..b3bd1b45b25700b1cb8c6d87fa21ad5769ab157d 100644 (file)
@@ -99,7 +99,6 @@ static char errordocument_default;
 static void *create_core_dir_config(apr_pool_t *a, char *dir)
 {
     core_dir_config *conf;
-    int i;
 
     conf = (core_dir_config *)apr_pcalloc(a, sizeof(core_dir_config));
 
@@ -118,10 +117,6 @@ static void *create_core_dir_config(apr_pool_t *a, char *dir)
     conf->use_canonical_phys_port = USE_CANONICAL_PHYS_PORT_UNSET;
 
     conf->hostname_lookups = HOSTNAME_LOOKUP_UNSET;
-    conf->satisfy = apr_palloc(a, sizeof(*conf->satisfy) * METHODS);
-    for (i = 0; i < METHODS; ++i) {
-        conf->satisfy[i] = SATISFY_NOSPEC;
-    }
 
 #ifdef RLIMIT_CPU
     conf->limit_cpu = NULL;
@@ -268,18 +263,6 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
         conf->ap_default_type = new->ap_default_type;
     }
 
-    if (new->ap_auth_type) {
-        conf->ap_auth_type = new->ap_auth_type;
-    }
-
-    if (new->ap_auth_name) {
-        conf->ap_auth_name = new->ap_auth_name;
-    }
-
-    if (new->ap_requires) {
-        conf->ap_requires = new->ap_requires;
-    }
-
     if (conf->response_code_strings == NULL) {
         conf->response_code_strings = new->response_code_strings;
     }
@@ -358,16 +341,6 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
     /* Otherwise we simply use the base->sec_file array
      */
 
-    /* use a separate ->satisfy[] array either way */
-    conf->satisfy = apr_palloc(a, sizeof(*conf->satisfy) * METHODS);
-    for (i = 0; i < METHODS; ++i) {
-        if (new->satisfy[i] != SATISFY_NOSPEC) {
-            conf->satisfy[i] = new->satisfy[i];
-        } else {
-            conf->satisfy[i] = base->satisfy[i];
-        }
-    }
-
     if (new->server_signature != srv_sig_unset) {
         conf->server_signature = new->server_signature;
     }
@@ -670,24 +643,30 @@ AP_DECLARE(int) ap_allow_overrides(request_rec *r)
     return conf->override;
 }
 
+/*
+ * Optional function coming from mod_ident, used for looking up ident user
+ */
+static APR_OPTIONAL_FN_TYPE(authn_ap_auth_type) *authn_ap_auth_type;
+
 AP_DECLARE(const char *) ap_auth_type(request_rec *r)
 {
-    core_dir_config *conf;
-
-    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
-                                                   &core_module);
-
-    return conf->ap_auth_type;
+    if (authn_ap_auth_type) {
+        return authn_ap_auth_type(r);
+    }
+    return NULL;
 }
 
+/*
+ * Optional function coming from mod_ident, used for looking up ident user
+ */
+static APR_OPTIONAL_FN_TYPE(authn_ap_auth_name) *authn_ap_auth_name;
+
 AP_DECLARE(const char *) ap_auth_name(request_rec *r)
 {
-    core_dir_config *conf;
-
-    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
-                                                   &core_module);
-
-    return conf->ap_auth_name;
+    if (authn_ap_auth_name) {
+        return authn_ap_auth_name(r);
+    }
+    return NULL;
 }
 
 AP_DECLARE(const char *) ap_default_type(request_rec *r)
@@ -712,26 +691,6 @@ AP_DECLARE(const char *) ap_document_root(request_rec *r) /* Don't use this! */
     return conf->ap_document_root;
 }
 
-AP_DECLARE(const apr_array_header_t *) ap_requires(request_rec *r)
-{
-    core_dir_config *conf;
-
-    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
-                                                   &core_module);
-
-    return conf->ap_requires;
-}
-
-AP_DECLARE(int) ap_satisfies(request_rec *r)
-{
-    core_dir_config *conf;
-
-    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
-                                                   &core_module);
-
-    return conf->satisfy[r->method_number];
-}
-
 /* Should probably just get rid of this... the only code that cares is
  * part of the core anyway (and in fact, it isn't publicised to other
  * modules).
@@ -1659,46 +1618,6 @@ static const char *set_enable_sendfile(cmd_parms *cmd, void *d_,
     return NULL;
 }
 
-static const char *satisfy(cmd_parms *cmd, void *c_, const char *arg)
-{
-    core_dir_config *c = c_;
-    int satisfy = SATISFY_NOSPEC;
-    int i;
-
-    if (!strcasecmp(arg, "all")) {
-        satisfy = SATISFY_ALL;
-    }
-    else if (!strcasecmp(arg, "any")) {
-        satisfy = SATISFY_ANY;
-    }
-    else {
-        return "Satisfy either 'any' or 'all'.";
-    }
-
-    for (i = 0; i < METHODS; ++i) {
-        if (cmd->limited & (AP_METHOD_BIT << i)) {
-            c->satisfy[i] = satisfy;
-        }
-    }
-
-    return NULL;
-}
-
-static const char *require(cmd_parms *cmd, void *c_, const char *arg)
-{
-    require_line *r;
-    core_dir_config *c = c_;
-
-    if (!c->ap_requires) {
-        c->ap_requires = apr_array_make(cmd->pool, 2, sizeof(require_line));
-    }
-
-    r = (require_line *)apr_array_push(c->ap_requires);
-    r->requirement = apr_pstrdup(cmd->pool, arg);
-    r->method_mask = cmd->limited;
-
-    return NULL;
-}
 
 /*
  * Report a missing-'>' syntax error.
@@ -2658,19 +2577,6 @@ AP_DECLARE(const char *) ap_psignature(const char *prefix, request_rec *r)
                        "</address>\n", NULL);
 }
 
-/*
- * Load an authorisation realm into our location configuration, applying the
- * usual rules that apply to realms.
- */
-static const char *set_authname(cmd_parms *cmd, void *mconfig,
-                                const char *word1)
-{
-    core_dir_config *aconfig = (core_dir_config *)mconfig;
-
-    aconfig->ap_auth_name = ap_escape_quotes(cmd->pool, word1);
-    return NULL;
-}
-
 /*
  * Handle a request to include the server's OS platform in the Server
  * response header field (the ServerTokens directive).  Unfortunately
@@ -3227,15 +3133,6 @@ AP_INIT_RAW_ARGS("<LocationMatch", urlsection, (void*)1, RSRC_CONF,
   "specified URL paths"),
 AP_INIT_RAW_ARGS("<FilesMatch", filesection, (void*)1, OR_ALL,
   "Container for directives affecting files matching specified patterns"),
-AP_INIT_TAKE1("AuthType", ap_set_string_slot,
-  (void*)APR_OFFSETOF(core_dir_config, ap_auth_type), OR_AUTHCFG,
-  "An HTTP authorization type (e.g., \"Basic\")"),
-AP_INIT_TAKE1("AuthName", set_authname, NULL, OR_AUTHCFG,
-  "The authentication realm (e.g. \"Members Only\")"),
-AP_INIT_RAW_ARGS("Require", require, NULL, OR_AUTHCFG,
-  "Selects which authenticated users or groups may access a protected space"),
-AP_INIT_TAKE1("Satisfy", satisfy, NULL, OR_AUTHCFG,
-  "access policy if both allow and require used ('all' or 'any')"),
 #ifdef GPROF
 AP_INIT_TAKE1("GprofDir", set_gprof_dir, NULL, RSRC_CONF,
   "Directory to plop gmon.out files"),
@@ -3718,11 +3615,15 @@ static int default_handler(request_rec *r)
  * traffic
  */
 APR_OPTIONAL_FN_TYPE(ap_logio_add_bytes_out) *logio_add_bytes_out;
+APR_OPTIONAL_FN_TYPE(authz_some_auth_required) *authz_ap_some_auth_required;
 
 static int core_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
 {
     logio_add_bytes_out = APR_RETRIEVE_OPTIONAL_FN(ap_logio_add_bytes_out);
     ident_lookup = APR_RETRIEVE_OPTIONAL_FN(ap_ident_lookup);
+    authz_ap_some_auth_required = APR_RETRIEVE_OPTIONAL_FN(authz_some_auth_required);
+    authn_ap_auth_type = APR_RETRIEVE_OPTIONAL_FN(authn_ap_auth_type);
+    authn_ap_auth_name = APR_RETRIEVE_OPTIONAL_FN(authn_ap_auth_name);
 
     ap_set_version(pconf);
     ap_setup_make_content_type(pconf);
index be7c49a8550e7ae2962adb1d96e38946753e1054..40e9fbf998749860d768774a31dfd17da66204d2 100644 (file)
@@ -183,56 +183,18 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
         r->ap_auth_type = r->prev->ap_auth_type;
     }
     else {
-        switch (ap_satisfies(r)) {
-        case SATISFY_ALL:
-        case SATISFY_NOSPEC:
-            if ((access_status = ap_run_access_checker(r)) != 0) {
-                return decl_die(access_status, "check access", r);
-            }
-
-            if (ap_some_auth_required(r)) {
-                if (((access_status = ap_run_check_user_id(r)) != 0)
-                    || !ap_auth_type(r)) {
-                    return decl_die(access_status, ap_auth_type(r)
-                                  ? "check user.  No user file?"
-                                  : "perform authentication. AuthType not set!",
-                                  r);
-                }
-
-                if (((access_status = ap_run_auth_checker(r)) != 0)
-                    || !ap_auth_type(r)) {
-                    return decl_die(access_status, ap_auth_type(r)
-                                  ? "check access.  No groups file?"
-                                  : "perform authentication. AuthType not set!",
-                                   r);
-                }
-            }
-            break;
-
-        case SATISFY_ANY:
-            if (((access_status = ap_run_access_checker(r)) != 0)) {
-                if (!ap_some_auth_required(r)) {
-                    return decl_die(access_status, "check access", r);
-                }
+        if ((access_status = ap_run_access_checker(r)) != 0) {
+            return decl_die(access_status, "check access", r);
+        }
 
-                if (((access_status = ap_run_check_user_id(r)) != 0)
-                    || !ap_auth_type(r)) {
-                    return decl_die(access_status, ap_auth_type(r)
-                                  ? "check user.  No user file?"
-                                  : "perform authentication. AuthType not set!",
-                                  r);
-                }
+        if ((access_status = ap_run_check_user_id(r)) != 0) {
+            return decl_die(access_status, "check user", r);
+        }
 
-                if (((access_status = ap_run_auth_checker(r)) != 0)
-                    || !ap_auth_type(r)) {
-                    return decl_die(access_status, ap_auth_type(r)
-                                  ? "check access.  No groups file?"
-                                  : "perform authentication. AuthType not set!",
-                                  r);
-                }
-            }
-            break;
+        if ((access_status = ap_run_auth_checker(r)) != 0) {
+            return decl_die(access_status, "check authorization", r);
         }
+
     }
     /* XXX Must make certain the ap_run_type_checker short circuits mime
      * in mod-proxy for r->proxyreq && r->parsed_uri.scheme
@@ -1555,28 +1517,16 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_sub_req_output_filter(ap_filter_t *f,
     return APR_SUCCESS;
 }
 
+extern APR_OPTIONAL_FN_TYPE(authz_some_auth_required) *authz_ap_some_auth_required;
 
 AP_DECLARE(int) ap_some_auth_required(request_rec *r)
 {
     /* Is there a require line configured for the type of *this* req? */
-
-    const apr_array_header_t *reqs_arr = ap_requires(r);
-    require_line *reqs;
-    int i;
-
-    if (!reqs_arr) {
-        return 0;
+    if (authz_ap_some_auth_required) {
+        return authz_ap_some_auth_required(r);
     }
-
-    reqs = (require_line *) reqs_arr->elts;
-
-    for (i = 0; i < reqs_arr->nelts; ++i) {
-        if (reqs[i].method_mask & (AP_METHOD_BIT << r->method_number)) {
-            return 1;
-        }
-    }
-
-    return 0;
+    else
+        return 0;
 }