walters / rpms / nfs-utils

Forked from rpms/nfs-utils 6 years ago
Clone
85ed8ab
commit 25cd5f9101b8969f9e1f9d7d486f11c215d0eeb4
85ed8ab
Author: Vince Busam <vbusam@google.com>
85ed8ab
Date:   Wed May 7 15:24:53 2008 -0400
85ed8ab
85ed8ab
    Kerberos credentials may be stored in multiple places.  Make it
85ed8ab
    possible to search several directories for valid credentials when
85ed8ab
    making NFS requests.
85ed8ab
    
85ed8ab
    Original patch from Vince Busam <vbusam@google.com>
85ed8ab
    
85ed8ab
    Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>.
85ed8ab
    Signed-off-by: Steve Dickson <steved@redhat.com>
85ed8ab
85ed8ab
diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
85ed8ab
index bbcad20..e8612a5 100644
85ed8ab
--- a/utils/gssd/gssd.c
85ed8ab
+++ b/utils/gssd/gssd.c
85ed8ab
@@ -57,6 +57,7 @@ char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
85ed8ab
 char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
85ed8ab
 char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
85ed8ab
 char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR;
85ed8ab
+char *ccachesearch[GSSD_MAX_CCACHE_SEARCH + 1];
85ed8ab
 int  use_memcache = 0;
85ed8ab
 int  root_uses_machine_creds = 1;
85ed8ab
 
85ed8ab
@@ -93,9 +94,11 @@ main(int argc, char *argv[])
85ed8ab
 	int verbosity = 0;
85ed8ab
 	int rpc_verbosity = 0;
85ed8ab
 	int opt;
85ed8ab
+	int i;
85ed8ab
 	extern char *optarg;
85ed8ab
 	char *progname;
85ed8ab
 
85ed8ab
+	memset(ccachesearch, 0, sizeof(ccachesearch));
85ed8ab
 	while ((opt = getopt(argc, argv, "fvrmnMp:k:d:")) != -1) {
85ed8ab
 		switch (opt) {
85ed8ab
 			case 'f':
85ed8ab
@@ -136,6 +139,13 @@ main(int argc, char *argv[])
85ed8ab
 				break;
85ed8ab
 		}
85ed8ab
 	}
85ed8ab
+
85ed8ab
+	i = 0;
85ed8ab
+	ccachesearch[i++] = strtok(ccachedir, ":");
85ed8ab
+	do {
85ed8ab
+		ccachesearch[i++] = strtok(NULL, ":");
85ed8ab
+	} while (ccachesearch[i-1] != NULL && i < GSSD_MAX_CCACHE_SEARCH);
85ed8ab
+
85ed8ab
 	snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s",
85ed8ab
 		 pipefs_dir, GSSD_SERVICE_NAME);
85ed8ab
 	if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0')
85ed8ab
diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h
85ed8ab
index 6f14c34..0f9f428 100644
85ed8ab
--- a/utils/gssd/gssd.h
85ed8ab
+++ b/utils/gssd/gssd.h
85ed8ab
@@ -50,6 +50,7 @@
85ed8ab
 #define GSSD_DEFAULT_KEYTAB_FILE		"/etc/krb5.keytab"
85ed8ab
 #define GSSD_SERVICE_NAME			"nfs"
85ed8ab
 #define GSSD_SERVICE_NAME_LEN			3
85ed8ab
+#define GSSD_MAX_CCACHE_SEARCH			16
85ed8ab
 
