Skip to content

Commit a64a32f

Browse files
iboukrissimo5
authored andcommitted
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
1 parent 63706ef commit a64a32f

File tree

7 files changed

+117
-16
lines changed

7 files changed

+117
-16
lines changed

src/environ.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ void mag_get_name_attributes(request_rec *req, struct mag_config *cfg,
168168
if (GSS_ERROR(maj)) {
169169
error = mag_error(req, "gss_inquire_name() failed", maj, min);
170170
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s", error);
171-
apr_table_set(req->subprocess_env, "GSS_NAME_ATTR_ERROR", error);
171+
apr_table_set(mc->env, "GSS_NAME_ATTR_ERROR", error);
172172
return;
173173
}
174174

@@ -237,22 +237,22 @@ void mag_get_name_attributes(request_rec *req, struct mag_config *cfg,
237237
static void mag_set_name_attributes(request_rec *req, struct mag_conn *mc)
238238
{
239239
for (int i = 0; i < mc->na_count; i++) {
240-
apr_table_set(req->subprocess_env,
240+
apr_table_set(mc->env,
241241
mc->name_attributes[i].name,
242242
mc->name_attributes[i].value);
243243
}
244244
}
245245

246246
static void mag_set_KRB5CCNAME(request_rec *req, struct mag_config *cfg,
247-
const char *ccname)
247+
struct mag_conn *mc)
248248
{
249249
apr_status_t status;
250250
apr_int32_t wanted = APR_FINFO_MIN | APR_FINFO_OWNER | APR_FINFO_PROT;
251251
apr_finfo_t finfo = { 0 };
252252
char *path;
253253
char *value;
254254

255-
path = apr_psprintf(req->pool, "%s/%s", cfg->deleg_ccache_dir, ccname);
255+
path = apr_psprintf(req->pool, "%s/%s", cfg->deleg_ccache_dir, mc->ccname);
256256

257257
status = apr_stat(&finfo, path, wanted, req->pool);
258258
if (status == APR_SUCCESS) {
@@ -287,19 +287,27 @@ static void mag_set_KRB5CCNAME(request_rec *req, struct mag_config *cfg,
287287
}
288288

289289
value = apr_psprintf(req->pool, "FILE:%s", path);
290-
apr_table_set(req->subprocess_env, "KRB5CCNAME", value);
290+
apr_table_set(mc->env, "KRB5CCNAME", value);
291+
}
292+
293+
void mag_export_req_env(request_rec *req, apr_table_t *env)
294+
{
295+
const apr_array_header_t *arr = apr_table_elts(env);
296+
const apr_table_entry_t *elts = (const apr_table_entry_t*)arr->elts;
297+
298+
for (int i = 0; i < arr->nelts; ++i)
299+
apr_table_set(req->subprocess_env, elts[i].key, elts[i].val);
291300
}
292301

293302
void mag_set_req_data(request_rec *req,
294303
struct mag_config *cfg,
295304
struct mag_conn *mc)
296305
{
297-
apr_table_set(req->subprocess_env, "GSS_NAME", mc->gss_name);
298-
apr_table_set(req->subprocess_env, "GSS_SESSION_EXPIRATION",
306+
apr_table_set(mc->env, "GSS_NAME", mc->gss_name);
307+
apr_table_set(mc->env, "GSS_SESSION_EXPIRATION",
299308
apr_psprintf(req->pool,
300309
"%ld", (long)mc->expiration));
301-
req->ap_auth_type = apr_pstrdup(req->pool,
302-
mag_str_auth_type(mc->auth_type));
310+
req->ap_auth_type = (char *) mag_str_auth_type(mc->auth_type);
303311
req->user = apr_pstrdup(req->pool, mc->user_name);
304312

305313
if (mc->name_attributes) {
@@ -308,7 +316,10 @@ void mag_set_req_data(request_rec *req,
308316

309317
#ifdef HAVE_CRED_STORE
310318
if (cfg->deleg_ccache_dir && mc->delegated && mc->ccname) {
311-
mag_set_KRB5CCNAME(req, cfg, mc->ccname);
319+
mag_set_KRB5CCNAME(req, cfg, mc);
312320
}
313321
#endif
322+
323+
ap_set_module_config(req->request_config, &auth_gssapi_module, mc->env);
324+
mag_export_req_env(req, mc->env);
314325
}

src/environ.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ void mag_get_name_attributes(request_rec *req,
88
gss_name_t name,
99
struct mag_conn *mc);
1010

11+
void mag_export_req_env(request_rec *req, apr_table_t *env);
12+
1113
void mag_set_req_data(request_rec *req,
1214
struct mag_config *cfg,
1315
struct mag_conn *mc);

src/mod_auth_gssapi.c

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,10 @@ struct mag_conn *mag_new_conn_ctx(apr_pool_t *pool)
107107
struct mag_conn *mc;
108108

109109
mc = apr_pcalloc(pool, sizeof(struct mag_conn));
110+
110111
apr_pool_create(&mc->pool, pool);
112+
mc->env = apr_table_make(mc->pool, 1);
113+
111114
/* register the context in the memory pool, so it can be freed
112115
* when the connection/request is terminated */
113116
apr_pool_cleanup_register(mc->pool, (void *)mc,
@@ -124,6 +127,7 @@ static void mag_conn_clear(struct mag_conn *mc)
124127
temp = mc->pool;
125128
memset(mc, 0, sizeof(struct mag_conn));
126129
mc->pool = temp;
130+
mc->env = apr_table_make(mc->pool, 1);
127131
}
128132

129133
static bool mag_conn_is_https(conn_rec *c)
@@ -823,20 +827,45 @@ static int mag_auth(request_rec *req)
823827
return HTTP_UNAUTHORIZED;
824828
}
825829

830+
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
831+
"URI: %s, %s main, %s prev", req->uri ?: "no-uri",
832+
req->main ? "with" : "no", req->prev ? "with" : "no");
833+
826834
/* implicit auth for subrequests if main auth already happened */
827-
if (!ap_is_initial_req(req) && req->main != NULL) {
828-
type = ap_auth_type(req->main);
835+
if (!ap_is_initial_req(req)) {
836+
request_rec *main_req = req;
837+
838+
/* Not initial means either a subrequest or an internal redirect */
839+
while (!ap_is_initial_req(main_req))
840+
if (main_req->main)
841+
main_req = main_req->main;
842+
else
843+
main_req = main_req->prev;
844+
845+
type = ap_auth_type(main_req);
829846
if ((type != NULL) && (strcasecmp(type, "GSSAPI") == 0)) {
830847
/* warn if the subrequest location and the main request
831848
* location have different configs */
832-
if (cfg != ap_get_module_config(req->main->per_dir_config,
849+
if (cfg != ap_get_module_config(main_req->per_dir_config,
833850
&auth_gssapi_module)) {
834851
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0,
835852
req, "Subrequest authentication bypass on "
836853
"location with different configuration!");
837854
}
838-
if (req->main->user) {
839-
req->user = apr_pstrdup(req->pool, req->main->user);
855+
if (main_req->user) {
856+
apr_table_t *env;
857+
858+
req->user = apr_pstrdup(req->pool, main_req->user);
859+
req->ap_auth_type = main_req->ap_auth_type;
860+
861+
env = ap_get_module_config(main_req->request_config,
862+
&auth_gssapi_module);
863+
if (!env) {
864+
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, req,
865+
"Failed to lookup env table in subrequest");
866+
} else
867+
mag_export_req_env(req, env);
868+
840869
return OK;
841870
} else {
842871
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,

src/mod_auth_gssapi.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
# endif
5353
#endif
5454

55+
extern module AP_MODULE_DECLARE_DATA auth_gssapi_module;
56+
5557
struct mag_na_map {
5658
char *env_name;
5759
char *attr_name;
@@ -77,7 +79,7 @@ struct mag_config {
7779
uid_t deleg_ccache_uid;
7880
gid_t deleg_ccache_gid;
7981
gss_key_value_set_desc *cred_store;
80-
bool deleg_ccache_unique;;
82+
bool deleg_ccache_unique;
8183
bool s4u2self;
8284
#endif
8385
struct seal_key *mag_skey;
@@ -124,6 +126,7 @@ struct mag_conn {
124126
int na_count;
125127
struct mag_attr *name_attributes;
126128
const char *ccname;
129+
apr_table_t *env;
127130
};
128131

129132
#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))

tests/httpd.conf

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,23 @@ CoreDumpDirectory /tmp
148148
Require valid-user
149149
</Location>
150150

151+
<Location /spnego_rewrite>
152+
Options +Includes
153+
AddOutputFilter INCLUDES .html
154+
155+
AuthType GSSAPI
156+
AuthName "Login"
157+
GssapiCredStore ccache:${HTTPROOT}/tmp/httpd_krb5_ccache
158+
GssapiCredStore keytab:${HTTPROOT}/http.keytab
159+
GssapiAllowedMech krb5
160+
Require valid-user
161+
162+
RewriteEngine on
163+
RewriteCond %{REQUEST_FILENAME} !-d
164+
RewriteCond %{REQUEST_FILENAME} !-f
165+
RewriteRule . /spnego_rewrite/index.html [L]
166+
</Location>
167+
151168
<Location /spnego_negotiate_once>
152169
AuthType GSSAPI
153170
AuthName "Login Negotiate Once"

tests/magtests.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,24 @@ def test_spnego_auth(testdir, testenv, testlog):
306306
sys.stderr.write('SPNEGO No Auth: SUCCESS\n')
307307

308308

309+
def test_spnego_rewrite(testdir, testenv, testlog):
310+
311+
spnego_rewrite_dir = os.path.join(testdir, 'httpd', 'html',
312+
'spnego_rewrite')
313+
os.mkdir(spnego_rewrite_dir)
314+
shutil.copy('tests/index.html', spnego_rewrite_dir)
315+
316+
with (open(testlog, 'a')) as logfile:
317+
spnego = subprocess.Popen(["tests/t_spnego_rewrite.py"],
318+
stdout=logfile, stderr=logfile,
319+
env=testenv, preexec_fn=os.setsid)
320+
spnego.wait()
321+
if spnego.returncode != 0:
322+
sys.stderr.write('SPNEGO Rewrite: FAILED\n')
323+
else:
324+
sys.stderr.write('SPNEGO Rewrite: SUCCESS\n')
325+
326+
309327
def test_spnego_negotiate_once(testdir, testenv, testlog):
310328

311329
spnego_negotiate_once_dir = os.path.join(testdir, 'httpd', 'html',
@@ -400,6 +418,9 @@ def test_basic_auth_krb5(testdir, testenv, testlog):
400418
USR_NAME + '@' + TESTREALM)
401419
test_spnego_auth(testdir, testenv, testlog)
402420

421+
testenv['MAG_GSS_NAME'] = USR_NAME + '@' + TESTREALM
422+
test_spnego_rewrite(testdir, testenv, testlog)
423+
403424
test_spnego_negotiate_once(testdir, testenv, testlog)
404425

405426
testenv = {'MAG_USER_NAME': USR_NAME,

tests/t_spnego_rewrite.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/python
2+
# Copyright (C) 2015 - mod_auth_gssapi contributors, see COPYING for license.
3+
4+
import os
5+
import requests
6+
from requests_kerberos import HTTPKerberosAuth, OPTIONAL
7+
8+
9+
if __name__ == '__main__':
10+
sess = requests.Session()
11+
url = 'http://%s/spnego_rewrite/xxx' % os.environ['NSS_WRAPPER_HOSTNAME']
12+
r = sess.get(url, auth=HTTPKerberosAuth())
13+
14+
if r.status_code != 200:
15+
raise ValueError('Spnego Rewrite failed')
16+
17+
if r.text.rstrip() != os.environ['MAG_GSS_NAME']:
18+
raise ValueError('Spnego Rewrite, GSS_NAME check failed')

0 commit comments

Comments
 (0)