Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 21 additions & 10 deletions src/environ.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -237,22 +237,22 @@ 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;
apr_finfo_t finfo = { 0 };
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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
}
2 changes: 2 additions & 0 deletions src/environ.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
39 changes: 34 additions & 5 deletions src/mod_auth_gssapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 4 additions & 1 deletion src/mod_auth_gssapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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)))
Expand Down
17 changes: 17 additions & 0 deletions tests/httpd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
21 changes: 21 additions & 0 deletions tests/magtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -400,6 +418,9 @@ def test_basic_auth_krb5(testdir, testenv, testlog):
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,
Expand Down
18 changes: 18 additions & 0 deletions tests/t_spnego_rewrite.py
Original file line number Diff line number Diff line change
@@ -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')