85ed8ab
 /*
85ed8ab
  * The gss mechanisms that we can handle
85ed8ab
@@ -61,7 +62,7 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUTHTYPE_LIPKEY};
85ed8ab
 extern char			pipefs_dir[PATH_MAX];
85ed8ab
 extern char			pipefs_nfsdir[PATH_MAX];
85ed8ab
 extern char			keytabfile[PATH_MAX];
85ed8ab
-extern char			ccachedir[PATH_MAX];
85ed8ab
+extern char			*ccachesearch[];
85ed8ab
 extern int			use_memcache;
85ed8ab
 extern int			root_uses_machine_creds;
85ed8ab
 
85ed8ab
diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
85ed8ab
index 2fa749e..8fa4f4a 100644
85ed8ab
--- a/utils/gssd/gssd.man
85ed8ab
+++ b/utils/gssd/gssd.man
85ed8ab
@@ -74,7 +74,11 @@ where to look for the rpc_pipefs filesystem.  The default value is
85ed8ab
 .B -d directory
85ed8ab
 Tells
85ed8ab
 .B rpc.gssd
85ed8ab
-where to look for kerberos credential files.  The default value is "/tmp".
85ed8ab
+where to look for Kerberos credential files.  The default value is "/tmp".
85ed8ab
+This can also be a colon separated list of directories to be searched
85ed8ab
+for Kerberos credential files.  Note that if machine credentials are being
85ed8ab
+stored in files, then the first directory on this list is where the
85ed8ab
+machine credentials are stored.
85ed8ab
 .TP
85ed8ab
 .B -v
85ed8ab
 Increases the verbosity of the output (can be specified multiple times).
85ed8ab
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
85ed8ab
index bac7295..be6f440 100644
85ed8ab
--- a/utils/gssd/gssd_proc.c
85ed8ab
+++ b/utils/gssd/gssd_proc.c
85ed8ab
@@ -685,6 +685,7 @@ handle_krb5_upcall(struct clnt_info *clp)
85ed8ab
 	gss_buffer_desc		token;
85ed8ab
 	char			**credlist = NULL;
85ed8ab
 	char			**ccname;
85ed8ab
+	char			**dirname;
85ed8ab
 	int			create_resp = -1;
85ed8ab
 
85ed8ab
 	printerr(1, "handling krb5 upcall\n");
85ed8ab
@@ -701,10 +702,14 @@ handle_krb5_upcall(struct clnt_info *clp)
85ed8ab
 
85ed8ab
 	if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0)) {
85ed8ab
 		/* Tell krb5 gss which credentials cache to use */
85ed8ab
-		gssd_setup_krb5_user_gss_ccache(uid, clp->servername);
85ed8ab
+		for (dirname = ccachesearch; *dirname != NULL; dirname++) {
85ed8ab
+			gssd_setup_krb5_user_gss_ccache(uid, clp->servername, *dirname);
85ed8ab
 
85ed8ab
-		create_resp = create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
85ed8ab
-						     AUTHTYPE_KRB5);
85ed8ab
+			create_resp = create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
85ed8ab
+							     AUTHTYPE_KRB5);
85ed8ab
+			if (create_resp == 0)
85ed8ab
+				break;
85ed8ab
+		}
85ed8ab
 	}
85ed8ab
 	if (create_resp != 0) {
85ed8ab
 		if (uid == 0 && root_uses_machine_creds == 1) {
85ed8ab
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
85ed8ab
index 0589cd8..512c1cf 100644
85ed8ab
--- a/utils/gssd/krb5_util.c
85ed8ab
+++ b/utils/gssd/krb5_util.c
85ed8ab
@@ -131,7 +131,8 @@ struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
85ed8ab
 /*==========================*/
85ed8ab
 
85ed8ab
 static int select_krb5_ccache(const struct dirent *d);
85ed8ab
-static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d);
85ed8ab
+static int gssd_find_existing_krb5_ccache(uid_t uid, char *dirname,
85ed8ab
+		struct dirent **d);
85ed8ab
 static int gssd_get_single_krb5_cred(krb5_context context,
85ed8ab
 		krb5_keytab kt, struct gssd_k5_kt_princ *ple);
85ed8ab
 
85ed8ab
@@ -159,7 +160,7 @@ select_krb5_ccache(const struct dirent *d)
85ed8ab
 }
85ed8ab
 
85ed8ab
 /*
85ed8ab
- * Look in the ccachedir for files that look like they
85ed8ab
+ * Look in directory "dirname" for files that look like they
85ed8ab
  * are Kerberos Credential Cache files for a given UID.  Return
85ed8ab
  * non-zero and the dirent pointer for the entry most likely to be
85ed8ab
  * what we want. Otherwise, return zero and no dirent pointer.
85ed8ab
@@ -170,7 +171,7 @@ select_krb5_ccache(const struct dirent *d)
85ed8ab
  *	1 => found an existing entry
85ed8ab
  */
85ed8ab
 static int
85ed8ab
-gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d)
85ed8ab
+gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, struct dirent **d)
85ed8ab
 {
85ed8ab
 	struct dirent **namelist;
85ed8ab
 	int n;
85ed8ab
@@ -181,9 +182,10 @@ gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d)
85ed8ab
 
85ed8ab
 	memset(&best_match_stat, 0, sizeof(best_match_stat));
85ed8ab
 	*d = NULL;
85ed8ab
-	n = scandir(ccachedir, &namelist, select_krb5_ccache, 0);
85ed8ab
+	n = scandir(dirname, &namelist, select_krb5_ccache, 0);
85ed8ab
 	if (n < 0) {
85ed8ab
-		perror("scandir looking for krb5 credentials caches");
85ed8ab
+		printerr(1, "Error doing scandir on directory '%s': %s\n",
85ed8ab
+			dirname, strerror(errno));
85ed8ab
 	}
85ed8ab
 	else if (n > 0) {
85ed8ab
 		char statname[1024];
85ed8ab
@@ -191,7 +193,7 @@ gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d)
85ed8ab
 			printerr(3, "CC file '%s' being considered\n",
85ed8ab
 				 namelist[i]->d_name);
85ed8ab
 			snprintf(statname, sizeof(statname),
85ed8ab
-				 "%s/%s", ccachedir, namelist[i]->d_name);
85ed8ab
+				 "%s/%s", dirname, namelist[i]->d_name);
85ed8ab
 			if (lstat(statname, &tmp_stat)) {
85ed8ab
 				printerr(0, "Error doing stat on file '%s'\n",
85ed8ab
 					 statname);
85ed8ab
@@ -291,8 +293,9 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
85ed8ab
 				    &credh, NULL, NULL);
85ed8ab
 
85ed8ab
 	if (maj_stat != GSS_S_COMPLETE) {
85ed8ab
-		pgsserr("gss_acquire_cred",
85ed8ab
-			maj_stat, min_stat, &krb5oid);
85ed8ab
+		if (get_verbosity() > 0)
85ed8ab
+			pgsserr("gss_acquire_cred",
85ed8ab
+				maj_stat, min_stat, &krb5oid);
85ed8ab
 		return -1;
85ed8ab
 	}
85ed8ab
 
85ed8ab
@@ -406,7 +409,7 @@ gssd_get_single_krb5_cred(krb5_context context,
85ed8ab
 	    cache_type = "FILE";
85ed8ab
 	snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s",
85ed8ab
 		cache_type,
85ed8ab
-		ccachedir, GSSD_DEFAULT_CRED_PREFIX,
85ed8ab
+		ccachesearch[0], GSSD_DEFAULT_CRED_PREFIX,
85ed8ab
 		GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm);
85ed8ab
 	ple->endtime = my_creds.times.endtime;
85ed8ab
 	if (ple->ccname != NULL)
85ed8ab
@@ -894,7 +897,7 @@ out:
85ed8ab
  *	void
85ed8ab
  */
85ed8ab
 void
85ed8ab
-gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername)
85ed8ab
+gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, char *dirname)
85ed8ab
 {
85ed8ab
 	char			buf[MAX_NETOBJ_SZ];
85ed8ab
 	struct dirent		*d;
85ed8ab
@@ -902,14 +905,13 @@ gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername)
85ed8ab
 	printerr(2, "getting credentials for client with uid %u for "
85ed8ab
 		    "server %s\n", uid, servername);
85ed8ab
 	memset(buf, 0, sizeof(buf));
85ed8ab
-	if (gssd_find_existing_krb5_ccache(uid, &d)) {
85ed8ab
-		snprintf(buf, sizeof(buf), "FILE:%s/%s",
85ed8ab
-			ccachedir, d->d_name);
85ed8ab
+	if (gssd_find_existing_krb5_ccache(uid, dirname, &d)) {
85ed8ab
+		snprintf(buf, sizeof(buf), "FILE:%s/%s", dirname, d->d_name);
85ed8ab
 		free(d);
85ed8ab
 	}
85ed8ab
 	else
85ed8ab
 		snprintf(buf, sizeof(buf), "FILE:%s/%s%u",
85ed8ab
-			ccachedir, GSSD_DEFAULT_CRED_PREFIX, uid);
85ed8ab
+			dirname, GSSD_DEFAULT_CRED_PREFIX, uid);
85ed8ab
 	printerr(2, "using %s as credentials cache for client with "
85ed8ab
 		    "uid %u for server %s\n", buf, uid, servername);
85ed8ab
 	gssd_set_krb5_ccache_name(buf);
85ed8ab
diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
85ed8ab
index 78ad45c..431fdaf 100644
85ed8ab
--- a/utils/gssd/krb5_util.h
85ed8ab
+++ b/utils/gssd/krb5_util.h
85ed8ab
@@ -17,7 +17,8 @@ struct gssd_k5_kt_princ {
85ed8ab
 };
85ed8ab
 
85ed8ab
 
85ed8ab
-void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername);
85ed8ab
+void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername,
85ed8ab
+				     char *dirname);
85ed8ab
 int  gssd_get_krb5_machine_cred_list(char ***list);
85ed8ab
 void gssd_free_krb5_machine_cred_list(char **list);
85ed8ab
 void gssd_setup_krb5_machine_gss_ccache(char *servername);