aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/fs/nfs/nfs_commonacl.c195
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c272
-rw-r--r--sys/fs/nfs/nfs_var.h3
3 files changed, 445 insertions, 25 deletions
diff --git a/sys/fs/nfs/nfs_commonacl.c b/sys/fs/nfs/nfs_commonacl.c
index bba1d8821a9b..2120b095823b 100644
--- a/sys/fs/nfs/nfs_commonacl.c
+++ b/sys/fs/nfs/nfs_commonacl.c
@@ -36,7 +36,7 @@ static int nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner,
__enum_uint8(vtype) type, acl_perm_t *permp);
/*
- * Handle xdr for an ace.
+ * Handle xdr for an NFSv4 ace.
*/
int
nfsrv_dissectace(struct nfsrv_descript *nd, struct acl_entry *acep,
@@ -181,6 +181,84 @@ nfsmout:
return (error);
}
+static acl_tag_t nfsv4_to_posixacltag[NFSV4_POSIXACL_TAG_OTHER + 1] =
+ { ACL_UNDEFINED_TAG, ACL_USER_OBJ, ACL_USER, ACL_GROUP_OBJ,
+ ACL_GROUP, ACL_MASK, ACL_OTHER };
+
+/*
+ * Handle xdr for a POSIX draft ace.
+ */
+int
+nfsrv_dissectposixace(struct nfsrv_descript *nd, struct acl_entry *acep,
+ bool server, int *aceerrp, int *acesizep)
+{
+ uint32_t *tl, tag;
+ int len, error = 0, aceerr = 0;
+ u_char *name, namestr[NFSV4_SMALLSTR + 1];
+ gid_t gid;
+ uid_t uid;
+
+ *aceerrp = 0;
+ NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED);
+ tag = fxdr_unsigned(uint32_t, *tl++);
+ acep->ae_perm = fxdr_unsigned(acl_perm_t, *tl++);
+ len = fxdr_unsigned(int, *tl);
+ /*
+ * The RFCs do not specify a limit to the length of the "who", but
+ * NFSV4_OPAQUELIMIT (1024) should be sufficient.
+ */
+ if (len < 0 || len > NFSV4_OPAQUELIMIT) {
+ error = NFSERR_BADXDR;
+ goto nfsmout;
+ }
+ if (tag < NFSV4_POSIXACL_TAG_USER_OBJ ||
+ tag > NFSV4_POSIXACL_TAG_OTHER) {
+ error = NFSERR_ATTRNOTSUPP;
+ goto nfsmout;
+ }
+ acep->ae_tag = nfsv4_to_posixacltag[tag];
+ if (len > NFSV4_SMALLSTR)
+ name = malloc(len + 1, M_NFSSTRING, M_WAITOK);
+ else
+ name = namestr;
+ if (len > 0)
+ error = nfsrv_mtostr(nd, name, len);
+ if (error != 0) {
+ if (len > NFSV4_SMALLSTR)
+ free(name, M_NFSSTRING);
+ goto nfsmout;
+ }
+ switch (acep->ae_tag) {
+ case ACL_USER:
+ aceerr = nfsv4_strtouid(nd, name, len, &uid);
+ if (aceerr == 0)
+ acep->ae_id = uid;
+ break;
+ case ACL_GROUP:
+ aceerr = nfsv4_strtogid(nd, name, len, &gid);
+ if (aceerr == 0)
+ acep->ae_id = (uid_t)gid;
+ break;
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_MASK:
+ case ACL_OTHER:
+ break;
+ default:
+ aceerr = NFSERR_ATTRNOTSUPP;
+ }
+ if (len > NFSV4_SMALLSTR)
+ free(name, M_NFSSTRING);
+
+ *aceerrp = aceerr;
+ if (acesizep != NULL)
+ *acesizep = NFSM_RNDUP(len) + (3 * NFSX_UNSIGNED);
+ error = 0;
+nfsmout:
+ NFSEXITCODE(error);
+ return (error);
+}
+
/*
* Turn an NFSv4 ace mask into R/W/X flag bits.
*/
@@ -277,9 +355,11 @@ out:
/* local functions */
static int nfsrv_buildace(struct nfsrv_descript *, u_char *, int,
__enum_uint8(vtype), int, int, struct acl_entry *);
+static int nfsrv_buildposixace(struct nfsrv_descript *, u_char *, int,
+ struct acl_entry *);
/*
- * This function builds an NFS ace.
+ * This function builds an NFSv4 ace.
*/
static int
nfsrv_buildace(struct nfsrv_descript *nd, u_char *name, int namelen,
@@ -400,6 +480,59 @@ nfs_aceperm(acl_perm_t ae_perm)
}
/*
+ * This function builds a POSIX draft ace.
+ */
+static int
+nfsrv_buildposixace(struct nfsrv_descript *nd, u_char *name, int namelen,
+ struct acl_entry *ace)
+{
+ uint32_t *tl;
+ int full_len;
+
+ full_len = NFSM_RNDUP(namelen);
+ NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED + full_len);
+
+ /*
+ * Fill in the ace tag.
+ */
+ switch (ace->ae_tag) {
+ case ACL_USER_OBJ:
+ *tl++ = txdr_unsigned(NFSV4_POSIXACL_TAG_USER_OBJ);
+ break;
+ case ACL_USER:
+ *tl++ = txdr_unsigned(NFSV4_POSIXACL_TAG_USER);
+ break;
+ case ACL_GROUP_OBJ:
+ *tl++ = txdr_unsigned(NFSV4_POSIXACL_TAG_GROUP_OBJ);
+ break;
+ case ACL_GROUP:
+ *tl++ = txdr_unsigned(NFSV4_POSIXACL_TAG_GROUP);
+ break;
+ case ACL_MASK:
+ *tl++ = txdr_unsigned(NFSV4_POSIXACL_TAG_MASK);
+ break;
+ case ACL_OTHER:
+ *tl++ = txdr_unsigned(NFSV4_POSIXACL_TAG_OTHER);
+ break;
+ default:
+ printf("nfsrv_buildposixace: bad ae_tag 0x%x\n", ace->ae_tag);
+ *tl++ = txdr_unsigned(0);
+ }
+
+ /*
+ * Fill in the permission bits.
+ */
+ *tl++ = txdr_unsigned(ace->ae_perm);
+ *tl++ = txdr_unsigned(namelen);
+ if (namelen > 0) {
+ if (full_len - namelen)
+ *(tl + (namelen / NFSX_UNSIGNED)) = 0x0;
+ memcpy(tl, name, namelen);
+ }
+ return (full_len + 3 * NFSX_UNSIGNED);
+}
+
+/*
* Build an NFSv4 ACL.
*/
int
@@ -462,6 +595,64 @@ nfsrv_buildacl(struct nfsrv_descript *nd, NFSACL_T *aclp, __enum_uint8(vtype) ty
}
/*
+ * Build a POSIX draft ACL.
+ */
+int
+nfsrv_buildposixacl(struct nfsrv_descript *nd, NFSACL_T *aclp,
+ acl_type_t acltype)
+{
+ int i, entrycnt = 0, retlen;
+ uint32_t *entrycntp;
+ unsigned int cnt;
+ int namelen;
+ u_char *name, namestr[NFSV4_SMALLSTR];
+ bool malloced;
+
+ NFSM_BUILD(entrycntp, uint32_t *, NFSX_UNSIGNED);
+ retlen = NFSX_UNSIGNED;
+ cnt = 0;
+ if (aclp != NULL)
+ cnt = aclp->acl_cnt;
+ /*
+ * Loop through the acl entries, building each one.
+ */
+ for (i = 0; i < cnt; i++) {
+ malloced = false;
+ switch (aclp->acl_entry[i].ae_tag) {
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_OTHER:
+ case ACL_MASK:
+ namelen = 0;
+ break;
+ case ACL_USER:
+ name = namestr;
+ nfsv4_uidtostr(aclp->acl_entry[i].ae_id, &name,
+ &namelen);
+ if (name != namestr)
+ malloced = true;
+ break;
+ case ACL_GROUP:
+ name = namestr;
+ nfsv4_gidtostr((gid_t)aclp->acl_entry[i].ae_id, &name,
+ &namelen);
+ if (name != namestr)
+ malloced = true;
+ break;
+ default:
+ continue;
+ }
+ retlen += nfsrv_buildposixace(nd, name, namelen,
+ &aclp->acl_entry[i]);
+ entrycnt++;
+ if (malloced)
+ free(name, M_NFSSTRING);
+ }
+ *entrycntp = txdr_unsigned(entrycnt);
+ return (retlen);
+}
+
+/*
* Compare two NFSv4 acls.
* Return 0 if they are the same, 1 if not the same.
*/
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index 707ad5749ab2..2b0ce45d05dd 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -228,7 +228,7 @@ static bool nfs_bigreply[NFSV42_NPROCS] = {
};
/* local functions */
-static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
+static int nfsrv_skipace(struct nfsrv_descript *nd, acl_type_t, int *acesizep);
static void nfsv4_wanted(struct nfsv4lock *lp);
static uint32_t nfsv4_filesavail(struct statfs *, struct mount *);
static int nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name);
@@ -240,6 +240,7 @@ static uint32_t vtonfsv4_type(struct vattr *);
static __enum_uint8(vtype) nfsv4tov_type(uint32_t, uint16_t *);
static void nfsv4_setsequence(struct nfsmount *, struct nfsrv_descript *,
struct nfsclsession *, bool, struct ucred *);
+static uint32_t nfs_trueform(struct vnode *);
static struct {
int op;
@@ -1149,18 +1150,19 @@ int
nfsrv_dissectacl(struct nfsrv_descript *nd, NFSACL_T *aclp, bool server,
int *aclerrp, int *aclsizep, __unused NFSPROC_T *p)
{
- u_int32_t *tl;
+ uint32_t *tl;
int i, aclsize;
int acecnt, error = 0, aceerr = 0, acesize;
+ bool posixacl = false;
*aclerrp = 0;
- if (aclp)
+ if (aclp != NULL)
aclp->acl_cnt = 0;
/*
* Parse out the ace entries and expect them to conform to
* what can be supported by R/W/X bits.
*/
- NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
aclsize = NFSX_UNSIGNED;
acecnt = fxdr_unsigned(int, *tl);
/*
@@ -1176,20 +1178,28 @@ nfsrv_dissectacl(struct nfsrv_descript *nd, NFSACL_T *aclp, bool server,
if (nfsrv_useacl == 0)
aceerr = NFSERR_ATTRNOTSUPP;
for (i = 0; i < acecnt; i++) {
- if (aclp && !aceerr)
- error = nfsrv_dissectace(nd, &aclp->acl_entry[i],
- server, &aceerr, &acesize, p);
+ if (aclp != NULL && aceerr == 0) {
+ if (posixacl)
+ error = nfsrv_dissectposixace(nd,
+ &aclp->acl_entry[i], server, &aceerr,
+ &acesize);
+ else
+ error = nfsrv_dissectace(nd,
+ &aclp->acl_entry[i], server, &aceerr,
+ &acesize, p);
+ } else if (posixacl)
+ error = nfsrv_skipace(nd, ACL_TYPE_ACCESS, &acesize);
else
- error = nfsrv_skipace(nd, &acesize);
- if (error)
+ error = nfsrv_skipace(nd, ACL_TYPE_NFS4, &acesize);
+ if (error != 0)
goto nfsmout;
aclsize += acesize;
}
- if (aclp && !aceerr)
+ if (aclp != NULL && aceerr == 0)
aclp->acl_cnt = acecnt;
- if (aceerr)
+ if (aceerr != 0)
*aclerrp = aceerr;
- if (aclsizep)
+ if (aclsizep != NULL)
*aclsizep = aclsize;
nfsmout:
NFSEXITCODE2(error, nd);
@@ -1200,16 +1210,22 @@ nfsmout:
* Skip over an NFSv4 ace entry. Just dissect the xdr and discard it.
*/
static int
-nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep)
+nfsrv_skipace(struct nfsrv_descript *nd, acl_type_t acltype, int *acesizep)
{
- u_int32_t *tl;
+ uint32_t *tl;
int error, len = 0;
- NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
- len = fxdr_unsigned(int, *(tl + 3));
+ if (acltype == ACL_TYPE_NFS4) {
+ NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED);
+ len = fxdr_unsigned(int, *(tl + 3));
+ *acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED);
+ } else {
+ NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED);
+ len = fxdr_unsigned(int, *(tl + 2));
+ *acesizep = NFSM_RNDUP(len) + (3 * NFSX_UNSIGNED);
+ }
error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
nfsmout:
- *acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED);
NFSEXITCODE2(error, nd);
return (error);
}
@@ -1437,6 +1453,11 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
NFSCLRBIT_ATTRBIT(&checkattrbits, NFSATTRBIT_ACL);
NFSCLRBIT_ATTRBIT(&checkattrbits, NFSATTRBIT_ACLSUPPORT);
}
+ /* Some filesystem do not support POSIX ACL */
+ if (nfsrv_useacl == 0 || nfs_supportsposixacls(vp) == 0) {
+ NFSCLRBIT_ATTRBIT(&checkattrbits, NFSATTRBIT_POSIXACCESSACL);
+ NFSCLRBIT_ATTRBIT(&checkattrbits, NFSATTRBIT_POSIXDEFAULTACL);
+ }
/* Some filesystems do not support uf_hidden */
if (vp == NULL || VOP_PATHCONF(vp,
_PC_HAS_HIDDENSYSTEM, &has_pathconf) != 0)
@@ -1655,7 +1676,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
if (error)
goto nfsmout;
}
-
+
attrsum += cnt;
break;
case NFSATTRBIT_ACLSUPPORT:
@@ -2440,6 +2461,111 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
}
attrsum += NFSX_UNSIGNED;
break;
+ case NFSATTRBIT_ACLTRUEFORM:
+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+ if (compare) {
+ if (!(*retcmpp)) {
+ tuint = nfs_trueform(vp);
+ if (tuint != fxdr_unsigned(uint32_t,
+ *tl))
+ *retcmpp = NFSERR_NOTSAME;
+ }
+#ifdef notyet
+ } else if (trueformp != NULL) {
+ *trueformp = fxdr_unsigned(uint32_t, *tl);
+ }
+#else
+ }
+#endif
+ attrsum += NFSX_UNSIGNED;
+ break;
+ case NFSATTRBIT_ACLTRUEFORMSCOPE:
+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+ if (compare) {
+ if (!(*retcmpp)) {
+ if (fxdr_unsigned(uint32_t, *tl) !=
+ NFSV4_ACL_SCOPE_FILE_SYSTEM)
+ *retcmpp = NFSERR_NOTSAME;
+ }
+ }
+ attrsum += NFSX_UNSIGNED;
+ break;
+ case NFSATTRBIT_POSIXACCESSACL:
+ if (compare) {
+ if (!(*retcmpp)) {
+ if (nfsrv_useacl && nfs_supportsposixacls(vp)) {
+ NFSACL_T *naclp;
+
+ naclp = acl_alloc(M_WAITOK);
+ error = nfsrv_dissectacl(nd, naclp, true,
+ &aceerr, &cnt, p);
+ if (error) {
+ acl_free(naclp);
+ goto nfsmout;
+ }
+ if (aceerr || aclp == NULL ||
+ nfsrv_compareacl(aclp, naclp))
+ *retcmpp = NFSERR_NOTSAME;
+ acl_free(naclp);
+ } else {
+ error = nfsrv_dissectacl(nd, NULL, true,
+ &aceerr, &cnt, p);
+ if (error)
+ goto nfsmout;
+ *retcmpp = NFSERR_ATTRNOTSUPP;
+ }
+ }
+ } else {
+ if (vp != NULL && aclp != NULL)
+ error = nfsrv_dissectacl(nd, aclp, false,
+ &aceerr, &cnt, p);
+ else
+ error = nfsrv_dissectacl(nd, NULL, false,
+ &aceerr, &cnt, p);
+ if (error)
+ goto nfsmout;
+ }
+
+ attrsum += cnt;
+ break;
+ case NFSATTRBIT_POSIXDEFAULTACL:
+ if (compare) {
+ if (!(*retcmpp)) {
+ if (nfsrv_useacl && nfs_supportsposixacls(vp)) {
+ NFSACL_T *naclp;
+
+ naclp = acl_alloc(M_WAITOK);
+ error = nfsrv_dissectacl(nd, naclp, true,
+ &aceerr, &cnt, p);
+ if (error) {
+ acl_free(naclp);
+ goto nfsmout;
+ }
+ if (aceerr || aclp == NULL ||
+ nfsrv_compareacl(aclp, naclp))
+ *retcmpp = NFSERR_NOTSAME;
+ acl_free(naclp);
+ } else {
+ error = nfsrv_dissectacl(nd, NULL, true,
+ &aceerr, &cnt, p);
+ if (error)
+ goto nfsmout;
+ *retcmpp = NFSERR_ATTRNOTSUPP;
+ }
+ }
+ } else {
+ if (vp != NULL && aclp != NULL)
+ error = nfsrv_dissectacl(nd, aclp, false,
+ &aceerr, &cnt, p);
+ else
+ error = nfsrv_dissectacl(nd, NULL, false,
+ &aceerr, &cnt, p);
+ if (error)
+ goto nfsmout;
+ }
+
+ attrsum += cnt;
+ break;
default:
printf("EEK! nfsv4_loadattr unknown attr=%d\n",
bitpos);
@@ -2711,7 +2837,8 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
struct statfs *fs;
struct nfsfsinfo fsinf;
struct timespec temptime;
- NFSACL_T *aclp, *naclp = NULL;
+ NFSACL_T *aclp, *naclp = NULL, *paclp, *npaclp = NULL, *daclp;
+ NFSACL_T *ndaclp = NULL;
short irflag;
#ifdef QUOTA
struct dqblk dqb;
@@ -2730,11 +2857,21 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
*/
if (p == NULL && cred == NULL) {
NFSCLRNOTSETABLE_ATTRBIT(retbitp, nd);
- aclp = saclp;
+ /* Only one of the ACL types can be set for a call. */
+ if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_ACL))
+ aclp = saclp;
+ else if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_POSIXACCESSACL))
+ paclp = saclp;
+ else if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_POSIXDEFAULTACL))
+ daclp = saclp;
} else {
NFSCLRNOTFILLABLE_ATTRBIT(retbitp, nd);
naclp = acl_alloc(M_WAITOK);
aclp = naclp;
+ npaclp = acl_alloc(M_WAITOK);
+ paclp = npaclp;
+ ndaclp = acl_alloc(M_WAITOK);
+ daclp = ndaclp;
}
nfsvno_getfs(&fsinf, isdgram);
/*
@@ -2769,12 +2906,12 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
*/
if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_ACLSUPPORT) &&
(nfsrv_useacl == 0 || ((cred != NULL || p != NULL) &&
- supports_nfsv4acls == 0))) {
+ supports_nfsv4acls != SUPPACL_NFSV4))) {
NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACLSUPPORT);
}
if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_ACL)) {
if (nfsrv_useacl == 0 || ((cred != NULL || p != NULL) &&
- supports_nfsv4acls == 0)) {
+ supports_nfsv4acls != SUPPACL_NFSV4)) {
NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACL);
} else if (naclp != NULL) {
if (NFSVOPLOCK(vp, LK_SHARED) == 0) {
@@ -2796,6 +2933,49 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
}
}
+ /* and the POSIX draft ACL. */
+ if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_POSIXACCESSACL)) {
+ if (nfsrv_useacl == 0 || ((cred != NULL || p != NULL) &&
+ supports_nfsv4acls != SUPPACL_POSIX)) {
+ NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_POSIXACCESSACL);
+ } else if (npaclp != NULL) {
+ if (NFSVOPLOCK(vp, LK_SHARED) == 0) {
+ error = VOP_ACCESSX(vp, VREAD_ACL, cred, p);
+ if (error == 0)
+ error = VOP_GETACL(vp, ACL_TYPE_ACCESS,
+ npaclp, cred, p);
+ NFSVOPUNLOCK(vp);
+ } else
+ error = NFSERR_PERM;
+ if (error != 0) {
+ if (reterr) {
+ nd->nd_repstat = NFSERR_INVAL;
+ free(fs, M_STATFS);
+ return (0);
+ }
+ NFSCLRBIT_ATTRBIT(retbitp,
+ NFSATTRBIT_POSIXACCESSACL);
+ }
+ }
+ }
+ if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_POSIXDEFAULTACL)) {
+ if (nfsrv_useacl == 0 || ((cred != NULL || p != NULL) &&
+ supports_nfsv4acls != SUPPACL_POSIX)) {
+ NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_POSIXDEFAULTACL);
+ } else if (ndaclp != NULL) {
+ if (NFSVOPLOCK(vp, LK_SHARED) == 0) {
+ error = VOP_ACCESSX(vp, VREAD_ACL, cred, p);
+ if (error == 0)
+ error = VOP_GETACL(vp, ACL_TYPE_DEFAULT,
+ ndaclp, cred, p);
+ NFSVOPUNLOCK(vp);
+ } else
+ error = NFSERR_PERM;
+ if (error != 0)
+ ndaclp->acl_cnt = 0;
+ }
+ }
+
/*
* Put out the attribute bitmap for the ones being filled in
* and get the field for the number of attributes returned.
@@ -2813,10 +2993,17 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
case NFSATTRBIT_SUPPORTEDATTRS:
NFSSETSUPP_ATTRBIT(&attrbits, nd);
if (nfsrv_useacl == 0 || ((cred != NULL || p != NULL)
- && supports_nfsv4acls == 0)) {
+ && supports_nfsv4acls != SUPPACL_NFSV4)) {
NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACLSUPPORT);
NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACL);
}
+ if (nfsrv_useacl == 0 || ((cred != NULL || p != NULL)
+ && supports_nfsv4acls != SUPPACL_POSIX)) {
+ NFSCLRBIT_ATTRBIT(&attrbits,
+ NFSATTRBIT_POSIXACCESSACL);
+ NFSCLRBIT_ATTRBIT(&attrbits,
+ NFSATTRBIT_POSIXDEFAULTACL);
+ }
if (!has_hiddensystem) {
NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_HIDDEN);
NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_SYSTEM);
@@ -3321,6 +3508,24 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
*tl = txdr_unsigned(clone_blksize);
retnum += NFSX_UNSIGNED;
break;
+ case NFSATTRBIT_ACLTRUEFORM:
+ NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+ *tl = txdr_unsigned(nfs_trueform(vp));
+ retnum += NFSX_UNSIGNED;
+ break;
+ case NFSATTRBIT_ACLTRUEFORMSCOPE:
+ NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+ *tl = txdr_unsigned(NFSV4_ACL_SCOPE_FILE_SYSTEM);
+ retnum += NFSX_UNSIGNED;
+ break;
+ case NFSATTRBIT_POSIXACCESSACL:
+ retnum += nfsrv_buildposixacl(nd, paclp,
+ ACL_TYPE_ACCESS);
+ break;
+ case NFSATTRBIT_POSIXDEFAULTACL:
+ retnum += nfsrv_buildposixacl(nd, daclp,
+ ACL_TYPE_DEFAULT);
+ break;
default:
printf("EEK! Bad V4 attribute bitpos=%d\n", bitpos);
}
@@ -3328,6 +3533,10 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
}
if (naclp != NULL)
acl_free(naclp);
+ if (npaclp != NULL)
+ acl_free(npaclp);
+ if (ndaclp != NULL)
+ acl_free(ndaclp);
free(fs, M_STATFS);
*retnump = txdr_unsigned(retnum);
return (retnum + prefixnum);
@@ -5347,6 +5556,23 @@ nfsrpc_destroysession(struct nfsmount *nmp, struct nfsclsession *tsep,
}
/*
+ * Determine the true form (the type of ACL stored on the file) for the
+ * vnode argument.
+ */
+static uint32_t
+nfs_trueform(struct vnode *vp)
+{
+ uint32_t trueform;
+
+ trueform = NFSV4_ACL_MODEL_NONE;
+ if ((vp->v_mount->mnt_flag & MNT_NFS4ACLS) != 0)
+ trueform = NFSV4_ACL_MODEL_NFS4;
+ else if ((vp->v_mount->mnt_flag & MNT_ACLS) != 0)
+ trueform = NFSV4_ACL_MODEL_POSIX_DRAFT;
+ return (trueform);
+}
+
+/*
* Translate a vnode type into an NFSv4 type, including the named
* attribute types.
*/
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h
index 49a94323a572..c04c3951d42d 100644
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -443,8 +443,11 @@ int nfs_supportsposixacls(struct vnode *);
int nfsrv_dissectace(struct nfsrv_descript *, struct acl_entry *,
bool, int *, int *, NFSPROC_T *);
uint32_t nfs_aceperm(acl_perm_t);
+int nfsrv_dissectposixace(struct nfsrv_descript *, struct acl_entry *,
+ bool, int *, int *);
int nfsrv_buildacl(struct nfsrv_descript *, NFSACL_T *, __enum_uint8(vtype),
NFSPROC_T *);
+int nfsrv_buildposixacl(struct nfsrv_descript *, NFSACL_T *, acl_type_t);
int nfsrv_compareacl(NFSACL_T *, NFSACL_T *);
/* nfs_clrpcops.c */