[PATCH] gssd: search multiple directories for credentials

J. Bruce Fields bfields at fieldses.org
Mon Mar 10 14:32:03 EDT 2008


On Mon, Mar 03, 2008 at 02:16:53PM -0800, Vince Busam wrote:
> On Thu, Feb 28, 2008 at 06:09:42PM -0500, J. Bruce Fields wrote:
> > On Wed, Feb 27, 2008 at 10:55:21AM -0800, Vince Busam wrote:
> > > Our setup involves keeping credential caches in multiple directories. 
> > 
> > Just out of curiosity--how do you find that useful?
> 
> We have different ccache files for different services, and need this to let
> gssd try all of them.

OK.  I'm not much of a Kerberos expert--maybe Kevin can comment--but it
seems to me like a reasonable thing to do.

> 
> > > This patch allows gssd to take a colon separated list of directories to 
> > > the -d argument to search through when looking for credentials.
> > > 
> > > http://sixpak.org/vince/google/gssd-search-credpaths.patch
> > 
> > Would it also be possible to add man page documentation for the new gssd
> > option?
> 
> Good idea

Some comments:

> --- nfs-utils-1.1.1/utils/gssd/gssd.c.orig	2008-02-26 10:58:07.000000000 -0800
> +++ nfs-utils-1.1.1/utils/gssd/gssd.c	2008-02-26 11:05:35.000000000 -0800
> @@ -57,6 +57,7 @@ char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_
>  char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
>  char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
>  char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR;
> +char *ccachesearch[GSSD_MAX_CCACHE_SEARCH];
>  int  use_memcache = 0;
>  int  root_uses_machine_creds = 1;
>  
> @@ -93,9 +94,12 @@ main(int argc, char *argv[])
>  	int verbosity = 0;
>  	int rpc_verbosity = 0;
>  	int opt;
> +	int i;
>  	extern char *optarg;
>  	char *progname;
> +	char *t;
>  
> +	memset(ccachesearch,0,sizeof(ccachesearch));

Style elsewhere in nfs-utils seems to follow kernel style, putting a
space after each of those commas.

