diff options
author | Nalin Dahyabhai <nalin@redhat.com> | 2012-08-23 11:14:56 -0400 |
---|---|---|
committer | Jeff Layton <jlayton@samba.org> | 2012-08-23 07:46:37 -0400 |
commit | ca0894e40480a9115c6bad670149b075646ead2c (patch) | |
tree | 2f8f50a0fa292fbfd62750b3aa1d443bd6ce881b | |
parent | d006986221b7f1aad50e894851dc573650b7611c (diff) | |
download | cifs-utils-ca0894e40480a9115c6bad670149b075646ead2c.tar.gz cifs-utils-ca0894e40480a9115c6bad670149b075646ead2c.tar.bz2 cifs-utils-ca0894e40480a9115c6bad670149b075646ead2c.zip |
cifs.upcall: scan /run/user/${UID} for ccaches, too
When scanning for credential caches, check the user's directory under
/run/user first, then fall back to /tmp as we have previously. Because
we now call find_krb5_cc() twice (once for each directory), we move its
state to be outside of the function. We also add a substitution
mechanism to make the process of resolving the location of the user's
home directory before searching it a bit more explicable.
-rw-r--r-- | cifs.upcall.c | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/cifs.upcall.c b/cifs.upcall.c index 6f95c1c..598a999 100644 --- a/cifs.upcall.c +++ b/cifs.upcall.c @@ -53,7 +53,8 @@ #include "cifs_spnego.h" #define CIFS_DEFAULT_KRB5_DIR "/tmp" -#define CIFS_DEFAULT_KRB5_PREFIX "krb5cc_" +#define CIFS_DEFAULT_KRB5_USER_DIR "/run/user/%U" +#define CIFS_DEFAULT_KRB5_PREFIX "krb5cc" #define CIFS_DEFAULT_KRB5_KEYTAB "/etc/krb5.keytab" #define MAX_CCNAME_LEN PATH_MAX + 5 @@ -258,14 +259,47 @@ 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) +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, *best_cache = NULL; + char ccname[MAX_CCNAME_LEN], *credpath; int i, n; - time_t cred_time, best_time = 0; + time_t cred_time; n = scandir(dirname, &namelist, krb5cc_filter, NULL); if (n < 0) { @@ -310,7 +344,7 @@ static char *find_krb5_cc(const char *dirname, uid_t uid) continue; } - if (cred_time <= best_time) { + if (cred_time <= *best_time) { syslog(LOG_DEBUG, "%s: %s expires sooner than current " "best.", __func__, ccname); free(namelist[i]); @@ -318,14 +352,14 @@ static char *find_krb5_cc(const char *dirname, uid_t uid) } 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(*best_cache); + *best_cache = strndup(ccname, MAX_CCNAME_LEN); + *best_time = cred_time; free(namelist[i]); } free(namelist); - return best_cache; + return *best_cache; } static int @@ -793,12 +827,13 @@ int main(const int argc, char *const argv[]) unsigned int have; long rc = 1; int c, try_dns = 0, legacy_uid = 0; - char *buf, *ccname = NULL; + char *buf, *ccdir = NULL, *ccname = NULL, *best_cache = NULL; char hostbuf[NI_MAXHOST], *host; struct decoded_args arg; const char *oid; uid_t uid; char *keytab_name = CIFS_DEFAULT_KRB5_KEYTAB; + time_t best_time = 0; hostbuf[0] = '\0'; memset(&arg, 0, sizeof(arg)); @@ -901,7 +936,12 @@ int main(const int argc, char *const argv[]) syslog(LOG_ERR, "setuid: %s", strerror(errno)); goto out; } - ccname = find_krb5_cc(CIFS_DEFAULT_KRB5_DIR, uid); + 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); /* Couldn't find credcache? Try to use keytab */ if (ccname == NULL && arg.username != NULL) |