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>