#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
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) {
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]);
}
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
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));
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)