summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/nfs/nfs_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs/nfs/nfs_server.c')
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_server.c58
1 files changed, 42 insertions, 16 deletions
diff --git a/usr/src/uts/common/fs/nfs/nfs_server.c b/usr/src/uts/common/fs/nfs/nfs_server.c
index c777d8acff..ca3d7d8bb9 100644
--- a/usr/src/uts/common/fs/nfs/nfs_server.c
+++ b/usr/src/uts/common/fs/nfs/nfs_server.c
@@ -191,7 +191,7 @@ static void common_dispatch(struct svc_req *, SVCXPRT *,
struct rpc_disptable *);
static void hanfsv4_failover(void);
static int checkauth(struct exportinfo *, struct svc_req *, cred_t *, int,
- bool_t);
+ bool_t, bool_t *);
static char *client_name(struct svc_req *req);
static char *client_addr(struct svc_req *req, char *buf);
extern int sec_svc_getcred(struct svc_req *, cred_t *cr, char **, int *);
@@ -649,14 +649,15 @@ restart:
/* ARGSUSED */
void
-rpc_null(caddr_t *argp, caddr_t *resp)
+rpc_null(caddr_t *argp, caddr_t *resp, struct exportinfo *exi,
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
}
/* ARGSUSED */
void
rpc_null_v3(caddr_t *argp, caddr_t *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr)
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
DTRACE_NFSV3_3(op__null__start, struct svc_req *, req,
cred_t *, cr, vnode_t *, NULL);
@@ -666,7 +667,8 @@ rpc_null_v3(caddr_t *argp, caddr_t *resp, struct exportinfo *exi,
/* ARGSUSED */
static void
-rfs_error(caddr_t *argp, caddr_t *resp)
+rfs_error(caddr_t *argp, caddr_t *resp, struct exportinfo *exi,
+ struct svc_req *req, cred_t *cr, bool_t ro)
{
/* return (EOPNOTSUPP); */
}
@@ -1503,6 +1505,7 @@ common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers,
struct exportinfo *nfslog_exi = NULL;
char **procnames;
char cbuf[INET6_ADDRSTRLEN]; /* to hold both IPv4 and IPv6 addr */
+ bool_t ro = FALSE;
vers = req->rq_vers;
@@ -1657,7 +1660,8 @@ common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers,
goto done;
}
- authres = checkauth(exi, req, cr, anon_ok, publicfh_ok);
+ authres = checkauth(exi, req, cr, anon_ok, publicfh_ok,
+ &ro);
/*
* authres > 0: authentication OK - proceed
* authres == 0: authentication weak - return error
@@ -1701,7 +1705,7 @@ common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers,
case DUP_DROP:
curthread->t_flag |= T_DONTPEND;
- (*disp->dis_proc)(args, res, exi, req, cr);
+ (*disp->dis_proc)(args, res, exi, req, cr, ro);
curthread->t_flag &= ~T_DONTPEND;
if (curthread->t_flag & T_WOULDBLOCK) {
@@ -1731,7 +1735,7 @@ common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers,
} else {
curthread->t_flag |= T_DONTPEND;
- (*disp->dis_proc)(args, res, exi, req, cr);
+ (*disp->dis_proc)(args, res, exi, req, cr, ro);
curthread->t_flag &= ~T_DONTPEND;
if (curthread->t_flag & T_WOULDBLOCK) {
@@ -2005,7 +2009,7 @@ checkwin(int flavor, int window, struct svc_req *req)
*/
static int
checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok,
- bool_t publicfh_ok)
+ bool_t publicfh_ok, bool_t *ro)
{
int i, nfsflavor, rpcflavor, stat, access;
struct secinfo *secp;
@@ -2013,6 +2017,9 @@ checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok,
char buf[INET6_ADDRSTRLEN]; /* to hold both IPv4 and IPv6 addr */
int anon_res = 0;
+ uid_t uid;
+ gid_t gid;
+
/*
* Check for privileged port number
* N.B.: this assumes that we know the format of a netbuf.
@@ -2044,7 +2051,7 @@ checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok,
stat = sec_svc_getcred(req, cr, &principal, &nfsflavor);
/*
- * A failed AUTH_UNIX svc_get_cred() implies we couldn't set
+ * A failed AUTH_UNIX sec_svc_getcred() implies we couldn't set
* the credentials; below we map that to anonymous.
*/
if (!stat && nfsflavor != AUTH_UNIX) {
@@ -2070,14 +2077,17 @@ checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok,
/*
* Check if the auth flavor is valid for this export
*/
- access = nfsauth_access(exi, req);
+ access = nfsauth_access(exi, req, cr, &uid, &gid);
if (access & NFSAUTH_DROP)
return (-1); /* drop the request */
+ if (access & NFSAUTH_RO)
+ *ro = TRUE;
+
if (access & NFSAUTH_DENIED) {
/*
* If anon_ok == 1 and we got NFSAUTH_DENIED, it was
- * probably due to the flavor not matching during the
+ * probably due to the flavor not matching during
* the mount attempt. So map the flavor to AUTH_NONE
* so that the credentials get mapped to the anonymous
* user.
@@ -2111,12 +2121,11 @@ checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok,
break;
case AUTH_UNIX:
- if (!stat || crgetuid(cr) == 0 && !(access & NFSAUTH_ROOT)) {
+ if (!stat || crgetuid(cr) == 0 && !(access & NFSAUTH_UIDMAP)) {
anon_res = crsetugid(cr, exi->exi_export.ex_anon,
exi->exi_export.ex_anon);
(void) crsetgroups(cr, 0, NULL);
- } else if (!stat || crgetuid(cr) == 0 &&
- access & NFSAUTH_ROOT) {
+ } else if (crgetuid(cr) == 0 && access & NFSAUTH_ROOT) {
/*
* It is root, so apply rootid to get real UID
* Find the secinfo structure. We should be able
@@ -2137,7 +2146,14 @@ checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok,
secp->s_rootid);
(void) crsetgroups(cr, 0, NULL);
}
+ } else if (crgetuid(cr) != uid || crgetgid(cr) != gid) {
+ if (crsetugid(cr, uid, gid) != 0)
+ anon_res = crsetugid(cr,
+ exi->exi_export.ex_anon,
+ exi->exi_export.ex_anon);
+ (void) crsetgroups(cr, 0, NULL);
}
+
break;
case AUTH_DES:
@@ -2253,6 +2269,9 @@ checkauth4(struct compound_state *cs, struct svc_req *req)
cred_t *cr;
caddr_t principal;
+ uid_t uid;
+ gid_t gid;
+
exi = cs->exi;
cr = cs->cr;
principal = cs->principal;
@@ -2292,7 +2311,7 @@ checkauth4(struct compound_state *cs, struct svc_req *req)
* Check the access right per auth flavor on the vnode of
* this export for the given request.
*/
- access = nfsauth4_access(cs->exi, cs->vp, req);
+ access = nfsauth4_access(cs->exi, cs->vp, req, cr, &uid, &gid);
if (access & NFSAUTH_WRONGSEC)
return (-2); /* no access for this security flavor */
@@ -2330,7 +2349,7 @@ checkauth4(struct compound_state *cs, struct svc_req *req)
break;
case AUTH_UNIX:
- if (crgetuid(cr) == 0 && !(access & NFSAUTH_ROOT)) {
+ if (crgetuid(cr) == 0 && !(access & NFSAUTH_UIDMAP)) {
anon_res = crsetugid(cr, exi->exi_export.ex_anon,
exi->exi_export.ex_anon);
(void) crsetgroups(cr, 0, NULL);
@@ -2355,7 +2374,14 @@ checkauth4(struct compound_state *cs, struct svc_req *req)
secp->s_rootid);
(void) crsetgroups(cr, 0, NULL);
}
+ } else if (crgetuid(cr) != uid || crgetgid(cr) != gid) {
+ if (crsetugid(cr, uid, gid) != 0)
+ anon_res = crsetugid(cr,
+ exi->exi_export.ex_anon,
+ exi->exi_export.ex_anon);
+ (void) crsetgroups(cr, 0, NULL);
}
+
break;
default: