Skip to content

Commit 3f9ed41

Browse files
simo5frozencemetery
authored andcommitted
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 <[email protected]> Merges: #206 Resolves: #199 Reviewed-by: Robbie Harwood <[email protected]>
1 parent 98fb40c commit 3f9ed41

11 files changed

+120
-1
lines changed

.gitignore

+1
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

+15
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ Configuration Directives
109109
[GssapiNameAttributes](#gssapinameattributes)<br>
110110
[GssapiNegotiateOnce](#gssapinegotiateonce)<br>
111111
[GssapiPublishErrors](#gssapipublisherrors)<br>
112+
[GssapiPublishMech](#gssapipublishmech)<br>
112113
[GssapiRequiredNameAttributes](#gssapirequirednameattributes)<br>
113114
[GssapiSessionKey](#gssapisessionkey)<br>
114115
[GssapiSignalPersistentAuth](#gssapisignalpersistentauth)<br>
@@ -543,3 +544,17 @@ Note: the value is specified in seconds.
543544
Sets ticket/session validity to 10 hours.
544545

545546

547+
### GssapiPublishMech
548+
549+
This option is used to publish the mech used for authentication as an
550+
Environment variable named GSS_MECH.
551+
552+
It will return a string of the form 'Authtype/Mechname'.
553+
Authtype represents the type of auth performed by the module. Possible values
554+
are 'Basic', 'Negotiate', 'NTLM', 'Impersonate'.
555+
Mechname is the name of the mechanism as reported by GSSAPI or the OID of the
556+
mechanism if a name is not available. In case of errors the 'Unavailable'
557+
string may also be returned for either Authtype or Mechname.
558+
559+
- **Enable with:** GssapiPublishMech On
560+
- **Default:** GssapiPublishMech Off

src/environ.c

+38
Original file line numberDiff line numberDiff line change
@@ -498,3 +498,41 @@ 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+
char *mechdata;
509+
uint32_t maj, min;
510+
511+
maj = gss_inquire_saslname_for_mech(&min, mech_type, &sasl_mech_name,
512+
&mech_name, &mech_description);
513+
if (maj != GSS_S_COMPLETE) {
514+
/* something failed, let's try to get a string OID */
515+
/* and if that fails there is nothing we can do */
516+
maj = gss_oid_to_str(&min, mech_type, &mech_name);
517+
if (maj != GSS_S_COMPLETE) {
518+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
519+
"Failed to source mechanism name or OID");
520+
mech_name.value = strdup("Unavailable");
521+
mech_name.length = strlen(mech_name.value);
522+
}
523+
}
524+
525+
mechdata = apr_psprintf(req->pool, "%s/%.*s", auth_type,
526+
(int)mech_name.length,
527+
(char *)mech_name.value);
528+
529+
apr_table_set(mc->env, "GSS_MECH", mechdata);
530+
531+
/* also log at info level */
532+
ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, req,
533+
"User %s authenticated with %s", mc->gss_name, mechdata);
534+
535+
(void)gss_release_buffer(&min, &sasl_mech_name);
536+
(void)gss_release_buffer(&min, &mech_name);
537+
(void)gss_release_buffer(&min, &mech_description);
538+
}

src/environ.h

+2
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

+7
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,10 @@ static int mag_complete(struct mag_req_cfg *req_cfg, struct mag_conn *mc,
12941294
mc->user_name = apr_pstrdup(mc->pool, mc->gss_name);
12951295
}
12961296

1297+
if (cfg->pubmech) {
1298+
mag_publish_mech(req, mc, mag_str_auth_type(mc->auth_type), mech_type);
1299+
}
1300+
12971301
mc->established = true;
12981302
if (req_cfg->use_sessions) {
12991303
mag_attempt_session(req_cfg, mc);
@@ -1899,6 +1903,9 @@ static const command_rec mag_commands[] = {
18991903
AP_INIT_FLAG("GssapiPublishErrors", ap_set_flag_slot,
19001904
(void *)APR_OFFSETOF(struct mag_config, enverrs), OR_AUTHCFG,
19011905
"Publish GSSAPI Errors in Envionment Variables"),
1906+
AP_INIT_FLAG("GssapiPublishMech", ap_set_flag_slot,
1907+
(void *)APR_OFFSETOF(struct mag_config, pubmech), OR_AUTHCFG,
1908+
"Publish GSSAPI Mech Name in Envionment Variables"),
19021909
AP_INIT_RAW_ARGS("GssapiAcceptorName", mag_acceptor_name, NULL, OR_AUTHCFG,
19031910
"Name of the acceptor credentials."),
19041911
AP_INIT_TAKE1("GssapiBasicTicketTimeout", mag_basic_timeout, NULL,

src/mod_auth_gssapi.h

+1
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
uint32_t basic_timeout;

tests/Makefile.am

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ EXTRA_DIST = \
66
index.html \
77
localname.html \
88
magtests.py \
9+
mech.html \
910
t_bad_acceptor_name.py \
1011
t_basic_k5_fail_second.py \
1112
t_basic_k5.py \
1213
t_basic_k5_two_users.py \
1314
t_basic_proxy.py \
1415
t_basic_timeout.py \
15-
t_localname.py \
1616
t_hostname_acceptor.py \
17+
t_localname.py \
18+
t_mech_name.py \
1719
t_nonego.py \
1820
t_required_name_attr.py \
1921
t_spnego_negotiate_once.py \

tests/httpd.conf

+15
Original file line numberDiff line numberDiff line change
@@ -331,3 +331,18 @@ CoreDumpDirectory "{HTTPROOT}"
331331
GssapiSessionKey file:{HTTPROOT}/session.key
332332
Require valid-user
333333
</Location>
334+
335+
<Location /mech_name>
336+
Options +Includes
337+
AddOutputFilter INCLUDES .html
338+
AuthType GSSAPI
339+
AuthName "Password Login"
340+
GssapiSSLonly Off
341+
GssapiCredStore ccache:{HTTPROOT}/tmp/httpd_krb5_ccache
342+
GssapiCredStore client_keytab:{HTTPROOT}/http.keytab
343+
GssapiCredStore keytab:{HTTPROOT}/http.keytab
344+
GssapiBasicAuth On
345+
GssapiBasicAuthMech krb5
346+
GssapiPublishMech On
347+
Require valid-user
348+
</Location>

tests/magtests.py

+18
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,22 @@ def http_restart(testdir, so_dir, testenv):
773773
return httpproc
774774

775775

776+
def test_mech_name(testdir, testenv, logfile):
777+
basicdir = os.path.join(testdir, 'httpd', 'html', 'mech_name')
778+
os.mkdir(basicdir)
779+
shutil.copy('tests/mech.html', basicdir)
780+
781+
mname = subprocess.Popen(["tests/t_mech_name.py"],
782+
stdout=logfile, stderr=logfile,
783+
env=testenv, preexec_fn=os.setsid)
784+
mname.wait()
785+
if mname.returncode != 0:
786+
sys.stderr.write('MECH-NAME: FAILED\n')
787+
return 1
788+
sys.stderr.write('MECH-NAME: SUCCESS\n')
789+
return 0
790+
791+
776792
if __name__ == '__main__':
777793
args = parse_args()
778794

@@ -832,6 +848,8 @@ def http_restart(testdir, so_dir, testenv):
832848

833849
errs += test_no_negotiate(testdir, testenv, logfile)
834850

851+
errs += test_mech_name(testdir, testenv, logfile)
852+
835853
# After this point we need to speed up httpd to test creds timeout
836854
try:
837855
fakeenv = faketime_setup(kdcenv)

tests/mech.html

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!--#echo var="GSS_MECH" -->

tests/t_mech_name.py

+19
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)