>  	while ((opt = getopt(argc, argv, "fvrmnMp:k:d:")) != -1) {
>  		switch (opt) {
>  			case 'f':
> @@ -130,6 +134,13 @@ main(int argc, char *argv[])
>  				strncpy(ccachedir, optarg, sizeof(ccachedir));
>  				if (ccachedir[sizeof(ccachedir)-1] != '\0')
>  					errx(1, "ccachedir path name too long");
> +				i = 0;
> +				t = ccachedir;
> +				do {
> +					ccachesearch[i] = strtok(t,":");
> +					t = NULL;
> +					i++;
> +				} while (ccachesearch[i-1] && (i<GSSD_MAX_CCACHE_SEARCH));
>  				break;
>  			default:
>  				usage(argv[0]);
> --- nfs-utils-1.1.1/utils/gssd/gssd.h.orig	2008-02-26 10:58:09.000000000 -0800
> +++ nfs-utils-1.1.1/utils/gssd/gssd.h	2008-02-26 10:59:10.000000000 -0800
> @@ -50,6 +50,7 @@
>  #define GSSD_DEFAULT_KEYTAB_FILE		"/etc/krb5.keytab"
>  #define GSSD_SERVICE_NAME			"nfs"
>  #define GSSD_SERVICE_NAME_LEN			3
> +#define GSSD_MAX_CCACHE_SEARCH			16
>  
>  /*
>   * The gss mechanisms that we can handle
> @@ -62,6 +63,7 @@ extern char			pipefs_dir[PATH_MAX];
>  extern char			pipefs_nfsdir[PATH_MAX];
>  extern char			keytabfile[PATH_MAX];
>  extern char			ccachedir[PATH_MAX];
> +extern char			*ccachesearch[GSSD_MAX_CCACHE_SEARCH];
>  extern int			use_memcache;
>  extern int			root_uses_machine_creds;
>  
> --- nfs-utils-1.1.1/utils/gssd/gssd_proc.c.orig	2008-02-26 10:58:26.000000000 -0800
> +++ nfs-utils-1.1.1/utils/gssd/gssd_proc.c	2008-02-26 11:06:08.000000000 -0800
> @@ -691,10 +691,18 @@ handle_krb5_upcall(struct clnt_info *clp
>  
>  	if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0)) {
>  		/* Tell krb5 gss which credentials cache to use */
> -		gssd_setup_krb5_user_gss_ccache(uid, clp->servername);
> +		gssd_setup_krb5_user_gss_ccache(uid, clp->servername, ccachedir);

Didn't the strtok() calls mangle ccachedir?  What's its value here?

>  
>  		create_resp = create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
>  						     AUTHTYPE_KRB5);
> +		for (ccname = ccachesearch; ccname && *ccname; ccname++) {

Surely the "ccname" check is unnecessary?

Also, you seem to be counting on the last entry of ccachesearch[] always
being NULL, but it looks to me like the code that reads into the array
can assign a non-NULL value to ccachesearch[GSSD_MAX_CCACHE_SEARCH - 1].
Am I confused?

--b.

> +			gssd_setup_krb5_user_gss_ccache(uid, clp->servername, *ccname);
> +
> +			create_resp = create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
> +							     AUTHTYPE_KRB5);
> +			if (create_resp == 0)
> +				break;
> +		}
>  	}
>  	if (create_resp != 0) {
>  		if (uid == 0 && root_uses_machine_creds == 1) {
> --- nfs-utils-1.1.1/utils/gssd/krb5_util.c.orig	2008-02-26 10:56:45.000000000 -0800
> +++ nfs-utils-1.1.1/utils/gssd/krb5_util.c	2008-02-26 10:59:10.000000000 -0800
> @@ -137,7 +137,8 @@ krb5_enctype *krb5_enctypes = NULL;
>  /*==========================*/
>  
>  static int select_krb5_ccache(const struct dirent *d);
> -static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d);
> +static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d,
> +		char *directory);
>  static int gssd_get_single_krb5_cred(krb5_context context,
>  		krb5_keytab kt, struct gssd_k5_kt_princ *ple);
>  
> @@ -176,7 +177,7 @@ select_krb5_ccache(const struct dirent *
>   *	1 => found an existing entry
>   */
>  static int
> -gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d)
> +gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d, char *directory)
>  {
>  	struct dirent **namelist;
>  	int n;
> @@ -187,7 +188,7 @@ gssd_find_existing_krb5_ccache(uid_t uid
>  
>  	memset(&best_match_stat, 0, sizeof(best_match_stat));
>  	*d = NULL;
> -	n = scandir(ccachedir, &namelist, select_krb5_ccache, 0);
> +	n = scandir(directory, &namelist, select_krb5_ccache, 0);
>  	if (n < 0) {
>  		perror("scandir looking for krb5 credentials caches");
>  	}
> @@ -197,7 +198,7 @@ gssd_find_existing_krb5_ccache(uid_t uid
>  			printerr(3, "CC file '%s' being considered\n",
>  				 namelist[i]->d_name);
>  			snprintf(statname, sizeof(statname),
> -				 "%s/%s", ccachedir, namelist[i]->d_name);
> +				 "%s/%s", directory, namelist[i]->d_name);
>  			if (lstat(statname, &tmp_stat)) {
>  				printerr(0, "Error doing stat on file '%s'\n",
>  					 statname);
> @@ -896,7 +897,7 @@ parse_enctypes(char *enctypes)
>   *	void
>   */
>  void
> -gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername)
> +gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, char *directory)
>  {
>  	char			buf[MAX_NETOBJ_SZ];
>  	struct dirent		*d;
> @@ -904,14 +905,14 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui
>  	printerr(2, "getting credentials for client with uid %u for "
>  		    "server %s\n", uid, servername);
>  	memset(buf, 0, sizeof(buf));
> -	if (gssd_find_existing_krb5_ccache(uid, &d)) {
> +	if (gssd_find_existing_krb5_ccache(uid, &d, directory)) {
>  		snprintf(buf, sizeof(buf), "FILE:%s/%s",
> -			ccachedir, d->d_name);
> +			directory, d->d_name);
>  		free(d);
>  	}
>  	else
>  		snprintf(buf, sizeof(buf), "FILE:%s/%s%u",
> -			ccachedir, GSSD_DEFAULT_CRED_PREFIX, uid);
> +			directory, 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);
> --- nfs-utils-1.1.1/utils/gssd/krb5_util.h.orig	2008-02-26 10:58:49.000000000 -0800
> +++ nfs-utils-1.1.1/utils/gssd/krb5_util.h	2008-02-26 10:59:10.000000000 -0800
> @@ -17,7 +17,8 @@ struct gssd_k5_kt_princ {
>  };
>  
>  
> -void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername);
> +void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername,
> +                                     char *directory);
>  int  gssd_get_krb5_machine_cred_list(char ***list);
>  void gssd_free_krb5_machine_cred_list(char **list);
>  void gssd_setup_krb5_machine_gss_ccache(char *servername);
> --- nfs-utils-1.1.1/utils/gssd/gssd.man.orig	2008-03-03 13:55:26.000000000 -0800
> +++ nfs-utils-1.1.1/utils/gssd/gssd.man	2008-03-03 13:56:21.000000000 -0800
> @@ -75,6 +75,8 @@ where to look for the rpc_pipefs filesys
>  Tells
>  .B rpc.gssd
>  where to look for kerberos credential files.  The default value is "/tmp".
> +This can also be a colon separated list of directories to search through
> +for a kerberos credential file.
>  .TP
>  .B -v
>  Increases the verbosity of the output (can be specified multiple times).


More information about the NFSv4 mailing list