You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by bn...@apache.org on 2005/11/30 05:23:08 UTC

svn commit: r349875 - in /httpd/httpd/branches/authz-dev: include/http_core.h modules/aaa/mod_auth.h modules/aaa/mod_authz_host.c server/core.c

Author: bnicholes
Date: Tue Nov 29 20:22:48 2005
New Revision: 349875

URL: http://svn.apache.org/viewcvs?rev=349875&view=rev
Log:
first cut at moving the require directive out of mod_core and implementing it as a provider vector.

Modified:
    httpd/httpd/branches/authz-dev/include/http_core.h
    httpd/httpd/branches/authz-dev/modules/aaa/mod_auth.h
    httpd/httpd/branches/authz-dev/modules/aaa/mod_authz_host.c
    httpd/httpd/branches/authz-dev/server/core.c

Modified: httpd/httpd/branches/authz-dev/include/http_core.h
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/authz-dev/include/http_core.h?rev=349875&r1=349874&r2=349875&view=diff
==============================================================================
--- httpd/httpd/branches/authz-dev/include/http_core.h (original)
+++ httpd/httpd/branches/authz-dev/include/http_core.h Tue Nov 29 20:22:48 2005
@@ -454,9 +454,9 @@
     /* Authentication stuff.  Groan... */
     
     int *satisfy; /* for every method one */
-    char *ap_auth_type;
-    char *ap_auth_name;
-    apr_array_header_t *ap_requires;
+    char *ap_auth_type; /* Deprecated see mod_authz_host */
+    char *ap_auth_name; /* Deprecated see mod_authz_host */
+    apr_array_header_t *ap_requires; /* Deprecated see mod_authz_host */
 
     /* 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,
@@ -679,6 +679,18 @@
 
 APR_DECLARE_OPTIONAL_FN(const char *, ap_ident_lookup,
                         (request_rec *r));
+
+/* ----------------------------------------------------------------------
+ *
+ * authorization values with mod_authz_host
+ */
+
+APR_DECLARE_OPTIONAL_FN(const apr_array_header_t *, authz_host_ap_requires,
+                        (request_rec *r));
+/*
+APR_DECLARE_OPTIONAL_FN(const char *, authz_host_ap_auth_type, (request_rec *r));
+APR_DECLARE_OPTIONAL_FN(const char *, authz_host_ap_auth_name, (request_rec *r));
+*/
 
 /* ---------------------------------------------------------------------- */
 

Modified: httpd/httpd/branches/authz-dev/modules/aaa/mod_auth.h
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/authz-dev/modules/aaa/mod_auth.h?rev=349875&r1=349874&r2=349875&view=diff
==============================================================================
--- httpd/httpd/branches/authz-dev/modules/aaa/mod_auth.h (original)
+++ httpd/httpd/branches/authz-dev/modules/aaa/mod_auth.h Tue Nov 29 20:22:48 2005
@@ -35,10 +35,13 @@
 #endif
 
 #define AUTHN_PROVIDER_GROUP "authn"
+#define AUTHZ_PROVIDER_GROUP "authz"
 #define AUTHN_DEFAULT_PROVIDER "file"
+#define AUTHZ_DEFAULT_PROVIDER "valid-user"
     
 #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,
@@ -72,9 +75,36 @@
 };
 
 typedef struct {
+    /* Given a username and password, expected to return AUTH_GRANTED
+    * if we can validate this user/password combination.
+    */
+    authn_status (*check_authorization)(request_rec *r);
+} 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 *next;
+    /** Where the require line is in the config file. */
+    apr_int64_t method_mask;
+    /** The complete string from the command line */
+    char *requirement;
+};
+
+/* Need to add an enum for authz_status.  Convert one of the authorization
+   modules to deal with the new require directive.
+*/
+
+
+#if 0
+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);
 } authz_provider;
+#endif
 
 #ifdef __cplusplus
 }

Modified: httpd/httpd/branches/authz-dev/modules/aaa/mod_authz_host.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/authz-dev/modules/aaa/mod_authz_host.c?rev=349875&r1=349874&r2=349875&view=diff
==============================================================================
--- httpd/httpd/branches/authz-dev/modules/aaa/mod_authz_host.c (original)
+++ httpd/httpd/branches/authz-dev/modules/aaa/mod_authz_host.c Tue Nov 29 20:22:48 2005
@@ -35,6 +35,10 @@
 #include "http_config.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>
@@ -66,6 +70,8 @@
     int order[METHODS];
     apr_array_header_t *allows;
     apr_array_header_t *denys;
+    apr_array_header_t *ap_requires;
+    authz_provider_list *providers;
 } authz_host_dir_conf;
 
 module AP_MODULE_DECLARE_DATA authz_host_module;
