Release 1.6.0

This commit is contained in:
Robbie Harwood 2017-11-06 10:43:55 -05:00
parent 34f8670124
commit c8bc300314
7 changed files with 7 additions and 410 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@
/mod_auth_gssapi-1.4.1.tar.gz
/mod_auth_gssapi-1.5.0.tar.gz
/mod_auth_gssapi-1.5.1.tar.gz
/mod_auth_gssapi-1.6.0.tar.gz

View File

@ -1,163 +0,0 @@
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,38 +0,0 @@
From 850e6d452e3ce4d46122f216613c4a14ec398686 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Thu, 19 Oct 2017 16:35:29 -0400
Subject: [PATCH] Document gssapi-no-negotiate
Adds new section for apache env vars.
(cherry picked from commit 5330fa4959ca9317bf5943decfaaf0bbe86f1853)
---
README | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/README b/README
index 1fdfe98..1393760 100644
--- a/README
+++ b/README
@@ -418,3 +418,21 @@ Note: The GSS_C_NT_HOSTBASED_SERVICE format is used for names (see example).
#### Example
GssapiAcceptorName HTTP@www.example.com
+Environment Variables
+---------------------
+
+(Note: these are not process environment variables, but rather Apache
+environment variables, as described
+[in the apache docs](https://httpd.apache.org/docs/2.4/env.html).)
+
+### gssapi-no-negotiate
+
+This environment variable is used to suppress setting Negotiate headers. Not
+sending these headers is useful to work around browsers that do not handle
+them properly (and incorrectly show authentication popups to users).
+
+#### Example
+
+For instance, to suppress negotiation on Windows browsers, one could set:
+
+ BrowserMatch Windows gssapi-no-negotiate

View File

@ -1,34 +0,0 @@
From 47795ee7ee34121d98b3bd528b499f19ebe3923d Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Tue, 3 Oct 2017 12:33:38 -0400
Subject: [PATCH] Fix strtol error checking
Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Robbie Harwood <rharwood@redhat.com>
(cherry picked from commit 7cddf31b6ea7d0c67ac8a086d6b61d3f3631f47c)
---
src/mod_auth_gssapi.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/mod_auth_gssapi.c b/src/mod_auth_gssapi.c
index 59120d1..74962d1 100644
--- a/src/mod_auth_gssapi.c
+++ b/src/mod_auth_gssapi.c
@@ -1502,7 +1502,7 @@ static const char *mag_deleg_ccache_perms(cmd_parms *parms, void *mconfig,
if (isdigit(*p)) {
char *endptr;
cfg->deleg_ccache_uid = strtol(p, &endptr, 0);
- if (errno != 0 || endptr != '\0') {
+ if (errno != 0 || (endptr && *endptr != '\0')) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
"Invalid GssapiDelegCcachePerms uid value [%s]",
p);
@@ -1527,7 +1527,7 @@ static const char *mag_deleg_ccache_perms(cmd_parms *parms, void *mconfig,
if (isdigit(*p)) {
char *endptr;
cfg->deleg_ccache_gid = strtol(p, &endptr, 0);
- if (errno != 0 || endptr != '\0') {
+ if (errno != 0 || (endptr && *endptr != '\0')) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
"Invalid GssapiDelegCcachePerms gid value [%s]",
p);

View File

@ -1,168 +0,0 @@
From 31372b8220da331e8dc81f343ff3d6b5585a842f Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Tue, 3 Oct 2017 12:31:02 -0400
Subject: [PATCH] Handle extra large NSS entries
Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Robbie Harwood <rharwood@redhat.com>
Closes #152
(cherry picked from commit 9813eb46c6c415a933c5edf5076fd0a8e39c86b2)
[rharwood@redhat.com: conflicts due to no lex/yacc stuff yet]
---
src/Makefile.am | 2 +-
src/mod_auth_gssapi.c | 26 +++++++-------------
src/mod_auth_gssapi.h | 2 ++
src/util.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 78 insertions(+), 18 deletions(-)
create mode 100644 src/util.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 0605261..d8dd3ec 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,7 +8,7 @@ dist_noinst_HEADERS = \
mod_auth_gssapi.h crypto.h sessions.h environ.h
mod_auth_gssapi_la_SOURCES = \
- mod_auth_gssapi.c crypto.c sessions.c environ.c
+ mod_auth_gssapi.c crypto.c sessions.c environ.c util.c
mod_auth_gssapi_la_CFLAGS = \
$(MAG_CFLAGS)
mod_auth_gssapi_la_LIBADD = \
diff --git a/src/mod_auth_gssapi.c b/src/mod_auth_gssapi.c
index 74962d1..c2dd039 100644
--- a/src/mod_auth_gssapi.c
+++ b/src/mod_auth_gssapi.c
@@ -1476,7 +1476,7 @@ static const char *mag_deleg_ccache_dir(cmd_parms *parms, void *mconfig,
#define CCMODE "mode:"
#define CCUID "uid:"
#define CCGID "gid:"
-#define NSS_BUF_LEN 2048 /* just use a uid/gid number if not big enough */
+
static const char *mag_deleg_ccache_perms(cmd_parms *parms, void *mconfig,
const char *w)
{
@@ -1510,15 +1510,11 @@ static const char *mag_deleg_ccache_perms(cmd_parms *parms, void *mconfig,
cfg->deleg_ccache_uid = 0;
}
} else {
- struct passwd pwd, *user;
- char buf[NSS_BUF_LEN];
- int ret = getpwnam_r(p, &pwd, buf, NSS_BUF_LEN, &user);
- if ((ret != 0) || user != &pwd) {
+ int ret = mag_get_user_uid(p, &cfg->deleg_ccache_uid);
+ if (ret != 0) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
- "Invalid GssapiDelegCcachePerms uid value [%s]",
- p);
- } else {
- cfg->deleg_ccache_uid = user->pw_uid;
+ "Invalid GssapiDelegCcachePerms uid value [%s](%s)",
+ p, strerror(ret));
}
}
} else if (strncmp(w, CCGID, sizeof(CCGID) - 1) == 0) {
@@ -1535,15 +1531,11 @@ static const char *mag_deleg_ccache_perms(cmd_parms *parms, void *mconfig,
cfg->deleg_ccache_gid = 0;
}
} else {
- struct group grp, *group;
- char buf[NSS_BUF_LEN];
- int ret = getgrnam_r(p, &grp, buf, NSS_BUF_LEN, &group);
- if ((ret != 0) || group != &grp) {
+ int ret = mag_get_group_gid(p, &cfg->deleg_ccache_gid);
+ if (ret != 0) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
- "Invalid GssapiDelegCcachePerms gid value [%s]",
- p);
- } else {
- cfg->deleg_ccache_gid = group->gr_gid;
+ "Invalid GssapiDelegCcachePerms gid value [%s](%s)",
+ p, strerror(ret));
}
}
} else {
diff --git a/src/mod_auth_gssapi.h b/src/mod_auth_gssapi.h
index 159d6b7..2ea52a3 100644
--- a/src/mod_auth_gssapi.h
+++ b/src/mod_auth_gssapi.h
@@ -138,3 +138,5 @@ struct mag_conn {
struct mag_conn *mag_new_conn_ctx(apr_pool_t *pool);
const char *mag_str_auth_type(int auth_type);
char *mag_error(apr_pool_t *pool, const char *msg, uint32_t maj, uint32_t min);
+int mag_get_user_uid(const char *name, uid_t *uid);
+int mag_get_group_gid(const char *name, gid_t *gid);
diff --git a/src/util.c b/src/util.c
new file mode 100644
index 0000000..6b2a4a0
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,66 @@
+/* Copyright (C) 2017 mod_auth_gssapi contributors - See COPYING for (C) terms */
+
+#include "mod_auth_gssapi.h"
+
+#define NSS_BUF_MIN 1024
+#define NSS_BUF_MAX 1024*1024
+static char *get_buf(char *cur, size_t *len)
+{
+ if (*len == 0) {
+ *len = NSS_BUF_MIN;
+ } else {
+ *len *= 2;
+ }
+ if (*len > NSS_BUF_MAX) {
+ *len = 0; /* will free the buf and return NULL */
+ }
+ return realloc(cur, *len);
+}
+
+int mag_get_user_uid(const char *name, uid_t *uid)
+{
+ struct passwd pwd, *user;
+ size_t buflen = 0;
+ char *buf = NULL;
+ int ret;
+
+ do {
+ buf = get_buf(buf, &buflen);
+ if (buf == NULL || buflen == 0) {
+ ret = ENOMEM;
+ break;
+ }
+ ret = getpwnam_r(name, &pwd, buf, buflen, &user);
+ } while (ret == ERANGE);
+ if (ret != 0 || user != &pwd) {
+ ret = (ret == 0) ? EINVAL : ret;
+ } else {
+ *uid = user->pw_uid;
+ }
+ free(buf);
+ return ret;
+}
+
+int mag_get_group_gid(const char *name, gid_t *gid)
+{
+ struct group grp, *group;
+ size_t buflen = 0;
+ char *buf = NULL;
+ int ret;
+
+ do {
+ buf = get_buf(buf, &buflen);
+ if (buf == NULL || buflen == 0) {
+ ret = ENOMEM;
+ break;
+ }
+ ret = getgrnam_r(name, &grp, buf, buflen, &group);
+ } while (ret == ERANGE);
+ if (ret != 0 || group != &grp) {
+ ret = (ret == 0) ? EINVAL : ret;
+ } else {
+ *gid = group->gr_gid;
+ }
+ free(buf);
+ return ret;
+}

View File

@ -1,6 +1,6 @@
Name: mod_auth_gssapi
Version: 1.5.1
Release: 6%{?dist}
Version: 1.6.0
Release: 1%{?dist}
Summary: A GSSAPI Authentication module for Apache
Group: System Environment/Daemons
@ -8,10 +8,6 @@ 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
Patch1: Fix-strtol-error-checking.patch
Patch2: Handle-extra-large-NSS-entries.patch
Patch3: Document-gssapi-no-negotiate.patch
BuildRequires: httpd-devel, krb5-devel, openssl-devel, autoconf, automake, libtool
BuildRequires: gssntlmssp-devel
@ -49,6 +45,9 @@ install -m 644 10-auth_gssapi.conf %{buildroot}%{_httpd_modconfdir}
%{_httpd_moddir}/mod_auth_gssapi.so
%changelog
* Mon Nov 06 2017 Robbie Harwood <rharwood@redhat.com> - 1.6.0-1
- Release 1.6.0
* Fri Oct 27 2017 Robbie Harwood <rharwood@redhat.com> - 1.5.1-6
- Document gssapi-no-negotiate

View File

@ -1 +1 @@
SHA512 (mod_auth_gssapi-1.5.1.tar.gz) = 73004ba27ce216247a92a4782a179717c5ae3611b4eea130ce99a339434b5f880f60e49e915afd7b4d6c11259354fe0cfb6ca67acf1d8a965e1f1b00631215ad
SHA512 (mod_auth_gssapi-1.6.0.tar.gz) = 511a7e1cf58cf43358ff08ee0f22d4d41545b232b40db1faeae62edc3b7853908433f759d87eb62cbcb7b1def2faaedcfe6ce64beb87cc8d49168657a7197870