]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/gssd/krb5_util.c
Use lstat rather than stat in gssd_find_existing_krb5_ccache
[nfs-utils.git] / utils / gssd / krb5_util.c
index 353a93ee258763e65fd51fdbc2f7dd724aaf93f1..6af286975c445f01c38904fc3c64b9248d784632 100644 (file)
@@ -158,7 +158,7 @@ select_krb5_ccache(const struct dirent *d)
 }
 
 /*
- * 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.
@@ -178,78 +178,73 @@ gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d)
        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);
        }
@@ -280,26 +275,29 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
 {
        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;
@@ -330,6 +328,7 @@ gssd_get_single_krb5_cred(krb5_context context,
        char cc_name[BUFSIZ];
        int code;
        time_t now = time(0);
+       char *cache_type;
 
        memset(&my_creds, 0, sizeof(my_creds));
 
@@ -376,7 +375,12 @@ gssd_get_single_krb5_cred(krb5_context context,
         * 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;
@@ -628,13 +632,12 @@ gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername)
        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);