1 /*- 2 * Copyright (c) 2009 Rick Macklem, University of Guelph 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #ifndef APPLEKEXT 32 #include <fs/nfs/nfsport.h> 33 34 extern int nfsrv_useacl; 35 #endif 36 37 static int nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner, 38 enum vtype type, acl_perm_t *permp); 39 40 #if defined(NFS4_ACL_EXTATTR_NAME) 41 /* 42 * Handle xdr for an ace. 43 */ 44 APPLESTATIC int 45 nfsrv_dissectace(struct nfsrv_descript *nd, struct acl_entry *acep, 46 int *aceerrp, int *acesizep, NFSPROC_T *p) 47 { 48 u_int32_t *tl; 49 int len, gotid = 0, owner = 0, error = 0, aceerr = 0; 50 u_char *name, namestr[NFSV4_SMALLSTR + 1]; 51 u_int32_t flag, mask, acetype; 52 gid_t gid; 53 uid_t uid; 54 55 *aceerrp = 0; 56 acep->ae_flags = 0; 57 NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 58 acetype = fxdr_unsigned(u_int32_t, *tl++); 59 flag = fxdr_unsigned(u_int32_t, *tl++); 60 mask = fxdr_unsigned(u_int32_t, *tl++); 61 len = fxdr_unsigned(int, *tl); 62 if (len < 0) { 63 return (NFSERR_BADXDR); 64 } else if (len == 0) { 65 /* Netapp filers return a 0 length who for nil users */ 66 acep->ae_tag = ACL_UNDEFINED_TAG; 67 acep->ae_id = ACL_UNDEFINED_ID; 68 acep->ae_perm = (acl_perm_t)0; 69 acep->ae_entry_type = ACL_ENTRY_TYPE_DENY; 70 if (acesizep) 71 *acesizep = 4 * NFSX_UNSIGNED; 72 return (0); 73 } 74 if (len > NFSV4_SMALLSTR) 75 name = malloc(len + 1, M_NFSSTRING, M_WAITOK); 76 else 77 name = namestr; 78 error = nfsrv_mtostr(nd, name, len); 79 if (error) { 80 if (len > NFSV4_SMALLSTR) 81 free(name, M_NFSSTRING); 82 return (error); 83 } 84 if (len == 6) { 85 if (!NFSBCMP(name, "OWNER@", 6)) { 86 acep->ae_tag = ACL_USER_OBJ; 87 acep->ae_id = ACL_UNDEFINED_ID; 88 owner = 1; 89 gotid = 1; 90 } else if (!NFSBCMP(name, "GROUP@", 6)) { 91 acep->ae_tag = ACL_GROUP_OBJ; 92 acep->ae_id = ACL_UNDEFINED_ID; 93 gotid = 1; 94 } 95 } else if (len == 9 && !NFSBCMP(name, "EVERYONE@", 9)) { 96 acep->ae_tag = ACL_EVERYONE; 97 acep->ae_id = ACL_UNDEFINED_ID; 98 gotid = 1; 99 } 100 if (gotid == 0) { 101 if (flag & NFSV4ACE_IDENTIFIERGROUP) { 102 acep->ae_tag = ACL_GROUP; 103 aceerr = nfsv4_strtogid(name, len, &gid, p); 104 if (aceerr == 0) 105 acep->ae_id = (uid_t)gid; 106 } else { 107 acep->ae_tag = ACL_USER; 108 aceerr = nfsv4_strtouid(name, len, &uid, p); 109 if (aceerr == 0) 110 acep->ae_id = uid; 111 } 112 } 113 if (len > NFSV4_SMALLSTR) 114 free(name, M_NFSSTRING); 115 116 if (aceerr == 0) { 117 /* 118 * Handle the flags. 119 */ 120 flag &= ~NFSV4ACE_IDENTIFIERGROUP; 121 if (flag & NFSV4ACE_FILEINHERIT) { 122 flag &= ~NFSV4ACE_FILEINHERIT; 123 acep->ae_flags |= ACL_ENTRY_FILE_INHERIT; 124 } 125 if (flag & NFSV4ACE_DIRECTORYINHERIT) { 126 flag &= ~NFSV4ACE_DIRECTORYINHERIT; 127 acep->ae_flags |= ACL_ENTRY_DIRECTORY_INHERIT; 128 } 129 if (flag & NFSV4ACE_NOPROPAGATEINHERIT) { 130 flag &= ~NFSV4ACE_NOPROPAGATEINHERIT; 131 acep->ae_flags |= ACL_ENTRY_NO_PROPAGATE_INHERIT; 132 } 133 if (flag & NFSV4ACE_INHERITONLY) { 134 flag &= ~NFSV4ACE_INHERITONLY; 135 acep->ae_flags |= ACL_ENTRY_INHERIT_ONLY; 136 } 137 if (flag & NFSV4ACE_SUCCESSFULACCESS) { 138 flag &= ~NFSV4ACE_SUCCESSFULACCESS; 139 acep->ae_flags |= ACL_ENTRY_SUCCESSFUL_ACCESS; 140 } 141 if (flag & NFSV4ACE_FAILEDACCESS) { 142 flag &= ~NFSV4ACE_FAILEDACCESS; 143 acep->ae_flags |= ACL_ENTRY_FAILED_ACCESS; 144 } 145 /* 146 * Set ae_entry_type. 147 */ 148 if (acetype == NFSV4ACE_ALLOWEDTYPE) 149 acep->ae_entry_type = ACL_ENTRY_TYPE_ALLOW; 150 else if (acetype == NFSV4ACE_DENIEDTYPE) 151 acep->ae_entry_type = ACL_ENTRY_TYPE_DENY; 152 else if (acetype == NFSV4ACE_AUDITTYPE) 153 acep->ae_entry_type = ACL_ENTRY_TYPE_AUDIT; 154 else if (acetype == NFSV4ACE_ALARMTYPE) 155 acep->ae_entry_type = ACL_ENTRY_TYPE_ALARM; 156 else 157 aceerr = NFSERR_ATTRNOTSUPP; 158 } 159 160 /* 161 * Now, check for unsupported flag bits. 162 */ 163 if (aceerr == 0 && flag != 0) 164 aceerr = NFSERR_ATTRNOTSUPP; 165 166 /* 167 * And turn the mask into perm bits. 168 */ 169 if (aceerr == 0) 170 aceerr = nfsrv_acemasktoperm(acetype, mask, owner, VREG, 171 &acep->ae_perm); 172 *aceerrp = aceerr; 173 if (acesizep) 174 *acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED); 175 return (0); 176 nfsmout: 177 return (error); 178 } 179 180 /* 181 * Turn an NFSv4 ace mask into R/W/X flag bits. 182 */ 183 static int 184 nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner, 185 enum vtype type, acl_perm_t *permp) 186 { 187 acl_perm_t perm = 0x0; 188 189 if (mask & NFSV4ACE_READDATA) { 190 mask &= ~NFSV4ACE_READDATA; 191 perm |= ACL_READ_DATA; 192 } 193 if (mask & NFSV4ACE_LISTDIRECTORY) { 194 mask &= ~NFSV4ACE_LISTDIRECTORY; 195 perm |= ACL_LIST_DIRECTORY; 196 } 197 if (mask & NFSV4ACE_WRITEDATA) { 198 mask &= ~NFSV4ACE_WRITEDATA; 199 perm |= ACL_WRITE_DATA; 200 } 201 if (mask & NFSV4ACE_ADDFILE) { 202 mask &= ~NFSV4ACE_ADDFILE; 203 perm |= ACL_ADD_FILE; 204 } 205 if (mask & NFSV4ACE_APPENDDATA) { 206 mask &= ~NFSV4ACE_APPENDDATA; 207 perm |= ACL_APPEND_DATA; 208 } 209 if (mask & NFSV4ACE_ADDSUBDIRECTORY) { 210 mask &= ~NFSV4ACE_ADDSUBDIRECTORY; 211 perm |= ACL_ADD_SUBDIRECTORY; 212 } 213 if (mask & NFSV4ACE_READNAMEDATTR) { 214 mask &= ~NFSV4ACE_READNAMEDATTR; 215 perm |= ACL_READ_NAMED_ATTRS; 216 } 217 if (mask & NFSV4ACE_WRITENAMEDATTR) { 218 mask &= ~NFSV4ACE_WRITENAMEDATTR; 219 perm |= ACL_WRITE_NAMED_ATTRS; 220 } 221 if (mask & NFSV4ACE_EXECUTE) { 222 mask &= ~NFSV4ACE_EXECUTE; 223 perm |= ACL_EXECUTE; 224 } 225 if (mask & NFSV4ACE_SEARCH) { 226 mask &= ~NFSV4ACE_SEARCH; 227 perm |= ACL_EXECUTE; 228 } 229 if (mask & NFSV4ACE_DELETECHILD) { 230 mask &= ~NFSV4ACE_DELETECHILD; 231 perm |= ACL_DELETE_CHILD; 232 } 233 if (mask & NFSV4ACE_READATTRIBUTES) { 234 mask &= ~NFSV4ACE_READATTRIBUTES; 235 perm |= ACL_READ_ATTRIBUTES; 236 } 237 if (mask & NFSV4ACE_WRITEATTRIBUTES) { 238 mask &= ~NFSV4ACE_WRITEATTRIBUTES; 239 perm |= ACL_WRITE_ATTRIBUTES; 240 } 241 if (mask & NFSV4ACE_DELETE) { 242 mask &= ~NFSV4ACE_DELETE; 243 perm |= ACL_DELETE; 244 } 245 if (mask & NFSV4ACE_READACL) { 246 mask &= ~NFSV4ACE_READACL; 247 perm |= ACL_READ_ACL; 248 } 249 if (mask & NFSV4ACE_WRITEACL) { 250 mask &= ~NFSV4ACE_WRITEACL; 251 perm |= ACL_WRITE_ACL; 252 } 253 if (mask & NFSV4ACE_WRITEOWNER) { 254 mask &= ~NFSV4ACE_WRITEOWNER; 255 perm |= ACL_WRITE_OWNER; 256 } 257 if (mask & NFSV4ACE_SYNCHRONIZE) { 258 mask &= ~NFSV4ACE_SYNCHRONIZE; 259 perm |= ACL_SYNCHRONIZE; 260 } 261 if (mask != 0) 262 return (NFSERR_ATTRNOTSUPP); 263 *permp = perm; 264 return (0); 265 } 266 #else 267 /* 268 * Handle xdr for an ace. 269 */ 270 APPLESTATIC int 271 nfsrv_dissectace(struct nfsrv_descript *nd, struct acl_entry *acep, 272 int *aceerrp, int *acesizep, NFSPROC_T *p) 273 { 274 u_int32_t *tl; 275 int len, gotid = 0, owner = 0, error = 0, aceerr = 0; 276 u_char *name, namestr[NFSV4_SMALLSTR + 1]; 277 u_int32_t flag, mask, acetype; 278 gid_t gid; 279 uid_t uid; 280 281 *aceerrp = 0; 282 NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 283 acetype = fxdr_unsigned(u_int32_t, *tl++); 284 flag = fxdr_unsigned(u_int32_t, *tl++); 285 mask = fxdr_unsigned(u_int32_t, *tl++); 286 len = fxdr_unsigned(int, *tl); 287 if (len < 0) { 288 return (NFSERR_BADXDR); 289 } else if (len == 0) { 290 /* Netapp filers return a 0 length who for nil users */ 291 acep->ae_tag = ACL_UNDEFINED_TAG; 292 acep->ae_id = ACL_UNDEFINED_ID; 293 acep->ae_perm = (acl_perm_t)0; 294 if (acesizep) 295 *acesizep = 4 * NFSX_UNSIGNED; 296 return (0); 297 } 298 if (len > NFSV4_SMALLSTR) 299 name = malloc(len + 1, M_NFSSTRING, M_WAITOK); 300 else 301 name = namestr; 302 error = nfsrv_mtostr(nd, name, len); 303 if (error) { 304 if (len > NFSV4_SMALLSTR) 305 free(name, M_NFSSTRING); 306 return (error); 307 } 308 if (len == 6) { 309 if (!NFSBCMP(name, "OWNER@", 6)) { 310 acep->ae_tag = ACL_USER_OBJ; 311 acep->ae_id = ACL_UNDEFINED_ID; 312 owner = 1; 313 gotid = 1; 314 } else if (!NFSBCMP(name, "GROUP@", 6)) { 315 acep->ae_tag = ACL_GROUP_OBJ; 316 acep->ae_id = ACL_UNDEFINED_ID; 317 gotid = 1; 318 flag &= ~NFSV4ACE_IDENTIFIERGROUP; 319 } 320 } else if (len == 9 && !NFSBCMP(name, "EVERYONE@", 9)) { 321 acep->ae_tag = ACL_OTHER; 322 acep->ae_id = ACL_UNDEFINED_ID; 323 gotid = 1; 324 } 325 if (!gotid) { 326 if (flag & NFSV4ACE_IDENTIFIERGROUP) { 327 flag &= ~NFSV4ACE_IDENTIFIERGROUP; 328 acep->ae_tag = ACL_GROUP; 329 aceerr = nfsv4_strtogid(name, len, &gid, p); 330 if (!aceerr) 331 acep->ae_id = (uid_t)gid; 332 } else { 333 acep->ae_tag = ACL_USER; 334 aceerr = nfsv4_strtouid(name, len, &uid, p); 335 if (!aceerr) 336 acep->ae_id = uid; 337 } 338 } 339 if (len > NFSV4_SMALLSTR) 340 free(name, M_NFSSTRING); 341 342 /* 343 * Now, check for unsupported types or flag bits. 344 */ 345 if (!aceerr && ((acetype != NFSV4ACE_ALLOWEDTYPE && 346 acetype != NFSV4ACE_AUDITTYPE && acetype != NFSV4ACE_ALARMTYPE 347 && acetype != NFSV4ACE_DENIEDTYPE) || flag)) 348 aceerr = NFSERR_ATTRNOTSUPP; 349 350 /* 351 * And turn the mask into perm bits. 352 */ 353 if (!aceerr) 354 aceerr = nfsrv_acemasktoperm(acetype, mask, owner, VREG, 355 &acep->ae_perm); 356 *aceerrp = aceerr; 357 if (acesizep) 358 *acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED); 359 return (0); 360 nfsmout: 361 return (error); 362 } 363 364 /* 365 * Turn an NFSv4 ace mask into R/W/X flag bits. 366 */ 367 static int 368 nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner, 369 enum vtype type, acl_perm_t *permp) 370 { 371 acl_perm_t perm = 0x0; 372 373 if (acetype != NFSV4ACE_ALLOWEDTYPE && acetype != NFSV4ACE_DENIEDTYPE){ 374 if (mask & ~NFSV4ACE_AUDITMASK) 375 return (NFSERR_ATTRNOTSUPP); 376 } 377 if (mask & NFSV4ACE_DELETE) { 378 return (NFSERR_ATTRNOTSUPP); 379 } 380 if (acetype == NFSV4ACE_DENIEDTYPE) { 381 if (mask & NFSV4ACE_ALLFILESMASK) { 382 return (NFSERR_ATTRNOTSUPP); 383 } 384 if (owner) { 385 if (mask & NFSV4ACE_OWNERMASK) { 386 return (NFSERR_ATTRNOTSUPP); 387 } 388 } else { 389 if ((mask & NFSV4ACE_OWNERMASK) != NFSV4ACE_OWNERMASK) { 390 return (NFSERR_ATTRNOTSUPP); 391 } 392 mask &= ~NFSV4ACE_OWNERMASK; 393 } 394 } else if (acetype == NFSV4ACE_ALLOWEDTYPE) { 395 if ((mask & NFSV4ACE_ALLFILESMASK) != NFSV4ACE_ALLFILESMASK) { 396 return (NFSERR_ATTRNOTSUPP); 397 } 398 mask &= ~NFSV4ACE_ALLFILESMASK; 399 if (owner) { 400 if ((mask & NFSV4ACE_OWNERMASK) != NFSV4ACE_OWNERMASK) { 401 return (NFSERR_ATTRNOTSUPP); 402 } 403 mask &= ~NFSV4ACE_OWNERMASK; 404 } else if (mask & NFSV4ACE_OWNERMASK) { 405 return (NFSERR_ATTRNOTSUPP); 406 } 407 } 408 if (type == VDIR) { 409 if ((mask & NFSV4ACE_DIRREADMASK) == NFSV4ACE_DIRREADMASK) { 410 perm |= ACL_READ; 411 mask &= ~NFSV4ACE_DIRREADMASK; 412 } 413 if ((mask & NFSV4ACE_DIRWRITEMASK) == NFSV4ACE_DIRWRITEMASK) { 414 perm |= ACL_WRITE; 415 mask &= ~NFSV4ACE_DIRWRITEMASK; 416 } 417 if ((mask & NFSV4ACE_DIREXECUTEMASK)==NFSV4ACE_DIREXECUTEMASK){ 418 perm |= ACL_EXECUTE; 419 mask &= ~NFSV4ACE_DIREXECUTEMASK; 420 } 421 } else { 422 if (acetype == NFSV4ACE_DENIEDTYPE && 423 (mask & NFSV4ACE_SYNCHRONIZE)) { 424 return (NFSERR_ATTRNOTSUPP); 425 } 426 mask &= ~(NFSV4ACE_SYNCHRONIZE | NFSV4ACE_DELETECHILD); 427 if ((mask & NFSV4ACE_READMASK) == NFSV4ACE_READMASK) { 428 perm |= ACL_READ; 429 mask &= ~NFSV4ACE_READMASK; 430 } 431 if ((mask & NFSV4ACE_WRITEMASK) == NFSV4ACE_WRITEMASK) { 432 perm |= ACL_WRITE; 433 mask &= ~NFSV4ACE_WRITEMASK; 434 } 435 if ((mask & NFSV4ACE_EXECUTEMASK) == NFSV4ACE_EXECUTEMASK) { 436 perm |= ACL_EXECUTE; 437 mask &= ~NFSV4ACE_EXECUTEMASK; 438 } 439 } 440 if (mask) { 441 return (NFSERR_ATTRNOTSUPP); 442 } 443 *permp = perm; 444 return (0); 445 } 446 #endif /* !NFS4_ACL_EXTATTR_NAME */ 447 448 #ifdef NFS4_ACL_EXTATTR_NAME 449 /* local functions */ 450 static int nfsrv_buildace(struct nfsrv_descript *, u_char *, int, 451 enum vtype, int, int, struct acl_entry *); 452 453 /* 454 * This function builds an NFS ace. 455 */ 456 static int 457 nfsrv_buildace(struct nfsrv_descript *nd, u_char *name, int namelen, 458 enum vtype type, int group, int owner, struct acl_entry *ace) 459 { 460 u_int32_t *tl, aceflag = 0x0, acemask = 0x0, acetype; 461 int full_len; 462 463 full_len = NFSM_RNDUP(namelen); 464 NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED + full_len); 465 466 /* 467 * Fill in the ace type. 468 */ 469 if (ace->ae_entry_type & ACL_ENTRY_TYPE_ALLOW) 470 acetype = NFSV4ACE_ALLOWEDTYPE; 471 else if (ace->ae_entry_type & ACL_ENTRY_TYPE_DENY) 472 acetype = NFSV4ACE_DENIEDTYPE; 473 else if (ace->ae_entry_type & ACL_ENTRY_TYPE_AUDIT) 474 acetype = NFSV4ACE_AUDITTYPE; 475 else 476 acetype = NFSV4ACE_ALARMTYPE; 477 *tl++ = txdr_unsigned(acetype); 478 479 /* 480 * Set the flag bits from the ACL. 481 */ 482 if (ace->ae_flags & ACL_ENTRY_FILE_INHERIT) 483 aceflag |= NFSV4ACE_FILEINHERIT; 484 if (ace->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT) 485 aceflag |= NFSV4ACE_DIRECTORYINHERIT; 486 if (ace->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT) 487 aceflag |= NFSV4ACE_NOPROPAGATEINHERIT; 488 if (ace->ae_flags & ACL_ENTRY_INHERIT_ONLY) 489 aceflag |= NFSV4ACE_INHERITONLY; 490 if (ace->ae_flags & ACL_ENTRY_SUCCESSFUL_ACCESS) 491 aceflag |= NFSV4ACE_SUCCESSFULACCESS; 492 if (ace->ae_flags & ACL_ENTRY_FAILED_ACCESS) 493 aceflag |= NFSV4ACE_FAILEDACCESS; 494 if (group) 495 aceflag |= NFSV4ACE_IDENTIFIERGROUP; 496 *tl++ = txdr_unsigned(aceflag); 497 if (type == VDIR) { 498 if (ace->ae_perm & ACL_LIST_DIRECTORY) 499 acemask |= NFSV4ACE_LISTDIRECTORY; 500 if (ace->ae_perm & ACL_ADD_FILE) 501 acemask |= NFSV4ACE_ADDFILE; 502 if (ace->ae_perm & ACL_ADD_SUBDIRECTORY) 503 acemask |= NFSV4ACE_ADDSUBDIRECTORY; 504 if (ace->ae_perm & ACL_READ_NAMED_ATTRS) 505 acemask |= NFSV4ACE_READNAMEDATTR; 506 if (ace->ae_perm & ACL_WRITE_NAMED_ATTRS) 507 acemask |= NFSV4ACE_WRITENAMEDATTR; 508 if (ace->ae_perm & ACL_EXECUTE) 509 acemask |= NFSV4ACE_SEARCH; 510 if (ace->ae_perm & ACL_DELETE_CHILD) 511 acemask |= NFSV4ACE_DELETECHILD; 512 if (ace->ae_perm & ACL_READ_ATTRIBUTES) 513 acemask |= NFSV4ACE_READATTRIBUTES; 514 if (ace->ae_perm & ACL_WRITE_ATTRIBUTES) 515 acemask |= NFSV4ACE_WRITEATTRIBUTES; 516 if (ace->ae_perm & ACL_DELETE) 517 acemask |= NFSV4ACE_DELETE; 518 if (ace->ae_perm & ACL_READ_ACL) 519 acemask |= NFSV4ACE_READACL; 520 if (ace->ae_perm & ACL_WRITE_ACL) 521 acemask |= NFSV4ACE_WRITEACL; 522 if (ace->ae_perm & ACL_WRITE_OWNER) 523 acemask |= NFSV4ACE_WRITEOWNER; 524 } else { 525 if (ace->ae_perm & ACL_READ_DATA) 526 acemask |= NFSV4ACE_READDATA; 527 if (ace->ae_perm & ACL_WRITE_DATA) 528 acemask |= NFSV4ACE_WRITEDATA; 529 if (ace->ae_perm & ACL_APPEND_DATA) 530 acemask |= NFSV4ACE_APPENDDATA; 531 if (ace->ae_perm & ACL_READ_NAMED_ATTRS) 532 acemask |= NFSV4ACE_READNAMEDATTR; 533 if (ace->ae_perm & ACL_WRITE_NAMED_ATTRS) 534 acemask |= NFSV4ACE_WRITENAMEDATTR; 535 if (ace->ae_perm & ACL_EXECUTE) 536 acemask |= NFSV4ACE_EXECUTE; 537 if (ace->ae_perm & ACL_READ_ATTRIBUTES) 538 acemask |= NFSV4ACE_READATTRIBUTES; 539 if (ace->ae_perm & ACL_WRITE_ATTRIBUTES) 540 acemask |= NFSV4ACE_WRITEATTRIBUTES; 541 if (ace->ae_perm & ACL_DELETE) 542 acemask |= NFSV4ACE_DELETE; 543 if (ace->ae_perm & ACL_READ_ACL) 544 acemask |= NFSV4ACE_READACL; 545 if (ace->ae_perm & ACL_WRITE_ACL) 546 acemask |= NFSV4ACE_WRITEACL; 547 if (ace->ae_perm & ACL_WRITE_OWNER) 548 acemask |= NFSV4ACE_WRITEOWNER; 549 if (ace->ae_perm & ACL_SYNCHRONIZE) 550 acemask |= NFSV4ACE_SYNCHRONIZE; 551 } 552 *tl++ = txdr_unsigned(acemask); 553 *tl++ = txdr_unsigned(namelen); 554 if (full_len - namelen) 555 *(tl + (namelen / NFSX_UNSIGNED)) = 0x0; 556 NFSBCOPY(name, (caddr_t)tl, namelen); 557 return (full_len + 4 * NFSX_UNSIGNED); 558 } 559 560 /* 561 * Build an NFSv4 ACL. 562 */ 563 APPLESTATIC int 564 nfsrv_buildacl(struct nfsrv_descript *nd, NFSACL_T *aclp, enum vtype type, 565 NFSPROC_T *p) 566 { 567 int i, entrycnt = 0, retlen; 568 u_int32_t *entrycntp; 569 int isowner, isgroup, namelen, malloced; 570 u_char *name, namestr[NFSV4_SMALLSTR]; 571 572 NFSM_BUILD(entrycntp, u_int32_t *, NFSX_UNSIGNED); 573 retlen = NFSX_UNSIGNED; 574 /* 575 * Loop through the acl entries, building each one. 576 */ 577 for (i = 0; i < aclp->acl_cnt; i++) { 578 isowner = isgroup = malloced = 0; 579 switch (aclp->acl_entry[i].ae_tag) { 580 case ACL_USER_OBJ: 581 isowner = 1; 582 name = "OWNER@"; 583 namelen = 6; 584 break; 585 case ACL_GROUP_OBJ: 586 isgroup = 1; 587 name = "GROUP@"; 588 namelen = 6; 589 break; 590 case ACL_EVERYONE: 591 name = "EVERYONE@"; 592 namelen = 9; 593 break; 594 case ACL_USER: 595 name = namestr; 596 nfsv4_uidtostr(aclp->acl_entry[i].ae_id, &name, 597 &namelen, p); 598 if (name != namestr) 599 malloced = 1; 600 break; 601 case ACL_GROUP: 602 isgroup = 1; 603 name = namestr; 604 nfsv4_gidtostr((gid_t)aclp->acl_entry[i].ae_id, &name, 605 &namelen, p); 606 if (name != namestr) 607 malloced = 1; 608 break; 609 default: 610 continue; 611 }; 612 retlen += nfsrv_buildace(nd, name, namelen, type, isgroup, 613 isowner, &aclp->acl_entry[i]); 614 entrycnt++; 615 if (malloced) 616 free(name, M_NFSSTRING); 617 } 618 *entrycntp = txdr_unsigned(entrycnt); 619 return (retlen); 620 } 621 622 /* 623 * Check access for an NFSv4 acl. 624 * The vflags are the basic VREAD, VWRITE, VEXEC. The mask is the NFSV4ACE 625 * mask bits for the more detailed check. 626 * If the more detailed check fails, due to no acl, do a basic one. 627 */ 628 APPLESTATIC int 629 nfsrv_aclaccess(vnode_t vp, accmode_t vflags, u_int32_t mask, 630 struct ucred *cred, NFSPROC_T *p) 631 { 632 int error = 0; 633 accmode_t access; 634 635 if (nfsrv_useacl == 0) { 636 error = VOP_ACCESS(vp, vflags, cred, p); 637 return (error); 638 } 639 640 /* Convert NFSV4ACE mask to vaccess_t */ 641 access = 0; 642 if (mask & NFSV4ACE_READDATA) 643 access |= VREAD; 644 if (mask & NFSV4ACE_LISTDIRECTORY) 645 access |= VREAD; 646 if (mask & NFSV4ACE_WRITEDATA) 647 access |= VWRITE; 648 if (mask & NFSV4ACE_ADDFILE) 649 access |= VWRITE; 650 if (mask & NFSV4ACE_APPENDDATA) 651 access |= VAPPEND; 652 if (mask & NFSV4ACE_ADDSUBDIRECTORY) 653 access |= VAPPEND; 654 if (mask & NFSV4ACE_READNAMEDATTR) 655 access |= VREAD_NAMED_ATTRS; 656 if (mask & NFSV4ACE_WRITENAMEDATTR) 657 access |= VWRITE_NAMED_ATTRS; 658 if (mask & NFSV4ACE_EXECUTE) 659 access |= VEXEC; 660 if (mask & NFSV4ACE_SEARCH) 661 access |= VEXEC; 662 if (mask & NFSV4ACE_DELETECHILD) 663 access |= VDELETE_CHILD; 664 if (mask & NFSV4ACE_READATTRIBUTES) 665 access |= VREAD_ATTRIBUTES; 666 if (mask & NFSV4ACE_WRITEATTRIBUTES) 667 access |= VWRITE_ATTRIBUTES; 668 if (mask & NFSV4ACE_DELETE) 669 access |= VDELETE; 670 if (mask & NFSV4ACE_READACL) 671 access |= VREAD_ACL; 672 if (mask & NFSV4ACE_WRITEACL) 673 access |= VWRITE_ACL; 674 if (mask & NFSV4ACE_WRITEOWNER) 675 access |= VWRITE_OWNER; 676 if (mask & NFSV4ACE_SYNCHRONIZE) 677 access |= VSYNCHRONIZE; 678 679 if (access != 0) 680 error = VOP_ACCESS(vp, access, cred, p); 681 else 682 error = VOP_ACCESS(vp, vflags, cred, p); 683 return (error); 684 } 685 686 /* 687 * Set an NFSv4 acl. 688 */ 689 APPLESTATIC int 690 nfsrv_setacl(vnode_t vp, NFSACL_T *aclp, struct ucred *cred, 691 NFSPROC_T *p) 692 { 693 int error; 694 695 if (nfsrv_useacl == 0 || !NFSHASNFS4ACL(vnode_mount(vp))) 696 return (NFSERR_ATTRNOTSUPP); 697 /* 698 * With NFS4 ACLs, chmod(2) may need to add additional entries. 699 * Make sure it has enough room for that - splitting every entry 700 * into two and appending "canonical six" entries at the end. 701 * Cribbed out of kern/vfs_acl.c - Rick M. 702 */ 703 if (aclp->acl_cnt > (ACL_MAX_ENTRIES - 6) / 2) 704 return (NFSERR_ATTRNOTSUPP); 705 error = VOP_ACLCHECK(vp, ACL_TYPE_NFS4, aclp, cred, p); 706 if (!error) 707 error = VOP_SETACL(vp, ACL_TYPE_NFS4, aclp, cred, p); 708 return (error); 709 } 710 711 /* 712 * Compare two NFSv4 acls. 713 * Return 0 if they are the same, 1 if not the same. 714 */ 715 APPLESTATIC int 716 nfsrv_compareacl(NFSACL_T *aclp1, NFSACL_T *aclp2) 717 { 718 int i; 719 struct acl_entry *acep1, *acep2; 720 721 if (aclp1->acl_cnt != aclp2->acl_cnt) 722 return (1); 723 acep1 = aclp1->acl_entry; 724 acep2 = aclp2->acl_entry; 725 for (i = 0; i < aclp1->acl_cnt; i++) { 726 if (acep1->ae_tag != acep2->ae_tag) 727 return (1); 728 switch (acep1->ae_tag) { 729 case ACL_GROUP: 730 case ACL_USER: 731 if (acep1->ae_id != acep2->ae_id) 732 return (1); 733 /* fall through */ 734 case ACL_USER_OBJ: 735 case ACL_GROUP_OBJ: 736 case ACL_OTHER: 737 if (acep1->ae_perm != acep2->ae_perm) 738 return (1); 739 }; 740 acep1++; 741 acep2++; 742 } 743 return (0); 744 } 745 746 #endif /* NFS4_ACL_EXTATTR_NAME */ 747