Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 24 May 2009 03:22:49 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r192675 - in head/sys/fs: nfs nfsclient
Message-ID:  <200905240322.n4O3Mn7F075755@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sun May 24 03:22:49 2009
New Revision: 192675
URL: http://svn.freebsd.org/changeset/base/192675

Log:
  Fix the experimental nfsv4 client so that it works for the
  case of a kerberized mount without a host based principal
  name. This will only work for mounts being done by a user
  other than root. Support for a host based principal name
  will not work until proposed changes to the rpcsec_gss part
  of the krpc are committed. It now builds for "options KGSSAPI".
  
  Approved by:	kib (mentor)

Modified:
  head/sys/fs/nfs/nfs_commonkrpc.c
  head/sys/fs/nfsclient/nfs_clvfsops.c

Modified: head/sys/fs/nfs/nfs_commonkrpc.c
==============================================================================
--- head/sys/fs/nfs/nfs_commonkrpc.c	Sun May 24 01:18:56 2009	(r192674)
+++ head/sys/fs/nfs/nfs_commonkrpc.c	Sun May 24 03:22:49 2009	(r192675)
@@ -341,7 +341,9 @@ nfs_getauth(struct nfssockreq *nrp, int 
 		else
 			auth = NULL;
 #endif
-		return (auth);
+		if (auth != NULL)
+			return (auth);
+		/* fallthrough */
 #endif	/* KGSSAPI */
 	case AUTH_SYS:
 	default:
@@ -402,7 +404,7 @@ newnfs_request(struct nfsrv_descript *nd
 {
 	u_int32_t *tl;
 	time_t waituntil;
-	int i, j;
+	int i, j, set_uid = 0;
 	int trycnt, error = 0, usegssname = 0, secflavour = AUTH_SYS;
 	u_int16_t procnum;
 	u_int trylater_delay = 1;
@@ -413,6 +415,7 @@ newnfs_request(struct nfsrv_descript *nd
 	enum clnt_stat stat;
 	struct nfsreq *rep = NULL;
 	char *srv_principal = NULL;
+	uid_t saved_uid = (uid_t)-1;
 
 	if (xidp != NULL)
 		*xidp = 0;
@@ -423,6 +426,14 @@ newnfs_request(struct nfsrv_descript *nd
 	}
 
 	/*
+	 * XXX if not already connected call nfs_connect now. Longer
+	 * term, change nfs_mount to call nfs_connect unconditionally
+	 * and let clnt_reconnect_create handle reconnects.
+	 */
+	if (nrp->nr_client == NULL)
+		newnfs_connect(nmp, nrp, cred, td, 0);
+
+	/*
 	 * For a client side mount, nmp is != NULL and clp == NULL. For
 	 * server calls (callbacks or upcalls), nmp == NULL.
 	 */
@@ -442,8 +453,30 @@ newnfs_request(struct nfsrv_descript *nd
 	     nd->nd_procnum != NFSPROC_NULL) {
 		if (NFSHASALLGSSNAME(nmp) && nmp->nm_krbnamelen > 0)
 			nd->nd_flag |= ND_USEGSSNAME;
-		if ((nd->nd_flag & ND_USEGSSNAME) && nmp->nm_krbnamelen > 0)
-			usegssname = 1;
+		if ((nd->nd_flag & ND_USEGSSNAME) != 0) {
+			/*
+			 * If there is a client side host based credential,
+			 * use that, otherwise use the system uid, if set.
+			 */
+			if (nmp->nm_krbnamelen > 0) {
+				usegssname = 1;
+			} else if (nmp->nm_uid != (uid_t)-1) {
+				saved_uid = cred->cr_uid;
+				cred->cr_uid = nmp->nm_uid;
+				set_uid = 1;
+			}
+		} else if (nmp->nm_krbnamelen == 0 &&
+		    nmp->nm_uid != (uid_t)-1 && cred->cr_uid == (uid_t)0) {
+			/*
+			 * If there is no host based principal name and
+			 * the system uid is set and this is root, use the
+			 * system uid, since root won't have user
+			 * credentials in a credentials cache file.
+			 */
+			saved_uid = cred->cr_uid;
+			cred->cr_uid = nmp->nm_uid;
+			set_uid = 1;
+		}
 		if (NFSHASINTEGRITY(nmp))
 			secflavour = RPCSEC_GSS_KRB5I;
 		else if (NFSHASPRIVACY(nmp))
@@ -462,14 +495,6 @@ newnfs_request(struct nfsrv_descript *nd
 		    ((nmp->nm_tprintf_delay)-(nmp->nm_tprintf_initial_delay));
 	}
 
-	/*
-	 * XXX if not already connected call nfs_connect now. Longer
-	 * term, change nfs_mount to call nfs_connect unconditionally
-	 * and let clnt_reconnect_create handle reconnects.
-	 */
-	if (nrp->nr_client == NULL)
-		newnfs_connect(nmp, nrp, cred, td, 0);
-
 	if (nd->nd_procnum == NFSPROC_NULL)
 		auth = authnone_create();
 	else if (usegssname)
@@ -478,6 +503,8 @@ newnfs_request(struct nfsrv_descript *nd
 	else
 		auth = nfs_getauth(nrp, secflavour, NULL,
 		    srv_principal, NULL, cred);
+	if (set_uid)
+		cred->cr_uid = saved_uid;
 	if (auth == NULL) {
 		m_freem(nd->nd_mreq);
 		return (EACCES);

Modified: head/sys/fs/nfsclient/nfs_clvfsops.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clvfsops.c	Sun May 24 01:18:56 2009	(r192674)
+++ head/sys/fs/nfsclient/nfs_clvfsops.c	Sun May 24 03:22:49 2009	(r192675)
@@ -1062,20 +1062,20 @@ mountnfs(struct nfs_args *argp, struct m
 		nmp->nm_krbnamelen = argp->krbnamelen;
 		nmp->nm_dirpathlen = argp->dirlen;
 		nmp->nm_srvkrbnamelen = argp->srvkrbnamelen;
-		if (nmp->nm_dirpathlen > 0) {
+		if (td->td_ucred->cr_uid != (uid_t)0) {
 			/*
-			 * Since we will be doing dirpath as root,
-			 * set nm_uid to the real uid doing the mount,
-			 * since that is normally the user with a valid TGT.
+			 * nm_uid is used to get KerberosV credentials for
+			 * the nfsv4 state handling operations if there is
+			 * no host based principal set. Use the uid of
+			 * this user if not root, since they are doing the
+			 * mount. I don't think setting this for root will
+			 * work, since root normally does not have user
+			 * credentials in a credentials cache.
 			 */
-			nmp->nm_uid = td->td_ucred->cr_ruid;
+			nmp->nm_uid = td->td_ucred->cr_uid;
 		} else {
 			/*
-			 * Just set to -1, so the first Op
-			 * will set it later, to the uid of
-			 * the process doing that (usually
-			 * from a first open in the mount
-			 * point).
+			 * Just set to -1, so it won't be used.
 			 */
 			nmp->nm_uid = (uid_t)-1;
 		}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905240322.n4O3Mn7F075755>