static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d);
static int gssd_get_single_krb5_cred(krb5_context context,
krb5_keytab kt, struct gssd_k5_kt_princ *ple);
-static int gssd_have_realm_ple(krb5_data *realm);
+static int gssd_have_realm_ple(void *realm);
static int gssd_process_krb5_keytab(krb5_context context, krb5_keytab kt,
char *kt_name);
}
/*
- * Look in the GSSD_DEFAULT_CRED_DIR for files that look like they
+ * Look in the ccachedir for files that look like they
* are Kerberos Credential Cache files for a given UID. Return
* non-zero and the dirent pointer for the entry most likely to be
* what we want. Otherwise, return zero and no dirent pointer.
struct dirent *best_match_dir = NULL;
struct stat best_match_stat, tmp_stat;
+ memset(&best_match_stat, 0, sizeof(best_match_stat));
*d = NULL;
- n = scandir(GSSD_DEFAULT_CRED_DIR, &namelist, select_krb5_ccache, 0);
+ n = scandir(ccachedir, &namelist, select_krb5_ccache, 0);
if (n < 0) {
perror("scandir looking for krb5 credentials caches");
}
else if (n > 0) {
- char substring[128];
- char fullstring[128];
char statname[1024];
- snprintf(substring, sizeof(substring), "_%d_", uid);
- snprintf(fullstring, sizeof(fullstring), "_%d", uid);
for (i = 0; i < n; i++) {
printerr(3, "CC file '%s' being considered\n",
namelist[i]->d_name);
- if (strstr(namelist[i]->d_name, substring) ||
- !strcmp(namelist[i]->d_name, fullstring)) {
- snprintf(statname, sizeof(statname),
- "%s/%s", GSSD_DEFAULT_CRED_DIR,
- namelist[i]->d_name);
- if (stat(statname, &tmp_stat)) {
- printerr(0, "Error doing stat "
- "on file '%s'\n",
- statname);
- continue;
- }
- if (!S_ISREG(tmp_stat.st_mode)) {
- printerr(3, "File '%s' is not "
- "a regular file\n",
- statname);
- continue;
- }
- printerr(3, "CC file '%s' matches "
- "name check and has "
- "mtime of %u\n",
- namelist[i]->d_name,
- tmp_stat.st_mtime);
- /* if more than one match is found,
- * return the most recent (the one
- * with the latest mtime),
- * and don't free the dirent */
- if (!found) {
+ snprintf(statname, sizeof(statname),
+ "%s/%s", ccachedir, namelist[i]->d_name);
+ if (lstat(statname, &tmp_stat)) {
+ printerr(0, "Error doing stat on file '%s'\n",
+ statname);
+ free(namelist[i]);
+ continue;
+ }
+ /* Only pick caches owned by the user (uid) */
+ if (tmp_stat.st_uid != uid) {
+ printerr(3, "'%s' owned by %u, not %u\n",
+ statname, tmp_stat.st_uid, uid);
+ free(namelist[i]);
+ continue;
+ }
+ if (!S_ISREG(tmp_stat.st_mode)) {
+ printerr(3, "'%s' is not a regular file\n",
+ statname);
+ free(namelist[i]);
+ continue;
+ }
+ printerr(3, "CC file '%s' matches owner check and has "
+ "mtime of %u\n",
+ namelist[i]->d_name, tmp_stat.st_mtime);
+ /*
+ * if more than one match is found, return the most
+ * recent (the one with the latest mtime), and
+ * don't free the dirent
+ */
+ if (!found) {
+ best_match_dir = namelist[i];
+ best_match_stat = tmp_stat;
+ found++;
+ }
+ else {
+ /*
+ * If the current match has an mtime later
+ * than the one we are looking at, then use
+ * the current match. Otherwise, we still
+ * have the best match.
+ */
+ if (tmp_stat.st_mtime >
+ best_match_stat.st_mtime) {
+ free(best_match_dir);
best_match_dir = namelist[i];
best_match_stat = tmp_stat;
- found++;
}
else {
- /*
- * If the current match has
- * an mtime later than the
- * one we are looking at,
- * then use the current match.
- * Otherwise, we still have
- * the best match.
- */
- if (tmp_stat.st_mtime >
- best_match_stat.st_mtime) {
- free(best_match_dir);
- best_match_dir = namelist[i];
- best_match_stat = tmp_stat;
- }
- else {
- free(namelist[i]);
- }
- printerr(3, "CC file '%s' is our "
- "current best match "
- "with mtime of %u\n",
- best_match_dir->d_name,
- best_match_stat.st_mtime);
+ free(namelist[i]);
}
+ printerr(3, "CC file '%s' is our "
+ "current best match "
+ "with mtime of %u\n",
+ best_match_dir->d_name,
+ best_match_stat.st_mtime);
}
- else
- free(namelist[i]);
}
free(namelist);
}
{
u_int maj_stat, min_stat;
gss_cred_id_t credh;
+ gss_OID_set_desc desired_mechs;
krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC };
int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
+ /* We only care about getting a krb5 cred */
+ desired_mechs.count = 1;
+ desired_mechs.elements = &krb5oid;
+
maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
- GSS_C_NULL_OID_SET, GSS_C_INITIATE,
+ &desired_mechs, GSS_C_INITIATE,
&credh, NULL, NULL);
if (maj_stat != GSS_S_COMPLETE) {
- printerr(0, "WARNING: error from gss_acquire_cred "
- "for user with uid %d (%s)\n",
- uid, error_message(min_stat));
+ pgsserr("gss_acquire_cred",
+ maj_stat, min_stat, &krb5oid);
return -1;
}
maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
num_enctypes, &enctypes);
if (maj_stat != GSS_S_COMPLETE) {
- printerr(0, "WARNING: error from gss_set_allowable_enctypes "
- "for user with uid %d (%s)\n",
- uid, error_message(min_stat));
+ pgsserr("gss_set_allowable_enctypes",
+ maj_stat, min_stat, &krb5oid);
return -1;
}
sec->cred = credh;
char cc_name[BUFSIZ];
int code;
time_t now = time(0);
+ char *cache_type;
memset(&my_creds, 0, sizeof(my_creds));
krb5_get_init_creds_opt_set_tkt_life(&options, 5*60);
#endif
if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
- kt, 0, 0, &options))) {
+ kt, 0, NULL, &options))) {
char *pname;
if ((krb5_unparse_name(context, ple->princ, &pname))) {
pname = NULL;
"principal '%s' from keytab '%s'\n",
error_message(code),
pname ? pname : "<unparsable>", kt_name);
+#ifdef HAVE_KRB5
if (pname) krb5_free_unparsed_name(context, pname);
+#else
+ if (pname) free(pname);
+#endif
goto out;
}
* Initialize cache file which we're going to be using
*/
- snprintf(cc_name, sizeof(cc_name), "FILE:%s/%s%s_%s",
+ if (use_memcache)
+ cache_type = "MEMORY";
+ else
+ cache_type = "FILE";
+ snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s",
+ cache_type,
GSSD_DEFAULT_CRED_DIR, GSSD_DEFAULT_CRED_PREFIX,
GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm);
ple->endtime = my_creds.times.endtime;
* 1 => found ple for given realm
*/
static int
-gssd_have_realm_ple(krb5_data *realm)
+gssd_have_realm_ple(void *r)
{
struct gssd_k5_kt_princ *ple;
+#ifdef HAVE_KRB5
+ krb5_data *realm = (krb5_data *)r;
+#else
+ char *realm = (char *)r;
+#endif
for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
+#ifdef HAVE_KRB5
if ((realm->length == strlen(ple->realm)) &&
(strncmp(realm->data, ple->realm, realm->length) == 0)) {
+#else
+ if (strcmp(realm, ple->realm) == 0) {
+#endif
return 1;
}
}
/*
* Process the given keytab file and create a list of principals we
- * might use to perform mount operations.
+ * might use as machine credentials.
*
* Returns:
* 0 => Sucess
/*
* Look through each entry in the keytab file and determine
- * if we might want to use it later to do a mount. If so,
- * save info in the global principal list
- * (gssd_k5_kt_princ_list).
+ * if we might want to use it as machine credentials. If so,
+ * save info in the global principal list (gssd_k5_kt_princ_list).
* Note: (ple == principal list entry)
*/
if ((code = krb5_kt_start_seq_get(context, kt, &cursor))) {
printerr(0, "WARNING: Skipping keytab entry because "
"we failed to unparse principal name: %s\n",
error_message(code));
+ krb5_kt_free_entry(context, &kte);
continue;
}
printerr(2, "Processing keytab entry for principal '%s'\n",
pname);
- if ( (kte.principal->data[0].length == GSSD_SERVICE_NAME_LEN) &&
- (strncmp(kte.principal->data[0].data, GSSD_SERVICE_NAME,
- GSSD_SERVICE_NAME_LEN) == 0) &&
- (!gssd_have_realm_ple(&kte.principal->realm)) ) {
- printerr(2, "We will use this entry (%s)\n", pname);
+ /* Just use the first keytab entry found for each realm */
+ if ((!gssd_have_realm_ple((void *)&kte.principal->realm)) ) {
+ printerr(2, "We WILL use this entry (%s)\n", pname);
ple = malloc(sizeof(struct gssd_k5_kt_princ));
if (ple == NULL) {
printerr(0, "ERROR: could not allocate storage "
"for principal list entry\n");
+#ifdef HAVE_KRB5
krb5_free_unparsed_name(context, pname);
+#else
+ free(pname);
+#endif
+ krb5_kt_free_entry(context, &kte);
retval = ENOMEM;
goto out;
}
ple->ccname = NULL;
ple->endtime = 0;
if ((ple->realm =
+#ifdef HAVE_KRB5
strndup(kte.principal->realm.data,
kte.principal->realm.length))
+#else
+ strdup(kte.principal->realm))
+#endif
== NULL) {
printerr(0, "ERROR: %s while copying realm to "
"principal list entry\n",
"not enough memory");
+#ifdef HAVE_KRB5
krb5_free_unparsed_name(context, pname);
+#else
+ free(pname);
+#endif
+ krb5_kt_free_entry(context, &kte);
retval = ENOMEM;
goto out;
}
printerr(0, "ERROR: %s while copying principal "
"to principal list entry\n",
error_message(code));
+#ifdef HAVE_KRB5
krb5_free_unparsed_name(context, pname);
+#else
+ free(pname);
+#endif
+ krb5_kt_free_entry(context, &kte);
retval = code;
goto out;
}
printerr(2, "We will NOT use this entry (%s)\n",
pname);
}
+#ifdef HAVE_KRB5
krb5_free_unparsed_name(context, pname);
+#else
+ free(pname);
+#endif
+ krb5_kt_free_entry(context, &kte);
}
if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) {
memset(buf, 0, sizeof(buf));
if (gssd_find_existing_krb5_ccache(uid, &d)) {
snprintf(buf, sizeof(buf), "FILE:%s/%s",
- GSSD_DEFAULT_CRED_DIR, d->d_name);
+ ccachedir, d->d_name);
free(d);
}
else
snprintf(buf, sizeof(buf), "FILE:%s/%s%u",
- GSSD_DEFAULT_CRED_DIR,
- GSSD_DEFAULT_CRED_PREFIX, uid);
+ ccachedir, GSSD_DEFAULT_CRED_PREFIX, uid);
printerr(2, "using %s as credentials cache for client with "
"uid %u for server %s\n", buf, uid, servername);
gssd_set_krb5_ccache_name(buf);