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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/errno.h> 28 #include <sys/tiuser.h> 29 #include <setjmp.h> 30 #include <pwd.h> 31 #include <grp.h> 32 33 #include <rpc/types.h> 34 #include <rpc/xdr.h> 35 #include <rpc/auth.h> 36 #include <rpc/clnt.h> 37 #include <rpc/rpc_msg.h> 38 #include <string.h> 39 #include "snoop.h" 40 41 #include <sys/stat.h> 42 43 extern char *get_sum_line(); 44 extern void check_retransmit(); 45 extern char *sum_nfsfh(); 46 extern int sum_nfsstat(); 47 extern int detail_nfsstat(); 48 extern void detail_nfsfh(); 49 extern void detail_fattr(); 50 extern void skip_fattr(); 51 extern char *sum_nfsfh3(); 52 extern int sum_nfsstat3(); 53 extern int detail_nfsstat3(); 54 extern void detail_post_op_attr(); 55 extern void detail_nfsfh3(); 56 extern int sum_nfsstat4(); 57 extern int detail_nfsstat4(); 58 59 extern jmp_buf xdr_err; 60 61 static void aclcall2(); 62 static void aclreply2(); 63 static void aclcall3(); 64 static void aclreply3(); 65 static void aclcall4(); 66 static void aclreply4(); 67 static void detail_access2(); 68 static char *sum_access2(); 69 static void detail_mask(); 70 static void detail_secattr(); 71 static void detail_aclent(); 72 static char *detail_uname(); 73 static char *detail_gname(); 74 static char *detail_perm(ushort_t); 75 static void interpret_nfs_acl2(int, int, int, int, int, char *, int); 76 static void interpret_nfs_acl3(int, int, int, int, int, char *, int); 77 static void interpret_nfs_acl4(int, int, int, int, int, char *, int); 78 79 #define ACLPROC2_NULL ((unsigned long)(0)) 80 #define ACLPROC2_GETACL ((unsigned long)(1)) 81 #define ACLPROC2_SETACL ((unsigned long)(2)) 82 #define ACLPROC2_GETATTR ((unsigned long)(3)) 83 #define ACLPROC2_ACCESS ((unsigned long)(4)) 84 #define ACLPROC2_GETXATTRDIR ((unsigned long)(5)) 85 86 #define ACLPROC3_NULL ((unsigned long)(0)) 87 #define ACLPROC3_GETACL ((unsigned long)(1)) 88 #define ACLPROC3_SETACL ((unsigned long)(2)) 89 #define ACLPROC3_GETXATTRDIR ((unsigned long)(3)) 90 91 #define ACLPROC4_NULL ((unsigned long)(0)) 92 #define ACLPROC4_GETACL ((unsigned long)(1)) 93 #define ACLPROC4_SETACL ((unsigned long)(2)) 94 95 #define NA_USER_OBJ 0x1 96 #define NA_USER 0x2 97 #define NA_GROUP_OBJ 0x4 98 #define NA_GROUP 0x8 99 #define NA_CLASS_OBJ 0x10 100 #define NA_OTHER_OBJ 0x20 101 #define NA_ACL_DEFAULT 0x1000 102 103 #define NA_DEF_USER_OBJ (NA_USER_OBJ | NA_ACL_DEFAULT) 104 #define NA_DEF_USER (NA_USER | NA_ACL_DEFAULT) 105 #define NA_DEF_GROUP_OBJ (NA_GROUP_OBJ | NA_ACL_DEFAULT) 106 #define NA_DEF_GROUP (NA_GROUP | NA_ACL_DEFAULT) 107 #define NA_DEF_CLASS_OBJ (NA_CLASS_OBJ | NA_ACL_DEFAULT) 108 #define NA_DEF_OTHER_OBJ (NA_OTHER_OBJ | NA_ACL_DEFAULT) 109 110 #define NA_ACL 0x1 111 #define NA_ACLCNT 0x2 112 #define NA_DFACL 0x4 113 #define NA_DFACLCNT 0x8 114 115 #define ACCESS2_READ 0x0001 116 #define ACCESS2_LOOKUP 0x0002 117 #define ACCESS2_MODIFY 0x0004 118 #define ACCESS2_EXTEND 0x0008 119 #define ACCESS2_DELETE 0x0010 120 #define ACCESS2_EXECUTE 0x0020 121 122 static char *procnames_short_v2[] = { 123 "NULL2", /* 0 */ 124 "GETACL2", /* 1 */ 125 "SETACL2", /* 2 */ 126 "GETATTR2", /* 3 */ 127 "ACCESS2", /* 4 */ 128 "GETXATTRDIR2", /* 5 */ 129 }; 130 static char *procnames_short_v3[] = { 131 "NULL3", /* 0 */ 132 "GETACL3", /* 1 */ 133 "SETACL3", /* 2 */ 134 "GETXATTRDIR3", /* 3 */ 135 }; 136 static char *procnames_short_v4[] = { 137 "NULL4", /* 0 */ 138 "GETACL4", /* 1 */ 139 "SETACL4", /* 2 */ 140 }; 141 142 static char *procnames_long_v2[] = { 143 "Null procedure", /* 0 */ 144 "Get file access control list", /* 1 */ 145 "Set file access control list", /* 2 */ 146 "Get file attributes", /* 3 */ 147 "Check access permission", /* 4 */ 148 "Get extended attribute directory", /* 5 */ 149 }; 150 static char *procnames_long_v3[] = { 151 "Null procedure", /* 0 */ 152 "Get file access control list", /* 1 */ 153 "Set file access control list", /* 2 */ 154 "Get extended attribute directory", /* 3 */ 155 }; 156 static char *procnames_long_v4[] = { 157 "Null procedure", /* 0 */ 158 "Get file access control list", /* 1 */ 159 "Set file access control list", /* 2 */ 160 }; 161 162 #define MAXPROC_V2 5 163 #define MAXPROC_V3 3 164 #define MAXPROC_V4 2 165 166 /* ARGSUSED */ 167 void 168 interpret_nfs_acl(flags, type, xid, vers, proc, data, len) 169 int flags, type, xid, vers, proc; 170 char *data; 171 int len; 172 { 173 174 if (vers == 2) { 175 interpret_nfs_acl2(flags, type, xid, vers, proc, data, len); 176 return; 177 } 178 179 if (vers == 3) { 180 interpret_nfs_acl3(flags, type, xid, vers, proc, data, len); 181 return; 182 } 183 184 if (vers == 4) { 185 interpret_nfs_acl4(flags, type, xid, vers, proc, data, len); 186 return; 187 } 188 } 189 190 static void 191 interpret_nfs_acl2(int flags, int type, int xid, int vers, int proc, 192 char *data, int len) 193 { 194 char *line; 195 char buff[2048]; 196 int off, sz; 197 char *fh; 198 ulong_t mask; 199 200 if (proc < 0 || proc > MAXPROC_V2) 201 return; 202 203 if (flags & F_SUM) { 204 line = get_sum_line(); 205 206 if (type == CALL) { 207 (void) sprintf(line, "NFS_ACL C %s", 208 procnames_short_v2[proc]); 209 line += strlen(line); 210 switch (proc) { 211 case ACLPROC2_GETACL: 212 fh = sum_nfsfh(); 213 mask = getxdr_u_long(); 214 (void) sprintf(line, "%s mask=%lu", fh, mask); 215 break; 216 case ACLPROC2_SETACL: 217 (void) sprintf(line, sum_nfsfh()); 218 break; 219 case ACLPROC2_GETATTR: 220 (void) sprintf(line, sum_nfsfh()); 221 break; 222 case ACLPROC2_ACCESS: 223 fh = sum_nfsfh(); 224 (void) sprintf(line, "%s (%s)", fh, 225 sum_access2()); 226 break; 227 case ACLPROC2_GETXATTRDIR: 228 fh = sum_nfsfh(); 229 (void) sprintf(line, "%s create=%s", fh, 230 getxdr_bool() ? "true" : "false"); 231 break; 232 default: 233 break; 234 } 235 236 check_retransmit(line, (ulong_t)xid); 237 } else { 238 (void) sprintf(line, "NFS_ACL R %s ", 239 procnames_short_v2[proc]); 240 line += strlen(line); 241 switch (proc) { 242 case ACLPROC2_GETACL: 243 (void) sum_nfsstat(line); 244 break; 245 case ACLPROC2_SETACL: 246 (void) sum_nfsstat(line); 247 break; 248 case ACLPROC2_GETATTR: 249 (void) sum_nfsstat(line); 250 break; 251 case ACLPROC2_ACCESS: 252 if (sum_nfsstat(line) == 0) { 253 skip_fattr(); 254 line += strlen(line); 255 (void) sprintf(line, " (%s)", 256 sum_access2()); 257 } 258 break; 259 case ACLPROC2_GETXATTRDIR: 260 if (sum_nfsstat(line) == 0) { 261 line += strlen(line); 262 (void) sprintf(line, sum_nfsfh()); 263 } 264 break; 265 default: 266 break; 267 } 268 } 269 } 270 271 if (flags & F_DTAIL) { 272 show_header("NFS_ACL: ", "Sun NFS_ACL", len); 273 show_space(); 274 (void) sprintf(get_line(0, 0), "Proc = %d (%s)", 275 proc, procnames_long_v2[proc]); 276 if (type == CALL) 277 aclcall2(proc); 278 else 279 aclreply2(proc); 280 show_trailer(); 281 } 282 } 283 284 static void 285 interpret_nfs_acl3(int flags, int type, int xid, int vers, int proc, 286 char *data, int len) 287 { 288 char *line; 289 char buff[2048]; 290 int off, sz; 291 char *fh; 292 ulong_t mask; 293 294 if (proc < 0 || proc > MAXPROC_V3) 295 return; 296 297 if (flags & F_SUM) { 298 line = get_sum_line(); 299 300 if (type == CALL) { 301 (void) sprintf(line, "NFS_ACL C %s", 302 procnames_short_v3[proc]); 303 line += strlen(line); 304 switch (proc) { 305 case ACLPROC3_GETACL: 306 fh = sum_nfsfh3(); 307 mask = getxdr_u_long(); 308 (void) sprintf(line, "%s mask=%lu", fh, mask); 309 break; 310 case ACLPROC3_SETACL: 311 (void) sprintf(line, sum_nfsfh3()); 312 break; 313 case ACLPROC3_GETXATTRDIR: 314 fh = sum_nfsfh3(); 315 (void) sprintf(line, "%s create=%s", fh, 316 getxdr_bool() ? "true" : "false"); 317 break; 318 default: 319 break; 320 } 321 322 check_retransmit(line, (ulong_t)xid); 323 } else { 324 (void) sprintf(line, "NFS_ACL R %s ", 325 procnames_short_v3[proc]); 326 line += strlen(line); 327 switch (proc) { 328 case ACLPROC3_GETACL: 329 (void) sum_nfsstat3(line); 330 break; 331 case ACLPROC3_SETACL: 332 (void) sum_nfsstat3(line); 333 break; 334 case ACLPROC3_GETXATTRDIR: 335 if (sum_nfsstat3(line) == 0) { 336 line += strlen(line); 337 (void) sprintf(line, sum_nfsfh3()); 338 } 339 break; 340 default: 341 break; 342 } 343 } 344 } 345 346 if (flags & F_DTAIL) { 347 show_header("NFS_ACL: ", "Sun NFS_ACL", len); 348 show_space(); 349 (void) sprintf(get_line(0, 0), "Proc = %d (%s)", 350 proc, procnames_long_v3[proc]); 351 if (type == CALL) 352 aclcall3(proc); 353 else 354 aclreply3(proc); 355 show_trailer(); 356 } 357 } 358 359 static void 360 interpret_nfs_acl4(int flags, int type, int xid, int vers, int proc, 361 char *data, int len) 362 { 363 char *line; 364 char buff[2048]; 365 int off, sz; 366 char *fh; 367 ulong_t mask; 368 369 if (proc < 0 || proc > MAXPROC_V4) 370 return; 371 372 if (flags & F_SUM) { 373 line = get_sum_line(); 374 375 if (type == CALL) { 376 (void) sprintf(line, "NFS_ACL C %s", 377 procnames_short_v4[proc]); 378 line += strlen(line); 379 switch (proc) { 380 case ACLPROC4_GETACL: 381 fh = sum_nfsfh3(); 382 mask = getxdr_u_long(); 383 (void) sprintf(line, "%s mask=%lu", fh, mask); 384 break; 385 case ACLPROC4_SETACL: 386 (void) sprintf(line, sum_nfsfh3()); 387 break; 388 default: 389 break; 390 } 391 392 check_retransmit(line, (ulong_t)xid); 393 } else { 394 (void) sprintf(line, "NFS_ACL R %s ", 395 procnames_short_v4[proc]); 396 line += strlen(line); 397 switch (proc) { 398 case ACLPROC4_GETACL: 399 (void) sum_nfsstat4(line); 400 break; 401 case ACLPROC4_SETACL: 402 (void) sum_nfsstat4(line); 403 break; 404 default: 405 break; 406 } 407 } 408 } 409 410 if (flags & F_DTAIL) { 411 show_header("NFS_ACL: ", "Sun NFS_ACL", len); 412 show_space(); 413 (void) sprintf(get_line(0, 0), "Proc = %d (%s)", 414 proc, procnames_long_v4[proc]); 415 if (type == CALL) 416 aclcall4(proc); 417 else 418 aclreply4(proc); 419 show_trailer(); 420 } 421 } 422 423 int 424 sum_nfsstat4(char *line) 425 { 426 ulong_t status; 427 char *p, *nfsstat4_to_name(int); 428 429 status = getxdr_long(); 430 p = nfsstat4_to_name(status); 431 (void) strcpy(line, p); 432 return (status); 433 } 434 435 int 436 detail_nfsstat4() 437 { 438 ulong_t status; 439 char buff[64]; 440 int pos; 441 442 pos = getxdr_pos(); 443 status = sum_nfsstat4(buff); 444 445 (void) sprintf(get_line(pos, getxdr_pos()), "Status = %d (%s)", 446 status, buff); 447 448 return ((int)status); 449 } 450 451 /* 452 * Print out version 2 NFS_ACL call packets 453 */ 454 static void 455 aclcall2(proc) 456 int proc; 457 { 458 459 switch (proc) { 460 case ACLPROC2_GETACL: 461 detail_nfsfh(); 462 detail_mask(); 463 break; 464 case ACLPROC2_SETACL: 465 detail_nfsfh(); 466 detail_secattr(); 467 break; 468 case ACLPROC2_GETATTR: 469 detail_nfsfh(); 470 break; 471 case ACLPROC2_ACCESS: 472 detail_nfsfh(); 473 detail_access2(); 474 break; 475 default: 476 break; 477 } 478 } 479 480 /* 481 * Print out version 2 NFS_ACL reply packets 482 */ 483 static void 484 aclreply2(proc) 485 int proc; 486 { 487 488 switch (proc) { 489 case ACLPROC2_GETACL: 490 if (detail_nfsstat() == 0) { 491 detail_fattr(); 492 detail_secattr(); 493 } 494 break; 495 case ACLPROC2_SETACL: 496 if (detail_nfsstat() == 0) 497 detail_fattr(); 498 break; 499 case ACLPROC2_GETATTR: 500 if (detail_nfsstat() == 0) 501 detail_fattr(); 502 break; 503 case ACLPROC2_ACCESS: 504 if (detail_nfsstat() == 0) { 505 detail_fattr(); 506 detail_access2(); 507 } 508 break; 509 default: 510 break; 511 } 512 } 513 514 /* 515 * Print out version 3 NFS_ACL call packets 516 */ 517 static void 518 aclcall3(proc) 519 int proc; 520 { 521 522 switch (proc) { 523 case ACLPROC3_GETACL: 524 detail_nfsfh3(); 525 detail_mask(); 526 break; 527 case ACLPROC3_SETACL: 528 detail_nfsfh3(); 529 detail_secattr(); 530 break; 531 default: 532 break; 533 } 534 } 535 536 /* 537 * Print out version 3 NFS_ACL reply packets 538 */ 539 static void 540 aclreply3(proc) 541 int proc; 542 { 543 544 switch (proc) { 545 case ACLPROC3_GETACL: 546 if (detail_nfsstat3() == 0) { 547 detail_post_op_attr(""); 548 detail_secattr(); 549 } 550 break; 551 case ACLPROC3_SETACL: 552 if (detail_nfsstat3() == 0) 553 detail_post_op_attr(""); 554 break; 555 default: 556 break; 557 } 558 } 559 560 /* 561 * Print out version 4 NFS_ACL call packets 562 */ 563 static void 564 aclcall4(proc) 565 int proc; 566 { 567 568 switch (proc) { 569 case ACLPROC4_GETACL: 570 detail_nfsfh3(); 571 detail_mask(); 572 break; 573 case ACLPROC4_SETACL: 574 detail_nfsfh3(); 575 detail_secattr(); 576 break; 577 default: 578 break; 579 } 580 } 581 582 /* 583 * Print out version 4 NFS_ACL reply packets 584 */ 585 static void 586 aclreply4(proc) 587 int proc; 588 { 589 590 switch (proc) { 591 case ACLPROC4_GETACL: 592 if (detail_nfsstat4() == 0) { 593 detail_post_op_attr(""); 594 detail_secattr(); 595 } 596 break; 597 case ACLPROC4_SETACL: 598 if (detail_nfsstat4() == 0) 599 detail_post_op_attr(""); 600 break; 601 default: 602 break; 603 } 604 } 605 606 static void 607 detail_access2() 608 { 609 uint_t bits; 610 611 bits = showxdr_u_long("Access bits = 0x%08x"); 612 (void) sprintf(get_line(0, 0), " %s", 613 getflag(bits, ACCESS2_READ, "Read", "(no read)")); 614 (void) sprintf(get_line(0, 0), " %s", 615 getflag(bits, ACCESS2_LOOKUP, "Lookup", "(no lookup)")); 616 (void) sprintf(get_line(0, 0), " %s", 617 getflag(bits, ACCESS2_MODIFY, "Modify", "(no modify)")); 618 (void) sprintf(get_line(0, 0), " %s", 619 getflag(bits, ACCESS2_EXTEND, "Extend", "(no extend)")); 620 (void) sprintf(get_line(0, 0), " %s", 621 getflag(bits, ACCESS2_DELETE, "Delete", "(no delete)")); 622 (void) sprintf(get_line(0, 0), " %s", 623 getflag(bits, ACCESS2_EXECUTE, "Execute", "(no execute)")); 624 } 625 626 static char * 627 sum_access2() 628 { 629 int bits; 630 static char buff[22]; 631 632 bits = getxdr_u_long(); 633 buff[0] = '\0'; 634 635 if (bits & ACCESS2_READ) 636 (void) strcat(buff, "read,"); 637 if (bits & ACCESS2_LOOKUP) 638 (void) strcat(buff, "lookup,"); 639 if (bits & ACCESS2_MODIFY) 640 (void) strcat(buff, "modify,"); 641 if (bits & ACCESS2_EXTEND) 642 (void) strcat(buff, "extend,"); 643 if (bits & ACCESS2_DELETE) 644 (void) strcat(buff, "delete,"); 645 if (bits & ACCESS2_EXECUTE) 646 (void) strcat(buff, "execute,"); 647 if (buff[0] != '\0') 648 buff[strlen(buff) - 1] = '\0'; 649 650 return (buff); 651 } 652 653 static void 654 detail_mask() 655 { 656 ulong_t mask; 657 658 mask = showxdr_u_long("Mask = 0x%lx"); 659 (void) sprintf(get_line(0, 0), " %s", 660 getflag(mask, NA_ACL, "aclent", "(no aclent)")); 661 (void) sprintf(get_line(0, 0), " %s", 662 getflag(mask, NA_ACLCNT, "aclcnt", "(no aclcnt)")); 663 (void) sprintf(get_line(0, 0), " %s", 664 getflag(mask, NA_DFACL, "dfaclent", "(no dfaclent)")); 665 (void) sprintf(get_line(0, 0), " %s", 666 getflag(mask, NA_DFACLCNT, "dfaclcnt", "(no dfaclcnt)")); 667 } 668 669 static void 670 detail_secattr() 671 { 672 673 detail_mask(); 674 showxdr_long("Aclcnt = %d"); 675 detail_aclent(); 676 showxdr_long("Dfaclcnt = %d"); 677 detail_aclent(); 678 } 679 680 static void 681 detail_aclent() 682 { 683 int count; 684 int type; 685 int id; 686 ushort_t perm; 687 688 count = getxdr_long(); 689 while (count-- > 0) { 690 type = getxdr_long(); 691 id = getxdr_long(); 692 perm = getxdr_u_short(); 693 switch (type) { 694 case NA_USER: 695 (void) sprintf(get_line(0, 0), "\tuser:%s:%s", 696 detail_uname(id), detail_perm(perm)); 697 break; 698 case NA_USER_OBJ: 699 (void) sprintf(get_line(0, 0), "\tuser::%s", 700 detail_perm(perm)); 701 break; 702 case NA_GROUP: 703 (void) sprintf(get_line(0, 0), "\tgroup:%s:%s", 704 detail_gname(id), detail_perm(perm)); 705 break; 706 case NA_GROUP_OBJ: 707 (void) sprintf(get_line(0, 0), "\tgroup::%s", 708 detail_perm(perm)); 709 break; 710 case NA_CLASS_OBJ: 711 (void) sprintf(get_line(0, 0), "\tmask:%s", 712 detail_perm(perm)); 713 break; 714 case NA_OTHER_OBJ: 715 (void) sprintf(get_line(0, 0), "\tother:%s", 716 detail_perm(perm)); 717 break; 718 case NA_DEF_USER: 719 (void) sprintf(get_line(0, 0), "\tdefault:user:%s:%s", 720 detail_uname(id), detail_perm(perm)); 721 break; 722 case NA_DEF_USER_OBJ: 723 (void) sprintf(get_line(0, 0), "\tdefault:user::%s", 724 detail_perm(perm)); 725 break; 726 case NA_DEF_GROUP: 727 (void) sprintf(get_line(0, 0), "\tdefault:group:%s:%s", 728 detail_gname(id), detail_perm(perm)); 729 break; 730 case NA_DEF_GROUP_OBJ: 731 (void) sprintf(get_line(0, 0), "\tdefault:group::%s", 732 detail_perm(perm)); 733 break; 734 case NA_DEF_CLASS_OBJ: 735 (void) sprintf(get_line(0, 0), "\tdefault:mask:%s", 736 detail_perm(perm)); 737 break; 738 case NA_DEF_OTHER_OBJ: 739 (void) sprintf(get_line(0, 0), "\tdefault:other:%s", 740 detail_perm(perm)); 741 break; 742 default: 743 (void) sprintf(get_line(0, 0), "\tunrecognized entry"); 744 break; 745 } 746 } 747 } 748 749 static char * 750 detail_uname(uid_t uid) 751 { 752 struct passwd *pwd; 753 static char uidp[10]; 754 755 pwd = getpwuid(uid); 756 if (pwd == NULL) { 757 sprintf(uidp, "%d", uid); 758 return (uidp); 759 } 760 return (pwd->pw_name); 761 } 762 763 static char * 764 detail_gname(gid_t gid) 765 { 766 struct group *grp; 767 static char gidp[10]; 768 769 grp = getgrgid(gid); 770 if (grp == NULL) { 771 sprintf(gidp, "%d", gid); 772 return (gidp); 773 } 774 return (grp->gr_name); 775 } 776 777 static char *perms[] = { 778 "---", 779 "--x", 780 "-w-", 781 "-wx", 782 "r--", 783 "r-x", 784 "rw-", 785 "rwx" 786 }; 787 static char * 788 detail_perm(ushort_t perm) 789 { 790 791 if (perm >= sizeof (perms) / sizeof (perms[0])) 792 return ("?"); 793 return (perms[perm]); 794 } 795