summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/fs/nfs/nfs_commonkrpc.c51
-rw-r--r--sys/fs/nfsclient/nfs_clvfsops.c20
2 files changed, 49 insertions, 22 deletions
diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c
index 7abff32..d487703 100644
--- a/sys/fs/nfs/nfs_commonkrpc.c
+++ b/sys/fs/nfs/nfs_commonkrpc.c
@@ -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;
@@ -423,6 +426,14 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
}
/*
+ * 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);
diff --git a/sys/fs/nfsclient/nfs_clvfsops.c b/sys/fs/nfsclient/nfs_clvfsops.c
index 412ad1d..73fb4e3 100644
--- a/sys/fs/nfsclient/nfs_clvfsops.c
+++ b/sys/fs/nfsclient/nfs_clvfsops.c
@@ -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;
}
OpenPOWER on IntegriCloud