@@ -85,6 +91,35 @@
     return (void *)conf;
 }
 
+static void *merge_authz_host_dir_config(apr_pool_t *a, void *basev, void *newv)
+{
+    authz_host_dir_conf *base = (authz_host_dir_conf *)basev;
+    authz_host_dir_conf *new = (authz_host_dir_conf *)newv;
+    authz_host_dir_conf *conf;
+    
+    /* Create this conf by duplicating the base, replacing elements
+    * (or creating copies for merging) where new-> values exist.
+    */
+    conf = (authz_host_dir_conf *)apr_palloc(a, sizeof(authz_host_dir_conf));
+    memcpy(conf, base, sizeof(authz_host_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;
+    }
+    */
+
+    if (new->ap_requires) {
+        conf->ap_requires = new->ap_requires;
+    }
+
+    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;
@@ -159,6 +194,85 @@
     return 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)
+{
+    authz_host_dir_conf *aconfig = (authz_host_dir_conf *)mconfig;
+
+    aconfig->ap_auth_name = ap_escape_quotes(cmd->pool, word1);
+    return NULL;
+}
+*/
+
+/*
+static const char *require(cmd_parms *cmd, void *c_, const char *arg)
+{
+    require_line *r;
+    authz_host_dir_conf *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;
+}
+*/
+
+static const char *add_authz_provider(cmd_parms *cmd, void *config,
+                                      const char *arg)
+{
+    authz_host_dir_conf *conf = (authz_host_dir_conf*)config;
+    authz_provider_list *newp;
+
+    newp = apr_pcalloc(cmd->pool, sizeof(authz_provider_list));
+    newp->provider_name = apr_pstrdup(cmd->pool, arg);
+    newp->requirement = apr_pstrdup(cmd->pool, arg);
+    newp->method_mask = cmd->limited;
+
+    /* lookup and cache the actual provider now */
+    newp->provider = ap_lookup_provider(AUTHZ_PROVIDER_GROUP,
+                                        newp->provider_name, "0");
+
+    if (newp->provider == NULL) {
+        /* by the time they use it, the provider should be loaded and
+        registered with us. */
+        return apr_psprintf(cmd->pool,
+                            "Unknown Authz provider: %s",
+                            newp->provider_name);
+    }
+
+    if (!newp->provider->check_authorization) {
+        /* if it doesn't provide the appropriate function, reject it */
+        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;
+
+        while (last->next) {
+            last = last->next;
+        }
+        last->next = newp;
+    }
+
+    return NULL;
+}
+
 static char its_an_allow;
 
 static const command_rec authz_host_cmds[] =
@@ -169,8 +283,17 @@
                      "'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"),
+    AP_INIT_RAW_ARGS("Require", add_authz_provider, NULL, OR_AUTHCFG,
+                     "Selects which authenticated users or groups may access a protected space"),
     {NULL}
 };
+/*
+    AP_INIT_TAKE1("AuthType", ap_set_string_slot,
+                  (void*)APR_OFFSETOF(authz_host_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\")"),
+*/
 
 static int in_domain(const char *domain, const char *what)
 {
@@ -304,17 +427,139 @@
     return ret;
 }
 
+static int authorize_user(request_rec *r)
+{
+    authz_host_dir_conf *conf = ap_get_module_config(r->per_dir_config,
+            &authz_host_module);
+    authn_status auth_result;
+    authz_provider_list *current_provider;
+
+    current_provider = conf->providers;
+    do {
+        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 Authz provider configured");
+                auth_result = AUTH_GENERAL_ERROR;
+                break;
+            }
+            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);
+        }
+
+
+        auth_result = provider->check_authorization(r);
+
+        apr_table_unset(r->notes, AUTHZ_PROVIDER_NAME_NOTE);
+
+        /* Something occured. Stop checking. */
+        if (auth_result != AUTH_DENIED) {
+            break;
+        }
+
+        /* If we're not really configured for providers, stop now. */
+        if (!conf->providers) {
+            break;
+        }
+
+        current_provider = current_provider->next;
+    } while (current_provider);
+
+    if (auth_result != AUTH_GRANTED) {
+        int return_code;
+
+/* XXX need to deal with DECLINED vs DENIED.  DECLINED may not even
+   be needed since we are only going to call registered require providers.
+   I assume that it will deal with passing from one provider to the next
+   according to the order and the Authz_xxx_Authoritative directives.
+*/
+        switch (auth_result) {
+            case AUTH_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 AUTH_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_basic_auth_failure (r);
+        }
+        return return_code;
+    }
+
+    return OK;
+}
+
+static const apr_array_header_t *authz_host_ap_requires(request_rec *r)
+{
+    authz_host_dir_conf *conf;
+
+    conf = (authz_host_dir_conf *)ap_get_module_config(r->per_dir_config,
+        &authz_host_module);
+
+    return conf->ap_requires;
+}
+
+/*
+static const char *authz_host_ap_auth_type(request_rec *r)
+{
+    authz_host_dir_conf *conf;
+
+    conf = (authz_host_dir_conf *)ap_get_module_config(r->per_dir_config,
+        &authz_host_module);
+
+    return conf->ap_auth_type;
+}
+
+static const char *authz_host_ap_auth_name(request_rec *r)
+{
+    authz_host_dir_conf *conf;
+
+    conf = (authz_host_dir_conf *)ap_get_module_config(r->per_dir_config,
+        &authz_host_module);
+
+    return conf->ap_auth_name;
+}
+*/
+
 static void register_hooks(apr_pool_t *p)
 {
+    APR_REGISTER_OPTIONAL_FN(authz_host_ap_requires);
+    /*
+    APR_REGISTER_OPTIONAL_FN(authz_host_ap_auth_type);
+    APR_REGISTER_OPTIONAL_FN(authz_host_ap_auth_name);
+    */
+
     /* 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_hook_auth_checker(authorize_user, NULL, NULL, APR_HOOK_MIDDLE);
 }
 
 module AP_MODULE_DECLARE_DATA authz_host_module =
 {
     STANDARD20_MODULE_STUFF,
     create_authz_host_dir_config,   /* dir config creater */
-    NULL,                           /* dir merger --- default is to override */
+    merge_authz_host_dir_config,    /* dir merger --- default is to override */
     NULL,                           /* server config */
     NULL,                           /* merge server config */
     authz_host_cmds,

Modified: httpd/httpd/branches/authz-dev/server/core.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/authz-dev/server/core.c?rev=349875&r1=349874&r2=349875&view=diff
==============================================================================
--- httpd/httpd/branches/authz-dev/server/core.c (original)
+++ httpd/httpd/branches/authz-dev/server/core.c Tue Nov 29 20:22:48 2005
@@ -268,18 +268,6 @@
         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;
     }
@@ -675,21 +663,51 @@
     core_dir_config *conf;
 
     conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
-                                                   &core_module);
+    &core_module);
 
     return conf->ap_auth_type;
 }
 
+/*
+ * Optional function coming from mod_ident, used for looking up ident user
+ */
+/*
+static APR_OPTIONAL_FN_TYPE(authz_host_ap_auth_type) *azh_ap_auth_type;
+
+AP_DECLARE(const char *) ap_auth_type(request_rec *r)
+{
+    if (azh_ap_auth_type) {
+        return azh_ap_auth_type(r);
+    }
+    return NULL;
+}
+*/
+
 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);
+    &core_module);
 
     return conf->ap_auth_name;
 }
 
+/*
+ * Optional function coming from mod_ident, used for looking up ident user
+ */
+/*
+static APR_OPTIONAL_FN_TYPE(authz_host_ap_auth_name) *azh_ap_auth_name;
+
+AP_DECLARE(const char *) ap_auth_name(request_rec *r)
+{
+    if (azh_ap_auth_name) {
+        return azh_ap_auth_name(r);
+    }
+    return NULL;
+}
+*/
+
 AP_DECLARE(const char *) ap_default_type(request_rec *r)
 {
     core_dir_config *conf;
@@ -712,14 +730,17 @@
     return conf->ap_document_root;
 }
 
+/*
+ * Optional function coming from mod_ident, used for looking up ident user
+ */
+static APR_OPTIONAL_FN_TYPE(authz_host_ap_requires) *azh_ap_requires;
+
 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;
+    if (azh_ap_requires) {
+        return azh_ap_requires(r);
+    }
+    return NULL;
 }
 
 AP_DECLARE(int) ap_satisfies(request_rec *r)
@@ -1684,22 +1705,6 @@
     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.
  */
@@ -3232,8 +3237,6 @@
   "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
@@ -3723,6 +3726,11 @@
 {
     logio_add_bytes_out = APR_RETRIEVE_OPTIONAL_FN(ap_logio_add_bytes_out);
     ident_lookup = APR_RETRIEVE_OPTIONAL_FN(ap_ident_lookup);
+    azh_ap_requires = APR_RETRIEVE_OPTIONAL_FN(authz_host_ap_requires);
+    /*
+    azh_ap_auth_type = APR_RETRIEVE_OPTIONAL_FN(authz_host_ap_auth_type);
+    azh_ap_auth_name = APR_RETRIEVE_OPTIONAL_FN(authz_host_ap_auth_name);
+    */
 
     ap_set_version(pconf);
     ap_setup_make_content_type(pconf);