summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIsaac Boukris <iboukris@gmail.com>2016-12-17 23:17:00 +0200
committerSimo Sorce <simo@redhat.com>2017-01-11 14:43:08 -0500
commita64a32f520884039be0a2240bfa2b5f4040c9c99 (patch)
tree530cd2646932424e87e8127e0a81c5b99cac6d48
parent63706efbbc75ae6fd928813cdd45242025c0fe61 (diff)
downloadmod_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.c31
-rw-r--r--src/environ.h2
-rw-r--r--src/mod_auth_gssapi.c39
-rw-r--r--src/mod_auth_gssapi.h5
-rw-r--r--tests/httpd.conf17
-rwxr-xr-xtests/magtests.py21
-rwxr-xr-xtests/t_spnego_rewrite.py18
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')