commit 123c14fd8862ee8f11f6084d25958cb380655f35 Author: Günther Deschner 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@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 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@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 #include #include +#include #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 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 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);