/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* * auditconfig - set and display audit parameters */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SUNW_OST_OSCMD" #endif #define AC_ARG_AUDIT 0 #define AC_ARG_CHKCONF 1 #define AC_ARG_CONF 2 #define AC_ARG_GETASID 3 /* same as GETSID */ #define AC_ARG_GETAUDIT 4 #define AC_ARG_GETAUID 5 #define AC_ARG_GETCAR 6 #define AC_ARG_GETCLASS 7 /* same as GETESTATE */ #define AC_ARG_GETCOND 8 #define AC_ARG_GETCWD 9 #define AC_ARG_GETESTATE 10 #define AC_ARG_GETKERNSTATE 11 #define AC_ARG_GETKMASK 12 /* same as GETKERNSTATE */ #define AC_ARG_GETPINFO 13 #define AC_ARG_GETPOLICY 14 #define AC_ARG_GETQBUFSZ 15 #define AC_ARG_GETQCTRL 16 #define AC_ARG_GETQDELAY 17 #define AC_ARG_GETQHIWATER 18 #define AC_ARG_GETQLOWATER 19 #define AC_ARG_GETSID 20 #define AC_ARG_GETSTAT 21 #define AC_ARG_GETTERMID 22 #define AC_ARG_GETUSERAUDIT 23 /* only CMW syscall w/out */ #define AC_ARG_LSEVENT 24 #define AC_ARG_LSPOLICY 25 #define AC_ARG_SETASID 26 #define AC_ARG_SETAUDIT 27 #define AC_ARG_SETAUID 28 #define AC_ARG_SETCLASS 29 /* same as SETESTATE */ /* AC_ARG_SETCOND 30 */ #define AC_ARG_SETESTATE 31 #define AC_ARG_SETKERNSTATE 32 #define AC_ARG_SETKMASK 33 /* same as SETKERNSTATE */ #define AC_ARG_SETPMASK 34 #define AC_ARG_SETSMASK 35 #define AC_ARG_SETSTAT 36 #define AC_ARG_SETPOLICY 37 #define AC_ARG_SETQBUFSZ 38 #define AC_ARG_SETQCTRL 39 #define AC_ARG_SETQDELAY 40 #define AC_ARG_SETQHIWATER 41 #define AC_ARG_SETQLOWATER 42 #define AC_ARG_SETTERMID 43 #define AC_ARG_SETUMASK 44 #define AC_ARG_SETUSERAUDIT 45 #define AC_ARG_GETFSIZE 46 #define AC_ARG_SETFSIZE 47 #define AC_ARG_GETKAUDIT 48 #define AC_ARG_SETKAUDIT 49 #define AC_ARG_ACONF 50 #define AC_ARG_CHKACONF 51 #define AC_KERN_EVENT 0 #define AC_USER_EVENT 1 #define NONE(s) (!strlen(s) ? gettext("none") : s) #define ALL_POLICIES (AUDIT_AHLT|\ AUDIT_ARGE|\ AUDIT_ARGV|\ AUDIT_CNT|\ AUDIT_GROUP|\ AUDIT_PASSWD|\ AUDIT_WINDATA|\ AUDIT_SEQ|\ AUDIT_TRAIL|\ AUDIT_PATH|\ AUDIT_PUBLIC|\ AUDIT_ZONENAME|\ AUDIT_PERZONE) #define NO_POLICIES (0) #define ONEK 1024 /* This should be defined in , but it is not */ extern int strncasecmp(); /* * remove this after the audit.h is fixed */ struct arg_entry { char *arg_str; char *arg_opts; int auditconfig_cmd; }; struct policy_entry { char *policy_str; uint_t policy_mask; char *policy_desc; }; static struct arg_entry arg_table[] = { { "-aconf", "", AC_ARG_ACONF}, { "-audit", "event sorf retval string", AC_ARG_AUDIT}, { "-chkaconf", "", AC_ARG_CHKACONF}, { "-chkconf", "", AC_ARG_CHKCONF}, { "-conf", "", AC_ARG_CONF}, { "-getasid", "", AC_ARG_GETASID}, { "-getaudit", "", AC_ARG_GETAUDIT}, { "-getauid", "", AC_ARG_GETAUID}, { "-getcar", "", AC_ARG_GETCAR}, { "-getclass", "", AC_ARG_GETCLASS}, { "-getcond", "", AC_ARG_GETCOND}, { "-getcwd", "", AC_ARG_GETCWD}, { "-getestate", "event", AC_ARG_GETESTATE}, { "-getfsize", "", AC_ARG_GETFSIZE}, { "-getkaudit", "", AC_ARG_GETKAUDIT}, { "-getkernstate", "", AC_ARG_GETKERNSTATE}, { "-getkmask", "", AC_ARG_GETKMASK}, { "-getpinfo", "", AC_ARG_GETPINFO}, { "-getpolicy", "", AC_ARG_GETPOLICY}, { "-getqbufsz", "", AC_ARG_GETQBUFSZ}, { "-getqctrl", "", AC_ARG_GETQCTRL}, { "-getqdelay", "", AC_ARG_GETQDELAY}, { "-getqhiwater", "", AC_ARG_GETQHIWATER}, { "-getqlowater", "", AC_ARG_GETQLOWATER}, { "-getsid", "", AC_ARG_GETSID}, { "-getstat", "", AC_ARG_GETSTAT}, { "-gettermid", "", AC_ARG_GETTERMID}, { "-gettid", "", AC_ARG_GETTERMID}, { "-getuseraudit", "user", AC_ARG_GETUSERAUDIT}, { "-lsevent", "", AC_ARG_LSEVENT}, { "-lspolicy", "", AC_ARG_LSPOLICY}, { "-setasid", "asid [cmd]", AC_ARG_SETASID}, { "-setaudit", "auid audit_flags termid sid [cmd]", AC_ARG_SETAUDIT}, { "-setauid", "auid [cmd]", AC_ARG_SETAUID}, { "-setclass", "event audit_flags", AC_ARG_SETCLASS}, { "-setestate", "event audit_flags", AC_ARG_SETESTATE}, { "-setfsize", "filesize", AC_ARG_SETFSIZE}, { "-setkaudit", "type IP_address", AC_ARG_SETKAUDIT}, { "-setkernstate", "audit_flags", AC_ARG_SETKERNSTATE}, { "-setkmask", "audit_flags", AC_ARG_SETKMASK}, { "-setpmask", "pid audit_flags [cmd]", AC_ARG_SETPMASK}, { "-setpolicy", "policy_flags", AC_ARG_SETPOLICY}, { "-setqbufsz", "bufsz", AC_ARG_SETQBUFSZ}, { "-setqctrl", "hiwater lowater bufsz delay", AC_ARG_SETQCTRL}, { "-setqdelay", "delay", AC_ARG_SETQDELAY}, { "-setqhiwater", "hiwater", AC_ARG_SETQHIWATER}, { "-setqlowater", "lowater", AC_ARG_SETQLOWATER}, { "-setsmask", "asid audit_flags", AC_ARG_SETSMASK}, { "-setstat", "", AC_ARG_SETSTAT}, { "-settid", "tid [cmd]", AC_ARG_SETTERMID}, { "-setumask", "user audit_flags", AC_ARG_SETUMASK}, { "-setuseraudit", "user audit_flags", AC_ARG_SETUSERAUDIT} }; #define ARG_TBL_SZ (sizeof (arg_table) / sizeof (struct arg_entry)) static struct arg_entry arg2_table[] = { { "-chkconf", "", AC_ARG_CHKCONF}, { "-conf", "", AC_ARG_CONF}, { "-getcond", "", AC_ARG_GETCOND}, { "-getclass", "event", AC_ARG_GETCLASS}, { "-setclass", "event audit_flags", AC_ARG_SETCLASS}, { "-lsevent", "", AC_ARG_LSEVENT}, { "-lspolicy", "", AC_ARG_LSPOLICY}, { "-getpolicy", "", AC_ARG_GETPOLICY}, { "-setpolicy", "policy_flags", AC_ARG_SETPOLICY}, { "-getstat", "", AC_ARG_GETSTAT}, { "-getpinfo", "pid", AC_ARG_GETPINFO}, { "-setpmask", "pid audit_flags", AC_ARG_SETPMASK}, { "-setsmask", "asid audit_flags", AC_ARG_SETSMASK}, { "-setumask", "user audit_flags", AC_ARG_SETUMASK}, { "-getfsize", "", AC_ARG_GETFSIZE}, { "-setfsize", "filesize", AC_ARG_SETFSIZE} }; #define ARG2_TBL_SZ (sizeof (arg2_table) / sizeof (struct arg_entry)) static struct policy_entry policy_table[] = { {"ahlt", AUDIT_AHLT, "halt machine if it can not record an " "async event"}, {"arge", AUDIT_ARGE, "include exec environment args in audit recs"}, {"argv", AUDIT_ARGV, "include exec command line args in audit recs"}, {"cnt", AUDIT_CNT, "when no more space, drop recs and keep a cnt"}, {"group", AUDIT_GROUP, "include supplementary groups in audit recs"}, {"seq", AUDIT_SEQ, "include a sequence number in audit recs"}, {"trail", AUDIT_TRAIL, "include trailer token in audit recs"}, {"path", AUDIT_PATH, "allow multiple paths per event"}, {"public", AUDIT_PUBLIC, "audit public files"}, {"zonename", AUDIT_ZONENAME, "generate zonename token"}, {"perzone", AUDIT_PERZONE, "use a separate queue and auditd per " "zone"}, {"all", ALL_POLICIES, "all policies"}, {"none", NO_POLICIES, "no policies"} }; #define POLICY_TBL_SZ (sizeof (policy_table) / sizeof (struct policy_entry)) static char *progname; static au_event_ent_t *egetauevnam(); static au_event_ent_t *egetauevnum(); static char *strtolower(); static int arg_ent_compare(); static int cond2str(); static int policy2str(); static int str2type(); static int str2policy(); static int str2ipaddr(); static int strisflags(); static int strisipaddr(); static int strisnum(); static struct arg_entry *get_arg_ent(); static struct policy_entry *get_policy_ent(); static uid_t get_user_id(); static void chk_event_num(); static void chk_event_str(); static void chk_retval(); static void chk_sorf(); static void chk_tid(); static void do_aconf(); static void do_args(); static void do_audit(); static void do_chkaconf(); static void do_chkconf(); static void do_conf(); static void do_getasid(); static void do_getaudit(); static void do_getkaudit(); static void do_setkaudit(); static void do_getauid(); static void do_getcar(); static void do_getclass(); static void do_getcond(); static void do_getcwd(); static void do_getkmask(); static void do_getpinfo(); static void do_getpolicy(); static void do_getqbufsz(); static void do_getqctrl(); static void do_getqdelay(); static void do_getqhiwater(); static void do_getqlowater(); static void do_getstat(); static void do_gettermid(); static void do_getuseraudit(); static void do_lsevent(); static void do_lspolicy(); static void do_setasid(); static void do_setaudit(); static void do_setauid(); static void do_setclass(); static void do_setkmask(); static void do_setpmask(); static void do_setsmask(); static void do_setumask(); static void do_setpolicy(); static void do_setqbufsz(); static void do_setqctrl(); static void do_setqdelay(); static void do_setqhiwater(); static void do_setqlowater(); static void do_setstat(); static void do_settid(); static void do_setuseraudit(); static void do_getfsize(); static void do_setfsize(); static void str2mask(); static void str2tid(); static void strsplit(); static void eauditon(); static void egetaudit(); static void egetkaudit(); static void esetkaudit(); static void egetauditflagsbin(); static void egetauid(); static void esetaudit(); static void esetauid(); static void execit(); static void exit_error(char *, ...); static void exit_usage(); static void parse_args(); static void print_asid(); static void print_auid(); static void print_mask(); static void print_mask1(); static void print_stats(); static void print_tid_ex(); extern char *sys_errlist[]; int main(argc, argv) int argc; char **argv; { progname = "auditconfig"; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); if (argc == 1) { exit_usage(0); exit(0); } if (argc == 2 && (argv[1][0] == '?' || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-?") == 0)) exit_usage(0); parse_args(argv); do_args(argv); return (0); } /* * parse_args() * Desc: Checks command line argument syntax. * Inputs: Command line argv; * Returns: If a syntax error is detected, a usage message is printed * and exit() is called. If a syntax error is not detected, * parse_args() returns without a value. */ static void parse_args(char **argv) { struct arg_entry *ae; au_mask_t pmask; au_mask_t smask; au_mask_t umask; uint_t type; uint_t addr[4]; for (++argv; *argv; argv++) { if ((ae = get_arg_ent(*argv)) == (struct arg_entry *)0) { exit_usage(1); } switch (ae->auditconfig_cmd) { case AC_ARG_AUDIT: ++argv; if (!*argv) exit_usage(1); if (strisnum(*argv)) { chk_event_num(AC_USER_EVENT, (au_event_t)atol(*argv)); } else chk_event_str(AC_USER_EVENT, *argv); ++argv; if (!*argv) exit_usage(1); chk_sorf(*argv); ++argv; if (!*argv) exit_usage(1); chk_retval(*argv); ++argv; if (!*argv) exit_usage(1); break; case AC_ARG_CHKCONF: break; case AC_ARG_CONF: break; case AC_ARG_ACONF: break; case AC_ARG_CHKACONF: break; case AC_ARG_GETASID: case AC_ARG_GETSID: break; case AC_ARG_GETAUID: break; case AC_ARG_GETAUDIT: break; case AC_ARG_GETKAUDIT: break; case AC_ARG_GETCLASS: case AC_ARG_GETESTATE: ++argv; if (!*argv) exit_usage(1); if (strisnum(*argv)) chk_event_num(AC_KERN_EVENT, (au_event_t)atol(*argv)); else chk_event_str(AC_KERN_EVENT, *argv); break; case AC_ARG_GETCAR: break; case AC_ARG_GETCOND: break; case AC_ARG_GETCWD: break; case AC_ARG_GETKERNSTATE: case AC_ARG_GETKMASK: break; case AC_ARG_GETPOLICY: break; case AC_ARG_GETQBUFSZ: break; case AC_ARG_GETQCTRL: break; case AC_ARG_GETQDELAY: break; case AC_ARG_GETQHIWATER: break; case AC_ARG_GETQLOWATER: break; case AC_ARG_GETSTAT: break; case AC_ARG_GETTERMID: break; case AC_ARG_GETUSERAUDIT: ++argv; if (!*argv) exit_usage(1); break; case AC_ARG_LSEVENT: break; case AC_ARG_LSPOLICY: break; case AC_ARG_SETASID: ++argv; if (!*argv) exit_usage(1); while (*argv) ++argv; --argv; break; case AC_ARG_SETAUID: ++argv; if (!*argv) exit_usage(1); while (*argv) ++argv; --argv; break; case AC_ARG_SETAUDIT: ++argv; if (!*argv) exit_usage(1); while (*argv) ++argv; --argv; break; case AC_ARG_SETKAUDIT: ++argv; if (!*argv) exit_usage(1); if (str2type (*argv, &type)) exit_error(gettext( "Invalid IP address type specified.")); ++argv; if (!*argv) exit_usage(1); if (str2ipaddr(*argv, addr, type)) exit_error(gettext( "Invalid IP address specified.")); break; case AC_ARG_SETCLASS: case AC_ARG_SETESTATE: ++argv; if (!*argv) exit_usage(1); if (strisnum(*argv)) chk_event_num(AC_KERN_EVENT, (au_event_t)atol(*argv)); else chk_event_str(AC_KERN_EVENT, *argv); ++argv; if (!*argv) exit_usage(1); str2mask(*argv, &pmask); break; case AC_ARG_SETKERNSTATE: case AC_ARG_SETKMASK: ++argv; if (!*argv) exit_usage(1); str2mask(*argv, &pmask); break; case AC_ARG_SETPOLICY: ++argv; if (!*argv) exit_usage(1); break; case AC_ARG_SETSTAT: break; case AC_ARG_GETPINFO: ++argv; if (!*argv) exit_usage(1); break; case AC_ARG_SETPMASK: ++argv; if (!*argv) exit_usage(1); ++argv; if (!*argv) exit_usage(1); str2mask(*argv, &pmask); break; case AC_ARG_SETQBUFSZ: ++argv; if (!*argv) exit_usage(1); if (!strisnum(*argv)) exit_error(gettext("Invalid bufsz specified.")); break; case AC_ARG_SETQCTRL: ++argv; if (!*argv) exit_usage(1); if (!strisnum(*argv)) exit_error(gettext( "Invalid hiwater specified.")); ++argv; if (!*argv) exit_usage(1); if (!strisnum(*argv)) exit_error(gettext( gettext("Invalid lowater specified."))); ++argv; if (!*argv) exit_usage(1); if (!strisnum(*argv)) exit_error(gettext("Invalid bufsz specified.")); ++argv; if (!*argv) exit_usage(1); if (!strisnum(*argv)) exit_error(gettext("Invalid delay specified.")); break; case AC_ARG_SETQDELAY: ++argv; if (!*argv) exit_usage(1); if (!strisnum(*argv)) exit_error(gettext("Invalid delay specified.")); break; case AC_ARG_SETQHIWATER: ++argv; if (!*argv) exit_usage(1); if (!strisnum(*argv)) exit_error(gettext( "Invalid hiwater specified.")); break; case AC_ARG_SETQLOWATER: ++argv; if (!*argv) exit_usage(1); if (!strisnum(*argv)) exit_error(gettext( "Invalid lowater specified.")); break; case AC_ARG_SETTERMID: ++argv; if (!*argv) exit_usage(1); chk_tid(*argv); break; case AC_ARG_SETUSERAUDIT: ++argv; if (!*argv) exit_usage(1); ++argv; if (!*argv) exit_usage(1); break; case AC_ARG_SETSMASK: ++argv; if (!*argv) exit_usage(1); ++argv; if (!*argv) exit_usage(1); str2mask(*argv, &smask); break; case AC_ARG_SETUMASK: ++argv; if (!*argv) exit_usage(1); ++argv; if (!*argv) exit_usage(1); str2mask(*argv, &umask); break; case AC_ARG_GETFSIZE: break; case AC_ARG_SETFSIZE: ++argv; if (!*argv) exit_usage(1); if (!strisnum(*argv)) exit_error(gettext( "Invalid hiwater specified.")); break; default: exit_error(gettext("Internal error #1.")); break; } } } /* * do_args() * Desc: Do command line arguments in the order in which they appear. */ static void do_args(argv) char **argv; { struct arg_entry *ae; for (++argv; *argv; argv++) { ae = get_arg_ent(*argv); switch (ae->auditconfig_cmd) { case AC_ARG_AUDIT: { char sorf; int retval; char *event_name; char *audit_str; ++argv; event_name = *argv; ++argv; sorf = (char)atoi(*argv); ++argv; retval = atoi(*argv); ++argv; audit_str = *argv; do_audit(event_name, sorf, retval, audit_str); } break; case AC_ARG_CHKCONF: do_chkconf(); break; case AC_ARG_CONF: do_conf(); break; case AC_ARG_CHKACONF: do_chkaconf(); break; case AC_ARG_ACONF: do_aconf(); break; case AC_ARG_GETASID: case AC_ARG_GETSID: do_getasid(); break; case AC_ARG_GETAUID: do_getauid(); break; case AC_ARG_GETAUDIT: do_getaudit(); break; case AC_ARG_GETKAUDIT: do_getkaudit(); break; case AC_ARG_GETCLASS: case AC_ARG_GETESTATE: ++argv; do_getclass(*argv); break; case AC_ARG_GETCAR: do_getcar(); break; case AC_ARG_GETCOND: do_getcond(); break; case AC_ARG_GETCWD: do_getcwd(); break; case AC_ARG_GETKERNSTATE: case AC_ARG_GETKMASK: do_getkmask(); break; case AC_ARG_GETPOLICY: do_getpolicy(); break; case AC_ARG_GETQBUFSZ: do_getqbufsz(); break; case AC_ARG_GETQCTRL: do_getqctrl(); break; case AC_ARG_GETQDELAY: do_getqdelay(); break; case AC_ARG_GETQHIWATER: do_getqhiwater(); break; case AC_ARG_GETQLOWATER: do_getqlowater(); break; case AC_ARG_GETSTAT: do_getstat(); break; case AC_ARG_GETTERMID: do_gettermid(); break; case AC_ARG_GETUSERAUDIT: ++argv; do_getuseraudit(*argv); break; case AC_ARG_LSEVENT: do_lsevent(); break; case AC_ARG_LSPOLICY: do_lspolicy(); break; case AC_ARG_SETASID: { char *sid_str; ++argv; sid_str = *argv; ++argv; do_setasid(sid_str, argv); } break; case AC_ARG_SETAUID: { char *user; ++argv; user = *argv; ++argv; do_setauid(user, argv); } break; case AC_ARG_SETAUDIT: { char *user_str; char *mask_str; char *tid_str; char *sid_str; ++argv; user_str = *argv; ++argv; mask_str = *argv; ++argv; tid_str = *argv; ++argv; sid_str = *argv; ++argv; do_setaudit(user_str, mask_str, tid_str, sid_str, argv); } break; case AC_ARG_SETKAUDIT: { char *address_type, *address; ++argv; address_type = *argv; ++argv; address = *argv; do_setkaudit(address_type, address); } break; case AC_ARG_SETCLASS: case AC_ARG_SETESTATE: { char *event_str, *audit_flags; ++argv; event_str = *argv; ++argv; audit_flags = *argv; do_setclass(event_str, audit_flags); } break; case AC_ARG_SETKERNSTATE: case AC_ARG_SETKMASK: ++argv; do_setkmask(*argv); break; case AC_ARG_SETPOLICY: ++argv; do_setpolicy(*argv); break; case AC_ARG_GETPINFO: { char *pid_str; ++argv; pid_str = *argv; do_getpinfo(pid_str); } break; case AC_ARG_SETPMASK: { char *pid_str; char *audit_flags; ++argv; pid_str = *argv; ++argv; audit_flags = *argv; do_setpmask(pid_str, audit_flags); } break; case AC_ARG_SETSTAT: do_setstat(); break; case AC_ARG_SETQBUFSZ: ++argv; do_setqbufsz(*argv); break; case AC_ARG_SETQCTRL: { char *hiwater, *lowater, *bufsz, *delay; ++argv; hiwater = *argv; ++argv; lowater = *argv; ++argv; bufsz = *argv; ++argv; delay = *argv; do_setqctrl(hiwater, lowater, bufsz, delay); } break; case AC_ARG_SETQDELAY: ++argv; do_setqdelay(*argv); break; case AC_ARG_SETQHIWATER: ++argv; do_setqhiwater(*argv); break; case AC_ARG_SETQLOWATER: ++argv; do_setqlowater(*argv); break; case AC_ARG_SETTERMID: ++argv; do_settid(*argv); break; case AC_ARG_SETUSERAUDIT: { char *user; char *aflags; ++argv; user = *argv; ++argv; aflags = *argv; do_setuseraudit(user, aflags); } break; case AC_ARG_SETSMASK: { char *asid_str; char *audit_flags; ++argv; asid_str = *argv; ++argv; audit_flags = *argv; do_setsmask(asid_str, audit_flags); } break; case AC_ARG_SETUMASK: { char *auid_str; char *audit_flags; ++argv; auid_str = *argv; ++argv; audit_flags = *argv; do_setumask(auid_str, audit_flags); } break; case AC_ARG_GETFSIZE: do_getfsize(); break; case AC_ARG_SETFSIZE: ++argv; do_setfsize(*argv); break; default: exit_error(gettext("Internal error #2.")); break; } } } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_chkconf() { register au_event_ent_t *evp; au_mask_t pmask; char conf_aflags[256]; char run_aflags[256]; au_stat_t as; int class; int len; struct au_evclass_map cmap; pmask.am_success = pmask.am_failure = 0; eauditon(A_GETSTAT, (caddr_t)&as, 0); setauevent(); if ((evp = getauevent()) == (au_event_ent_t *)NULL) { (void) exit_error(gettext( "NO AUDIT EVENTS: Could not read %s\n."), AUDITEVENTFILE); } setauevent(); while ((evp = getauevent()) != (au_event_ent_t *)NULL) { cmap.ec_number = evp->ae_number; len = sizeof (struct au_evclass_map); if (evp->ae_number <= as.as_numevent) if (auditon(A_GETCLASS, (caddr_t)&cmap, len) == -1) { (void) printf("%s(%d):%s", evp->ae_name, evp->ae_number, gettext( "UNKNOWN EVENT: Could not get class for event. Configuration may be bad.\n")); } else { class = cmap.ec_class; if (class != evp->ae_class) { conf_aflags[0] = run_aflags[0] = '\0'; pmask.am_success = class; pmask.am_failure = class; (void) getauditflagschar(run_aflags, &pmask, 0); pmask.am_success = evp->ae_class; pmask.am_failure = evp->ae_class; (void) getauditflagschar(conf_aflags, &pmask, 0); (void) printf(gettext( "%s(%d): CLASS MISMATCH: runtime class (%s) != configured class (%s)\n"), evp->ae_name, evp->ae_number, NONE(run_aflags), NONE(conf_aflags)); } } } endauevent(); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_conf() { register au_event_ent_t *evp; register int i; au_evclass_map_t ec; au_stat_t as; eauditon(A_GETSTAT, (caddr_t)&as, 0); i = 0; setauevent(); while ((evp = getauevent()) != (au_event_ent_t *)NULL) { if (evp->ae_number <= as.as_numevent) { ++i; ec.ec_number = evp->ae_number; ec.ec_class = evp->ae_class; eauditon(A_SETCLASS, (caddr_t)&ec, (int)sizeof (ec)); } } endauevent(); (void) printf(gettext("Configured %d kernel events.\n"), i); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_chkaconf() { char buf[1024]; au_mask_t pmask, kmask; if (getacna(buf, sizeof (buf)) < 0) { (void) fprintf(stderr, gettext("bad non-attributable flags in audit_control\n")); exit(1); } if (getauditflagsbin(buf, &pmask) < 0) { (void) fprintf(stderr, gettext("bad audit flag value encountered\n")); exit(1); } eauditon(A_GETKMASK, (caddr_t)&kmask, (int)sizeof (kmask)); if ((pmask.am_success != kmask.am_success) || (pmask.am_failure != kmask.am_failure)) { char kbuf[2048]; if (getauditflagschar(kbuf, &kmask, 0) < 0) { (void) fprintf(stderr, gettext("bad kernel non-attributable mask\n")); exit(1); } (void) printf(gettext("non-attributable event mismatch ")); (void) printf(gettext("audit_control(%s) kernel(%s)\n"), buf, kbuf); } } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_aconf() { char buf[2048]; au_mask_t pmask; if (getacna(buf, sizeof (buf)) < 0) { (void) fprintf(stderr, gettext("bad non-attributable flags in audit_control\n")); exit(1); } if (getauditflagsbin(buf, &pmask) < 0) { (void) fprintf(stderr, gettext("bad audit flag value encountered\n")); exit(1); } eauditon(A_SETKMASK, (caddr_t)&pmask, (int)sizeof (pmask)); (void) printf(gettext("Configured non-attributable events.\n")); } static void do_audit(event, sorf, retval, audit_str) char *event; char sorf; int retval; char *audit_str; { int rtn; int rd; au_event_t event_num; au_event_ent_t *evp; auditinfo_addr_t ai; token_t *tokp; egetaudit(&ai, sizeof (ai)); if (strisnum(event)) { event_num = (au_event_t)atoi(event); evp = egetauevnum(event_num); } else evp = egetauevnam(event); rtn = au_preselect(evp->ae_number, &ai.ai_mask, (int)sorf, AU_PRS_USECACHE); if (rtn == -1) exit_error("%s\n%s %d\n", gettext("Check audit event configuration."), gettext("Could not get audit class for event number"), evp->ae_number); /* record is preselected */ if (rtn == 1) { if ((rd = au_open()) == -1) exit_error(gettext( "Could not get and audit record descriptor\n")); if ((tokp = au_to_me()) == (token_t *)NULL) exit_error(gettext( "Could not allocate subject token\n")); if (au_write(rd, tokp) == -1) exit_error(gettext("Could not construct subject token of audit record\n")); if ((tokp = au_to_text(audit_str)) == (token_t *)NULL) exit_error(gettext("Could not allocate text token\n")); if (au_write(rd, tokp) == -1) exit_error(gettext("Could not construct text token of audit record\n")); #ifdef _LP64 if ((tokp = au_to_return64(sorf, retval)) == (token_t *)NULL) #else if ((tokp = au_to_return32(sorf, retval)) == (token_t *)NULL) #endif exit_error(gettext( "Could not allocate return token\n")); if (au_write(rd, tokp) == -1) exit_error(gettext( "Could not construct return token of audit record\n")); if (au_close(rd, 1, evp->ae_number) == -1) exit_error(gettext( "Could not write audit record: %s\n"), strerror(errno)); } } static void do_getauid() { au_id_t auid; egetauid(&auid); print_auid(auid); } static void do_getaudit() { auditinfo_addr_t ai; egetaudit(&ai, sizeof (ai)); print_auid(ai.ai_auid); print_mask(gettext("process preselection mask"), &ai.ai_mask); print_tid_ex(&ai.ai_termid); print_asid(ai.ai_asid); } static void do_getkaudit() { auditinfo_addr_t ai; egetkaudit(&ai, sizeof (ai)); print_auid(ai.ai_auid); print_mask(gettext("process preselection mask"), &ai.ai_mask); print_tid_ex(&ai.ai_termid); print_asid(ai.ai_asid); } /* * per zone if AUDIT_PERZONE set, else only in global zone. */ static void do_setkaudit(t, s) char *t; char *s; { uint_t type; auditinfo_addr_t ai; egetkaudit(&ai, sizeof (ai)); (void) str2type(t, &type); (void) str2ipaddr(s, &ai.ai_termid.at_addr[0], type); ai.ai_termid.at_type = type; esetkaudit(&ai, sizeof (ai)); } /* * returns zone-relative root */ static void do_getcar() { char path[MAXPATHLEN]; eauditon(A_GETCAR, (caddr_t)path, (int)sizeof (path)); (void) printf(gettext("current active root = %s\n"), path); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_getclass(event_str) char *event_str; { au_evclass_map_t ec; au_event_ent_t *evp; au_event_t event_number; char *event_name; char desc[256]; if (strisnum(event_str)) { event_number = atol(event_str); if ((evp = egetauevnum(event_number)) != (au_event_ent_t *)NULL) { event_number = evp->ae_number; event_name = evp->ae_name; } else event_name = gettext("unknown"); } else { event_name = event_str; if ((evp = egetauevnam(event_str)) != (au_event_ent_t *)NULL) event_number = evp->ae_number; } ec.ec_number = event_number; eauditon(A_GETCLASS, (caddr_t)&ec, 0); (void) sprintf(desc, gettext("audit class mask for event %s(%d)"), event_name, event_number); print_mask1(desc, ec.ec_class); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. (AUC_DISABLED is always global, the other states are per zone * if AUDIT_PERZONE is set) */ static void do_getcond() { char cond_str[16]; uint_t cond; eauditon(A_GETCOND, (caddr_t)&cond, (int)sizeof (cond)); (void) cond2str(cond, cond_str); (void) printf(gettext("audit condition = %s\n"), cond_str); } /* * returned path is relative to zone root */ static void do_getcwd() { char path[MAXPATHLEN]; eauditon(A_GETCWD, (caddr_t)path, (int)sizeof (path)); (void) printf(gettext("current working directory = %s\n"), path); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_getkmask() { au_mask_t pmask; eauditon(A_GETKMASK, (caddr_t)&pmask, (int)sizeof (pmask)); print_mask(gettext("audit flags for non-attributable events"), &pmask); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. (some policies can only be set from the global zone, but all * can be read from anywhere.) */ static void do_getpolicy() { char policy_str[1024]; uint_t policy; eauditon(A_GETPOLICY, (caddr_t)&policy, 0); (void) policy2str(policy, policy_str, sizeof (policy_str)); (void) printf(gettext("audit policies = %s\n"), policy_str); } static void do_getpinfo(pid_str) char *pid_str; { struct auditpinfo_addr ap; if (strisnum(pid_str)) ap.ap_pid = (pid_t)atoi(pid_str); else exit_usage(1); eauditon(A_GETPINFO_ADDR, (caddr_t)&ap, sizeof (ap)); print_auid(ap.ap_auid); print_mask(gettext("process preselection mask"), &(ap.ap_mask)); print_tid_ex(&(ap.ap_termid)); print_asid(ap.ap_asid); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_getqbufsz() { struct au_qctrl qctrl; eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0); (void) printf(gettext("audit queue buffer size (bytes) = %ld\n"), qctrl.aq_bufsz); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_getqctrl() { struct au_qctrl qctrl; eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0); (void) printf(gettext("audit queue hiwater mark (records) = %ld\n"), qctrl.aq_hiwater); (void) printf(gettext("audit queue lowater mark (records) = %ld\n"), qctrl.aq_lowater); (void) printf(gettext("audit queue buffer size (bytes) = %ld\n"), qctrl.aq_bufsz); (void) printf(gettext("audit queue delay (ticks) = %ld\n"), qctrl.aq_delay); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_getqdelay() { struct au_qctrl qctrl; eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0); (void) printf(gettext("audit queue delay (ticks) = %ld\n"), qctrl.aq_delay); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_getqhiwater() { struct au_qctrl qctrl; eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0); (void) printf(gettext("audit queue hiwater mark (records) = %ld\n"), qctrl.aq_hiwater); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_getqlowater() { struct au_qctrl qctrl; eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0); (void) printf(gettext("audit queue lowater mark (records) = %ld\n"), qctrl.aq_lowater); } static void do_getasid() { auditinfo_addr_t ai; if (getaudit_addr(&ai, sizeof (ai))) { exit_error(gettext("getaudit_addr(2) failed")); } print_asid(ai.ai_asid); } /* * The stats are for the entire system unless AUDIT_PERZONE is set. */ static void do_getstat() { au_stat_t as; eauditon(A_GETSTAT, (caddr_t)&as, 0); print_stats(&as); } static void do_gettermid() { auditinfo_addr_t ai; if (getaudit_addr(&ai, sizeof (ai))) { exit_error(gettext("getaudit_addr(2) failed")); } print_tid_ex(&ai.ai_termid); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_getfsize() { au_fstat_t fstat; eauditon(A_GETFSIZE, (caddr_t)&fstat, 0); (void) printf(gettext("Maximum file size %d, current file size %d\n"), fstat.af_filesz, fstat.af_currsz); } /*ARGSUSED*/ static void do_getuseraudit(user) char *user; { (void) printf(gettext("-getuseraudit supported on SunOS CMW only.\n")); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_lsevent() { register au_event_ent_t *evp; au_mask_t pmask; char auflags[256]; setauevent(); if ((evp = getauevent()) == (au_event_ent_t *)NULL) { (void) exit_error(gettext( "NO AUDIT EVENTS: Could not read %s\n."), AUDITEVENTFILE); } setauevent(); while ((evp = getauevent()) != (au_event_ent_t *)NULL) { pmask.am_success = pmask.am_failure = evp->ae_class; if (getauditflagschar(auflags, &pmask, 0) == -1) (void) strcpy(auflags, "unknown"); (void) printf("%-30s %5d %s %s\n", evp->ae_name, evp->ae_number, auflags, evp->ae_desc); } endauevent(); } /* * The returned value is for the global zone unless AUDIT_PERZONE is * set. */ static void do_lspolicy() { int i; /* * TRANSLATION_NOTE * Print a properly aligned header. */ (void) printf(gettext("policy string description:\n")); for (i = 0; i < POLICY_TBL_SZ; i++) (void) printf("%-17s%s\n", policy_table[i].policy_str, gettext(policy_table[i].policy_desc)); } static void do_setasid(sid_str, argv) char *sid_str; char **argv; { struct auditinfo_addr ai; if (getaudit_addr(&ai, sizeof (ai))) { exit_error(gettext("getaudit_addr(2) failed")); } ai.ai_asid = (au_asid_t)atol(sid_str); if (setaudit_addr(&ai, sizeof (ai))) { exit_error(gettext("setaudit_addr(2) failed")); } execit(argv); } static void do_setaudit(user_str, mask_str, tid_str, sid_str, argv) char *user_str; char *mask_str; char *tid_str; char *sid_str; char **argv; { auditinfo_addr_t ai; ai.ai_auid = (au_id_t)get_user_id(user_str); str2mask(mask_str, &ai.ai_mask), str2tid(tid_str, &ai.ai_termid); ai.ai_asid = (au_asid_t)atol(sid_str); esetaudit(&ai, sizeof (ai)); execit(argv); } static void do_setauid(user, argv) char *user; char **argv; { au_id_t auid; auid = get_user_id(user); esetauid(&auid); execit(argv); } static void do_setpmask(pid_str, audit_flags) char *pid_str; char *audit_flags; { struct auditpinfo ap; if (strisnum(pid_str)) ap.ap_pid = (pid_t)atoi(pid_str); else exit_usage(1); str2mask(audit_flags, &ap.ap_mask); eauditon(A_SETPMASK, (caddr_t)&ap, (int)sizeof (ap)); } static void do_setsmask(asid_str, audit_flags) char *asid_str; char *audit_flags; { struct auditinfo ainfo; if (strisnum(asid_str)) ainfo.ai_asid = (pid_t)atoi(asid_str); else exit_usage(1); str2mask(audit_flags, &ainfo.ai_mask); eauditon(A_SETSMASK, (caddr_t)&ainfo, (int)sizeof (ainfo)); } static void do_setumask(auid_str, audit_flags) char *auid_str; char *audit_flags; { struct auditinfo ainfo; if (strisnum(auid_str)) ainfo.ai_auid = (pid_t)atoi(auid_str); else exit_usage(1); str2mask(audit_flags, &ainfo.ai_mask); eauditon(A_SETUMASK, (caddr_t)&ainfo, (int)sizeof (ainfo)); } /* * local zone use is valid if AUDIT_PERZONE is set, otherwise the * syscall returns EPERM. */ static void do_setstat() { au_stat_t as; as.as_audit = (uint_t)-1; as.as_auditctl = (uint_t)-1; as.as_dropped = (uint_t)-1; as.as_enqueue = (uint_t)-1; as.as_generated = (uint_t)-1; as.as_kernel = (uint_t)-1; as.as_nonattrib = (uint_t)-1; as.as_rblocked = (uint_t)-1; as.as_totalsize = (uint_t)-1; as.as_wblocked = (uint_t)-1; as.as_written = (uint_t)-1; eauditon(A_SETSTAT, (caddr_t)&as, (int)sizeof (as)); (void) puts(gettext("audit stats reset")); } /*ARGSUSED*/ static void do_setuseraudit(user, auditflags) char *user; char *auditflags; { (void) printf(gettext("-setuseraudit supported on SunOS CMW only.\n")); } /* * AUDIT_PERZONE set: valid in all zones * AUDIT_PERZONE not set: valid in global zone only */ static void do_setclass(event_str, audit_flags) char *event_str; char *audit_flags; { au_event_t event; int mask; au_mask_t pmask; au_evclass_map_t ec; au_event_ent_t *evp; if (strisnum(event_str)) event = (uint_t)atol(event_str); else { if ((evp = egetauevnam(event_str)) != (au_event_ent_t *)NULL) event = evp->ae_number; } if (strisnum(audit_flags)) mask = atoi(audit_flags); else { str2mask(audit_flags, &pmask); mask = pmask.am_success | pmask.am_failure; } ec.ec_number = event; ec.ec_class = mask; eauditon(A_SETCLASS, (caddr_t)&ec, (int)sizeof (ec)); } /* * AUDIT_PERZONE set: valid in all zones * AUDIT_PERZONE not set: valid in global zone only */ static void do_setkmask(audit_flags) char *audit_flags; { au_mask_t pmask; str2mask(audit_flags, &pmask); eauditon(A_SETKMASK, (caddr_t)&pmask, (int)sizeof (pmask)); print_mask(gettext("audit flags for non-attributable events"), &pmask); } /* * ahlt and perzone are global zone only; the other policies are valid * in a local zone if AUDIT_PERZONE is set. The kernel insures that * a local zone can't change ahlt and perzone (EINVAL). */ static void do_setpolicy(policy_str) char *policy_str; { uint_t policy; switch (str2policy(policy_str, &policy)) { case 2: exit_error(gettext( "policy (%s) invalid in a local zone."), policy_str); break; default: exit_error(gettext( "Invalid policy (%s) specified."), policy_str); break; case 0: eauditon(A_SETPOLICY, (caddr_t)&policy, 0); break; } } /* * AUDIT_PERZONE set: valid in all zones * AUDIT_PERZONE not set: valid in global zone only */ static void do_setqbufsz(bufsz) char *bufsz; { struct au_qctrl qctrl; eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0); qctrl.aq_bufsz = atol(bufsz); eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0); } /* * AUDIT_PERZONE set: valid in all zones * AUDIT_PERZONE not set: valid in global zone only */ static void do_setqctrl(hiwater, lowater, bufsz, delay) char *hiwater; char *lowater; char *bufsz; char *delay; { struct au_qctrl qctrl; qctrl.aq_hiwater = atol(hiwater); qctrl.aq_lowater = atol(lowater); qctrl.aq_bufsz = atol(bufsz); qctrl.aq_delay = atol(delay); eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0); } /* * AUDIT_PERZONE set: valid in all zones * AUDIT_PERZONE not set: valid in global zone only */ static void do_setqdelay(delay) char *delay; { struct au_qctrl qctrl; eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0); qctrl.aq_delay = atol(delay); eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0); } /* * AUDIT_PERZONE set: valid in all zones * AUDIT_PERZONE not set: valid in global zone only */ static void do_setqhiwater(hiwater) char *hiwater; { struct au_qctrl qctrl; eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0); qctrl.aq_hiwater = atol(hiwater); eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0); } /* * AUDIT_PERZONE set: valid in all zones * AUDIT_PERZONE not set: valid in global zone only */ static void do_setqlowater(lowater) char *lowater; { struct au_qctrl qctrl; eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0); qctrl.aq_lowater = atol(lowater); eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0); } /* * AUDIT_PERZONE set: valid in all zones * AUDIT_PERZONE not set: valid in global zone only */ static void do_settid(char *tid_str) { struct auditinfo_addr ai; if (getaudit_addr(&ai, sizeof (ai))) { exit_error(gettext("getaudit_addr(2) failed")); } str2tid(tid_str, &ai.ai_termid); if (setaudit_addr(&ai, sizeof (ai))) { exit_error(gettext("setaudit_addr(2) failed")); } } /* * AUDIT_PERZONE set: valid in all zones * AUDIT_PERZONE not set: valid in global zone only */ static void do_setfsize(size) char *size; { au_fstat_t fstat; fstat.af_filesz = atol(size); eauditon(A_SETFSIZE, (caddr_t)&fstat, 0); } static void eauditon(cmd, data, length) int cmd; caddr_t data; int length; { if (auditon(cmd, data, length) == -1) exit_error(gettext("auditon(2) failed.")); } static void egetauid(auid) au_id_t *auid; { if (getauid(auid) == -1) exit_error(gettext("getauid(2) failed.")); } static void egetaudit(ai, size) auditinfo_addr_t *ai; int size; { if (getaudit_addr(ai, size) == -1) exit_error(gettext("getaudit_addr(2) failed.")); } static void egetkaudit(ai, size) auditinfo_addr_t *ai; int size; { if (auditon(A_GETKAUDIT, (char *)ai, size) < 0) exit_error(gettext("auditon: A_GETKAUDIT failed.")); } static void esetkaudit(ai, size) auditinfo_addr_t *ai; int size; { if (auditon(A_SETKAUDIT, (char *)ai, size) < 0) exit_error(gettext("auditon: A_SETKAUDIT failed.")); } static void egetauditflagsbin(auditflags, pmask) char *auditflags; au_mask_t *pmask; { pmask->am_success = pmask->am_failure = 0; if (strcmp(auditflags, "none") == 0) return; if (getauditflagsbin(auditflags, pmask) < 0) { exit_error(gettext("Could not get audit flags (%s)"), auditflags); } } static au_event_ent_t * egetauevnum(event_number) au_event_t event_number; { au_event_ent_t *evp; if ((evp = getauevnum(event_number)) == (au_event_ent_t *)NULL) exit_error(gettext("Could not get audit event %d"), event_number); return (evp); } static au_event_ent_t * egetauevnam(event_name) char *event_name; { register au_event_ent_t *evp; if ((evp = getauevnam(event_name)) == (au_event_ent_t *)NULL) exit_error(gettext("Could not get audit event %s"), event_name); return (evp); } static void esetauid(auid) au_id_t *auid; { if (setauid(auid) == -1) exit_error(gettext("setauid(2) failed.")); } static void esetaudit(ai, size) auditinfo_addr_t *ai; int size; { if (setaudit_addr(ai, size) == -1) exit_error(gettext("setaudit_addr(2) failed.")); } static uid_t get_user_id(user) char *user; { struct passwd *pwd; uid_t uid; setpwent(); if (isdigit(*user)) { uid = atoi(user); if ((pwd = getpwuid(uid)) == (struct passwd *)NULL) { exit_error(gettext("Invalid user: %s"), user); } } else { if ((pwd = getpwnam(user)) == (struct passwd *)NULL) { exit_error(gettext("Invalid user: %s"), user); } } endpwent(); return (pwd->pw_uid); } /* * get_arg_ent() * Inputs: command line argument string * Returns ptr to policy_entry if found; null, if not found */ static struct arg_entry * get_arg_ent(arg_str) char *arg_str; { struct arg_entry key; key.arg_str = arg_str; return ((struct arg_entry *)bsearch((char *)&key, (char *)arg_table, ARG_TBL_SZ, sizeof (struct arg_entry), arg_ent_compare)); } /* * arg_ent_compare() * Compares two command line arguments to determine which is * lexicographically greater. * Inputs: two argument map table entry pointers * Returns: > 1: aep1->arg_str > aep2->arg_str * < 1: aep1->arg_str < aep2->arg_str * 0: aep1->arg_str = aep->arg_str2 */ static int arg_ent_compare(aep1, aep2) struct arg_entry *aep1, *aep2; { return (strcmp(aep1->arg_str, aep2->arg_str)); } /* * Convert mask of the following forms: * * audit_flags (ie. +lo,-ad,pc) * 0xffffffff,0xffffffff * ffffffff,ffffffff * 20,20 */ static void str2mask(mask_str, mp) char *mask_str; au_mask_t *mp; { char sp[256]; char fp[256]; mp->am_success = 0; mp->am_failure = 0; /* * a mask of the form +aa,bb,cc,-dd */ if (strisflags(mask_str)) { egetauditflagsbin(mask_str, mp); /* * a mask of the form 0xffffffff,0xffffffff or 1,1 */ } else { strsplit(mask_str, sp, fp, ','); if (strlen(sp) > (size_t)2 && !strncasecmp(sp, "0x", 2)) (void) sscanf(sp + 2, "%x", &mp->am_success); else (void) sscanf(sp, "%u", &mp->am_success); if (strlen(fp) > (size_t)2 && !strncasecmp(fp, "0x", 2)) (void) sscanf(fp + 2, "%x", &mp->am_failure); else (void) sscanf(fp, "%u", &mp->am_failure); } } /* * tid_str is major,minor,host -- host is a name or an ip address */ static void str2tid(char *tid_str, au_tid_addr_t *tp) { char *major_str = (char *)NULL; char *minor_str = (char *)NULL; char *host_str = (char *)NULL; major_t major = 0; major_t minor = 0; dev_t dev = 0; struct hostent *phe; int err; uint32_t ibuf; uint32_t ibuf6[4]; tp->at_port = 0; tp->at_type = 0; bzero(tp->at_addr, 16); major_str = tid_str; if ((minor_str = strchr(tid_str, ',')) != NULL) { *minor_str = '\0'; minor_str++; } if (minor_str) if ((host_str = strchr(minor_str, ',')) != NULL) { *host_str = '\0'; host_str++; } if (major_str) major = (major_t)atoi(major_str); if (minor_str) minor = (minor_t)atoi(minor_str); if ((dev = makedev(major, minor)) != NODEV) tp->at_port = dev; if (host_str) { if (strisipaddr(host_str)) { if (inet_pton(AF_INET, host_str, &ibuf)) { tp->at_addr[0] = ibuf; tp->at_type = AU_IPv4; } else if (inet_pton(AF_INET6, host_str, ibuf6)) { tp->at_addr[0] = ibuf6[0]; tp->at_addr[1] = ibuf6[1]; tp->at_addr[2] = ibuf6[2]; tp->at_addr[3] = ibuf6[3]; tp->at_type = AU_IPv6; } } else { phe = getipnodebyname((const void *)host_str, AF_INET, 0, &err); if (phe == 0) { phe = getipnodebyname((const void *)host_str, AF_INET6, 0, &err); } if (phe != NULL) { if (phe->h_addrtype == AF_INET6) { /* address is IPv6 (128 bits) */ (void) memcpy(&tp->at_addr[0], phe->h_addr_list[0], 16); tp->at_type = AU_IPv6; } else { /* address is IPv4 (32 bits) */ (void) memcpy(&tp->at_addr[0], phe->h_addr_list[0], 4); tp->at_type = AU_IPv4; } freehostent(phe); } } } } static int cond2str(cond, cond_str) uint_t cond; char *cond_str; { *cond_str = '\0'; if (cond == AUC_AUDITING) { (void) strcpy(cond_str, "auditing"); return (0); } if ((cond == AUC_NOAUDIT) || (cond == AUC_INIT_AUDIT)) { (void) strcpy(cond_str, "noaudit"); return (0); } if (cond == AUC_UNSET) { (void) strcpy(cond_str, "unset"); return (0); } if (cond == AUC_NOSPACE) { (void) strcpy(cond_str, "nospace"); return (0); } return (1); } static struct policy_entry * get_policy_ent(policy) char *policy; { int i; for (i = 0; i < POLICY_TBL_SZ; i++) if (strcmp(strtolower(policy), policy_table[i].policy_str) == 0) return (&policy_table[i]); return ((struct policy_entry *)NULL); } static int str2policy(char *policy_str, uint_t *policy_mask) { char *buf; char *tok; char pfix; boolean_t is_all = 0; uint_t pm = 0; uint_t curp = 0; struct policy_entry *pep; pfix = *policy_str; if (pfix == '-' || pfix == '+' || pfix == '=') ++policy_str; if ((buf = strdup(policy_str)) == NULL) return (1); for (tok = strtok(buf, ","); tok != NULL; tok = strtok(NULL, ",")) { if ((pep = get_policy_ent(tok)) == NULL) { return (1); } else { pm |= pep->policy_mask; if (pep->policy_mask == ALL_POLICIES) is_all = 1; } } free(buf); if (pfix == '-') { if (!is_all && (getzoneid() != GLOBAL_ZONEID) && (pm & ~AUDIT_LOCAL)) return (2); eauditon(A_GETPOLICY, (caddr_t)&curp, 0); if (getzoneid() != GLOBAL_ZONEID) curp &= AUDIT_LOCAL; *policy_mask = curp & ~pm; } else if (pfix == '+') { /* * if the user is in a local zone and tries ahlt or * perzone, that's an error. But if the user uses "all" * then make it work */ if (!is_all && (getzoneid() != GLOBAL_ZONEID) && (pm & ~AUDIT_LOCAL)) return (2); eauditon(A_GETPOLICY, (caddr_t)&curp, 0); if (getzoneid() != GLOBAL_ZONEID) { curp &= AUDIT_LOCAL; if (is_all) pm &= AUDIT_LOCAL; } *policy_mask = curp | pm; } else { if (is_all && (getzoneid() != GLOBAL_ZONEID)) pm &= AUDIT_LOCAL; *policy_mask = pm; } return (0); } static int policy2str(policy, policy_str, len) uint_t policy; char *policy_str; size_t len; { int i, j; if (policy == ALL_POLICIES) { (void) strcpy(policy_str, "all"); return (1); } if (policy == NO_POLICIES) { (void) strcpy(policy_str, "none"); return (1); } *policy_str = '\0'; for (i = 0, j = 0; i < POLICY_TBL_SZ; i++) if (policy & policy_table[i].policy_mask && policy_table[i].policy_mask != ALL_POLICIES) { if (j++) (void) strcat(policy_str, ","); (void) strlcat(policy_str, policy_table[i].policy_str, len); } if (*policy_str) return (0); return (1); } static int strisnum(s) char *s; { if (s == (char *)NULL || !*s) return (0); for (; *s == '-' || *s == '+'; s++) if (!*s) return (0); for (; *s; s++) if (!isdigit(*s)) return (0); return (1); } static int strisflags(s) char *s; { if (s == (char *)NULL || !*s) return (0); for (; *s; s++) { if (!isalpha(*s) && (*s != '+' && *s != '-' && *s != '^' && *s != ',')) return (0); } return (1); } static int strisipaddr(s) char *s; { int dot = 0; int colon = 0; /* no string */ if ((s == (char *)NULL) || (!*s)) return (0); for (; *s; s++) { if (!(isxdigit(*s) || *s != '.' || *s != ':')) return (0); if (*s == '.') dot++; if (*s == ':') colon++; } if (dot && colon) return (0); if (!dot && !colon) return (0); return (1); } static void strsplit(s, p1, p2, c) char *s; char *p1; char *p2; char c; { *p1 = *p2 = '\0'; while (*s != '\0' && *s != c) *p1++ = *s++; *p1 = '\0'; s++; while (*s != '\0') *p2++ = *s++; *p2 = '\0'; } static char * strtolower(s) char *s; { char *save; for (save = s; *s; s++) (void) tolower(*s); return (save); } static void chk_event_num(etype, event) int etype; au_event_t event; { au_stat_t as; eauditon(A_GETSTAT, (caddr_t)&as, 0); if (etype == AC_KERN_EVENT) { if (event > as.as_numevent) { exit_error(gettext("Invalid kernel audit event number " "specified.\n\t%d is outside allowable range 0-%d."), event, as.as_numevent); } } else { /* user event */ if (event <= as.as_numevent) { exit_error(gettext( "Invalid user level audit event number specified %d."), event); } } } static void chk_event_str(etype, event_str) int etype; char *event_str; { au_event_ent_t *evp; au_stat_t as; eauditon(A_GETSTAT, (caddr_t)&as, 0); evp = egetauevnam(event_str); if (etype == AC_KERN_EVENT && (evp->ae_number > as.as_numevent)) { exit_error( gettext("Invalid kernel audit event string specified.\n" "\t\"%s\" appears to be a user level event. " "Check configuration."), event_str); } else if (etype == AC_USER_EVENT && (evp->ae_number < as.as_numevent)) { exit_error( gettext("Invalid user audit event string specified.\n" "\t\"%s\" appears to be a kernel event. " "Check configuration."), event_str); } } static void chk_sorf(sorf_str) char *sorf_str; { if (!strisnum(sorf_str)) exit_error(gettext("Invalid sorf specified: %s"), sorf_str); } static void chk_retval(retval_str) char *retval_str; { if (!strisnum(retval_str)) exit_error(gettext("Invalid retval specified: %s"), retval_str); } static void chk_tid(tid_str) char *tid_str; { int c; char *p; /* need two commas (maj,min,hostname) */ for (p = tid_str, c = 0; *p; p++) if (*p == ',') ++c; if (c != 2) exit_error(gettext("Invalid tid specified: %s"), tid_str); } static void execit(argv) char **argv; { char *shell; if (*argv) (void) execvp(*argv, argv); else { if (((shell = getenv("SHELL")) == (char *)NULL) || *shell != '/') shell = "/bin/csh"; (void) execlp(shell, shell, (char *)NULL); } exit_error(gettext("exec(2) failed")); } /* * exit_error() * Desc: Prints an error message along with corresponding system * error number and error message, then exits. * Inputs: Program name, program error message. */ /*PRINTFLIKE1*/ static void exit_error(char *fmt, ...) { va_list args; (void) fprintf(stderr, "%s: ", progname); va_start(args, fmt); (void) vfprintf(stderr, fmt, args); va_end(args); (void) fputc('\n', stderr); if (errno) (void) fprintf(stderr, gettext("%s: error = %s(%d)\n"), progname, strerror(errno), errno); (void) fflush(stderr); exit(1); } static void exit_usage(status) int status; { FILE *fp; int i; fp = (status ? stderr : stdout); (void) fprintf(fp, gettext("usage: %s option ...\n"), progname); for (i = 0; i < ARG2_TBL_SZ; i++) (void) fprintf(fp, " %s %s\n", arg2_table[i].arg_str, arg2_table[i].arg_opts); exit(status); } static void print_asid(asid) au_asid_t asid; { (void) printf(gettext("audit session id = %u\n"), asid); } static void print_auid(auid) au_id_t auid; { struct passwd *pwd; char *username; setpwent(); if ((pwd = getpwuid((uid_t)auid)) != (struct passwd *)NULL) username = pwd->pw_name; else username = gettext("unknown"); endpwent(); (void) printf(gettext("audit id = %s(%d)\n"), username, auid); } static void print_mask(desc, pmp) char *desc; au_mask_t *pmp; { char auflags[512]; if (getauditflagschar(auflags, pmp, NULL) < 0) (void) strlcpy(auflags, gettext("unknown"), sizeof (auflags)); (void) printf("%s = %s(0x%x,0x%x)\n", desc, auflags, pmp->am_success, pmp->am_failure); } static void print_mask1(desc, mask1) char *desc; au_class_t mask1; { (void) printf("%s = 0x%x\n", desc, (int)mask1); } static void print_stats(s) au_stat_t *s; { int offset[12]; /* used to line the header up correctly */ char buf[512]; (void) sprintf(buf, "%4lu %n%4lu %n%4lu %n%4lu %n%4lu %n%4lu %n%4lu " "%n%4lu %n%4lu %n%4lu %n%4lu %n%4lu%n", (ulong_t)s->as_generated, &(offset[0]), (ulong_t)s->as_nonattrib, &(offset[1]), (ulong_t)s->as_kernel, &(offset[2]), (ulong_t)s->as_audit, &(offset[3]), (ulong_t)s->as_auditctl, &(offset[4]), (ulong_t)s->as_enqueue, &(offset[5]), (ulong_t)s->as_written, &(offset[6]), (ulong_t)s->as_wblocked, &(offset[7]), (ulong_t)s->as_rblocked, &(offset[8]), (ulong_t)s->as_dropped, &(offset[9]), (ulong_t)s->as_totalsize / ONEK, &(offset[10]), (ulong_t)s->as_memused / ONEK, &(offset[11])); /* * TRANSLATION_NOTE * Print a properly aligned header. */ (void) printf("%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s\n", offset[0] - 1, gettext("gen"), offset[1] - offset[0] -1, gettext("nona"), offset[2] - offset[1] -1, gettext("kern"), offset[3] - offset[2] -1, gettext("aud"), offset[4] - offset[3] -1, gettext("ctl"), offset[5] - offset[4] -1, gettext("enq"), offset[6] - offset[5] -1, gettext("wrtn"), offset[7] - offset[6] -1, gettext("wblk"), offset[8] - offset[7] -1, gettext("rblk"), offset[9] - offset[8] -1, gettext("drop"), offset[10] - offset[9] -1, gettext("tot"), offset[11] - offset[10], gettext("mem")); (void) puts(buf); } static void print_tid_ex(tidp) au_tid_addr_t *tidp; { struct hostent *phe; char *hostname; struct in_addr ia; uint32_t *addr; int err; char buf[256]; char *bufp; /* IPV6 or IPV4 address */ if (tidp->at_type == AU_IPv4) { if ((phe = gethostbyaddr((char *)&tidp->at_addr[0], sizeof (tidp->at_addr[0]), AF_INET)) != (struct hostent *)NULL) hostname = phe->h_name; else hostname = gettext("unknown"); ia.s_addr = tidp->at_addr[0]; (void) printf(gettext( "terminal id (maj,min,host) = %u,%u,%s(%s)\n"), major(tidp->at_port), minor(tidp->at_port), hostname, inet_ntoa(ia)); } else { addr = &tidp->at_addr[0]; phe = getipnodebyaddr((const void *)addr, 16, AF_INET6, &err); bzero(buf, sizeof (buf)); (void) inet_ntop(AF_INET6, (void *)addr, buf, sizeof (buf)); if (phe == (struct hostent *)0) { bufp = gettext("unknown"); } else bufp = phe->h_name; (void) printf(gettext( "terminal id (maj,min,host) = %u,%u,%s(%s)\n"), major(tidp->at_port), minor(tidp->at_port), bufp, buf); if (phe) freehostent(phe); } } static int str2ipaddr(s, addr, type) char *s; uint32_t *addr; uint32_t type; { int j, sl; char *ss; unsigned int v; bzero(addr, 16); if (strisipaddr(s)) { if (type == AU_IPv4) { if (inet_pton(AF_INET, s, addr)) return (0); return (1); } if (type == AU_IPv6) { if (inet_pton(AF_INET6, s, addr)) return (0); return (1); } return (1); } else { if (type == AU_IPv4) { (void) sscanf(s, "%x", &addr[0]); return (0); } if (type == AU_IPv6) { sl = strlen(s); ss = s; for (j = 3; j >= 0; j--) { if ((sl - 8) <= 0) { (void) sscanf(s, "%x", &v); addr[j] = v; return (0); } ss = &s[sl-8]; (void) sscanf(ss, "%x", &v); addr[j] = v; sl -= 8; *ss = '\0'; } } return (0); } } static int str2type(s, type) char *s; uint_t *type; { if (strcmp(s, "ipv6") == 0) { *type = AU_IPv6; return (0); } if (strcmp(s, "ipv4") == 0) { *type = AU_IPv4; return (0); } return (1); }