Skip to content

Commit fee81f6

Browse files
committed
Add ability to expose the used mechanism
A new option named GssapiPublishMech enables setting an environemnt variable named GSS_MECH that exposed the authentication type and mechanism used for authentication. Signed-off-by: Simo Sorce <simo@redhat.com>
1 parent 4a22af7 commit fee81f6

File tree

10 files changed

+109
-0
lines changed

10 files changed

+109
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ ylwrap
2525
src/lex.c
2626
src/parser.c
2727
src/parser.h
28+
testdir/
2829
*.o
2930
*.lo
3031
*.la

README

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,4 +507,16 @@ Note: The GSS_C_NT_HOSTBASED_SERVICE format is used for names (see example).
507507
#### Example
508508
GssapiAcceptorName HTTP@www.example.com
509509

510+
### GssapiPublishMech
510511

512+
This option is used to publish the mech used for authentication as an
513+
Environment variable named GSS_MECH.
514+
515+
It will return a string of the form authtype/mechname.
516+
Where authtype is a string representing the type of auth performed by the
517+
module. Possible values are 'Basic', 'Negotiate', 'NTLM', 'Impersonate'.
518+
And mechname is the name of the mechanism as reported by GSSAPI or the OID
519+
of the mechanism if a name is not available.
520+
521+
- **Enable with:** GssapiPublishMech On
522+
- **Default:** GssapiPublishMEch Off

src/environ.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,3 +498,35 @@ void mag_publish_error(request_rec *req, uint32_t maj, uint32_t min,
498498
if (mag_err)
499499
apr_table_set(req->subprocess_env, "MAG_ERROR", mag_err);
500500
}
501+
502+
void mag_publish_mech(request_rec *req, struct mag_conn *mc,
503+
const char *auth_type, gss_OID mech_type)
504+
{
505+
gss_buffer_desc sasl_mech_name = GSS_C_EMPTY_BUFFER;
506+
gss_buffer_desc mech_name = GSS_C_EMPTY_BUFFER;
507+
gss_buffer_desc mech_description = GSS_C_EMPTY_BUFFER;
508+
uint32_t maj, min;
509+
510+
maj = gss_inquire_saslname_for_mech(&min, mech_type, &sasl_mech_name,
511+
&mech_name, &mech_description);
512+
if (maj != GSS_S_COMPLETE) {
513+
/* something failed, let's try to get a string OID */
514+
/* and if that fails there is nothing we can do */
515+
maj = gss_oid_to_str(&min, mech_type, &mech_name);
516+
if (maj != GSS_S_COMPLETE) {
517+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
518+
"Failed to source mechanism name or OID");
519+
mech_name.value = strdup("Unavailable");
520+
mech_name.length = strlen(mech_name.value);
521+
}
522+
}
523+
524+
apr_table_set(mc->env, "GSS_MECH",
525+
apr_psprintf(req->pool, "%s/%.*s", auth_type,
526+
(int)mech_name.length,
527+
(char *)mech_name.value));
528+
529+
(void)gss_release_buffer(&min, &sasl_mech_name);
530+
(void)gss_release_buffer(&min, &mech_name);
531+
(void)gss_release_buffer(&min, &mech_description);
532+
}

src/environ.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ void mag_publish_error(request_rec *req, uint32_t maj, uint32_t min,
1818
const char *gss_err, const char *mag_err);
1919
void mag_set_req_attr_fail(request_rec *req, struct mag_config *cfg,
2020
struct mag_conn *mc);
21+
void mag_publish_mech(request_rec *req, struct mag_conn *mc,
22+
const char *auth_type, gss_OID mech_type);

src/mod_auth_gssapi.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,10 @@ static int mag_complete(struct mag_req_cfg *req_cfg, struct mag_conn *mc,
12831283
mc->user_name = apr_pstrdup(mc->pool, mc->gss_name);
12841284
}
12851285

