Re: [PATCH 3/7] gssd: add support for callback authentication

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Apr 29, 2009 at 05:56:26PM -0400, Kevin Coffman wrote:
> From: Olga Kornievskaia <aglo@xxxxxxxxxxxxxx>
> 
> Add support for handling upcalls on the new "nfsd4_cb" directory pipes.
> Only new kernels (2.6.29) have support for this new pipe directory.
> (The need for this new pipe directory will go away with NFSv4.1 where
> the callback can be done on the same connection as the fore-channel.)

My only complaint is that the code would be robust (and more
future-proof) if instead of specifically looking for "nfs" and
"nfsd4_cb", we just look at all top-level rpc_pipefs directories and
handed directories under any of them in the same way.

--b.

> 
> Signed-off-by: Olga Kornievskaia <aglo@xxxxxxxxxxxxxx>
> Signed-off-by: Kevin Coffman <kwc@xxxxxxxxxxxxxx>
> ---
> 
>  utils/gssd/gssd.c           |    5 +++
>  utils/gssd/gssd.h           |    2 +
>  utils/gssd/gssd_main_loop.c |   18 ++++++++++-
>  utils/gssd/gssd_proc.c      |   73 +++++++++++++++++++++++++++++--------------
>  4 files changed, 74 insertions(+), 24 deletions(-)
> 
> diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
> index f6949db..7a23362 100644
> --- a/utils/gssd/gssd.c
> +++ b/utils/gssd/gssd.c
> @@ -57,6 +57,7 @@
>  
>  char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
>  char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
> +char pipefs_nfscbdir[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 + 1];
> @@ -163,6 +164,10 @@ main(int argc, char *argv[])
>  		 pipefs_dir, GSSD_SERVICE_NAME);
>  	if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0')
>  		errx(1, "pipefs_nfsdir path name too long");
> +	snprintf(pipefs_nfscbdir, sizeof(pipefs_nfscbdir), "%s/%s",
> +		 pipefs_dir, GSSD_NFSCB_NAME);
> +	if (pipefs_nfscbdir[sizeof(pipefs_nfscbdir)-1] != '\0')
> +		errx(1, "pipefs_nfscbdir path name too long");
>  
>  	if ((progname = strrchr(argv[0], '/')))
>  		progname++;
> diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h
> index 3c52f46..ef2ac54 100644
> --- a/utils/gssd/gssd.h
> +++ b/utils/gssd/gssd.h
> @@ -49,6 +49,7 @@
>  #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX	"machine"
>  #define GSSD_DEFAULT_KEYTAB_FILE		"/etc/krb5.keytab"
>  #define GSSD_SERVICE_NAME			"nfs"
> +#define GSSD_NFSCB_NAME				"nfsd4_cb"
>  #define GSSD_SERVICE_NAME_LEN			3
>  #define GSSD_MAX_CCACHE_SEARCH			16
>  
> @@ -61,6 +62,7 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUTHTYPE_LIPKEY};
>  
>  extern char			pipefs_dir[PATH_MAX];
>  extern char			pipefs_nfsdir[PATH_MAX];
> +extern char			pipefs_nfscbdir[PATH_MAX];
>  extern char			keytabfile[PATH_MAX];
>  extern char			*ccachesearch[];
>  extern int			use_memcache;
> diff --git a/utils/gssd/gssd_main_loop.c b/utils/gssd/gssd_main_loop.c
> index 397fd14..1c1ff4f 100644
> --- a/utils/gssd/gssd_main_loop.c
> +++ b/utils/gssd/gssd_main_loop.c
> @@ -103,7 +103,7 @@ gssd_run()
>  {
>  	int			ret;
>  	struct sigaction	dn_act;
> -	int			fd;
> +	int			fd, fd_cb;
>  	sigset_t		set;
>  
>  	/* Taken from linux/Documentation/dnotify.txt: */
> @@ -125,6 +125,20 @@ gssd_run()
>  	fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL);
>  	fcntl(fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
>  
> +	/* Attempt to open new callback pipe.  If the open fails,
> +	 * don't try to process it. */
> +	if ((fd_cb = open(pipefs_nfscbdir, O_RDONLY)) == -1) {
> +		/* could be an older kernel or a newer one doing NFS 4.1 */
> +		if (errno != ENOENT)
> +			printerr(0, "WARNING: failed to open %s: %s\n",
> +				 pipefs_nfscbdir, strerror(errno));
> +		memset(pipefs_nfscbdir, '\0', sizeof(pipefs_nfscbdir));
> +	} else {
> +		fcntl(fd_cb, F_SETSIG, DNOTIFY_SIGNAL);
> +		fcntl(fd_cb, F_NOTIFY,
> +			DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
> +	}
> +
>  	init_client_list();
>  
>  	printerr(1, "beginning poll\n");
> @@ -151,5 +165,7 @@ gssd_run()
>  		}
>  	}
>  	close(fd);
> +	if (fd_cb != -1)
> +		close(fd_cb);
>  	return;
>  }
> diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
> index 0fc0c42..969d113 100644
> --- a/utils/gssd/gssd_proc.c
> +++ b/utils/gssd/gssd_proc.c
> @@ -232,11 +232,19 @@ read_service_info(char *info_file_name, char **servicename, char **servername,
>  		sscanf(p, "port: %127s\n", cb_port);
>  
>  	/* check service, program, and version */
> -	if(memcmp(service, "nfs", 3)) return -1;
> +	if (memcmp(service, "nfs", 3) != 0)
> +		return -1;
>  	*prog = atoi(program + 1); /* skip open paren */
>  	*vers = atoi(version);
> -	if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4)))
> -		goto fail;
> +
> +	if (strlen(service) == 3 ) {
> +		if ((*prog != 100003) || ((*vers != 2) && (*vers != 3) &&
> +		    (*vers != 4)))
> +			goto fail;
> +	} else if (memcmp(service, "nfs4_cb", 7) == 0) {
> +		if (*vers != 1)
> +			goto fail;
> +	}
>  
>  	if (cb_port[0] != '\0') {
>  		port = atoi(cb_port);
> @@ -315,19 +323,18 @@ out:
>  static int
>  process_clnt_dir_files(struct clnt_info * clp)
>  {
> -	char	kname[32];
> -	char	sname[32];
> -	char	info_file_name[32];
> +	char	name[PATH_MAX];
> +	char	info_file_name[PATH_MAX];
>  
>  	if (clp->krb5_fd == -1) {
> -		snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname);
> -		clp->krb5_fd = open(kname, O_RDWR);
> +		snprintf(name, sizeof(name), "%s/krb5", clp->dirname);
> +		clp->krb5_fd = open(name, O_RDWR);
>  	}
>  	if (clp->spkm3_fd == -1) {
> -		snprintf(sname, sizeof(sname), "%s/spkm3", clp->dirname);
> -		clp->spkm3_fd = open(sname, O_RDWR);
> +		snprintf(name, sizeof(name), "%s/spkm3", clp->dirname);
> +		clp->spkm3_fd = open(name, O_RDWR);
>  	}
> -	if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1))
> +	if ((clp->krb5_fd == -1) && (clp->spkm3_fd == -1))
>  		return -1;
>  	snprintf(info_file_name, sizeof(info_file_name), "%s/info",
>  			clp->dirname);
> @@ -384,17 +391,18 @@ insert_clnt_poll(struct clnt_info *clp)
>  }
>  
>  static void
> -process_clnt_dir(char *dir)
> +process_clnt_dir(char *dir, char *pdir)
>  {
>  	struct clnt_info *	clp;
>  
>  	if (!(clp = insert_new_clnt()))
>  		goto fail_destroy_client;
>  
> -	if (!(clp->dirname = calloc(strlen(dir) + 1, 1))) {
> +	/* An extra for the '/', and an extra for the null */
> +	if (!(clp->dirname = calloc(strlen(dir) + strlen(pdir) + 2, 1))) {
>  		goto fail_destroy_client;
>  	}
> -	memcpy(clp->dirname, dir, strlen(dir));
> +	sprintf(clp->dirname, "%s/%s", pdir, dir);
>  	if ((clp->dir_fd = open(clp->dirname, O_RDONLY)) == -1) {
>  		printerr(0, "ERROR: can't open %s: %s\n",
>  			 clp->dirname, strerror(errno));
> @@ -438,16 +446,24 @@ init_client_list(void)
>   * directories, since the DNOTIFY could have been in there.
>   */
>  static void
> -update_old_clients(struct dirent **namelist, int size)
> +update_old_clients(struct dirent **namelist, int size, char *pdir)
>  {
>  	struct clnt_info *clp;
>  	void *saveprev;
>  	int i, stillhere;
> +	char fname[PATH_MAX];
>  
>  	for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next) {
> +		/* only compare entries in the global list that are from the
> +		 * same pipefs parent directory as "pdir"
> +		 */
> +		if (strncmp(clp->dirname, pdir, strlen(pdir)) != 0) continue;
> +
>  		stillhere = 0;
>  		for (i=0; i < size; i++) {
> -			if (!strcmp(clp->dirname, namelist[i]->d_name)) {
> +			snprintf(fname, sizeof(fname), "%s/%s",
> +				 pdir, namelist[i]->d_name);
> +			if (strcmp(clp->dirname, fname) == 0) {
>  				stillhere = 1;
>  				break;
>  			}
> @@ -468,13 +484,16 @@ update_old_clients(struct dirent **namelist, int size)
>  
>  /* Search for a client by directory name, return 1 if found, 0 otherwise */
>  static int
> -find_client(char *dirname)
> +find_client(char *dirname, char *pdir)
>  {
>  	struct clnt_info	*clp;
> +	char fname[PATH_MAX];
>  
> -	for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next)
> -		if (!strcmp(clp->dirname, dirname))
> +	for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next) {
> +		snprintf(fname, sizeof(fname), "%s/%s", pdir, dirname);
> +		if (strcmp(clp->dirname, fname) == 0)
>  			return 1;
> +	}
>  	return 0;
>  }
>  
> @@ -497,12 +516,12 @@ process_pipedir(char *pipe_name)
>  		return -1;
>  	}
>  
> -	update_old_clients(namelist, j);
> +	update_old_clients(namelist, j, pipe_name);
>  	for (i=0; i < j; i++) {
>  		if (i < FD_ALLOC_BLOCK
>  				&& !strncmp(namelist[i]->d_name, "clnt", 4)
> -				&& !find_client(namelist[i]->d_name))
> -			process_clnt_dir(namelist[i]->d_name);
> +				&& !find_client(namelist[i]->d_name, pipe_name))
> +			process_clnt_dir(namelist[i]->d_name, pipe_name);
>  		free(namelist[i]);
>  	}
>  
> @@ -510,7 +529,6 @@ process_pipedir(char *pipe_name)
>  
>  	return 0;
>  }
> -
>  /* Used to read (and re-read) list of clients, set up poll array. */
>  int
>  update_client_list(void)
> @@ -521,6 +539,15 @@ update_client_list(void)
>  	if (retval)
>  		printerr(0, "ERROR: processing %s\n", pipefs_nfsdir);
>  
> +	/* If we successfully processed nfsdir and callback directory exists
> +	 * process any events in the callback directory
> +	 */
> +	if (retval == 0 && pipefs_nfscbdir[0] != '\0') {
> +		retval = process_pipedir(pipefs_nfscbdir);
> +		if (retval)
> +			printerr(0, "ERROR: processing %s\n", pipefs_nfscbdir);
> +	}
> +
>  	return retval;
>  }
>  
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux