diff options
author | Isaac Boukris <iboukris@gmail.com> | 2016-12-17 23:17:00 +0200 |
---|---|---|
committer | Simo Sorce <simo@redhat.com> | 2017-01-11 14:43:08 -0500 |
commit | a64a32f520884039be0a2240bfa2b5f4040c9c99 (patch) | |
tree | 530cd2646932424e87e8127e0a81c5b99cac6d48 | |
parent | 63706efbbc75ae6fd928813cdd45242025c0fe61 (diff) | |
download | mod_auth_gssapi-a64a32f520884039be0a2240bfa2b5f4040c9c99.tar.gz mod_auth_gssapi-a64a32f520884039be0a2240bfa2b5f4040c9c99.tar.xz mod_auth_gssapi-a64a32f520884039be0a2240bfa2b5f4040c9c99.zip |
rewrite: implicitly handle internal redirects
Internal redirects are a special case of subrequest - they
have no req->main but req->prev instead, so we should check
for that too in case the request is not initial.
Also, make sure to export MAG environment variables to
subrequests and internal redirects.
Signed-off-by: Isaac Boukris <iboukris@gmail.com>
Reviewed-by: Simo Sorce <simo@redhat.com>
Reported-by: scopev24
Closes #119
-rw-r--r-- | src/environ.c | 31 | ||||
-rw-r--r-- | src/environ.h | 2 | ||||
-rw-r--r-- | src/mod_auth_gssapi.c | 39 | ||||
-rw-r--r-- | src/mod_auth_gssapi.h | 5 | ||||
-rw-r--r-- | tests/httpd.conf | 17 | ||||
-rwxr-xr-x | tests/magtests.py | 21 | ||||
-rwxr-xr-x | tests/t_spnego_rewrite.py | 18 |
7 files changed, 117 insertions, 16 deletions
diff --git a/src/environ.c b/src/environ.c index 7b8a54b..bc59bae 100644 --- a/src/environ.c +++ b/src/environ.c @@ -168,7 +168,7 @@ void mag_get_name_attributes(request_rec *req, struct mag_config *cfg, if (GSS_ERROR(maj)) { error = mag_error(req, "gss_inquire_name() failed", maj, min); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s", error); - apr_table_set(req->subprocess_env, "GSS_NAME_ATTR_ERROR", error); + apr_table_set(mc->env, "GSS_NAME_ATTR_ERROR", error); return; } @@ -237,14 +237,14 @@ void mag_get_name_attributes(request_rec *req, struct mag_config *cfg, static void mag_set_name_attributes(request_rec *req, struct mag_conn *mc) { for (int i = 0; i < mc->na_count; i++) { - apr_table_set(req->subprocess_env, + apr_table_set(mc->env, mc->name_attributes[i].name, mc->name_attributes[i].value); } } static void mag_set_KRB5CCNAME(request_rec *req, struct mag_config *cfg, - const char *ccname) + struct mag_conn *mc) { apr_status_t status; apr_int32_t wanted = APR_FINFO_MIN | APR_FINFO_OWNER | APR_FINFO_PROT; @@ -252,7 +252,7 @@ static void mag_set_KRB5CCNAME(request_rec *req, struct mag_config *cfg, char *path; char *value; - path = apr_psprintf(req->pool, "%s/%s", cfg->deleg_ccache_dir, ccname); + path = apr_psprintf(req->pool, "%s/%s", cfg->deleg_ccache_dir, mc->ccname); status = apr_stat(&finfo, path, wanted, req->pool); if (status == APR_SUCCESS) { @@ -287,19 +287,27 @@ static void mag_set_KRB5CCNAME(request_rec *req, struct mag_config *cfg, } value = apr_psprintf(req->pool, "FILE:%s", path); - apr_table_set(req->subprocess_env, "KRB5CCNAME", value); + apr_table_set(mc->env, "KRB5CCNAME", value); +} + +void mag_export_req_env(request_rec *req, apr_table_t *env) +{ + const apr_array_header_t *arr = apr_table_elts(env); + const apr_table_entry_t *elts = (const apr_table_entry_t*)arr->elts; + + for (int i = 0; i < arr->nelts; ++i) + apr_table_set(req->subprocess_env, elts[i].key, elts[i].val); } void mag_set_req_data(request_rec *req, struct mag_config *cfg, struct mag_conn *mc) { - apr_table_set(req->subprocess_env, "GSS_NAME", mc->gss_name); - apr_table_set(req->subprocess_env, "GSS_SESSION_EXPIRATION", + apr_table_set(mc->env, "GSS_NAME", mc->gss_name); + apr_table_set(mc->env, "GSS_SESSION_EXPIRATION", apr_psprintf(req->pool, "%ld", (long)mc->expiration)); - req->ap_auth_type = apr_pstrdup(req->pool, - mag_str_auth_type(mc->auth_type)); + req->ap_auth_type = (char *) mag_str_auth_type(mc->auth_type); req->user = apr_pstrdup(req->pool, mc->user_name); if (mc->name_attributes) { @@ -308,7 +316,10 @@ void mag_set_req_data(request_rec *req, #ifdef HAVE_CRED_STORE if (cfg->deleg_ccache_dir && mc->delegated && mc->ccname) { - mag_set_KRB5CCNAME(req, cfg, mc->ccname); + mag_set_KRB5CCNAME(req, cfg, mc); } #endif + + ap_set_module_config(req->request_config, &auth_gssapi_module, mc->env); + mag_export_req_env(req, mc->env); } diff --git a/src/environ.h b/src/environ.h index 8e5dde5..1169406 100644 --- a/src/environ.h +++ b/src/environ.h @@ -8,6 +8,8 @@ void mag_get_name_attributes(request_rec *req, gss_name_t name, struct mag_conn *mc); +void mag_export_req_env(request_rec *req, apr_table_t *env); + void mag_set_req_data(request_rec *req, struct mag_config *cfg, struct mag_conn *mc); diff --git a/src/mod_auth_gssapi.c b/src/mod_auth_gssapi.c index 9f311c5..ed4342b 100644 --- a/src/mod_auth_gssapi.c +++ b/src/mod_auth_gssapi.c @@ -107,7 +107,10 @@ struct mag_conn *mag_new_conn_ctx(apr_pool_t *pool) struct mag_conn *mc; mc = apr_pcalloc(pool, sizeof(struct mag_conn)); + apr_pool_create(&mc->pool, pool); + mc->env = apr_table_make(mc->pool, 1); + /* register the context in the memory pool, so it can be freed * when the connection/request is terminated */ apr_pool_cleanup_register(mc->pool, (void *)mc, @@ -124,6 +127,7 @@ static void mag_conn_clear(struct mag_conn *mc) temp = mc->pool; memset(mc, 0, sizeof(struct mag_conn)); mc->pool = temp; + mc->env = apr_table_make(mc->pool, 1); } static bool mag_conn_is_https(conn_rec *c) @@ -823,20 +827,45 @@ static int mag_auth(request_rec *req) return HTTP_UNAUTHORIZED; } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req, + "URI: %s, %s main, %s prev", req->uri ?: "no-uri", + req->main ? "with" : "no", req->prev ? "with" : "no"); + /* implicit auth for subrequests if main auth already happened */ - if (!ap_is_initial_req(req) && req->main != NULL) { - type = ap_auth_type(req->main); + if (!ap_is_initial_req(req)) { + request_rec *main_req = req; + + /* Not initial means either a subrequest or an internal redirect */ + while (!ap_is_initial_req(main_req)) + if (main_req->main) + main_req = main_req->main; + else + main_req = main_req->prev; + + type = ap_auth_type(main_req); if ((type != NULL) && (strcasecmp(type, "GSSAPI") == 0)) { /* warn if the subrequest location and the main request * location have different configs */ - if (cfg != ap_get_module_config(req->main->per_dir_config, + if (cfg != ap_get_module_config(main_req->per_dir_config, &auth_gssapi_module)) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, req, "Subrequest authentication bypass on " "location with different configuration!"); } - if (req->main->user) { - req->user = apr_pstrdup(req->pool, req->main->user); + if (main_req->user) { + apr_table_t *env; + + req->user = apr_pstrdup(req->pool, main_req->user); + req->ap_auth_type = main_req->ap_auth_type; + + env = ap_get_module_config(main_req->request_config, + &auth_gssapi_module); + if (!env) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, req, + "Failed to lookup env table in subrequest"); + } else + mag_export_req_env(req, env); + return OK; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, diff --git a/src/mod_auth_gssapi.h b/src/mod_auth_gssapi.h index 1a5ff8b..2aa81f1 100644 --- a/src/mod_auth_gssapi.h +++ b/src/mod_auth_gssapi.h @@ -52,6 +52,8 @@ # endif #endif +extern module AP_MODULE_DECLARE_DATA auth_gssapi_module; + struct mag_na_map { char *env_name; char *attr_name; @@ -77,7 +79,7 @@ struct mag_config { uid_t deleg_ccache_uid; gid_t deleg_ccache_gid; gss_key_value_set_desc *cred_store; - bool deleg_ccache_unique;; + bool deleg_ccache_unique; bool s4u2self; #endif struct seal_key *mag_skey; @@ -124,6 +126,7 @@ struct mag_conn { int na_count; struct mag_attr *name_attributes; const char *ccname; + apr_table_t *env; }; #define discard_const(ptr) ((void *)((uintptr_t)(ptr))) diff --git a/tests/httpd.conf b/tests/httpd.conf index 66054c1..60d23c8 100644 --- a/tests/httpd.conf +++ b/tests/httpd.conf @@ -148,6 +148,23 @@ CoreDumpDirectory /tmp Require valid-user </Location> +<Location /spnego_rewrite> + Options +Includes + AddOutputFilter INCLUDES .html + + AuthType GSSAPI + AuthName "Login" + GssapiCredStore ccache:${HTTPROOT}/tmp/httpd_krb5_ccache + GssapiCredStore keytab:${HTTPROOT}/http.keytab + GssapiAllowedMech krb5 + Require valid-user + + RewriteEngine on + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule . /spnego_rewrite/index.html [L] +</Location> + <Location /spnego_negotiate_once> AuthType GSSAPI AuthName "Login Negotiate Once" diff --git a/tests/magtests.py b/tests/magtests.py index 3a29365..b60e648 100755 --- a/tests/magtests.py +++ b/tests/magtests.py @@ -306,6 +306,24 @@ def test_spnego_auth(testdir, testenv, testlog): sys.stderr.write('SPNEGO No Auth: SUCCESS\n') +def test_spnego_rewrite(testdir, testenv, testlog): + + spnego_rewrite_dir = os.path.join(testdir, 'httpd', 'html', + 'spnego_rewrite') + os.mkdir(spnego_rewrite_dir) + shutil.copy('tests/index.html', spnego_rewrite_dir) + + with (open(testlog, 'a')) as logfile: + spnego = subprocess.Popen(["tests/t_spnego_rewrite.py"], + stdout=logfile, stderr=logfile, + env=testenv, preexec_fn=os.setsid) + spnego.wait() + if spnego.returncode != 0: + sys.stderr.write('SPNEGO Rewrite: FAILED\n') + else: + sys.stderr.write('SPNEGO Rewrite: SUCCESS\n') + + def test_spnego_negotiate_once(testdir, testenv, testlog): spnego_negotiate_once_dir = os.path.join(testdir, 'httpd', 'html', @@ -400,6 +418,9 @@ if __name__ == '__main__': USR_NAME + '@' + TESTREALM) test_spnego_auth(testdir, testenv, testlog) + testenv['MAG_GSS_NAME'] = USR_NAME + '@' + TESTREALM + test_spnego_rewrite(testdir, testenv, testlog) + test_spnego_negotiate_once(testdir, testenv, testlog) testenv = {'MAG_USER_NAME': USR_NAME, diff --git a/tests/t_spnego_rewrite.py b/tests/t_spnego_rewrite.py new file mode 100755 index 0000000..0014bf5 --- /dev/null +++ b/tests/t_spnego_rewrite.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +# Copyright (C) 2015 - mod_auth_gssapi contributors, see COPYING for license. + +import os +import requests +from requests_kerberos import HTTPKerberosAuth, OPTIONAL + + +if __name__ == '__main__': + sess = requests.Session() + url = 'http://%s/spnego_rewrite/xxx' % os.environ['NSS_WRAPPER_HOSTNAME'] + r = sess.get(url, auth=HTTPKerberosAuth()) + + if r.status_code != 200: + raise ValueError('Spnego Rewrite failed') + + if r.text.rstrip() != os.environ['MAG_GSS_NAME']: + raise ValueError('Spnego Rewrite, GSS_NAME check failed') |