1286+
if (cfg->pubmech) {
1287+
mag_publish_mech(req, mc, auth_types[mc->auth_type], mech_type);
1288+
}
1289+
12861290
mc->established = true;
12871291
if (req_cfg->use_sessions) {
12881292
mag_attempt_session(req_cfg, mc);
@@ -1872,6 +1876,9 @@ static const command_rec mag_commands[] = {
18721876
AP_INIT_FLAG("GssapiPublishErrors", ap_set_flag_slot,
18731877
(void *)APR_OFFSETOF(struct mag_config, enverrs), OR_AUTHCFG,
18741878
"Publish GSSAPI Errors in Envionment Variables"),
1879+
AP_INIT_FLAG("GssapiPublishMech", ap_set_flag_slot,
1880+
(void *)APR_OFFSETOF(struct mag_config, pubmech), OR_AUTHCFG,
1881+
"Publish GSSAPI Mech Name in Envionment Variables"),
18751882
AP_INIT_RAW_ARGS("GssapiAcceptorName", mag_acceptor_name, NULL, OR_AUTHCFG,
18761883
"Name of the acceptor credentials."),
18771884
{ NULL }

src/mod_auth_gssapi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ struct mag_config {
9595
struct mag_name_attributes *name_attributes;
9696
const char *required_na_expr;
9797
int enverrs;
98+
int pubmech;
9899
gss_name_t acceptor_name;
99100
bool acceptor_name_from_req;
100101
};

tests/httpd.conf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,21 @@ CoreDumpDirectory "{HTTPROOT}"
274274
Require valid-user
275275
</Location>
276276

277+
<Location /mech_name>
278+
Options +Includes
279+
AddOutputFilter INCLUDES .html
280+
AuthType GSSAPI
281+
AuthName "Password Login"
282+
GssapiSSLonly Off
283+
GssapiCredStore ccache:{HTTPROOT}/tmp/httpd_krb5_ccache
284+
GssapiCredStore client_keytab:{HTTPROOT}/http.keytab
285+
GssapiCredStore keytab:{HTTPROOT}/http.keytab
286+
GssapiBasicAuth On
287+
GssapiBasicAuthMech krb5
288+
GssapiPublishMech On
289+
Require valid-user
290+
</Location>
291+
277292
<VirtualHost *:{PROXYPORT}>
278293
ProxyRequests On
279294
ProxyVia On

tests/magtests.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,23 @@ def test_hostname_acceptor(testdir, testenv, logfile):
660660
return 0
661661

662662

663+
def test_mech_name(testdir, testenv, logfile):
664+
basicdir = os.path.join(testdir, 'httpd', 'html', 'mech_name')
665+
os.mkdir(basicdir)
666+
shutil.copy('tests/mech.html', basicdir)
667+
error_count = 0
668+
669+
basick5 = subprocess.Popen(["tests/t_mech_name.py"],
670+
stdout=logfile, stderr=logfile,
671+
env=testenv, preexec_fn=os.setsid)
672+
basick5.wait()
673+
if basick5.returncode != 0:
674+
sys.stderr.write('MECH-NAME: FAILED\n')
675+
return 1
676+
sys.stderr.write('MECH-NAME: SUCCESS\n')
677+
return 0
678+
679+
663680
if __name__ == '__main__':
664681
args = parse_args()
665682

@@ -721,6 +738,8 @@ def test_hostname_acceptor(testdir, testenv, logfile):
721738
errs += test_basic_auth_krb5(testdir, testenv, logfile)
722739

723740
errs += test_no_negotiate(testdir, testenv, logfile)
741+
742+
errs += test_mech_name(testdir, testenv, logfile)
724743
except Exception:
725744
traceback.print_exc()
726745
finally:

tests/mech.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!--#echo var="GSS_MECH" -->

tests/t_mech_name.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env python
2+
# Copyright (C) 2015 - mod_auth_gssapi contributors, see COPYING for license.
3+
4+
import os
5+
import requests
6+
from requests.auth import HTTPBasicAuth
7+
8+
9+
if __name__ == '__main__':
10+
url = 'http://%s/mech_name/mech.html' % os.environ['NSS_WRAPPER_HOSTNAME']
11+
r = requests.get(url, auth=HTTPBasicAuth(os.environ['MAG_USER_NAME'],
12+
os.environ['MAG_USER_PASSWORD']))
13+
if r.status_code != 200:
14+
raise ValueError('Basic Auth Failed')
15+
16+
if r.text.rstrip() != 'Basic/krb5':
17+
raise ValueError(
18+
'GSS_MECH check failed, expected Basic/krb5, got "%s"' %
19+
r.text.rstrip())

0 commit comments

Comments
 (0)