1191783Srmacklem/*- 2191783Srmacklem * Copyright (c) 2009 Rick Macklem, University of Guelph 3191783Srmacklem * All rights reserved. 4191783Srmacklem * 5191783Srmacklem * Redistribution and use in source and binary forms, with or without 6191783Srmacklem * modification, are permitted provided that the following conditions 7191783Srmacklem * are met: 8191783Srmacklem * 1. Redistributions of source code must retain the above copyright 9191783Srmacklem * notice, this list of conditions and the following disclaimer. 10191783Srmacklem * 2. Redistributions in binary form must reproduce the above copyright 11191783Srmacklem * notice, this list of conditions and the following disclaimer in the 12191783Srmacklem * documentation and/or other materials provided with the distribution. 13191783Srmacklem * 14191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15191783Srmacklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16191783Srmacklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17191783Srmacklem * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18191783Srmacklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19191783Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20191783Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21191783Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22191783Srmacklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23191783Srmacklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24191783Srmacklem * SUCH DAMAGE. 25191783Srmacklem * 26191783Srmacklem */ 27191783Srmacklem 28191783Srmacklem#include <sys/cdefs.h> 29191783Srmacklem__FBSDID("$FreeBSD: stable/11/sys/fs/nfs/nfs_commonacl.c 361236 2020-05-19 01:43:00Z freqlabs $"); 30191783Srmacklem 31191783Srmacklem#include <fs/nfs/nfsport.h> 32191783Srmacklem 33191783Srmacklemextern int nfsrv_useacl; 34191783Srmacklem 35191783Srmacklemstatic int nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner, 36191783Srmacklem enum vtype type, acl_perm_t *permp); 37191783Srmacklem 38191783Srmacklem/* 39191783Srmacklem * Handle xdr for an ace. 40191783Srmacklem */ 41361236Sfreqlabsint 42191783Srmacklemnfsrv_dissectace(struct nfsrv_descript *nd, struct acl_entry *acep, 43191783Srmacklem int *aceerrp, int *acesizep, NFSPROC_T *p) 44191783Srmacklem{ 45191783Srmacklem u_int32_t *tl; 46191783Srmacklem int len, gotid = 0, owner = 0, error = 0, aceerr = 0; 47191783Srmacklem u_char *name, namestr[NFSV4_SMALLSTR + 1]; 48191783Srmacklem u_int32_t flag, mask, acetype; 49191783Srmacklem gid_t gid; 50191783Srmacklem uid_t uid; 51191783Srmacklem 52191783Srmacklem *aceerrp = 0; 53191783Srmacklem acep->ae_flags = 0; 54191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 55191783Srmacklem acetype = fxdr_unsigned(u_int32_t, *tl++); 56191783Srmacklem flag = fxdr_unsigned(u_int32_t, *tl++); 57191783Srmacklem mask = fxdr_unsigned(u_int32_t, *tl++); 58191783Srmacklem len = fxdr_unsigned(int, *tl); 59191783Srmacklem if (len < 0) { 60224086Szack error = NFSERR_BADXDR; 61224086Szack goto nfsmout; 62191783Srmacklem } else if (len == 0) { 63191783Srmacklem /* Netapp filers return a 0 length who for nil users */ 64191783Srmacklem acep->ae_tag = ACL_UNDEFINED_TAG; 65191783Srmacklem acep->ae_id = ACL_UNDEFINED_ID; 66191783Srmacklem acep->ae_perm = (acl_perm_t)0; 67192818Strasz acep->ae_entry_type = ACL_ENTRY_TYPE_DENY; 68191783Srmacklem if (acesizep) 69191783Srmacklem *acesizep = 4 * NFSX_UNSIGNED; 70224086Szack error = 0; 71224086Szack goto nfsmout; 72191783Srmacklem } 73191783Srmacklem if (len > NFSV4_SMALLSTR) 74191783Srmacklem name = malloc(len + 1, M_NFSSTRING, M_WAITOK); 75191783Srmacklem else 76191783Srmacklem name = namestr; 77191783Srmacklem error = nfsrv_mtostr(nd, name, len); 78191783Srmacklem if (error) { 79191783Srmacklem if (len > NFSV4_SMALLSTR) 80191783Srmacklem free(name, M_NFSSTRING); 81224086Szack goto nfsmout; 82191783Srmacklem } 83191783Srmacklem if (len == 6) { 84191783Srmacklem if (!NFSBCMP(name, "OWNER@", 6)) { 85191783Srmacklem acep->ae_tag = ACL_USER_OBJ; 86191783Srmacklem acep->ae_id = ACL_UNDEFINED_ID; 87191783Srmacklem owner = 1; 88191783Srmacklem gotid = 1; 89191783Srmacklem } else if (!NFSBCMP(name, "GROUP@", 6)) { 90191783Srmacklem acep->ae_tag = ACL_GROUP_OBJ; 91191783Srmacklem acep->ae_id = ACL_UNDEFINED_ID; 92191783Srmacklem gotid = 1; 93191783Srmacklem } 94191783Srmacklem } else if (len == 9 && !NFSBCMP(name, "EVERYONE@", 9)) { 95191783Srmacklem acep->ae_tag = ACL_EVERYONE; 96191783Srmacklem acep->ae_id = ACL_UNDEFINED_ID; 97191783Srmacklem gotid = 1; 98191783Srmacklem } 99191783Srmacklem if (gotid == 0) { 100191783Srmacklem if (flag & NFSV4ACE_IDENTIFIERGROUP) { 101191783Srmacklem acep->ae_tag = ACL_GROUP; 102240720Srmacklem aceerr = nfsv4_strtogid(nd, name, len, &gid, p); 103191783Srmacklem if (aceerr == 0) 104191783Srmacklem acep->ae_id = (uid_t)gid; 105191783Srmacklem } else { 106191783Srmacklem acep->ae_tag = ACL_USER; 107240720Srmacklem aceerr = nfsv4_strtouid(nd, name, len, &uid, p); 108191783Srmacklem if (aceerr == 0) 109191783Srmacklem acep->ae_id = uid; 110191783Srmacklem } 111191783Srmacklem } 112191783Srmacklem if (len > NFSV4_SMALLSTR) 113191783Srmacklem free(name, M_NFSSTRING); 114191783Srmacklem 115191783Srmacklem if (aceerr == 0) { 116191783Srmacklem /* 117191783Srmacklem * Handle the flags. 118191783Srmacklem */ 119191783Srmacklem flag &= ~NFSV4ACE_IDENTIFIERGROUP; 120191783Srmacklem if (flag & NFSV4ACE_FILEINHERIT) { 121191783Srmacklem flag &= ~NFSV4ACE_FILEINHERIT; 122191783Srmacklem acep->ae_flags |= ACL_ENTRY_FILE_INHERIT; 123191783Srmacklem } 124191783Srmacklem if (flag & NFSV4ACE_DIRECTORYINHERIT) { 125191783Srmacklem flag &= ~NFSV4ACE_DIRECTORYINHERIT; 126191783Srmacklem acep->ae_flags |= ACL_ENTRY_DIRECTORY_INHERIT; 127191783Srmacklem } 128191783Srmacklem if (flag & NFSV4ACE_NOPROPAGATEINHERIT) { 129191783Srmacklem flag &= ~NFSV4ACE_NOPROPAGATEINHERIT; 130192818Strasz acep->ae_flags |= ACL_ENTRY_NO_PROPAGATE_INHERIT; 131191783Srmacklem } 132191783Srmacklem if (flag & NFSV4ACE_INHERITONLY) { 133191783Srmacklem flag &= ~NFSV4ACE_INHERITONLY; 134192818Strasz acep->ae_flags |= ACL_ENTRY_INHERIT_ONLY; 135191783Srmacklem } 136191783Srmacklem if (flag & NFSV4ACE_SUCCESSFULACCESS) { 137191783Srmacklem flag &= ~NFSV4ACE_SUCCESSFULACCESS; 138191783Srmacklem acep->ae_flags |= ACL_ENTRY_SUCCESSFUL_ACCESS; 139191783Srmacklem } 140191783Srmacklem if (flag & NFSV4ACE_FAILEDACCESS) { 141191783Srmacklem flag &= ~NFSV4ACE_FAILEDACCESS; 142191783Srmacklem acep->ae_flags |= ACL_ENTRY_FAILED_ACCESS; 143191783Srmacklem } 144191783Srmacklem /* 145192818Strasz * Set ae_entry_type. 146191783Srmacklem */ 147191783Srmacklem if (acetype == NFSV4ACE_ALLOWEDTYPE) 148192818Strasz acep->ae_entry_type = ACL_ENTRY_TYPE_ALLOW; 149191783Srmacklem else if (acetype == NFSV4ACE_DENIEDTYPE) 150192818Strasz acep->ae_entry_type = ACL_ENTRY_TYPE_DENY; 151191783Srmacklem else if (acetype == NFSV4ACE_AUDITTYPE) 152192818Strasz acep->ae_entry_type = ACL_ENTRY_TYPE_AUDIT; 153191783Srmacklem else if (acetype == NFSV4ACE_ALARMTYPE) 154192818Strasz acep->ae_entry_type = ACL_ENTRY_TYPE_ALARM; 155191783Srmacklem else 156191783Srmacklem aceerr = NFSERR_ATTRNOTSUPP; 157191783Srmacklem } 158191783Srmacklem 159191783Srmacklem /* 160191783Srmacklem * Now, check for unsupported flag bits. 161191783Srmacklem */ 162191783Srmacklem if (aceerr == 0 && flag != 0) 163191783Srmacklem aceerr = NFSERR_ATTRNOTSUPP; 164191783Srmacklem 165191783Srmacklem /* 166191783Srmacklem * And turn the mask into perm bits. 167191783Srmacklem */ 168191783Srmacklem if (aceerr == 0) 169191783Srmacklem aceerr = nfsrv_acemasktoperm(acetype, mask, owner, VREG, 170191783Srmacklem &acep->ae_perm); 171191783Srmacklem *aceerrp = aceerr; 172191783Srmacklem if (acesizep) 173191783Srmacklem *acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED); 174224086Szack error = 0; 175191783Srmacklemnfsmout: 176224086Szack NFSEXITCODE(error); 177191783Srmacklem return (error); 178191783Srmacklem} 179191783Srmacklem 180191783Srmacklem/* 181191783Srmacklem * Turn an NFSv4 ace mask into R/W/X flag bits. 182191783Srmacklem */ 183191783Srmacklemstatic int 184191783Srmacklemnfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner, 185191783Srmacklem enum vtype type, acl_perm_t *permp) 186191783Srmacklem{ 187191783Srmacklem acl_perm_t perm = 0x0; 188224086Szack int error = 0; 189191783Srmacklem 190191783Srmacklem if (mask & NFSV4ACE_READDATA) { 191191783Srmacklem mask &= ~NFSV4ACE_READDATA; 192191783Srmacklem perm |= ACL_READ_DATA; 193191783Srmacklem } 194191783Srmacklem if (mask & NFSV4ACE_LISTDIRECTORY) { 195191783Srmacklem mask &= ~NFSV4ACE_LISTDIRECTORY; 196191783Srmacklem perm |= ACL_LIST_DIRECTORY; 197191783Srmacklem } 198191783Srmacklem if (mask & NFSV4ACE_WRITEDATA) { 199191783Srmacklem mask &= ~NFSV4ACE_WRITEDATA; 200191783Srmacklem perm |= ACL_WRITE_DATA; 201191783Srmacklem } 202191783Srmacklem if (mask & NFSV4ACE_ADDFILE) { 203191783Srmacklem mask &= ~NFSV4ACE_ADDFILE; 204191783Srmacklem perm |= ACL_ADD_FILE; 205191783Srmacklem } 206191783Srmacklem if (mask & NFSV4ACE_APPENDDATA) { 207191783Srmacklem mask &= ~NFSV4ACE_APPENDDATA; 208191783Srmacklem perm |= ACL_APPEND_DATA; 209191783Srmacklem } 210191783Srmacklem if (mask & NFSV4ACE_ADDSUBDIRECTORY) { 211191783Srmacklem mask &= ~NFSV4ACE_ADDSUBDIRECTORY; 212191783Srmacklem perm |= ACL_ADD_SUBDIRECTORY; 213191783Srmacklem } 214191783Srmacklem if (mask & NFSV4ACE_READNAMEDATTR) { 215191783Srmacklem mask &= ~NFSV4ACE_READNAMEDATTR; 216191783Srmacklem perm |= ACL_READ_NAMED_ATTRS; 217191783Srmacklem } 218191783Srmacklem if (mask & NFSV4ACE_WRITENAMEDATTR) { 219191783Srmacklem mask &= ~NFSV4ACE_WRITENAMEDATTR; 220191783Srmacklem perm |= ACL_WRITE_NAMED_ATTRS; 221191783Srmacklem } 222191783Srmacklem if (mask & NFSV4ACE_EXECUTE) { 223191783Srmacklem mask &= ~NFSV4ACE_EXECUTE; 224191783Srmacklem perm |= ACL_EXECUTE; 225191783Srmacklem } 226191783Srmacklem if (mask & NFSV4ACE_SEARCH) { 227191783Srmacklem mask &= ~NFSV4ACE_SEARCH; 228192861Srmacklem perm |= ACL_EXECUTE; 229191783Srmacklem } 230191783Srmacklem if (mask & NFSV4ACE_DELETECHILD) { 231191783Srmacklem mask &= ~NFSV4ACE_DELETECHILD; 232191783Srmacklem perm |= ACL_DELETE_CHILD; 233191783Srmacklem } 234191783Srmacklem if (mask & NFSV4ACE_READATTRIBUTES) { 235191783Srmacklem mask &= ~NFSV4ACE_READATTRIBUTES; 236191783Srmacklem perm |= ACL_READ_ATTRIBUTES; 237191783Srmacklem } 238191783Srmacklem if (mask & NFSV4ACE_WRITEATTRIBUTES) { 239191783Srmacklem mask &= ~NFSV4ACE_WRITEATTRIBUTES; 240191783Srmacklem perm |= ACL_WRITE_ATTRIBUTES; 241191783Srmacklem } 242191783Srmacklem if (mask & NFSV4ACE_DELETE) { 243191783Srmacklem mask &= ~NFSV4ACE_DELETE; 244191783Srmacklem perm |= ACL_DELETE; 245191783Srmacklem } 246191783Srmacklem if (mask & NFSV4ACE_READACL) { 247191783Srmacklem mask &= ~NFSV4ACE_READACL; 248191783Srmacklem perm |= ACL_READ_ACL; 249191783Srmacklem } 250191783Srmacklem if (mask & NFSV4ACE_WRITEACL) { 251191783Srmacklem mask &= ~NFSV4ACE_WRITEACL; 252191783Srmacklem perm |= ACL_WRITE_ACL; 253191783Srmacklem } 254191783Srmacklem if (mask & NFSV4ACE_WRITEOWNER) { 255191783Srmacklem mask &= ~NFSV4ACE_WRITEOWNER; 256191783Srmacklem perm |= ACL_WRITE_OWNER; 257191783Srmacklem } 258191783Srmacklem if (mask & NFSV4ACE_SYNCHRONIZE) { 259191783Srmacklem mask &= ~NFSV4ACE_SYNCHRONIZE; 260191783Srmacklem perm |= ACL_SYNCHRONIZE; 261191783Srmacklem } 262224086Szack if (mask != 0) { 263224086Szack error = NFSERR_ATTRNOTSUPP; 264224086Szack goto out; 265224086Szack } 266191783Srmacklem *permp = perm; 267224086Szack 268224086Szackout: 269224086Szack NFSEXITCODE(error); 270224086Szack return (error); 271191783Srmacklem} 272191783Srmacklem 273191783Srmacklem/* local functions */ 274191783Srmacklemstatic int nfsrv_buildace(struct nfsrv_descript *, u_char *, int, 275191783Srmacklem enum vtype, int, int, struct acl_entry *); 276191783Srmacklem 277191783Srmacklem/* 278191783Srmacklem * This function builds an NFS ace. 279191783Srmacklem */ 280191783Srmacklemstatic int 281191783Srmacklemnfsrv_buildace(struct nfsrv_descript *nd, u_char *name, int namelen, 282191783Srmacklem enum vtype type, int group, int owner, struct acl_entry *ace) 283191783Srmacklem{ 284191783Srmacklem u_int32_t *tl, aceflag = 0x0, acemask = 0x0, acetype; 285191783Srmacklem int full_len; 286191783Srmacklem 287191783Srmacklem full_len = NFSM_RNDUP(namelen); 288191783Srmacklem NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED + full_len); 289191783Srmacklem 290191783Srmacklem /* 291191783Srmacklem * Fill in the ace type. 292191783Srmacklem */ 293192818Strasz if (ace->ae_entry_type & ACL_ENTRY_TYPE_ALLOW) 294191783Srmacklem acetype = NFSV4ACE_ALLOWEDTYPE; 295192818Strasz else if (ace->ae_entry_type & ACL_ENTRY_TYPE_DENY) 296191783Srmacklem acetype = NFSV4ACE_DENIEDTYPE; 297192818Strasz else if (ace->ae_entry_type & ACL_ENTRY_TYPE_AUDIT) 298191783Srmacklem acetype = NFSV4ACE_AUDITTYPE; 299191783Srmacklem else 300191783Srmacklem acetype = NFSV4ACE_ALARMTYPE; 301191783Srmacklem *tl++ = txdr_unsigned(acetype); 302191783Srmacklem 303191783Srmacklem /* 304191783Srmacklem * Set the flag bits from the ACL. 305191783Srmacklem */ 306191783Srmacklem if (ace->ae_flags & ACL_ENTRY_FILE_INHERIT) 307191783Srmacklem aceflag |= NFSV4ACE_FILEINHERIT; 308191783Srmacklem if (ace->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT) 309191783Srmacklem aceflag |= NFSV4ACE_DIRECTORYINHERIT; 310192818Strasz if (ace->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT) 311191783Srmacklem aceflag |= NFSV4ACE_NOPROPAGATEINHERIT; 312192818Strasz if (ace->ae_flags & ACL_ENTRY_INHERIT_ONLY) 313191783Srmacklem aceflag |= NFSV4ACE_INHERITONLY; 314191783Srmacklem if (ace->ae_flags & ACL_ENTRY_SUCCESSFUL_ACCESS) 315191783Srmacklem aceflag |= NFSV4ACE_SUCCESSFULACCESS; 316191783Srmacklem if (ace->ae_flags & ACL_ENTRY_FAILED_ACCESS) 317191783Srmacklem aceflag |= NFSV4ACE_FAILEDACCESS; 318191783Srmacklem if (group) 319191783Srmacklem aceflag |= NFSV4ACE_IDENTIFIERGROUP; 320191783Srmacklem *tl++ = txdr_unsigned(aceflag); 321191783Srmacklem if (type == VDIR) { 322191783Srmacklem if (ace->ae_perm & ACL_LIST_DIRECTORY) 323191783Srmacklem acemask |= NFSV4ACE_LISTDIRECTORY; 324191783Srmacklem if (ace->ae_perm & ACL_ADD_FILE) 325191783Srmacklem acemask |= NFSV4ACE_ADDFILE; 326191783Srmacklem if (ace->ae_perm & ACL_ADD_SUBDIRECTORY) 327191783Srmacklem acemask |= NFSV4ACE_ADDSUBDIRECTORY; 328191783Srmacklem if (ace->ae_perm & ACL_READ_NAMED_ATTRS) 329191783Srmacklem acemask |= NFSV4ACE_READNAMEDATTR; 330191783Srmacklem if (ace->ae_perm & ACL_WRITE_NAMED_ATTRS) 331191783Srmacklem acemask |= NFSV4ACE_WRITENAMEDATTR; 332192861Srmacklem if (ace->ae_perm & ACL_EXECUTE) 333191783Srmacklem acemask |= NFSV4ACE_SEARCH; 334191783Srmacklem if (ace->ae_perm & ACL_DELETE_CHILD) 335191783Srmacklem acemask |= NFSV4ACE_DELETECHILD; 336191783Srmacklem if (ace->ae_perm & ACL_READ_ATTRIBUTES) 337191783Srmacklem acemask |= NFSV4ACE_READATTRIBUTES; 338191783Srmacklem if (ace->ae_perm & ACL_WRITE_ATTRIBUTES) 339191783Srmacklem acemask |= NFSV4ACE_WRITEATTRIBUTES; 340191783Srmacklem if (ace->ae_perm & ACL_DELETE) 341191783Srmacklem acemask |= NFSV4ACE_DELETE; 342191783Srmacklem if (ace->ae_perm & ACL_READ_ACL) 343191783Srmacklem acemask |= NFSV4ACE_READACL; 344191783Srmacklem if (ace->ae_perm & ACL_WRITE_ACL) 345191783Srmacklem acemask |= NFSV4ACE_WRITEACL; 346191783Srmacklem if (ace->ae_perm & ACL_WRITE_OWNER) 347191783Srmacklem acemask |= NFSV4ACE_WRITEOWNER; 348287256Strasz if (ace->ae_perm & ACL_SYNCHRONIZE) 349287256Strasz acemask |= NFSV4ACE_SYNCHRONIZE; 350191783Srmacklem } else { 351191783Srmacklem if (ace->ae_perm & ACL_READ_DATA) 352191783Srmacklem acemask |= NFSV4ACE_READDATA; 353191783Srmacklem if (ace->ae_perm & ACL_WRITE_DATA) 354191783Srmacklem acemask |= NFSV4ACE_WRITEDATA; 355191783Srmacklem if (ace->ae_perm & ACL_APPEND_DATA) 356191783Srmacklem acemask |= NFSV4ACE_APPENDDATA; 357191783Srmacklem if (ace->ae_perm & ACL_READ_NAMED_ATTRS) 358191783Srmacklem acemask |= NFSV4ACE_READNAMEDATTR; 359191783Srmacklem if (ace->ae_perm & ACL_WRITE_NAMED_ATTRS) 360191783Srmacklem acemask |= NFSV4ACE_WRITENAMEDATTR; 361191783Srmacklem if (ace->ae_perm & ACL_EXECUTE) 362191783Srmacklem acemask |= NFSV4ACE_EXECUTE; 363191783Srmacklem if (ace->ae_perm & ACL_READ_ATTRIBUTES) 364191783Srmacklem acemask |= NFSV4ACE_READATTRIBUTES; 365191783Srmacklem if (ace->ae_perm & ACL_WRITE_ATTRIBUTES) 366191783Srmacklem acemask |= NFSV4ACE_WRITEATTRIBUTES; 367191783Srmacklem if (ace->ae_perm & ACL_DELETE) 368191783Srmacklem acemask |= NFSV4ACE_DELETE; 369191783Srmacklem if (ace->ae_perm & ACL_READ_ACL) 370191783Srmacklem acemask |= NFSV4ACE_READACL; 371191783Srmacklem if (ace->ae_perm & ACL_WRITE_ACL) 372191783Srmacklem acemask |= NFSV4ACE_WRITEACL; 373191783Srmacklem if (ace->ae_perm & ACL_WRITE_OWNER) 374191783Srmacklem acemask |= NFSV4ACE_WRITEOWNER; 375191783Srmacklem if (ace->ae_perm & ACL_SYNCHRONIZE) 376191783Srmacklem acemask |= NFSV4ACE_SYNCHRONIZE; 377191783Srmacklem } 378191783Srmacklem *tl++ = txdr_unsigned(acemask); 379191783Srmacklem *tl++ = txdr_unsigned(namelen); 380191783Srmacklem if (full_len - namelen) 381191783Srmacklem *(tl + (namelen / NFSX_UNSIGNED)) = 0x0; 382191783Srmacklem NFSBCOPY(name, (caddr_t)tl, namelen); 383191783Srmacklem return (full_len + 4 * NFSX_UNSIGNED); 384191783Srmacklem} 385191783Srmacklem 386191783Srmacklem/* 387191783Srmacklem * Build an NFSv4 ACL. 388191783Srmacklem */ 389361236Sfreqlabsint 390191783Srmacklemnfsrv_buildacl(struct nfsrv_descript *nd, NFSACL_T *aclp, enum vtype type, 391191783Srmacklem NFSPROC_T *p) 392191783Srmacklem{ 393191783Srmacklem int i, entrycnt = 0, retlen; 394191783Srmacklem u_int32_t *entrycntp; 395191783Srmacklem int isowner, isgroup, namelen, malloced; 396191783Srmacklem u_char *name, namestr[NFSV4_SMALLSTR]; 397191783Srmacklem 398191783Srmacklem NFSM_BUILD(entrycntp, u_int32_t *, NFSX_UNSIGNED); 399191783Srmacklem retlen = NFSX_UNSIGNED; 400191783Srmacklem /* 401191783Srmacklem * Loop through the acl entries, building each one. 402191783Srmacklem */ 403191783Srmacklem for (i = 0; i < aclp->acl_cnt; i++) { 404191783Srmacklem isowner = isgroup = malloced = 0; 405191783Srmacklem switch (aclp->acl_entry[i].ae_tag) { 406191783Srmacklem case ACL_USER_OBJ: 407191783Srmacklem isowner = 1; 408191783Srmacklem name = "OWNER@"; 409191783Srmacklem namelen = 6; 410191783Srmacklem break; 411191783Srmacklem case ACL_GROUP_OBJ: 412191783Srmacklem isgroup = 1; 413191783Srmacklem name = "GROUP@"; 414191783Srmacklem namelen = 6; 415191783Srmacklem break; 416191783Srmacklem case ACL_EVERYONE: 417191783Srmacklem name = "EVERYONE@"; 418191783Srmacklem namelen = 9; 419191783Srmacklem break; 420191783Srmacklem case ACL_USER: 421191783Srmacklem name = namestr; 422191783Srmacklem nfsv4_uidtostr(aclp->acl_entry[i].ae_id, &name, 423191783Srmacklem &namelen, p); 424191783Srmacklem if (name != namestr) 425191783Srmacklem malloced = 1; 426191783Srmacklem break; 427191783Srmacklem case ACL_GROUP: 428191783Srmacklem isgroup = 1; 429191783Srmacklem name = namestr; 430191783Srmacklem nfsv4_gidtostr((gid_t)aclp->acl_entry[i].ae_id, &name, 431191783Srmacklem &namelen, p); 432191783Srmacklem if (name != namestr) 433191783Srmacklem malloced = 1; 434191783Srmacklem break; 435191783Srmacklem default: 436191783Srmacklem continue; 437297793Spfg } 438191783Srmacklem retlen += nfsrv_buildace(nd, name, namelen, type, isgroup, 439191783Srmacklem isowner, &aclp->acl_entry[i]); 440191783Srmacklem entrycnt++; 441191783Srmacklem if (malloced) 442191783Srmacklem free(name, M_NFSSTRING); 443191783Srmacklem } 444191783Srmacklem *entrycntp = txdr_unsigned(entrycnt); 445191783Srmacklem return (retlen); 446191783Srmacklem} 447191783Srmacklem 448191783Srmacklem/* 449191783Srmacklem * Set an NFSv4 acl. 450191783Srmacklem */ 451361236Sfreqlabsint 452191783Srmacklemnfsrv_setacl(vnode_t vp, NFSACL_T *aclp, struct ucred *cred, 453191783Srmacklem NFSPROC_T *p) 454191783Srmacklem{ 455191783Srmacklem int error; 456191783Srmacklem 457224086Szack if (nfsrv_useacl == 0 || nfs_supportsnfsv4acls(vp) == 0) { 458224086Szack error = NFSERR_ATTRNOTSUPP; 459224086Szack goto out; 460224086Szack } 461191783Srmacklem /* 462197650Strasz * With NFSv4 ACLs, chmod(2) may need to add additional entries. 463191783Srmacklem * Make sure it has enough room for that - splitting every entry 464191783Srmacklem * into two and appending "canonical six" entries at the end. 465191783Srmacklem * Cribbed out of kern/vfs_acl.c - Rick M. 466191783Srmacklem */ 467224086Szack if (aclp->acl_cnt > (ACL_MAX_ENTRIES - 6) / 2) { 468224086Szack error = NFSERR_ATTRNOTSUPP; 469224086Szack goto out; 470224086Szack } 471235568Srmacklem error = VOP_SETACL(vp, ACL_TYPE_NFS4, aclp, cred, p); 472224086Szack 473224086Szackout: 474224086Szack NFSEXITCODE(error); 475191783Srmacklem return (error); 476191783Srmacklem} 477191783Srmacklem 478191783Srmacklem/* 479191783Srmacklem * Compare two NFSv4 acls. 480191783Srmacklem * Return 0 if they are the same, 1 if not the same. 481191783Srmacklem */ 482361236Sfreqlabsint 483191783Srmacklemnfsrv_compareacl(NFSACL_T *aclp1, NFSACL_T *aclp2) 484191783Srmacklem{ 485191783Srmacklem int i; 486191783Srmacklem struct acl_entry *acep1, *acep2; 487191783Srmacklem 488191783Srmacklem if (aclp1->acl_cnt != aclp2->acl_cnt) 489191783Srmacklem return (1); 490191783Srmacklem acep1 = aclp1->acl_entry; 491191783Srmacklem acep2 = aclp2->acl_entry; 492191783Srmacklem for (i = 0; i < aclp1->acl_cnt; i++) { 493191783Srmacklem if (acep1->ae_tag != acep2->ae_tag) 494191783Srmacklem return (1); 495191783Srmacklem switch (acep1->ae_tag) { 496191783Srmacklem case ACL_GROUP: 497191783Srmacklem case ACL_USER: 498191783Srmacklem if (acep1->ae_id != acep2->ae_id) 499191783Srmacklem return (1); 500191783Srmacklem /* fall through */ 501191783Srmacklem case ACL_USER_OBJ: 502191783Srmacklem case ACL_GROUP_OBJ: 503191783Srmacklem case ACL_OTHER: 504191783Srmacklem if (acep1->ae_perm != acep2->ae_perm) 505191783Srmacklem return (1); 506297793Spfg } 507191783Srmacklem acep1++; 508191783Srmacklem acep2++; 509191783Srmacklem } 510191783Srmacklem return (0); 511191783Srmacklem} 512