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 }