Currently we end up groveling around in /tmp, trying to guess what the credcache will be. Instead, just get the default ccname for the user, and then see if it has a valid tgt. If it doesn't then we try to use the keytab to init the credcache before proceeding. Signed-off-by: Jeff Layton <jlayton@xxxxxxxxx> --- cifs.upcall.c | 148 +++++++++++----------------------------------------------- 1 file changed, 27 insertions(+), 121 deletions(-) diff --git a/cifs.upcall.c b/cifs.upcall.c index e8544c2b68ad..d0f6d089d8e1 100644 --- a/cifs.upcall.c +++ b/cifs.upcall.c @@ -52,12 +52,6 @@ #include "spnego.h" #include "cifs_spnego.h" -#define CIFS_DEFAULT_KRB5_DIR "/tmp" -#define CIFS_DEFAULT_KRB5_USER_DIR "/run/user/%U" -#define CIFS_DEFAULT_KRB5_PREFIX "krb5cc" - -#define MAX_CCNAME_LEN PATH_MAX + 5 - static const char *prog = "cifs.upcall"; typedef enum _sectype { NONE = 0, @@ -178,13 +172,34 @@ err_cache: return credtime; } -static int krb5cc_filter(const struct dirent *dirent) +static char * +get_default_cc(void) { - /* subtract 1 for the null terminator */ - return !strncmp(dirent->d_name, CIFS_DEFAULT_KRB5_PREFIX, - sizeof(CIFS_DEFAULT_KRB5_PREFIX) - 1); + krb5_error_code ret; + const char *ccname; + char *rcc = NULL; + krb5_context context = NULL; + + ret = krb5_init_context(&context); + if (ret) { + syslog(LOG_DEBUG, "krb5_init_context: %d", (int)ret); + return NULL; + } + + ccname = krb5_cc_default_name(context); + if (!ccname) { + syslog(LOG_DEBUG, "krb5_cc_default returned NULL."); + goto out_free_context; + } + + if (get_tgt_time(ccname)) + rcc = strdup(ccname); +out_free_context: + krb5_free_context(context); + return rcc; } + static char * init_cc_from_keytab(const char *keytab_name, const char *user) { @@ -263,109 +278,6 @@ icfk_cleanup: return ccname; } -/* resolve a pattern to an actual directory path */ -static char *resolve_krb5_dir(const char *pattern, uid_t uid) -{ - char name[MAX_CCNAME_LEN]; - int i; - size_t j; - for (i = 0, j = 0; (pattern[i] != '\0') && (j < sizeof(name)); i++) { - switch (pattern[i]) { - case '%': - switch (pattern[i + 1]) { - case '%': - name[j++] = pattern[i]; - i++; - break; - case 'U': - j += snprintf(name + j, sizeof(name) - j, - "%lu", (unsigned long) uid); - i++; - break; - } - break; - default: - name[j++] = pattern[i]; - break; - } - } - if ((j > 0) && (j < sizeof(name))) - return strndup(name, MAX_CCNAME_LEN); - else - return NULL; -} - -/* search for a credcache that looks like a likely candidate */ -static char *find_krb5_cc(const char *dirname, uid_t uid, - char **best_cache, time_t *best_time) -{ - struct dirent **namelist; - struct stat sbuf; - char ccname[MAX_CCNAME_LEN], *credpath; - int i, n; - time_t cred_time; - - n = scandir(dirname, &namelist, krb5cc_filter, NULL); - if (n < 0) { - syslog(LOG_DEBUG, "%s: scandir error on directory '%s': %s", - __func__, dirname, strerror(errno)); - return NULL; - } - - for (i = 0; i < n; i++) { - snprintf(ccname, sizeof(ccname), "FILE:%s/%s", dirname, - namelist[i]->d_name); - credpath = ccname + 5; - syslog(LOG_DEBUG, "%s: considering %s", __func__, credpath); - - if (lstat(credpath, &sbuf)) { - syslog(LOG_DEBUG, "%s: stat error on '%s': %s", - __func__, credpath, strerror(errno)); - free(namelist[i]); - continue; - } - if (sbuf.st_uid != uid) { - syslog(LOG_DEBUG, "%s: %s is owned by %u, not %u", - __func__, credpath, sbuf.st_uid, uid); - free(namelist[i]); - continue; - } - if (S_ISDIR(sbuf.st_mode)) { - snprintf(ccname, sizeof(ccname), "DIR:%s/%s", dirname, - namelist[i]->d_name); - credpath = ccname + 4; - } else - if (!S_ISREG(sbuf.st_mode)) { - syslog(LOG_DEBUG, "%s: %s is not a regular file", - __func__, credpath); - free(namelist[i]); - continue; - } - if (!(cred_time = get_tgt_time(ccname))) { - syslog(LOG_DEBUG, "%s: %s is not a valid credcache.", - __func__, ccname); - free(namelist[i]); - continue; - } - - if (cred_time <= *best_time) { - syslog(LOG_DEBUG, "%s: %s expires sooner than current " - "best.", __func__, ccname); - free(namelist[i]); - continue; - } - - syslog(LOG_DEBUG, "%s: %s is valid ccache", __func__, ccname); - free(*best_cache); - *best_cache = strndup(ccname, MAX_CCNAME_LEN); - *best_time = cred_time; - free(namelist[i]); - } - free(namelist); - - return *best_cache; -} - static int cifs_krb5_get_req(const char *host, const char *ccname, DATA_BLOB * mechtoken, DATA_BLOB * sess_key) @@ -841,13 +753,12 @@ int main(const int argc, char *const argv[]) unsigned int have; long rc = 1; int c, try_dns = 0, legacy_uid = 0; - char *buf, *ccdir = NULL, *ccname = NULL, *best_cache = NULL; + char *buf, *ccname = NULL; char hostbuf[NI_MAXHOST], *host; struct decoded_args arg; const char *oid; uid_t uid; char *keytab_name = NULL; - time_t best_time = 0; hostbuf[0] = '\0'; memset(&arg, 0, sizeof(arg)); @@ -954,13 +865,8 @@ int main(const int argc, char *const argv[]) syslog(LOG_ERR, "setuid: %s", strerror(errno)); goto out; } - ccdir = resolve_krb5_dir(CIFS_DEFAULT_KRB5_USER_DIR, uid); - if (ccdir != NULL) - find_krb5_cc(ccdir, uid, &best_cache, &best_time); - ccname = find_krb5_cc(CIFS_DEFAULT_KRB5_DIR, uid, &best_cache, - &best_time); - SAFE_FREE(ccdir); + ccname = get_default_cc(); /* Couldn't find credcache? Try to use keytab */ if (ccname == NULL && arg.username != NULL) ccname = init_cc_from_keytab(keytab_name, arg.username); -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html