[krb5] Backport support for scanning /etc/gss/mech.d/*.conf

Nalin Dahyabhai nalin at fedoraproject.org
Tue Jun 24 20:47:42 UTC 2014


commit 40e2189edee334ce5f9df46659e3f8ef58e5e746
Author: Nalin Dahyabhai <nalin at redhat.com>
Date:   Tue Jun 24 16:47:17 2014 -0400

    Backport support for scanning /etc/gss/mech.d/*.conf
    
    - pull in changes from upstream which add processing of the contents of
      /etc/gss/mech.d/*.conf when loading GSS modules (#1102839)

 krb5-master-mechd.patch |  313 +++++++++++++++++++++++++++++++++++++++++++++++
 krb5.spec               |   15 ++-
 2 files changed, 326 insertions(+), 2 deletions(-)
---
diff --git a/krb5-master-mechd.patch b/krb5-master-mechd.patch
new file mode 100644
index 0000000..8982fdd
--- /dev/null
+++ b/krb5-master-mechd.patch
@@ -0,0 +1,313 @@
+commit 123c14fd8862ee8f11f6084d25958cb380655f35
+Author: Günther Deschner <gdeschner at redhat.com>
+Date:   Wed Mar 5 16:21:55 2014 +0100
+
+    Remove dead code from the mechglue initialization
+    
+    The stat check in gss_indicate_mechs had no consequent and would have
+    been redundant with logic in updateMechList if it did.
+    
+    [ghudson at mit.edu: elaborated commit message; removed unused
+    g_mechSetTime and now-irrelevant comment]
+
+diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c
+index 48a825e..c6904e0 100644
+--- a/src/lib/gssapi/mechglue/g_initialize.c
++++ b/src/lib/gssapi/mechglue/g_initialize.c
+@@ -91,7 +91,6 @@ static gss_mech_info g_mechListTail = NULL;
+ static k5_mutex_t g_mechListLock = K5_MUTEX_PARTIAL_INITIALIZER;
+ static time_t g_confFileModTime = (time_t)0;
+ 
+-static time_t g_mechSetTime = (time_t)0;
+ static gss_OID_set_desc g_mechSet = { 0, NULL };
+ static k5_mutex_t g_mechSetLock = K5_MUTEX_PARTIAL_INITIALIZER;
+ 
+@@ -213,8 +212,6 @@ gss_indicate_mechs(minorStatus, mechSet_out)
+ OM_uint32 *minorStatus;
+ gss_OID_set *mechSet_out;
+ {
+-	char *fileName;
+-	struct stat fileInfo;
+ 	OM_uint32 status;
+ 
+ 	/* Initialize outputs. */
+@@ -233,16 +230,6 @@ gss_OID_set *mechSet_out;
+ 	if (*minorStatus != 0)
+ 		return (GSS_S_FAILURE);
+ 
+-	fileName = MECH_CONF;
+-
+-	/*
+-	 * If we have already computed the mechanisms supported and if it
+-	 * is still valid; make a copy and return to caller,
+-	 * otherwise build it first.
+-	 */
+-	if ((stat(fileName, &fileInfo) == 0 &&
+-		fileInfo.st_mtime > g_mechSetTime)) {
+-	} /* if g_mechSet is out of date or not initialized */
+ 	if (build_mechSet())
+ 		return GSS_S_FAILURE;
+ 
+@@ -289,20 +276,6 @@ build_mechSet(void)
+ 	 */
+ 	k5_mutex_lock(&g_mechListLock);
+ 
+-#if 0
+-	/*
+-	 * this checks for the case when we need to re-construct the
+-	 * g_mechSet structure, but the mechanism list is upto date
+-	 * (because it has been read by someone calling
+-	 * gssint_get_mechanism)
+-	 */
+-	if (fileInfo.st_mtime > g_confFileModTime)
+-	{
+-		g_confFileModTime = fileInfo.st_mtime;
+-		loadConfigFile(fileName);
+-	}
+-#endif
+-
+ 	updateMechList();
+ 
+ 	/*
+
+commit 05cbef80d53f49d30a5d0563501226dc173734d4
+Author: Günther Deschner <gdeschner at redhat.com>
+Date:   Wed Mar 5 15:25:43 2014 +0100
+
+    Load mechglue config files from /etc/gss/mech.d
+    
+    In addition to loading /etc/gss/mech, glob for *.conf files in
+    /etc/gss/mech.d.  Load only config files which have changed since the
+    highest mtime we saw in the previous scan.  Scan at most once per
+    second to avoid excessive numbers of filesystem syscalls for busy
+    GSSAPI applications.
+    
+    [ghudson at mit.edu: rewrote commit message; style changes; added
+    once-per-second throttle on glob/stat calls]
+    
+    ticket: 7882 (new)
+
+diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c
+index c6904e0..f0acf1a 100644
+--- a/src/lib/gssapi/mechglue/g_initialize.c
++++ b/src/lib/gssapi/mechglue/g_initialize.c
+@@ -41,6 +41,7 @@
+ #include <string.h>
+ #include <ctype.h>
+ #include <errno.h>
++#include <glob.h>
+ 
+ #define	M_DEFAULT	"default"
+ 
+@@ -58,6 +59,7 @@
+ #ifndef MECH_CONF
+ #define	MECH_CONF "/etc/gss/mech"
+ #endif
++#define MECH_CONF_PATTERN MECH_CONF ".d/*.conf"
+ 
+ /* Local functions */
+ static void addConfigEntry(const char *oidStr, const char *oid,
+@@ -90,6 +92,7 @@ static gss_mech_info g_mechList = NULL;
+ static gss_mech_info g_mechListTail = NULL;
+ static k5_mutex_t g_mechListLock = K5_MUTEX_PARTIAL_INITIALIZER;
+ static time_t g_confFileModTime = (time_t)0;
++static time_t g_confLastCall = (time_t)0;
+ 
+ static gss_OID_set_desc g_mechSet = { 0, NULL };
+ static k5_mutex_t g_mechSetLock = K5_MUTEX_PARTIAL_INITIALIZER;
+@@ -383,6 +386,56 @@ const gss_OID oid;
+ 	return (modOptions);
+ } /* gssint_get_modOptions */
+ 
++/* Return the mtime of filename or its eventual symlink target (if it is a
++ * symlink), whichever is larger.  Return (time_t)-1 if lstat or stat fails. */
++static time_t
++check_link_mtime(const char *filename, time_t *mtime_out)
++{
++	struct stat st1, st2;
++
++	if (lstat(filename, &st1) != 0)
++		return (time_t)-1;
++	if (!S_ISLNK(st1.st_mode))
++		return st1.st_mtime;
++	if (stat(filename, &st2) != 0)
++		return (time_t)-1;
++	return (st1.st_mtime > st2.st_mtime) ? st1.st_mtime : st2.st_mtime;
++}
++
++/* Try to load any config files which have changed since the last call.  Config
++ * files are MECH_CONF and any files matching MECH_CONF_PATTERN. */
++static void
++loadConfigFiles()
++{
++	glob_t globbuf;
++	time_t highest_mtime = 0, mtime, now;
++	char **pathptr;
++
++	/* Don't glob and stat more than once per second. */
++	if (time(&now) == (time_t)-1 || now == g_confLastCall)
++		return;
++	g_confLastCall = now;
++
++	globbuf.gl_offs = 1;
++	if (glob(MECH_CONF_PATTERN, GLOB_DOOFFS, NULL, &globbuf) != 0)
++		return;
++	globbuf.gl_pathv[0] = MECH_CONF;
++
++	for (pathptr = globbuf.gl_pathv; *pathptr != NULL; pathptr++) {
++		mtime = check_link_mtime(*pathptr, &mtime);
++		if (mtime == (time_t)-1)
++			continue;
++		if (mtime > highest_mtime)
++			highest_mtime = mtime;
++		if (mtime > g_confFileModTime)
++			loadConfigFile(*pathptr);
++	}
++	g_confFileModTime = highest_mtime;
++
++	globbuf.gl_pathv[0] = NULL;
++	globfree(&globbuf);
++}
++
+ /*
+  * determines if the mechList needs to be updated from file
+  * and performs the update.
+@@ -401,17 +454,7 @@ updateMechList(void)
+ 	loadConfigFromRegistry(HKEY_CURRENT_USER, MECH_KEY);
+ 	loadConfigFromRegistry(HKEY_LOCAL_MACHINE, MECH_KEY);
+ #else /* _WIN32 */
+-	char *fileName;
+-	struct stat fileInfo;
+-
+-	fileName = MECH_CONF;
+-
+-	/* check if mechList needs updating */
+-	if (stat(fileName, &fileInfo) != 0 ||
+-	    g_confFileModTime >= fileInfo.st_mtime)
+-		return;
+-	g_confFileModTime = fileInfo.st_mtime;
+-	loadConfigFile(fileName);
++	loadConfigFiles();
+ #endif /* !_WIN32 */
+ 
+ 	/* Load any unloaded interposer mechanisms immediately, to make sure we
+
+commit ac98187641f6943ae571606c0b6a97f236f9b60c
+Author: Greg Hudson <ghudson at mit.edu>
+Date:   Wed May 28 23:51:49 2014 -0400
+
+    Read /etc/gss/mech if no mech.d/*.conf found
+    
+    Always read /etc/gss/mech, even if globbing /etc/gss/mech.d/*.conf
+    doesn't work.  Doing this using GLOB_DOOFFS proved error-prone, so use
+    a simpler approach: factor out the per-pathname handling into a helper
+    function load_if_changed, call it with MECH_CONF before the glob, then
+    pass each glob result through the helper.
+    
+    ticket: 7925
+
+diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c
+index f0acf1a..8bce14c 100644
+--- a/src/lib/gssapi/mechglue/g_initialize.c
++++ b/src/lib/gssapi/mechglue/g_initialize.c
+@@ -402,38 +402,45 @@ check_link_mtime(const char *filename, time_t *mtime_out)
+ 	return (st1.st_mtime > st2.st_mtime) ? st1.st_mtime : st2.st_mtime;
+ }
+ 
++/* Load pathname if it is newer than last.  Update *highest to the maximum of
++ * its current value and pathname's mod time. */
++static void
++load_if_changed(const char *pathname, time_t last, time_t *highest)
++{
++	time_t mtime;
++
++	mtime = check_link_mtime(pathname, &mtime);
++	if (mtime == (time_t)-1)
++		return;
++	if (mtime > *highest)
++		*highest = mtime;
++	if (mtime > last)
++		loadConfigFile(pathname);
++}
++
+ /* Try to load any config files which have changed since the last call.  Config
+  * files are MECH_CONF and any files matching MECH_CONF_PATTERN. */
+ static void
+ loadConfigFiles()
+ {
+ 	glob_t globbuf;
+-	time_t highest_mtime = 0, mtime, now;
+-	char **pathptr;
++	time_t highest = 0, now;
++	char **path;
+ 
+ 	/* Don't glob and stat more than once per second. */
+ 	if (time(&now) == (time_t)-1 || now == g_confLastCall)
+ 		return;
+ 	g_confLastCall = now;
+ 
+-	globbuf.gl_offs = 1;
+-	if (glob(MECH_CONF_PATTERN, GLOB_DOOFFS, NULL, &globbuf) != 0)
+-		return;
+-	globbuf.gl_pathv[0] = MECH_CONF;
++	load_if_changed(MECH_CONF, g_confFileModTime, &highest);
+ 
+-	for (pathptr = globbuf.gl_pathv; *pathptr != NULL; pathptr++) {
+-		mtime = check_link_mtime(*pathptr, &mtime);
+-		if (mtime == (time_t)-1)
+-			continue;
+-		if (mtime > highest_mtime)
+-			highest_mtime = mtime;
+-		if (mtime > g_confFileModTime)
+-			loadConfigFile(*pathptr);
++	if (glob(MECH_CONF_PATTERN, 0, NULL, &globbuf) == 0) {
++		for (path = globbuf.gl_pathv; *path != NULL; path++)
++			load_if_changed(*path, g_confFileModTime, &highest);
++		globfree(&globbuf);
+ 	}
+-	g_confFileModTime = highest_mtime;
+ 
+-	globbuf.gl_pathv[0] = NULL;
+-	globfree(&globbuf);
++	g_confFileModTime = highest;
+ }
+ 
+ /*
+
+commit 41d38531043b99e8daa334f2b6ddf376adf1e878
+Author: Sam Hartman <hartmans at debian.org>
+Date:   Wed Jun 4 12:06:27 2014 -0400
+
+    Do not loop on add_cred_from and other new methods
+    
+    Several new GSS-API methods were added but GSSAPI_ADD_METHOD was
+    called to add them rather than GSSAPI_ADD_METHOD_NOLOOP.  This means
+    that the implementation from the GSS-API mechglue would be used if the
+    mechanism had no implementation.  As a result, the mechglue will call
+    into itself exhausting the call stack in an endless loop when one of
+    these methods is called.
+    
+    ticket: 7926
+    target_version: 1.12.2
+    tags: pullup
+
+diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c
+index 8bce14c..b0eb40a 100644
+--- a/src/lib/gssapi/mechglue/g_initialize.c
++++ b/src/lib/gssapi/mechglue/g_initialize.c
+@@ -703,11 +703,11 @@ build_dynamicMech(void *dl, const gss_OID mech_type)
+         GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_mech_for_saslname);
+         /* RFC 5587 */
+         GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_attrs_for_mech);
+-	GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_acquire_cred_from);
+-	GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_store_cred_into);
++	GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_acquire_cred_from);
++	GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_store_cred_into);
+ 	GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_acquire_cred_with_password);
+-	GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_export_cred);
+-	GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_import_cred);
++	GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_cred);
++	GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_import_cred);
+ 	GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_import_sec_context_by_mech);
+ 	GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_import_name_by_mech);
+ 	GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_import_cred_by_mech);
diff --git a/krb5.spec b/krb5.spec
index 04197f9..f6ad6af 100644
--- a/krb5.spec
+++ b/krb5.spec
@@ -41,7 +41,7 @@
 Summary: The Kerberos network authentication system
 Name: krb5
 Version: 1.12.1
-Release: 8%{?dist}
+Release: 9%{?dist}
 # Maybe we should explode from the now-available-to-everybody tarball instead?
 # http://web.mit.edu/kerberos/dist/krb5/1.12/krb5-1.12.1-signed.tar
 Source0: krb5-%{version}.tar.gz
@@ -103,6 +103,7 @@ Patch141: krb5-master-rcache-acquirecred-test.patch
 Patch142: krb5-master-move-otp-sockets.patch
 Patch143: krb5-master-spnego-preserve-oid.patch
 Patch144: krb5-1.12-tcl86.patch
+Patch145: krb5-master-mechd.patch
 Patch201: 0001-Don-t-try-to-stat-not-on-disk-ccache-residuals.patch
 Patch202: 0002-Use-an-in-memory-cache-until-we-need-the-target-s.patch
 Patch203: 0003-Learn-to-destroy-the-ccache-we-re-copying-from.patch
@@ -354,6 +355,7 @@ ln -s NOTICE LICENSE
 %patch142 -p1 -b .move-otp-sockets
 %patch143 -p1 -b .spnego-preserve-oid
 %patch144 -p1 -b .tcl86
+%patch145 -p1 -b .master-mechd
 
 # Take the execute bit off of documentation.
 chmod -x doc/krb5-protocol/*.txt doc/ccapi/*.html
@@ -542,6 +544,10 @@ install -pm 644 %{SOURCE6} $RPM_BUILD_ROOT/etc/krb5.conf
 # Parent of configuration file for list of loadable GSS mechs ("mechs").  This
 # location is not relative to sysconfdir, but is hard-coded in g_initialize.c.
 mkdir -m 755 -p $RPM_BUILD_ROOT/etc/gss
+# Parent of groups of configuration files for a list of loadable GSS mechs
+# ("mechs").  This location is not relative to sysconfdir, and is also
+# hard-coded in g_initialize.c.
+mkdir -m 755 -p $RPM_BUILD_ROOT/etc/gss/mech.d
 
 # If the default configuration needs to start specifying a default cache
 # location, add it now, then fixup the timestamp so that it looks the same.
@@ -929,8 +935,9 @@ exit 0
 %defattr(-,root,root,-)
 %doc README NOTICE LICENSE
 %docdir %{_mandir}
-# This is a hard-coded, not-dependent-on-the-configure-script path.
+# These are hard-coded, not-dependent-on-the-configure-script paths.
 %dir /etc/gss
+%dir /etc/gss/mech.d
 %verify(not md5 size mtime) %config(noreplace) /etc/krb5.conf
 /%{_mandir}/man5/.k5identity.5*
 /%{_mandir}/man5/.k5login.5*
@@ -1023,6 +1030,10 @@ exit 0
 %{_sbindir}/uuserver
 
 %changelog
+* Tue Jun 24 2014 Nalin Dahyabhai <nalin at redhat.com> - 1.12.1-9
+- pull in changes from upstream which add processing of the contents of
+  /etc/gss/mech.d/*.conf when loading GSS modules (#1102839)
+
 * Thu Jun 12 2014 Nalin Dahyabhai <nalin at redhat.com> - 1.12.1-8
 - pull in fix for building against tcl 8.6 (#1107061)
 


More information about the scm-commits mailing list