diff options
Diffstat (limited to 'usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_nfs_acl.c')
-rw-r--r-- | usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_nfs_acl.c | 797 |
1 files changed, 797 insertions, 0 deletions
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_nfs_acl.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_nfs_acl.c new file mode 100644 index 0000000..4883ed5 --- /dev/null +++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_nfs_acl.c @@ -0,0 +1,797 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + */ + +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/tiuser.h> +#include <setjmp.h> +#include <pwd.h> +#include <grp.h> + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/auth.h> +#include <rpc/clnt.h> +#include <rpc/rpc_msg.h> +#include <string.h> +#include "snoop.h" + +#include <sys/stat.h> + +extern char *get_sum_line(); +extern void check_retransmit(); +extern char *sum_nfsfh(); +extern int sum_nfsstat(); +extern int detail_nfsstat(); +extern void detail_nfsfh(); +extern void detail_fattr(); +extern void skip_fattr(); +extern char *sum_nfsfh3(); +extern int sum_nfsstat3(); +extern int detail_nfsstat3(); +extern void detail_post_op_attr(); +extern void detail_nfsfh3(); +extern int sum_nfsstat4(); +extern int detail_nfsstat4(); + +extern jmp_buf xdr_err; + +static void aclcall2(); +static void aclreply2(); +static void aclcall3(); +static void aclreply3(); +static void aclcall4(); +static void aclreply4(); +static void detail_access2(); +static char *sum_access2(); +static void detail_mask(); +static void detail_secattr(); +static void detail_aclent(); +static char *detail_uname(); +static char *detail_gname(); +static char *detail_perm(ushort_t); +static void interpret_nfs_acl2(int, int, int, int, int, char *, int); +static void interpret_nfs_acl3(int, int, int, int, int, char *, int); +static void interpret_nfs_acl4(int, int, int, int, int, char *, int); + +#define ACLPROC2_NULL ((unsigned long)(0)) +#define ACLPROC2_GETACL ((unsigned long)(1)) +#define ACLPROC2_SETACL ((unsigned long)(2)) +#define ACLPROC2_GETATTR ((unsigned long)(3)) +#define ACLPROC2_ACCESS ((unsigned long)(4)) +#define ACLPROC2_GETXATTRDIR ((unsigned long)(5)) + +#define ACLPROC3_NULL ((unsigned long)(0)) +#define ACLPROC3_GETACL ((unsigned long)(1)) +#define ACLPROC3_SETACL ((unsigned long)(2)) +#define ACLPROC3_GETXATTRDIR ((unsigned long)(3)) + +#define ACLPROC4_NULL ((unsigned long)(0)) +#define ACLPROC4_GETACL ((unsigned long)(1)) +#define ACLPROC4_SETACL ((unsigned long)(2)) + +#define NA_USER_OBJ 0x1 +#define NA_USER 0x2 +#define NA_GROUP_OBJ 0x4 +#define NA_GROUP 0x8 +#define NA_CLASS_OBJ 0x10 +#define NA_OTHER_OBJ 0x20 +#define NA_ACL_DEFAULT 0x1000 + +#define NA_DEF_USER_OBJ (NA_USER_OBJ | NA_ACL_DEFAULT) +#define NA_DEF_USER (NA_USER | NA_ACL_DEFAULT) +#define NA_DEF_GROUP_OBJ (NA_GROUP_OBJ | NA_ACL_DEFAULT) +#define NA_DEF_GROUP (NA_GROUP | NA_ACL_DEFAULT) +#define NA_DEF_CLASS_OBJ (NA_CLASS_OBJ | NA_ACL_DEFAULT) +#define NA_DEF_OTHER_OBJ (NA_OTHER_OBJ | NA_ACL_DEFAULT) + +#define NA_ACL 0x1 +#define NA_ACLCNT 0x2 +#define NA_DFACL 0x4 +#define NA_DFACLCNT 0x8 + +#define ACCESS2_READ 0x0001 +#define ACCESS2_LOOKUP 0x0002 +#define ACCESS2_MODIFY 0x0004 +#define ACCESS2_EXTEND 0x0008 +#define ACCESS2_DELETE 0x0010 +#define ACCESS2_EXECUTE 0x0020 + +static char *procnames_short_v2[] = { + "NULL2", /* 0 */ + "GETACL2", /* 1 */ + "SETACL2", /* 2 */ + "GETATTR2", /* 3 */ + "ACCESS2", /* 4 */ + "GETXATTRDIR2", /* 5 */ +}; +static char *procnames_short_v3[] = { + "NULL3", /* 0 */ + "GETACL3", /* 1 */ + "SETACL3", /* 2 */ + "GETXATTRDIR3", /* 3 */ +}; +static char *procnames_short_v4[] = { + "NULL4", /* 0 */ + "GETACL4", /* 1 */ + "SETACL4", /* 2 */ +}; + +static char *procnames_long_v2[] = { + "Null procedure", /* 0 */ + "Get file access control list", /* 1 */ + "Set file access control list", /* 2 */ + "Get file attributes", /* 3 */ + "Check access permission", /* 4 */ + "Get extended attribute directory", /* 5 */ +}; +static char *procnames_long_v3[] = { + "Null procedure", /* 0 */ + "Get file access control list", /* 1 */ + "Set file access control list", /* 2 */ + "Get extended attribute directory", /* 3 */ +}; +static char *procnames_long_v4[] = { + "Null procedure", /* 0 */ + "Get file access control list", /* 1 */ + "Set file access control list", /* 2 */ +}; + +#define MAXPROC_V2 5 +#define MAXPROC_V3 3 +#define MAXPROC_V4 2 + +/* ARGSUSED */ +void +interpret_nfs_acl(flags, type, xid, vers, proc, data, len) + int flags, type, xid, vers, proc; + char *data; + int len; +{ + + if (vers == 2) { + interpret_nfs_acl2(flags, type, xid, vers, proc, data, len); + return; + } + + if (vers == 3) { + interpret_nfs_acl3(flags, type, xid, vers, proc, data, len); + return; + } + + if (vers == 4) { + interpret_nfs_acl4(flags, type, xid, vers, proc, data, len); + return; + } +} + +static void +interpret_nfs_acl2(int flags, int type, int xid, int vers, int proc, + char *data, int len) +{ + char *line; + char buff[2048]; + int off, sz; + char *fh; + ulong_t mask; + + if (proc < 0 || proc > MAXPROC_V2) + return; + + if (flags & F_SUM) { + line = get_sum_line(); + + if (type == CALL) { + (void) sprintf(line, "NFS_ACL C %s", + procnames_short_v2[proc]); + line += strlen(line); + switch (proc) { + case ACLPROC2_GETACL: + fh = sum_nfsfh(); + mask = getxdr_u_long(); + (void) sprintf(line, "%s mask=0x%lx", fh, mask); + break; + case ACLPROC2_SETACL: + (void) sprintf(line, sum_nfsfh()); + break; + case ACLPROC2_GETATTR: + (void) sprintf(line, sum_nfsfh()); + break; + case ACLPROC2_ACCESS: + fh = sum_nfsfh(); + (void) sprintf(line, "%s (%s)", fh, + sum_access2()); + break; + case ACLPROC2_GETXATTRDIR: + fh = sum_nfsfh(); + (void) sprintf(line, "%s create=%s", fh, + getxdr_bool() ? "true" : "false"); + break; + default: + break; + } + + check_retransmit(line, (ulong_t)xid); + } else { + (void) sprintf(line, "NFS_ACL R %s ", + procnames_short_v2[proc]); + line += strlen(line); + switch (proc) { + case ACLPROC2_GETACL: + (void) sum_nfsstat(line); + break; + case ACLPROC2_SETACL: + (void) sum_nfsstat(line); + break; + case ACLPROC2_GETATTR: + (void) sum_nfsstat(line); + break; + case ACLPROC2_ACCESS: + if (sum_nfsstat(line) == 0) { + skip_fattr(); + line += strlen(line); + (void) sprintf(line, " (%s)", + sum_access2()); + } + break; + case ACLPROC2_GETXATTRDIR: + if (sum_nfsstat(line) == 0) { + line += strlen(line); + (void) sprintf(line, sum_nfsfh()); + } + break; + default: + break; + } + } + } + + if (flags & F_DTAIL) { + show_header("NFS_ACL: ", "Sun NFS_ACL", len); + show_space(); + (void) sprintf(get_line(0, 0), "Proc = %d (%s)", + proc, procnames_long_v2[proc]); + if (type == CALL) + aclcall2(proc); + else + aclreply2(proc); + show_trailer(); + } +} + +static void +interpret_nfs_acl3(int flags, int type, int xid, int vers, int proc, + char *data, int len) +{ + char *line; + char buff[2048]; + int off, sz; + char *fh; + ulong_t mask; + + if (proc < 0 || proc > MAXPROC_V3) + return; + + if (flags & F_SUM) { + line = get_sum_line(); + + if (type == CALL) { + (void) sprintf(line, "NFS_ACL C %s", + procnames_short_v3[proc]); + line += strlen(line); + switch (proc) { + case ACLPROC3_GETACL: + fh = sum_nfsfh3(); + mask = getxdr_u_long(); + (void) sprintf(line, "%s mask=0x%lx", fh, mask); + break; + case ACLPROC3_SETACL: + (void) sprintf(line, sum_nfsfh3()); + break; + case ACLPROC3_GETXATTRDIR: + fh = sum_nfsfh3(); + (void) sprintf(line, "%s create=%s", fh, + getxdr_bool() ? "true" : "false"); + break; + default: + break; + } + + check_retransmit(line, (ulong_t)xid); + } else { + (void) sprintf(line, "NFS_ACL R %s ", + procnames_short_v3[proc]); + line += strlen(line); + switch (proc) { + case ACLPROC3_GETACL: + (void) sum_nfsstat3(line); + break; + case ACLPROC3_SETACL: + (void) sum_nfsstat3(line); + break; + case ACLPROC3_GETXATTRDIR: + if (sum_nfsstat3(line) == 0) { + line += strlen(line); + (void) sprintf(line, sum_nfsfh3()); + } + break; + default: + break; + } + } + } + + if (flags & F_DTAIL) { + show_header("NFS_ACL: ", "Sun NFS_ACL", len); + show_space(); + (void) sprintf(get_line(0, 0), "Proc = %d (%s)", + proc, procnames_long_v3[proc]); + if (type == CALL) + aclcall3(proc); + else + aclreply3(proc); + show_trailer(); + } +} + +static void +interpret_nfs_acl4(int flags, int type, int xid, int vers, int proc, + char *data, int len) +{ + char *line; + char buff[2048]; + int off, sz; + char *fh; + ulong_t mask; + + if (proc < 0 || proc > MAXPROC_V4) + return; + + if (flags & F_SUM) { + line = get_sum_line(); + + if (type == CALL) { + (void) sprintf(line, "NFS_ACL C %s", + procnames_short_v4[proc]); + line += strlen(line); + switch (proc) { + case ACLPROC4_GETACL: + fh = sum_nfsfh3(); + mask = getxdr_u_long(); + (void) sprintf(line, "%s mask=0x%lx", fh, mask); + break; + case ACLPROC4_SETACL: + (void) sprintf(line, sum_nfsfh3()); + break; + default: + break; + } + + check_retransmit(line, (ulong_t)xid); + } else { + (void) sprintf(line, "NFS_ACL R %s ", + procnames_short_v4[proc]); + line += strlen(line); + switch (proc) { + case ACLPROC4_GETACL: + (void) sum_nfsstat4(line); + break; + case ACLPROC4_SETACL: + (void) sum_nfsstat4(line); + break; + default: + break; + } + } + } + + if (flags & F_DTAIL) { + show_header("NFS_ACL: ", "Sun NFS_ACL", len); + show_space(); + (void) sprintf(get_line(0, 0), "Proc = %d (%s)", + proc, procnames_long_v4[proc]); + if (type == CALL) + aclcall4(proc); + else + aclreply4(proc); + show_trailer(); + } +} + +int +sum_nfsstat4(char *line) +{ + ulong_t status; + char *p, *nfsstat4_to_name(int); + + status = getxdr_long(); + p = nfsstat4_to_name(status); + (void) strcpy(line, p); + return (status); +} + +int +detail_nfsstat4() +{ + ulong_t status; + char buff[64]; + int pos; + + pos = getxdr_pos(); + status = sum_nfsstat4(buff); + + (void) sprintf(get_line(pos, getxdr_pos()), "Status = %d (%s)", + status, buff); + + return ((int)status); +} + +/* + * Print out version 2 NFS_ACL call packets + */ +static void +aclcall2(proc) + int proc; +{ + + switch (proc) { + case ACLPROC2_GETACL: + detail_nfsfh(); + detail_mask(); + break; + case ACLPROC2_SETACL: + detail_nfsfh(); + detail_secattr(); + break; + case ACLPROC2_GETATTR: + detail_nfsfh(); + break; + case ACLPROC2_ACCESS: + detail_nfsfh(); + detail_access2(); + break; + default: + break; + } +} + +/* + * Print out version 2 NFS_ACL reply packets + */ +static void +aclreply2(proc) + int proc; +{ + + switch (proc) { + case ACLPROC2_GETACL: + if (detail_nfsstat() == 0) { + detail_fattr(); + detail_secattr(); + } + break; + case ACLPROC2_SETACL: + if (detail_nfsstat() == 0) + detail_fattr(); + break; + case ACLPROC2_GETATTR: + if (detail_nfsstat() == 0) + detail_fattr(); + break; + case ACLPROC2_ACCESS: + if (detail_nfsstat() == 0) { + detail_fattr(); + detail_access2(); + } + break; + default: + break; + } +} + +/* + * Print out version 3 NFS_ACL call packets + */ +static void +aclcall3(proc) + int proc; +{ + + switch (proc) { + case ACLPROC3_GETACL: + detail_nfsfh3(); + detail_mask(); + break; + case ACLPROC3_SETACL: + detail_nfsfh3(); + detail_secattr(); + break; + default: + break; + } +} + +/* + * Print out version 3 NFS_ACL reply packets + */ +static void +aclreply3(proc) + int proc; +{ + + switch (proc) { + case ACLPROC3_GETACL: + if (detail_nfsstat3() == 0) { + detail_post_op_attr(""); + detail_secattr(); + } + break; + case ACLPROC3_SETACL: + if (detail_nfsstat3() == 0) + detail_post_op_attr(""); + break; + default: + break; + } +} + +/* + * Print out version 4 NFS_ACL call packets + */ +static void +aclcall4(proc) + int proc; +{ + + switch (proc) { + case ACLPROC4_GETACL: + detail_nfsfh3(); + detail_mask(); + break; + case ACLPROC4_SETACL: + detail_nfsfh3(); + detail_secattr(); + break; + default: + break; + } +} + +/* + * Print out version 4 NFS_ACL reply packets + */ +static void +aclreply4(proc) + int proc; +{ + + switch (proc) { + case ACLPROC4_GETACL: + if (detail_nfsstat4() == 0) { + detail_post_op_attr(""); + detail_secattr(); + } + break; + case ACLPROC4_SETACL: + if (detail_nfsstat4() == 0) + detail_post_op_attr(""); + break; + default: + break; + } +} + +static void +detail_access2() +{ + uint_t bits; + + bits = showxdr_u_long("Access bits = 0x%08x"); + (void) sprintf(get_line(0, 0), " %s", + getflag(bits, ACCESS2_READ, "Read", "(no read)")); + (void) sprintf(get_line(0, 0), " %s", + getflag(bits, ACCESS2_LOOKUP, "Lookup", "(no lookup)")); + (void) sprintf(get_line(0, 0), " %s", + getflag(bits, ACCESS2_MODIFY, "Modify", "(no modify)")); + (void) sprintf(get_line(0, 0), " %s", + getflag(bits, ACCESS2_EXTEND, "Extend", "(no extend)")); + (void) sprintf(get_line(0, 0), " %s", + getflag(bits, ACCESS2_DELETE, "Delete", "(no delete)")); + (void) sprintf(get_line(0, 0), " %s", + getflag(bits, ACCESS2_EXECUTE, "Execute", "(no execute)")); +} + +static char * +sum_access2() +{ + int bits; + static char buff[22]; + + bits = getxdr_u_long(); + buff[0] = '\0'; + + if (bits & ACCESS2_READ) + (void) strcat(buff, "read,"); + if (bits & ACCESS2_LOOKUP) + (void) strcat(buff, "lookup,"); + if (bits & ACCESS2_MODIFY) + (void) strcat(buff, "modify,"); + if (bits & ACCESS2_EXTEND) + (void) strcat(buff, "extend,"); + if (bits & ACCESS2_DELETE) + (void) strcat(buff, "delete,"); + if (bits & ACCESS2_EXECUTE) + (void) strcat(buff, "execute,"); + if (buff[0] != '\0') + buff[strlen(buff) - 1] = '\0'; + + return (buff); +} + +static void +detail_mask() +{ + ulong_t mask; + + mask = showxdr_u_long("Mask = 0x%lx"); + (void) sprintf(get_line(0, 0), " %s", + getflag(mask, NA_ACL, "aclent", "(no aclent)")); + (void) sprintf(get_line(0, 0), " %s", + getflag(mask, NA_ACLCNT, "aclcnt", "(no aclcnt)")); + (void) sprintf(get_line(0, 0), " %s", + getflag(mask, NA_DFACL, "dfaclent", "(no dfaclent)")); + (void) sprintf(get_line(0, 0), " %s", + getflag(mask, NA_DFACLCNT, "dfaclcnt", "(no dfaclcnt)")); +} + +static void +detail_secattr() +{ + + detail_mask(); + showxdr_long("Aclcnt = %d"); + detail_aclent(); + showxdr_long("Dfaclcnt = %d"); + detail_aclent(); +} + +static void +detail_aclent() +{ + int count; + int type; + int id; + ushort_t perm; + + count = getxdr_long(); + while (count-- > 0) { + type = getxdr_long(); + id = getxdr_long(); + perm = getxdr_u_short(); + switch (type) { + case NA_USER: + (void) sprintf(get_line(0, 0), "\tuser:%s:%s", + detail_uname(id), detail_perm(perm)); + break; + case NA_USER_OBJ: + (void) sprintf(get_line(0, 0), "\tuser::%s", + detail_perm(perm)); + break; + case NA_GROUP: + (void) sprintf(get_line(0, 0), "\tgroup:%s:%s", + detail_gname(id), detail_perm(perm)); + break; + case NA_GROUP_OBJ: + (void) sprintf(get_line(0, 0), "\tgroup::%s", + detail_perm(perm)); + break; + case NA_CLASS_OBJ: + (void) sprintf(get_line(0, 0), "\tmask:%s", + detail_perm(perm)); + break; + case NA_OTHER_OBJ: + (void) sprintf(get_line(0, 0), "\tother:%s", + detail_perm(perm)); + break; + case NA_DEF_USER: + (void) sprintf(get_line(0, 0), "\tdefault:user:%s:%s", + detail_uname(id), detail_perm(perm)); + break; + case NA_DEF_USER_OBJ: + (void) sprintf(get_line(0, 0), "\tdefault:user::%s", + detail_perm(perm)); + break; + case NA_DEF_GROUP: + (void) sprintf(get_line(0, 0), "\tdefault:group:%s:%s", + detail_gname(id), detail_perm(perm)); + break; + case NA_DEF_GROUP_OBJ: + (void) sprintf(get_line(0, 0), "\tdefault:group::%s", + detail_perm(perm)); + break; + case NA_DEF_CLASS_OBJ: + (void) sprintf(get_line(0, 0), "\tdefault:mask:%s", + detail_perm(perm)); + break; + case NA_DEF_OTHER_OBJ: + (void) sprintf(get_line(0, 0), "\tdefault:other:%s", + detail_perm(perm)); + break; + default: + (void) sprintf(get_line(0, 0), "\tunrecognized entry"); + break; + } + } +} + +static char * +detail_uname(uid_t uid) +{ + struct passwd *pwd; + static char uidp[10]; + + pwd = getpwuid(uid); + if (pwd == NULL) { + sprintf(uidp, "%d", uid); + return (uidp); + } + return (pwd->pw_name); +} + +static char * +detail_gname(gid_t gid) +{ + struct group *grp; + static char gidp[10]; + + grp = getgrgid(gid); + if (grp == NULL) { + sprintf(gidp, "%d", gid); + return (gidp); + } + return (grp->gr_name); +} + +static char *perms[] = { + "---", + "--x", + "-w-", + "-wx", + "r--", + "r-x", + "rw-", + "rwx" +}; +static char * +detail_perm(ushort_t perm) +{ + + if (perm >= sizeof (perms) / sizeof (perms[0])) + return ("?"); + return (perms[perm]); +} |