Allow admins to selectively suppress negotiation

Also migrate to %autosetup
This commit is contained in:
Robbie Harwood 2017-10-02 16:55:13 -04:00
parent b721c11554
commit 8bc6d6bb1c
2 changed files with 172 additions and 2 deletions

View File

@ -0,0 +1,163 @@
From 0e13e07c3205bcaea9bfe9cdaaf188276f8ce57e Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Mon, 24 Apr 2017 15:40:33 -0400
Subject: [PATCH] Allow admins to selectively suppress negotiation
If the admin sets the gssapi-no-negotiate requets enironemnt variable,
then we suppress the ability to send Negotiate headers.
This is useful to slectively send negotiate only to specific whielisted
or blacklisted browsers, clients, IP Addresses, etc... based on
directives like BrowserMatch or SetEnvIf.
Signed-off-by: Simo Sorce <simo@redhat.com>
Resolves #135
(cherry picked from commit 114e4408523ca4d06da32c265680b9faa74ad882)
---
src/mod_auth_gssapi.c | 13 ++++++++++---
tests/httpd.conf | 13 +++++++++++++
tests/magtests.py | 19 +++++++++++++++++++
tests/t_nonego.py | 29 +++++++++++++++++++++++++++++
4 files changed, 71 insertions(+), 3 deletions(-)
create mode 100755 tests/t_nonego.py
diff --git a/src/mod_auth_gssapi.c b/src/mod_auth_gssapi.c
index 755654d..59120d1 100644
--- a/src/mod_auth_gssapi.c
+++ b/src/mod_auth_gssapi.c
@@ -833,7 +833,7 @@ static int mag_auth(request_rec *req)
gss_OID_set desired_mechs = GSS_C_NO_OID_SET;
struct mag_conn *mc = NULL;
int i;
- bool send_auth_header = true;
+ bool send_nego_header = true;
type = ap_auth_type(req);
if ((type == NULL) || (strcasecmp(type, "GSSAPI") != 0)) {
@@ -907,6 +907,11 @@ static int mag_auth(request_rec *req)
}
}
+ /* check if admin wants to disable negotiate with this client */
+ if (apr_table_get(req->subprocess_env, "gssapi-no-negotiate")) {
+ send_nego_header = false;
+ }
+
if (cfg->ssl_only) {
if (!mag_conn_is_https(req->connection)) {
mag_post_error(req, cfg, MAG_AUTH_NOT_ALLOWED, 0, 0,
@@ -965,7 +970,9 @@ static int mag_auth(request_rec *req)
}
/* We got auth header, sending auth header would mean re-auth */
- send_auth_header = !cfg->negotiate_once;
+ if (cfg->negotiate_once) {
+ send_nego_header = false;
+ }
for (i = 0; auth_types[i] != NULL; i++) {
if (strcasecmp(auth_header_type, auth_types[i]) == 0) {
@@ -1126,7 +1133,7 @@ done:
apr_table_add(req->err_headers_out, req_cfg->rep_proto, reply);
}
} else if (ret == HTTP_UNAUTHORIZED) {
- if (send_auth_header) {
+ if (send_nego_header) {
apr_table_add(req->err_headers_out,
req_cfg->rep_proto, "Negotiate");
if (is_mech_allowed(desired_mechs, gss_mech_ntlmssp,
diff --git a/tests/httpd.conf b/tests/httpd.conf
index 7879727..e17cf0a 100644
--- a/tests/httpd.conf
+++ b/tests/httpd.conf
@@ -211,6 +211,19 @@ CoreDumpDirectory "${HTTPROOT}"
Require valid-user
</Location>
+<Location /nonego>
+ BrowserMatch NONEGO gssapi-no-negotiate
+ AuthType GSSAPI
+ AuthName "Login"
+ GssapiSSLonly Off
+ GssapiCredStore ccache:${HTTPROOT}/tmp/httpd_krb5_ccache
+ GssapiCredStore client_keytab:${HTTPROOT}/http.keytab
+ GssapiCredStore keytab:${HTTPROOT}/http.keytab
+ GssapiBasicAuth On
+ GssapiAllowedMech krb5
+ Require valid-user
+</Location>
+
<VirtualHost *:${PROXYPORT}>
ProxyRequests On
ProxyVia On
diff --git a/tests/magtests.py b/tests/magtests.py
index a008d81..4d276df 100755
--- a/tests/magtests.py
+++ b/tests/magtests.py
@@ -410,6 +410,23 @@ def test_bad_acceptor_name(testdir, testenv, testlog):
sys.stderr.write('BAD ACCEPTOR: FAILED\n')
+def test_no_negotiate(testdir, testenv, testlog):
+
+ nonego_dir = os.path.join(testdir, 'httpd', 'html', 'nonego')
+ os.mkdir(nonego_dir)
+ shutil.copy('tests/index.html', nonego_dir)
+
+ with (open(testlog, 'a')) as logfile:
+ spnego = subprocess.Popen(["tests/t_nonego.py"],
+ stdout=logfile, stderr=logfile,
+ env=testenv, preexec_fn=os.setsid)
+ spnego.wait()
+ if spnego.returncode != 0:
+ sys.stderr.write('NO Negotiate: FAILED\n')
+ else:
+ sys.stderr.write('NO Negotiate: SUCCESS\n')
+
+
if __name__ == '__main__':
args = parse_args()
@@ -454,6 +471,8 @@ if __name__ == '__main__':
testenv.update(kdcenv)
test_basic_auth_krb5(testdir, testenv, testlog)
+ test_no_negotiate(testdir, testenv, testlog)
+
finally:
with (open(testlog, 'a')) as logfile:
for name in processes:
diff --git a/tests/t_nonego.py b/tests/t_nonego.py
new file mode 100755
index 0000000..c4f2bdd
--- /dev/null
+++ b/tests/t_nonego.py
@@ -0,0 +1,29 @@
+#!/usr/bin/python
+# Copyright (C) 2015 - mod_auth_gssapi contributors, see COPYING for license.
+
+import os
+import requests
+
+
+if __name__ == '__main__':
+ url = 'http://%s/nonego/' % (os.environ['NSS_WRAPPER_HOSTNAME'])
+
+ # ensure a 401 with the appropriate WWW-Authenticate header is returned
+ # when no auth is provided
+ r = requests.get(url)
+ if r.status_code != 401:
+ raise ValueError('NO Negotiate failed - 401 expected')
+ if not (r.headers.get("WWW-Authenticate") and
+ r.headers.get("WWW-Authenticate").startswith("Negotiate")):
+ raise ValueError('NO Negotiate failed - WWW-Authenticate '
+ 'Negotiate header is absent')
+
+ # ensure a 401 with the WWW-Authenticate Negotiate header is absent
+ # when the special User-Agent is sent
+ r = requests.get(url, headers={'User-Agent': 'NONEGO'})
+ if r.status_code != 401:
+ raise ValueError('NO Negotiate failed - 401 expected')
+ if (r.headers.get("WWW-Authenticate") and
+ r.headers.get("WWW-Authenticate").startswith("Negotiate")):
+ raise ValueError('NO Negotiate failed - WWW-Authenticate '
+ 'Negotiate header is present, should be absent')

View File

@ -1,6 +1,6 @@
Name: mod_auth_gssapi
Version: 1.5.1
Release: 3%{?dist}
Release: 4%{?dist}
Summary: A GSSAPI Authentication module for Apache
Group: System Environment/Daemons
@ -8,8 +8,11 @@ License: MIT
URL: https://github.com/modauthgssapi/mod_auth_gssapi
Source0: https://github.com/modauthgssapi/%{name}/releases/download/v%{version}/%name-%{version}.tar.gz
Patch0: Allow-admins-to-selectively-suppress-negotiation.patch
BuildRequires: httpd-devel, krb5-devel, openssl-devel, autoconf, automake, libtool
BuildRequires: gssntlmssp-devel
BuildRequires: git
Requires: httpd-mmn = %{_httpd_mmn}
Requires: krb5-libs >= 1.11.5
@ -18,7 +21,7 @@ The mod_auth_gssapi module is an authentication service that implements the
SPNEGO based HTTP Authentication protocol defined in RFC4559.
%prep
%setup -q
%autosetup -S git
%build
export APXS=%{_httpd_apxs}
@ -43,6 +46,10 @@ install -m 644 10-auth_gssapi.conf %{buildroot}%{_httpd_modconfdir}
%{_httpd_moddir}/mod_auth_gssapi.so
%changelog
* Mon Oct 02 2017 Robbie Harwood <rharwood@redhat.com> - 1.5.1-4
- Allow admins to selectively suppress negotiation
- Migrate to autosetup
* Thu Aug 03 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.5.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild