From c8bc300314756c700981e1c95b0aad4d81ed8de9 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Mon, 6 Nov 2017 10:43:55 -0500 Subject: [PATCH] Release 1.6.0 --- .gitignore | 1 + ...-to-selectively-suppress-negotiation.patch | 163 ----------------- Document-gssapi-no-negotiate.patch | 38 ---- Fix-strtol-error-checking.patch | 34 ---- Handle-extra-large-NSS-entries.patch | 168 ------------------ mod_auth_gssapi.spec | 11 +- sources | 2 +- 7 files changed, 7 insertions(+), 410 deletions(-) delete mode 100644 Allow-admins-to-selectively-suppress-negotiation.patch delete mode 100644 Document-gssapi-no-negotiate.patch delete mode 100644 Fix-strtol-error-checking.patch delete mode 100644 Handle-extra-large-NSS-entries.patch diff --git a/.gitignore b/.gitignore index 2d93631..846c703 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/Allow-admins-to-selectively-suppress-negotiation.patch b/Allow-admins-to-selectively-suppress-negotiation.patch deleted file mode 100644 index dd959c0..0000000 --- a/Allow-admins-to-selectively-suppress-negotiation.patch +++ /dev/null @@ -1,163 +0,0 @@ -From 0e13e07c3205bcaea9bfe9cdaaf188276f8ce57e Mon Sep 17 00:00:00 2001 -From: Simo Sorce -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 -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 - - -+ -+ 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 -+ -+ - - 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') diff --git a/Document-gssapi-no-negotiate.patch b/Document-gssapi-no-negotiate.patch deleted file mode 100644 index e3e142c..0000000 --- a/Document-gssapi-no-negotiate.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 850e6d452e3ce4d46122f216613c4a14ec398686 Mon Sep 17 00:00:00 2001 -From: Robbie Harwood -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 diff --git a/Fix-strtol-error-checking.patch b/Fix-strtol-error-checking.patch deleted file mode 100644 index 5ae5bc3..0000000 --- a/Fix-strtol-error-checking.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 47795ee7ee34121d98b3bd528b499f19ebe3923d Mon Sep 17 00:00:00 2001 -From: Simo Sorce -Date: Tue, 3 Oct 2017 12:33:38 -0400 -Subject: [PATCH] Fix strtol error checking - -Signed-off-by: Simo Sorce -Reviewed-by: Robbie Harwood -(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); diff --git a/Handle-extra-large-NSS-entries.patch b/Handle-extra-large-NSS-entries.patch deleted file mode 100644 index 7731c52..0000000 --- a/Handle-extra-large-NSS-entries.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 31372b8220da331e8dc81f343ff3d6b5585a842f Mon Sep 17 00:00:00 2001 -From: Simo Sorce -Date: Tue, 3 Oct 2017 12:31:02 -0400 -Subject: [PATCH] Handle extra large NSS entries - -Signed-off-by: Simo Sorce -Reviewed-by: Robbie Harwood - -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; -+} diff --git a/mod_auth_gssapi.spec b/mod_auth_gssapi.spec index c96a3ff..4fc8594 100644 --- a/mod_auth_gssapi.spec +++ b/mod_auth_gssapi.spec @@ -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 - 1.6.0-1 +- Release 1.6.0 + * Fri Oct 27 2017 Robbie Harwood - 1.5.1-6 - Document gssapi-no-negotiate diff --git a/sources b/sources index ba8f4bf..5379c34 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (mod_auth_gssapi-1.5.1.tar.gz) = 73004ba27ce216247a92a4782a179717c5ae3611b4eea130ce99a339434b5f880f60e49e915afd7b4d6c11259354fe0cfb6ca67acf1d8a965e1f1b00631215ad +SHA512 (mod_auth_gssapi-1.6.0.tar.gz) = 511a7e1cf58cf43358ff08ee0f22d4d41545b232b40db1faeae62edc3b7853908433f759d87eb62cbcb7b1def2faaedcfe6ce64beb87cc8d49168657a7197870