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)
This commit is contained in:
Rick Macklem 2009-05-24 03:22:49 +00:00
parent 20d0a5e544
commit 63bde62e9a
2 changed files with 49 additions and 22 deletions

View file

@ -341,7 +341,9 @@ nfs_getauth(struct nfssockreq *nrp, int secflavour, char *clnt_principal,
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, struct nfsmount *nmp,
{
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, struct nfsmount *nmp,
enum clnt_stat stat;
struct nfsreq *rep = NULL;
char *srv_principal = NULL;
uid_t saved_uid = (uid_t)-1;
if (xidp != NULL)
*xidp = 0;
@ -422,6 +425,14 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
return (ESTALE);
}
/*
* 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, struct nfsmount *nmp,
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, struct nfsmount *nmp,
((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, struct nfsmount *nmp,
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);

View file

@ -1062,20 +1062,20 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
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;
}