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