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$"); 30191783Srmacklem 31191783Srmacklem#ifndef APPLEKEXT 32191783Srmacklem#include <fs/nfs/nfsport.h> 33191783Srmacklem 34191783Srmacklemextern int nfsrv_useacl; 35191783Srmacklem#endif 36191783Srmacklem 37191783Srmacklemstatic int nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner, 38191783Srmacklem enum vtype type, acl_perm_t *permp); 39191783Srmacklem 40191783Srmacklem/* 41191783Srmacklem * Handle xdr for an ace. 42191783Srmacklem */ 43191783SrmacklemAPPLESTATIC int 44191783Srmacklemnfsrv_dissectace(struct nfsrv_descript *nd, struct acl_entry *acep, 45191783Srmacklem int *aceerrp, int *acesizep, NFSPROC_T *p) 46191783Srmacklem{ 47191783Srmacklem u_int32_t *tl; 48191783Srmacklem int len, gotid = 0, owner = 0, error = 0, aceerr = 0; 49191783Srmacklem u_char *name, namestr[NFSV4_SMALLSTR + 1]; 50191783Srmacklem u_int32_t flag, mask, acetype; 51191783Srmacklem gid_t gid; 52191783Srmacklem uid_t uid; 53191783Srmacklem 54191783Srmacklem *aceerrp = 0; 55191783Srmacklem acep->ae_flags = 0; 56191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 57191783Srmacklem acetype = fxdr_unsigned(u_int32_t, *tl++); 58191783Srmacklem flag = fxdr_unsigned(u_int32_t, *tl++); 59191783Srmacklem mask = fxdr_unsigned(u_int32_t, *tl++); 60191783Srmacklem len = fxdr_unsigned(int, *tl); 61191783Srmacklem if (len < 0) { 62224086Szack error = NFSERR_BADXDR; 63224086Szack goto nfsmout; 64191783Srmacklem } else if (len == 0) { 65191783Srmacklem /* Netapp filers return a 0 length who for nil users */ 66191783Srmacklem acep->ae_tag = ACL_UNDEFINED_TAG; 67191783Srmacklem acep->ae_id = ACL_UNDEFINED_ID; 68191783Srmacklem acep->ae_perm = (acl_perm_t)0; 69192818Strasz acep->ae_entry_type = ACL_ENTRY_TYPE_DENY; 70191783Srmacklem if (acesizep) 71191783Srmacklem *acesizep = 4 * NFSX_UNSIGNED; 72224086Szack error = 0; 73224086Szack goto nfsmout; 74191783Srmacklem } 75191783Srmacklem if (len > NFSV4_SMALLSTR) 76191783Srmacklem name = malloc(len + 1, M_NFSSTRING, M_WAITOK); 77191783Srmacklem else 78191783Srmacklem name = namestr; 79191783Srmacklem error = nfsrv_mtostr(nd, name, len); 80191783Srmacklem if (error) { 81191783Srmacklem if (len > NFSV4_SMALLSTR) 82191783Srmacklem free(name, M_NFSSTRING); 83224086Szack goto nfsmout; 84191783Srmacklem } 85191783Srmacklem if (len == 6) { 86191783Srmacklem if (!NFSBCMP(name, "OWNER@", 6)) { 87191783Srmacklem acep->ae_tag = ACL_USER_OBJ; 88191783Srmacklem acep->ae_id = ACL_UNDEFINED_ID; 89191783Srmacklem owner = 1; 90191783Srmacklem gotid = 1; 91191783Srmacklem } else if (!NFSBCMP(name, "GROUP@", 6)) { 92191783Srmacklem acep->ae_tag = ACL_GROUP_OBJ; 93191783Srmacklem acep->ae_id = ACL_UNDEFINED_ID; 94191783Srmacklem gotid = 1; 95191783Srmacklem } 96191783Srmacklem } else if (len == 9 && !NFSBCMP(name, "EVERYONE@", 9)) { 97191783Srmacklem acep->ae_tag = ACL_EVERYONE; 98191783Srmacklem acep->ae_id = ACL_UNDEFINED_ID; 99191783Srmacklem gotid = 1; 100191783Srmacklem } 101191783Srmacklem if (gotid == 0) { 102191783Srmacklem if (flag & NFSV4ACE_IDENTIFIERGROUP) { 103191783Srmacklem acep->ae_tag = ACL_GROUP; 104240720Srmacklem aceerr = nfsv4_strtogid(nd, name, len, &gid, p); 105191783Srmacklem if (aceerr == 0) 106191783Srmacklem acep->ae_id = (uid_t)gid; 107191783Srmacklem } else { 108191783Srmacklem acep->ae_tag = ACL_USER; 109240720Srmacklem aceerr = nfsv4_strtouid(nd, name, len, &uid, p); 110191783Srmacklem if (aceerr == 0) 111191783Srmacklem acep->ae_id = uid; 112191783Srmacklem } 113191783Srmacklem } 114191783Srmacklem if (len > NFSV4_SMALLSTR) 115191783Srmacklem free(name, M_NFSSTRING); 116191783Srmacklem 117191783Srmacklem if (aceerr == 0) { 118191783Srmacklem /* 119191783Srmacklem * Handle the flags. 120191783Srmacklem */ 121191783Srmacklem flag &= ~NFSV4ACE_IDENTIFIERGROUP; 122191783Srmacklem if (flag & NFSV4ACE_FILEINHERIT) { 123191783Srmacklem flag &= ~NFSV4ACE_FILEINHERIT; 124191783Srmacklem acep->ae_flags |= ACL_ENTRY_FILE_INHERIT; 125191783Srmacklem } 126191783Srmacklem if (flag & NFSV4ACE_DIRECTORYINHERIT) { 127191783Srmacklem flag &= ~NFSV4ACE_DIRECTORYINHERIT; 128191783Srmacklem acep->ae_flags |= ACL_ENTRY_DIRECTORY_INHERIT; 129191783Srmacklem } 130191783Srmacklem if (flag & NFSV4ACE_NOPROPAGATEINHERIT) { 131191783Srmacklem flag &= ~NFSV4ACE_NOPROPAGATEINHERIT; 132192818Strasz acep->ae_flags |= ACL_ENTRY_NO_PROPAGATE_INHERIT; 133191783Srmacklem } 134191783Srmacklem if (flag & NFSV4ACE_INHERITONLY) { 135191783Srmacklem flag &= ~NFSV4ACE_INHERITONLY; 136192818Strasz acep->ae_flags |= ACL_ENTRY_INHERIT_ONLY; 137191783Srmacklem } 138191783Srmacklem if (flag & NFSV4ACE_SUCCESSFULACCESS) { 139191783Srmacklem flag &= ~NFSV4ACE_SUCCESSFULACCESS; 140191783Srmacklem acep->ae_flags |= ACL_ENTRY_SUCCESSFUL_ACCESS; 141191783Srmacklem } 142191783Srmacklem if (flag & NFSV4ACE_FAILEDACCESS) { 143191783Srmacklem flag &= ~NFSV4ACE_FAILEDACCESS; 144191783Srmacklem acep->ae_flags |= ACL_ENTRY_FAILED_ACCESS; 145191783Srmacklem } 146191783Srmacklem /* 147192818Strasz * Set ae_entry_type. 148191783Srmacklem */ 149191783Srmacklem if (acetype == NFSV4ACE_ALLOWEDTYPE) 150192818Strasz acep->ae_entry_type = ACL_ENTRY_TYPE_ALLOW; 151191783Srmacklem else if (acetype == NFSV4ACE_DENIEDTYPE) 152192818Strasz acep->ae_entry_type = ACL_ENTRY_TYPE_DENY; 153191783Srmacklem else if (acetype == NFSV4ACE_AUDITTYPE) 154192818Strasz acep->ae_entry_type = ACL_ENTRY_TYPE_AUDIT; 155191783Srmacklem else if (acetype == NFSV4ACE_ALARMTYPE) 156192818Strasz acep->ae_entry_type = ACL_ENTRY_TYPE_ALARM; 157191783Srmacklem else 158191783Srmacklem aceerr = NFSERR_ATTRNOTSUPP; 159191783Srmacklem } 160191783Srmacklem 161191783Srmacklem /* 162191783Srmacklem * Now, check for unsupported flag bits. 163191783Srmacklem */ 164191783Srmacklem if (aceerr == 0 && flag != 0) 165191783Srmacklem aceerr = NFSERR_ATTRNOTSUPP; 166191783Srmacklem 167191783Srmacklem /* 168191783Srmacklem * And turn the mask into perm bits. 169191783Srmacklem */ 170191783Srmacklem if (aceerr == 0) 171191783Srmacklem aceerr = nfsrv_acemasktoperm(acetype, mask, owner, VREG, 172191783Srmacklem &acep->ae_perm); 173191783Srmacklem *aceerrp = aceerr; 174191783Srmacklem if (acesizep) 175191783Srmacklem *acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED); 176224086Szack error = 0; 177191783Srmacklemnfsmout: 178224086Szack NFSEXITCODE(error); 179191783Srmacklem return (error); 180191783Srmacklem} 181191783Srmacklem 182191783Srmacklem/* 183191783Srmacklem * Turn an NFSv4 ace mask into R/W/X flag bits. 184191783Srmacklem */ 185191783Srmacklemstatic int 186191783Srmacklemnfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner, 187191783Srmacklem enum vtype type, acl_perm_t *permp) 188191783Srmacklem{ 189191783Srmacklem acl_perm_t perm = 0x0; 190224086Szack int error = 0; 191191783Srmacklem 192191783Srmacklem if (mask & NFSV4ACE_READDATA) { 193191783Srmacklem mask &= ~NFSV4ACE_READDATA; 194191783Srmacklem perm |= ACL_READ_DATA; 195191783Srmacklem } 196191783Srmacklem if (mask & NFSV4ACE_LISTDIRECTORY) { 197191783Srmacklem mask &= ~NFSV4ACE_LISTDIRECTORY; 198191783Srmacklem perm |= ACL_LIST_DIRECTORY; 199191783Srmacklem } 200191783Srmacklem if (mask & NFSV4ACE_WRITEDATA) { 201191783Srmacklem mask &= ~NFSV4ACE_WRITEDATA; 202191783Srmacklem perm |= ACL_WRITE_DATA; 203191783Srmacklem } 204191783Srmacklem if (mask & NFSV4ACE_ADDFILE) { 205191783Srmacklem mask &= ~NFSV4ACE_ADDFILE; 206191783Srmacklem perm |= ACL_ADD_FILE; 207191783Srmacklem } 208191783Srmacklem if (mask & NFSV4ACE_APPENDDATA) { 209191783Srmacklem mask &= ~NFSV4ACE_APPENDDATA; 210191783Srmacklem perm |= ACL_APPEND_DATA; 211191783Srmacklem } 212191783Srmacklem if (mask & NFSV4ACE_ADDSUBDIRECTORY) { 213191783Srmacklem mask &= ~NFSV4ACE_ADDSUBDIRECTORY; 214191783Srmacklem perm |= ACL_ADD_SUBDIRECTORY; 215191783Srmacklem } 216191783Srmacklem if (mask & NFSV4ACE_READNAMEDATTR) { 217191783Srmacklem mask &= ~NFSV4ACE_READNAMEDATTR; 218191783Srmacklem perm |= ACL_READ_NAMED_ATTRS; 219191783Srmacklem } 220191783Srmacklem if (mask & NFSV4ACE_WRITENAMEDATTR) { 221191783Srmacklem mask &= ~NFSV4ACE_WRITENAMEDATTR; 222191783Srmacklem perm |= ACL_WRITE_NAMED_ATTRS; 223191783Srmacklem } 224191783Srmacklem if (mask & NFSV4ACE_EXECUTE) { 225191783Srmacklem mask &= ~NFSV4ACE_EXECUTE; 226191783Srmacklem perm |= ACL_EXECUTE; 227191783Srmacklem } 228191783Srmacklem if (mask & NFSV4ACE_SEARCH) { 229191783Srmacklem mask &= ~NFSV4ACE_SEARCH; 230192861Srmacklem perm |= ACL_EXECUTE; 231191783Srmacklem } 232191783Srmacklem if (mask & NFSV4ACE_DELETECHILD) { 233191783Srmacklem mask &= ~NFSV4ACE_DELETECHILD; 234191783Srmacklem perm |= ACL_DELETE_CHILD; 235191783Srmacklem } 236191783Srmacklem if (mask & NFSV4ACE_READATTRIBUTES) { 237191783Srmacklem mask &= ~NFSV4ACE_READATTRIBUTES; 238191783Srmacklem perm |= ACL_READ_ATTRIBUTES; 239191783Srmacklem } 240191783Srmacklem if (mask & NFSV4ACE_WRITEATTRIBUTES) { 241191783Srmacklem mask &= ~NFSV4ACE_WRITEATTRIBUTES; 242191783Srmacklem perm |= ACL_WRITE_ATTRIBUTES; 243191783Srmacklem } 244191783Srmacklem if (mask & NFSV4ACE_DELETE) { 245191783Srmacklem mask &= ~NFSV4ACE_DELETE; 246191783Srmacklem perm |= ACL_DELETE; 247191783Srmacklem } 248191783Srmacklem if (mask & NFSV4ACE_READACL) { 249191783Srmacklem mask &= ~NFSV4ACE_READACL; 250191783Srmacklem perm |= ACL_READ_ACL; 251191783Srmacklem } 252191783Srmacklem if (mask & NFSV4ACE_WRITEACL) { 253191783Srmacklem mask &= ~NFSV4ACE_WRITEACL; 254191783Srmacklem perm |= ACL_WRITE_ACL; 255191783Srmacklem } 256191783Srmacklem if (mask & NFSV4ACE_WRITEOWNER) { 257191783Srmacklem mask &= ~NFSV4ACE_WRITEOWNER; 258191783Srmacklem perm |= ACL_WRITE_OWNER; 259191783Srmacklem } 260191783Srmacklem if (mask & NFSV4ACE_SYNCHRONIZE) { 261191783Srmacklem mask &= ~NFSV4ACE_SYNCHRONIZE; 262191783Srmacklem perm |= ACL_SYNCHRONIZE; 263191783Srmacklem } 264224086Szack if (mask != 0) { 265224086Szack error = NFSERR_ATTRNOTSUPP; 266224086Szack goto out; 267224086Szack } 268191783Srmacklem *permp = perm; 269224086Szack 270224086Szackout: 271224086Szack NFSEXITCODE(error); 272224086Szack return (error); 273191783Srmacklem} 274191783Srmacklem 275191783Srmacklem/* local functions */ 276191783Srmacklemstatic int nfsrv_buildace(struct nfsrv_descript *, u_char *, int, 277191783Srmacklem enum vtype, int, int, struct acl_entry *); 278191783Srmacklem 279191783Srmacklem/* 280191783Srmacklem * This function builds an NFS ace. 281191783Srmacklem */ 282191783Srmacklemstatic int 283191783Srmacklemnfsrv_buildace(struct nfsrv_descript *nd, u_char *name, int namelen, 284191783Srmacklem enum vtype type, int group, int owner, struct acl_entry *ace) 285191783Srmacklem{ 286191783Srmacklem u_int32_t *tl, aceflag = 0x0, acemask = 0x0, acetype; 287191783Srmacklem int full_len; 288191783Srmacklem 289191783Srmacklem full_len = NFSM_RNDUP(namelen); 290191783Srmacklem NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED + full_len); 291191783Srmacklem 292191783Srmacklem /* 293191783Srmacklem * Fill in the ace type. 294191783Srmacklem */ 295192818Strasz if (ace->ae_entry_type & ACL_ENTRY_TYPE_ALLOW) 296191783Srmacklem acetype = NFSV4ACE_ALLOWEDTYPE; 297192818Strasz else if (ace->ae_entry_type & ACL_ENTRY_TYPE_DENY) 298191783Srmacklem acetype = NFSV4ACE_DENIEDTYPE; 299192818Strasz else if (ace->ae_entry_type & ACL_ENTRY_TYPE_AUDIT) 300191783Srmacklem acetype = NFSV4ACE_AUDITTYPE; 301191783Srmacklem else 302191783Srmacklem acetype = NFSV4ACE_ALARMTYPE; 303191783Srmacklem *tl++ = txdr_unsigned(acetype); 304191783Srmacklem 305191783Srmacklem /* 306191783Srmacklem * Set the flag bits from the ACL. 307191783Srmacklem */ 308191783Srmacklem if (ace->ae_flags & ACL_ENTRY_FILE_INHERIT) 309191783Srmacklem aceflag |= NFSV4ACE_FILEINHERIT; 310191783Srmacklem if (ace->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT) 311191783Srmacklem aceflag |= NFSV4ACE_DIRECTORYINHERIT; 312192818Strasz if (ace->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT) 313191783Srmacklem aceflag |= NFSV4ACE_NOPROPAGATEINHERIT; 314192818Strasz if (ace->ae_flags & ACL_ENTRY_INHERIT_ONLY) 315191783Srmacklem aceflag |= NFSV4ACE_INHERITONLY; 316191783Srmacklem if (ace->ae_flags & ACL_ENTRY_SUCCESSFUL_ACCESS) 317191783Srmacklem aceflag |= NFSV4ACE_SUCCESSFULACCESS; 318191783Srmacklem if (ace->ae_flags & ACL_ENTRY_FAILED_ACCESS) 319191783Srmacklem aceflag |= NFSV4ACE_FAILEDACCESS; 320191783Srmacklem if (group) 321191783Srmacklem aceflag |= NFSV4ACE_IDENTIFIERGROUP; 322191783Srmacklem *tl++ = txdr_unsigned(aceflag); 323191783Srmacklem if (type == VDIR) { 324191783Srmacklem if (ace->ae_perm & ACL_LIST_DIRECTORY) 325191783Srmacklem acemask |= NFSV4ACE_LISTDIRECTORY; 326191783Srmacklem if (ace->ae_perm & ACL_ADD_FILE) 327191783Srmacklem acemask |= NFSV4ACE_ADDFILE; 328191783Srmacklem if (ace->ae_perm & ACL_ADD_SUBDIRECTORY) 329191783Srmacklem acemask |= NFSV4ACE_ADDSUBDIRECTORY; 330191783Srmacklem if (ace->ae_perm & ACL_READ_NAMED_ATTRS) 331191783Srmacklem acemask |= NFSV4ACE_READNAMEDATTR; 332191783Srmacklem if (ace->ae_perm & ACL_WRITE_NAMED_ATTRS) 333191783Srmacklem acemask |= NFSV4ACE_WRITENAMEDATTR; 334192861Srmacklem if (ace->ae_perm & ACL_EXECUTE) 335191783Srmacklem acemask |= NFSV4ACE_SEARCH; 336191783Srmacklem if (ace->ae_perm & ACL_DELETE_CHILD) 337191783Srmacklem acemask |= NFSV4ACE_DELETECHILD; 338191783Srmacklem if (ace->ae_perm & ACL_READ_ATTRIBUTES) 339191783Srmacklem acemask |= NFSV4ACE_READATTRIBUTES; 340191783Srmacklem if (ace->ae_perm & ACL_WRITE_ATTRIBUTES) 341191783Srmacklem acemask |= NFSV4ACE_WRITEATTRIBUTES; 342191783Srmacklem if (ace->ae_perm & ACL_DELETE) 343191783Srmacklem acemask |= NFSV4ACE_DELETE; 344191783Srmacklem if (ace->ae_perm & ACL_READ_ACL) 345191783Srmacklem acemask |= NFSV4ACE_READACL; 346191783Srmacklem if (ace->ae_perm & ACL_WRITE_ACL) 347191783Srmacklem acemask |= NFSV4ACE_WRITEACL; 348191783Srmacklem if (ace->ae_perm & ACL_WRITE_OWNER) 349191783Srmacklem acemask |= NFSV4ACE_WRITEOWNER; 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 */ 389191783SrmacklemAPPLESTATIC int 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; 437191783Srmacklem }; 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 */ 451191783SrmacklemAPPLESTATIC int 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 */ 482191783SrmacklemAPPLESTATIC int 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); 506191783Srmacklem }; 507191783Srmacklem acep1++; 508191783Srmacklem acep2++; 509191783Srmacklem } 510191783Srmacklem return (0); 511191783Srmacklem} 512