Add session support to mod_auth_basic (2.4.x branch) --- modules/aaa/mod_auth_basic.c.orig 2017-02-07 13:59:16.000000000 +0100 +++ modules/aaa/mod_auth_basic.c 2017-02-07 15:23:01.000000000 +0100 @@ -31,19 +31,31 @@ #include "ap_provider.h" #include "ap_expr.h" #include "mod_auth.h" +#include "mod_session.h" +#include "mod_request.h" + +static int (*ap_session_load_fn) (request_rec * r, session_rec ** z) = NULL; +static apr_status_t (*ap_session_get_fn)(request_rec * r, session_rec * z, + const char *key, const char **value) = NULL; +static apr_status_t (*ap_session_set_fn)(request_rec * r, session_rec * z, + const char *key, const char *value) = NULL; +static int have_session = 0; + typedef struct { authn_provider_list *providers; char *dir; /* unused variable */ int authoritative; + int use_session; ap_expr_info_t *fakeuser; ap_expr_info_t *fakepass; const char *use_digest_algorithm; int fake_set:1; int use_digest_algorithm_set:1; int authoritative_set:1; + int use_session_set:1; } auth_basic_config_rec; static void *create_auth_basic_dir_config(apr_pool_t *p, char *d) { @@ -66,8 +78,14 @@ base->authoritative; newconf->authoritative_set = overrides->authoritative_set || base->authoritative_set; + newconf->use_session = + overrides->use_session_set ? overrides->use_session : + base->use_session; + newconf->use_session_set = overrides->use_session_set + || base->use_session_set; + newconf->fakeuser = overrides->fake_set ? overrides->fakeuser : base->fakeuser; newconf->fakepass = overrides->fake_set ? overrides->fakepass : base->fakepass; @@ -138,8 +156,18 @@ return NULL; } +static const char *set_use_session(cmd_parms * cmd, void *config, int flag) +{ + auth_basic_config_rec *conf = (auth_basic_config_rec *) config; + + conf->use_session = flag; + conf->use_session_set = 1; + + return NULL; +} + static const char *add_basic_fake(cmd_parms * cmd, void *config, const char *user, const char *pass) { auth_basic_config_rec *conf = (auth_basic_config_rec *) config; @@ -207,8 +235,10 @@ "specify the auth providers for a directory or location"), AP_INIT_FLAG("AuthBasicAuthoritative", set_authoritative, NULL, OR_AUTHCFG, "Set to 'Off' to allow access control to be passed along to " "lower modules if the UserID is not known to this module"), + AP_INIT_FLAG("AuthBasicUseSession", set_use_session, NULL, OR_AUTHCFG, + "Set to 'On' to use session to cache user credentials."), AP_INIT_TAKE12("AuthBasicFake", add_basic_fake, NULL, OR_AUTHCFG, "Fake basic authentication using the given expressions for " "username and password, 'off' to disable. Password defaults " "to 'password' if missing."), @@ -248,8 +278,83 @@ note_basic_auth_failure(r); return OK; } + +static void init_session(request_rec *r) +{ + ap_session_load_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_load); + ap_session_get_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_get); + ap_session_set_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_set); + + if (ap_session_load_fn && ap_session_get_fn && ap_session_set_fn) { + have_session = 1; + } else { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Session not enabled: mod_session is not available"); + } + + return; +} + +/** + * Set user and pw in the session, delete them if NULL + */ +static void set_session_auth(request_rec * r, + const char *user, const char *pw) +{ + const char *realm = ap_auth_name(r); + session_rec *z = NULL; + + ap_session_load_fn(r, &z); + ap_session_set_fn(r, z, + apr_pstrcat(r->pool, realm, "-" MOD_SESSION_USER, NULL), + user); + ap_session_set_fn(r, z, + apr_pstrcat(r->pool, realm, "-" MOD_SESSION_PW, NULL), + pw); + + return; + +} + +/** + * Get the user and pw from the main request * notes table, if present. + */ +static apr_status_t get_session_auth(request_rec * r, + const char **user, const char **pw) +{ + const char *realm = ap_auth_name(r); + session_rec *z = NULL; + + ap_session_load_fn(r, &z); + + if (user) + ap_session_get_fn(r, z, + apr_pstrcat(r->pool, + realm, "-" MOD_SESSION_USER, NULL), + user); + + if (pw) + ap_session_get_fn(r, z, + apr_pstrcat(r->pool, + realm, "-" MOD_SESSION_PW, NULL), + pw); + + if (!*user || !*pw) + return APR_EGENERAL; + + /* set the user, even though the user is unauthenticated at this point */ + if (user && *user) + r->user = (char *) *user; + + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "User %s authenticated from session", + user ? *user : ""); + + return APR_SUCCESS; +} + static int get_basic_auth(request_rec *r, const char **user, const char **pw) { const char *auth_line; @@ -315,11 +420,20 @@ "need AuthName: %s", r->uri); return HTTP_INTERNAL_SERVER_ERROR; } + if (conf->use_session && !have_session) + init_session(r); + r->ap_auth_type = (char*)current_auth; res = get_basic_auth(r, &sent_user, &sent_pw); + if (res && conf->use_session && have_session) { + /* try get the username and password from a session, if present */ + if (get_session_auth(r, &sent_user, &sent_pw) == APR_SUCCESS) + res = OK; + } + if (res) { return res; } @@ -430,8 +544,12 @@ } return return_code; } + /* Success, save username and password in session */ + if (conf->use_session && have_session) + set_session_auth(r, sent_user, sent_pw); + return OK; } /* If requested, create a fake basic authentication header for the benefit