1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 29 #include <sys/param.h> 30 #include <sys/types.h> 31 #include <sys/systm.h> 32 #include <sys/user.h> 33 #include <sys/vnode.h> 34 #include <sys/file.h> 35 #include <sys/dirent.h> 36 #include <sys/vfs.h> 37 #include <sys/stream.h> 38 #include <sys/strsubr.h> 39 #include <sys/debug.h> 40 #include <sys/t_lock.h> 41 #include <sys/acl.h> 42 43 #include <rpc/types.h> 44 #include <rpc/xdr.h> 45 46 #include <nfs/nfs.h> 47 #include <nfs/nfs_clnt.h> 48 #include <nfs/nfs_acl.h> 49 50 /* 51 * These are the XDR routines used to serialize and deserialize 52 * the various structures passed as parameters accross the network 53 * between ACL clients and servers. 54 */ 55 56 bool_t 57 xdr_uid(XDR *xdrs, uid32_t *objp) 58 { 59 if (!xdr_u_int(xdrs, objp)) 60 return (FALSE); 61 return (TRUE); 62 } 63 64 bool_t 65 xdr_o_mode(XDR *xdrs, o_mode *objp) 66 { 67 68 if (!xdr_u_short(xdrs, (ushort_t *)objp)) 69 return (FALSE); 70 return (TRUE); 71 } 72 73 bool_t 74 xdr_aclent(XDR *xdrs, aclent_t *objp) 75 { 76 77 if (!xdr_int(xdrs, &objp->a_type)) 78 return (FALSE); 79 if (!xdr_uid(xdrs, &objp->a_id)) 80 return (FALSE); 81 if (!xdr_o_mode(xdrs, &objp->a_perm)) 82 return (FALSE); 83 return (TRUE); 84 } 85 86 /* 87 * Serialize and de-serialize access control attributes 88 */ 89 bool_t 90 xdr_secattr(XDR *xdrs, vsecattr_t *objp) 91 { 92 uint_t count = 0; 93 uint_t dfacount = 0; 94 95 if (!xdr_u_int(xdrs, &objp->vsa_mask)) { 96 return (FALSE); 97 } 98 99 /* 100 * Refuse request if we do not understand it completely. 101 * There should be at least one valid bit set in the mask and 102 * none of the unknown bits set. 103 */ 104 if ((objp->vsa_mask & 105 (VSA_ACL | VSA_ACLCNT | VSA_DFACL | VSA_DFACLCNT)) == 0) { 106 return (FALSE); 107 } 108 if ((objp->vsa_mask & 109 ~(VSA_ACL | VSA_ACLCNT | VSA_DFACL | VSA_DFACLCNT)) != 0) { 110 return (FALSE); 111 } 112 113 if (!xdr_int(xdrs, &objp->vsa_aclcnt)) { 114 return (FALSE); 115 } 116 if (objp->vsa_aclentp != NULL) { 117 count = (uint_t)objp->vsa_aclcnt; 118 } 119 120 if (!xdr_array(xdrs, (char **)&objp->vsa_aclentp, &count, 121 NFS_ACL_MAX_ENTRIES, sizeof (aclent_t), (xdrproc_t)xdr_aclent)) { 122 return (FALSE); 123 } 124 125 if (count != 0 && count != (uint_t)objp->vsa_aclcnt) { 126 /* 127 * Assign the actual array size to vsa_aclcnt before 128 * aborting on error 129 */ 130 objp->vsa_aclcnt = (int)count; 131 return (FALSE); 132 } 133 134 /* 135 * For VSA_ACL the count should be zero or there should 136 * be array attached. 137 */ 138 if ((objp->vsa_mask & VSA_ACL) != 0) { 139 if ((objp->vsa_aclcnt != 0) && (objp->vsa_aclentp == NULL)) { 140 objp->vsa_aclcnt = 0; 141 return (FALSE); 142 } 143 } 144 145 if (!xdr_int(xdrs, &objp->vsa_dfaclcnt)) { 146 return (FALSE); 147 } 148 if (objp->vsa_dfaclentp != NULL) { 149 dfacount = (uint_t)objp->vsa_dfaclcnt; 150 } 151 152 if (!xdr_array(xdrs, (char **)&objp->vsa_dfaclentp, &dfacount, 153 NFS_ACL_MAX_ENTRIES, sizeof (aclent_t), (xdrproc_t)xdr_aclent)) { 154 return (FALSE); 155 } 156 157 if (dfacount != 0 && dfacount != (uint_t)objp->vsa_dfaclcnt) { 158 /* 159 * Assign the actual array size to vsa_dfaclcnt before 160 * aborting on error 161 */ 162 objp->vsa_dfaclcnt = (int)dfacount; 163 return (FALSE); 164 } 165 166 /* 167 * for VSA_DFACL The count should be zero or there should 168 * be array attached 169 */ 170 if ((objp->vsa_mask & VSA_DFACL) != 0) { 171 if ((objp->vsa_dfaclcnt != 0) && 172 (objp->vsa_dfaclentp == NULL)) { 173 objp->vsa_dfaclcnt = 0; 174 return (FALSE); 175 } 176 } 177 178 179 return (TRUE); 180 } 181 182 bool_t 183 xdr_GETACL2args(XDR *xdrs, GETACL2args *objp) 184 { 185 186 if (!xdr_fhandle(xdrs, &objp->fh)) 187 return (FALSE); 188 if (!xdr_u_int(xdrs, &objp->mask)) 189 return (FALSE); 190 return (TRUE); 191 } 192 bool_t 193 xdr_fastGETACL2args(XDR *xdrs, GETACL2args **objpp) 194 { 195 int32_t *ptr; 196 #ifdef _LITTLE_ENDIAN 197 GETACL2args *objp; 198 #endif 199 200 if (xdrs->x_op != XDR_DECODE) 201 return (FALSE); 202 203 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (GETACL2args))); 204 if (ptr != NULL) { 205 *objpp = (GETACL2args *)ptr; 206 #ifdef _LITTLE_ENDIAN 207 objp = (GETACL2args *)ptr; 208 objp->mask = ntohl(objp->mask); 209 #endif 210 return (TRUE); 211 } 212 213 return (FALSE); 214 } 215 216 bool_t 217 xdr_GETACL2resok(XDR *xdrs, GETACL2resok *objp) 218 { 219 220 if (!xdr_fattr(xdrs, &objp->attr)) 221 return (FALSE); 222 if (!xdr_secattr(xdrs, &objp->acl)) 223 return (FALSE); 224 return (TRUE); 225 } 226 227 bool_t 228 xdr_GETACL2res(XDR *xdrs, GETACL2res *objp) 229 { 230 231 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 232 return (FALSE); 233 switch (objp->status) { 234 case NFS_OK: 235 if (!xdr_GETACL2resok(xdrs, &objp->resok)) 236 return (FALSE); 237 break; 238 } 239 return (TRUE); 240 } 241 242 bool_t 243 xdr_SETACL2args(XDR *xdrs, SETACL2args *objp) 244 { 245 246 if (!xdr_fhandle(xdrs, &objp->fh)) 247 return (FALSE); 248 if (!xdr_secattr(xdrs, &objp->acl)) 249 return (FALSE); 250 return (TRUE); 251 } 252 253 bool_t 254 xdr_SETACL2resok(XDR *xdrs, SETACL2resok *objp) 255 { 256 257 if (!xdr_fattr(xdrs, &objp->attr)) 258 return (FALSE); 259 return (TRUE); 260 } 261 #ifdef _LITTLE_ENDIAN 262 bool_t 263 xdr_fastSETACL2resok(XDR *xdrs, SETACL2resok *objp) 264 { 265 266 if (!xdr_fastfattr(xdrs, &objp->attr)) 267 return (FALSE); 268 return (TRUE); 269 } 270 #endif 271 272 bool_t 273 xdr_SETACL2res(XDR *xdrs, SETACL2res *objp) 274 { 275 276 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 277 return (FALSE); 278 switch (objp->status) { 279 case NFS_OK: 280 if (!xdr_SETACL2resok(xdrs, &objp->resok)) 281 return (FALSE); 282 break; 283 } 284 return (TRUE); 285 } 286 #ifdef _LITTLE_ENDIAN 287 bool_t 288 xdr_fastSETACL2res(XDR *xdrs, SETACL2res *objp) 289 { 290 291 if (!xdr_fastenum(xdrs, (enum_t *)&objp->status)) 292 return (FALSE); 293 switch (objp->status) { 294 case NFS_OK: 295 if (!xdr_fastSETACL2resok(xdrs, &objp->resok)) 296 return (FALSE); 297 break; 298 } 299 return (TRUE); 300 } 301 #endif 302 303 bool_t 304 xdr_GETATTR2args(XDR *xdrs, GETATTR2args *objp) 305 { 306 307 if (!xdr_fhandle(xdrs, &objp->fh)) 308 return (FALSE); 309 return (TRUE); 310 } 311 bool_t 312 xdr_fastGETATTR2args(XDR *xdrs, GETATTR2args **objpp) 313 { 314 int32_t *ptr; 315 316 if (xdrs->x_op != XDR_DECODE) 317 return (FALSE); 318 319 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (GETATTR2args))); 320 if (ptr != NULL) { 321 *objpp = (GETATTR2args *)ptr; 322 return (TRUE); 323 } 324 325 return (FALSE); 326 } 327 328 bool_t 329 xdr_GETATTR2resok(XDR *xdrs, GETATTR2resok *objp) 330 { 331 332 if (!xdr_fattr(xdrs, &objp->attr)) 333 return (FALSE); 334 return (TRUE); 335 } 336 #ifdef _LITTLE_ENDIAN 337 bool_t 338 xdr_fastGETATTR2resok(XDR *xdrs, GETATTR2resok *objp) 339 { 340 341 if (!xdr_fastfattr(xdrs, &objp->attr)) 342 return (FALSE); 343 return (TRUE); 344 } 345 #endif 346 347 bool_t 348 xdr_GETATTR2res(XDR *xdrs, GETATTR2res *objp) 349 { 350 351 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 352 return (FALSE); 353 switch (objp->status) { 354 case NFS_OK: 355 if (!xdr_GETATTR2resok(xdrs, &objp->resok)) 356 return (FALSE); 357 break; 358 } 359 return (TRUE); 360 } 361 #ifdef _LITTLE_ENDIAN 362 bool_t 363 xdr_fastGETATTR2res(XDR *xdrs, GETATTR2res *objp) 364 { 365 366 if (!xdr_fastenum(xdrs, (enum_t *)&objp->status)) 367 return (FALSE); 368 switch (objp->status) { 369 case NFS_OK: 370 if (!xdr_fastGETATTR2resok(xdrs, &objp->resok)) 371 return (FALSE); 372 break; 373 } 374 return (TRUE); 375 } 376 #endif 377 378 bool_t 379 xdr_ACCESS2args(XDR *xdrs, ACCESS2args *objp) 380 { 381 382 if (!xdr_fhandle(xdrs, &objp->fh)) 383 return (FALSE); 384 if (!xdr_uint32(xdrs, &objp->access)) 385 return (FALSE); 386 return (TRUE); 387 } 388 bool_t 389 xdr_fastACCESS2args(XDR *xdrs, ACCESS2args **objpp) 390 { 391 int32_t *ptr; 392 #ifdef _LITTLE_ENDIAN 393 ACCESS2args *objp; 394 #endif 395 396 if (xdrs->x_op != XDR_DECODE) 397 return (FALSE); 398 399 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (ACCESS2args))); 400 if (ptr != NULL) { 401 *objpp = (ACCESS2args *)ptr; 402 #ifdef _LITTLE_ENDIAN 403 objp = (ACCESS2args *)ptr; 404 objp->access = ntohl(objp->access); 405 #endif 406 return (TRUE); 407 } 408 409 return (FALSE); 410 } 411 412 bool_t 413 xdr_ACCESS2resok(XDR *xdrs, ACCESS2resok *objp) 414 { 415 416 if (!xdr_fattr(xdrs, &objp->attr)) 417 return (FALSE); 418 if (!xdr_uint32(xdrs, &objp->access)) 419 return (FALSE); 420 return (TRUE); 421 } 422 #ifdef _LITTLE_ENDIAN 423 bool_t 424 xdr_fastACCESS2resok(XDR *xdrs, ACCESS2resok *objp) 425 { 426 427 if (!xdr_fastfattr(xdrs, &objp->attr)) 428 return (FALSE); 429 objp->access = ntohl(objp->access); 430 return (TRUE); 431 } 432 #endif 433 434 bool_t 435 xdr_ACCESS2res(XDR *xdrs, ACCESS2res *objp) 436 { 437 438 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 439 return (FALSE); 440 switch (objp->status) { 441 case NFS_OK: 442 if (!xdr_ACCESS2resok(xdrs, &objp->resok)) 443 return (FALSE); 444 break; 445 } 446 return (TRUE); 447 } 448 #ifdef _LITTLE_ENDIAN 449 bool_t 450 xdr_fastACCESS2res(XDR *xdrs, ACCESS2res *objp) 451 { 452 453 if (!xdr_fastenum(xdrs, (enum_t *)&objp->status)) 454 return (FALSE); 455 switch (objp->status) { 456 case NFS_OK: 457 if (!xdr_fastACCESS2resok(xdrs, &objp->resok)) 458 return (FALSE); 459 break; 460 } 461 return (TRUE); 462 } 463 #endif 464 465 bool_t 466 xdr_GETXATTRDIR2args(XDR *xdrs, GETXATTRDIR2args *objp) 467 { 468 if (!xdr_fhandle(xdrs, &objp->fh)) 469 return (FALSE); 470 if (!xdr_bool(xdrs, &objp->create)) 471 return (FALSE); 472 return (TRUE); 473 } 474 475 bool_t 476 xdr_GETXATTRDIR2resok(XDR *xdrs, GETXATTRDIR2resok *objp) 477 { 478 if (!xdr_fhandle(xdrs, &objp->fh)) 479 return (FALSE); 480 if (!xdr_fattr(xdrs, &objp->attr)) 481 return (FALSE); 482 return (TRUE); 483 } 484 485 bool_t 486 xdr_GETXATTRDIR2res(XDR *xdrs, GETXATTRDIR2res *objp) 487 { 488 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 489 return (FALSE); 490 switch (objp->status) { 491 case NFS_OK: 492 if (!xdr_GETXATTRDIR2resok(xdrs, &objp->resok)) 493 return (FALSE); 494 break; 495 } 496 return (TRUE); 497 } 498 499 bool_t 500 xdr_GETACL3args(XDR *xdrs, GETACL3args *objp) 501 { 502 503 switch (xdrs->x_op) { 504 case XDR_FREE: 505 case XDR_ENCODE: 506 if (!xdr_nfs_fh3(xdrs, &objp->fh)) 507 return (FALSE); 508 break; 509 case XDR_DECODE: 510 if (!xdr_nfs_fh3_server(xdrs, &objp->fh)) 511 return (FALSE); 512 break; 513 } 514 if (!xdr_u_int(xdrs, &objp->mask)) 515 return (FALSE); 516 return (TRUE); 517 } 518 519 bool_t 520 xdr_GETACL3resok(XDR *xdrs, GETACL3resok *objp) 521 { 522 523 if (!xdr_post_op_attr(xdrs, &objp->attr)) 524 return (FALSE); 525 if (!xdr_secattr(xdrs, &objp->acl)) 526 return (FALSE); 527 return (TRUE); 528 } 529 530 bool_t 531 xdr_GETACL3resfail(XDR *xdrs, GETACL3resfail *objp) 532 { 533 534 if (!xdr_post_op_attr(xdrs, &objp->attr)) 535 return (FALSE); 536 return (TRUE); 537 } 538 539 bool_t 540 xdr_GETACL3res(XDR *xdrs, GETACL3res *objp) 541 { 542 543 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 544 return (FALSE); 545 switch (objp->status) { 546 case NFS3_OK: 547 if (!xdr_GETACL3resok(xdrs, &objp->resok)) 548 return (FALSE); 549 break; 550 default: 551 if (!xdr_GETACL3resfail(xdrs, &objp->resfail)) 552 return (FALSE); 553 break; 554 } 555 return (TRUE); 556 } 557 558 bool_t 559 xdr_SETACL3args(XDR *xdrs, SETACL3args *objp) 560 { 561 562 switch (xdrs->x_op) { 563 case XDR_FREE: 564 case XDR_ENCODE: 565 if (!xdr_nfs_fh3(xdrs, &objp->fh)) 566 return (FALSE); 567 break; 568 case XDR_DECODE: 569 if (!xdr_nfs_fh3_server(xdrs, &objp->fh)) 570 return (FALSE); 571 break; 572 } 573 if (!xdr_secattr(xdrs, &objp->acl)) 574 return (FALSE); 575 return (TRUE); 576 } 577 578 bool_t 579 xdr_SETACL3resok(XDR *xdrs, SETACL3resok *objp) 580 { 581 582 if (!xdr_post_op_attr(xdrs, &objp->attr)) 583 return (FALSE); 584 return (TRUE); 585 } 586 587 bool_t 588 xdr_SETACL3resfail(XDR *xdrs, SETACL3resfail *objp) 589 { 590 591 if (!xdr_post_op_attr(xdrs, &objp->attr)) 592 return (FALSE); 593 return (TRUE); 594 } 595 596 bool_t 597 xdr_SETACL3res(XDR *xdrs, SETACL3res *objp) 598 { 599 600 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 601 return (FALSE); 602 switch (objp->status) { 603 case NFS3_OK: 604 if (!xdr_SETACL3resok(xdrs, &objp->resok)) 605 return (FALSE); 606 break; 607 default: 608 if (!xdr_SETACL3resfail(xdrs, &objp->resfail)) 609 return (FALSE); 610 break; 611 } 612 return (TRUE); 613 } 614 615 bool_t 616 xdr_GETXATTRDIR3args(XDR *xdrs, GETXATTRDIR3args *objp) 617 { 618 switch (xdrs->x_op) { 619 case XDR_FREE: 620 case XDR_ENCODE: 621 if (!xdr_nfs_fh3(xdrs, &objp->fh)) 622 return (FALSE); 623 break; 624 case XDR_DECODE: 625 if (!xdr_nfs_fh3_server(xdrs, &objp->fh)) 626 return (FALSE); 627 break; 628 } 629 if (!xdr_bool(xdrs, &objp->create)) 630 return (FALSE); 631 return (TRUE); 632 } 633 634 bool_t 635 xdr_GETXATTRDIR3resok(XDR *xdrs, GETXATTRDIR3resok *objp) 636 { 637 switch (xdrs->x_op) { 638 case XDR_ENCODE: 639 if (!xdr_nfs_fh3_server(xdrs, &objp->fh)) 640 return (FALSE); 641 break; 642 case XDR_FREE: 643 case XDR_DECODE: 644 if (!xdr_nfs_fh3(xdrs, &objp->fh)) 645 return (FALSE); 646 break; 647 } 648 if (!xdr_post_op_attr(xdrs, &objp->attr)) 649 return (FALSE); 650 return (TRUE); 651 } 652 653 bool_t 654 xdr_GETXATTRDIR3res(XDR *xdrs, GETXATTRDIR3res *objp) 655 { 656 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 657 return (FALSE); 658 switch (objp->status) { 659 case NFS_OK: 660 if (!xdr_GETXATTRDIR3resok(xdrs, &objp->resok)) 661 return (FALSE); 662 break; 663 } 664 return (TRUE); 665 }