/*
* 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 (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
* auditconfig - set and display audit parameters
*/
#include <locale.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <sys/param.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <nlist.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/mkdev.h>
#include <sys/param.h>
#include <pwd.h>
#include <libintl.h>
#include <zone.h>
#include <libscf_priv.h>
#include <tsol/label.h>
#include <bsm/libbsm.h>
#include <audit_policy.h>
#include <audit_scf.h>
enum commands {
AC_ARG_ACONF,
AC_ARG_AUDIT,
AC_ARG_CHKACONF,
AC_ARG_CHKCONF,
AC_ARG_CONF,
AC_ARG_GETASID,
AC_ARG_GETAUDIT,
AC_ARG_GETAUID,
AC_ARG_GETCAR,
AC_ARG_GETCLASS,
AC_ARG_GETCOND,
AC_ARG_GETCWD,
AC_ARG_GETESTATE,
AC_ARG_GETFLAGS,
AC_ARG_GETKAUDIT,
AC_ARG_GETKMASK,
AC_ARG_GETNAFLAGS,
AC_ARG_GETPINFO,
AC_ARG_GETPLUGIN,
AC_ARG_GETPOLICY,
AC_ARG_GETQBUFSZ,
AC_ARG_GETQCTRL,
AC_ARG_GETQDELAY,
AC_ARG_GETQHIWATER,
AC_ARG_GETQLOWATER,
AC_ARG_GETSTAT,
AC_ARG_GETTERMID,
AC_ARG_LSEVENT,
AC_ARG_LSPOLICY,
AC_ARG_SETASID,
AC_ARG_SETAUDIT,
AC_ARG_SETAUID,
AC_ARG_SETCLASS,
AC_ARG_SETFLAGS,
AC_ARG_SETKAUDIT,
AC_ARG_SETKMASK,
AC_ARG_SETNAFLAGS,
AC_ARG_SETPLUGIN,
AC_ARG_SETPMASK,
AC_ARG_SETPOLICY,
AC_ARG_SETQBUFSZ,
AC_ARG_SETQCTRL,
AC_ARG_SETQDELAY,
AC_ARG_SETQHIWATER,
AC_ARG_SETQLOWATER,
AC_ARG_SETSMASK,
AC_ARG_SETSTAT,
AC_ARG_SETUMASK,
AC_ARG_SET_TEMPORARY
};
#define AC_KERN_EVENT 0
#define AC_USER_EVENT 1
#define NONE(s) (!strlen(s) ? gettext("none") : s)
#define ONEK 1024
/*
* remove this after the audit.h is fixed
*/
struct arg_entry {
char *arg_str;
char *arg_opts;
enum commands auditconfig_cmd;
boolean_t temporary_allowed; /* -t allowed for the option */
};
typedef struct arg_entry arg_entry_t;
/* arg_table - command option and usage message table */
static arg_entry_t arg_table[] = {
{ "-aconf", "", AC_ARG_ACONF, B_FALSE},
{ "-audit", " event sorf retval string", AC_ARG_AUDIT, B_FALSE},
{ "-chkaconf", "", AC_ARG_CHKACONF, B_FALSE},
{ "-chkconf", "", AC_ARG_CHKCONF, B_FALSE},
{ "-conf", "", AC_ARG_CONF, B_FALSE},
{ "-getasid", "", AC_ARG_GETASID, B_FALSE},
{ "-getaudit", "", AC_ARG_GETAUDIT, B_FALSE},
{ "-getauid", "", AC_ARG_GETAUID, B_FALSE},
{ "-getcar", "", AC_ARG_GETCAR, B_FALSE},
{ "-getclass", " event", AC_ARG_GETCLASS, B_FALSE},
{ "-getcond", "", AC_ARG_GETCOND, B_FALSE},
{ "-getcwd", "", AC_ARG_GETCWD, B_FALSE},
{ "-getestate", " event", AC_ARG_GETESTATE, B_FALSE},
{ "-getflags", "", AC_ARG_GETFLAGS, B_FALSE},
{ "-getkaudit", "", AC_ARG_GETKAUDIT, B_FALSE},
{ "-getkmask", "", AC_ARG_GETKMASK, B_FALSE},
{ "-getnaflags", "", AC_ARG_GETNAFLAGS, B_FALSE},
{ "-getpinfo", " pid", AC_ARG_GETPINFO, B_FALSE},
{ "-getplugin", " [plugin]", AC_ARG_GETPLUGIN, B_FALSE},
{ "-getpolicy", "", AC_ARG_GETPOLICY, B_TRUE},
{ "-getqbufsz", "", AC_ARG_GETQBUFSZ, B_TRUE},
{ "-getqctrl", "", AC_ARG_GETQCTRL, B_TRUE},
{ "-getqdelay", "", AC_ARG_GETQDELAY, B_TRUE},
{ "-getqhiwater", "", AC_ARG_GETQHIWATER, B_TRUE},
{ "-getqlowater", "", AC_ARG_GETQLOWATER, B_TRUE},
{ "-getstat", "", AC_ARG_GETSTAT, B_FALSE},
{ "-gettid", "", AC_ARG_GETTERMID, B_FALSE},
{ "-lsevent", "", AC_ARG_LSEVENT, B_FALSE},
{ "-lspolicy", "", AC_ARG_LSPOLICY, B_FALSE},
{ "-setasid", " asid [cmd]", AC_ARG_SETASID, B_FALSE},
{ "-setaudit", " auid audit_flags termid asid [cmd]",
AC_ARG_SETAUDIT, B_FALSE},
{ "-setauid", " auid [cmd]", AC_ARG_SETAUID, B_FALSE},
{ "-setclass", " event audit_flags", AC_ARG_SETCLASS, B_FALSE},
{ "-setflags", " audit_flags", AC_ARG_SETFLAGS, B_FALSE},
{ "-setkaudit", " type IP_address", AC_ARG_SETKAUDIT, B_FALSE},
{ "-setkmask", " audit_flags", AC_ARG_SETKMASK, B_FALSE},
{ "-setnaflags", " audit_naflags", AC_ARG_SETNAFLAGS, B_FALSE},
{ "-setplugin", " name active|inactive [attributes [qsize]]",
AC_ARG_SETPLUGIN, B_FALSE},
{ "-setpmask", " pid audit_flags", AC_ARG_SETPMASK, B_FALSE},
{ "-setpolicy", " [+|-]policy_flags", AC_ARG_SETPOLICY, B_TRUE},
{ "-setqbufsz", " bufsz", AC_ARG_SETQBUFSZ, B_TRUE},
{ "-setqctrl", " hiwater lowater bufsz delay",
AC_ARG_SETQCTRL, B_TRUE},
{ "-setqdelay", " delay", AC_ARG_SETQDELAY, B_TRUE},
{ "-setqhiwater", " hiwater", AC_ARG_SETQHIWATER, B_TRUE},
{ "-setqlowater", " lowater", AC_ARG_SETQLOWATER, B_TRUE},
{ "-setsmask", " asid audit_flags", AC_ARG_SETSMASK, B_FALSE},
{ "-setstat", "", AC_ARG_SETSTAT, B_FALSE},
{ "-setumask", " user audit_flags", AC_ARG_SETUMASK, B_FALSE},
{ "-t", "", AC_ARG_SET_TEMPORARY, B_FALSE},
};
#define ARG_TBL_SZ (sizeof (arg_table) / sizeof (arg_entry_t))
char *progname = "auditconfig";
/*
* temporary_set true to get/set only kernel settings,
* false to get/set kernel settings and service properties
*/
static boolean_t temporary_set = B_FALSE;
static au_event_ent_t *egetauevnam(char *event_name);
static au_event_ent_t *egetauevnum(au_event_t event_number);
static int arg_ent_compare(const void *aep1, const void *aep2);
static char *cond2str(void);
static int policy2str(uint32_t policy, char *policy_str, size_t len);
static int str2type(char *s, uint_t *type);
static int str2policy(char *policy_str, uint32_t *policy_mask);
static int str2ipaddr(char *s, uint32_t *addr, uint32_t type);
static int strisipaddr(char *s);
static int strisnum(char *s);
static arg_entry_t *get_arg_ent(char *arg_str);
static uid_t get_user_id(char *user);
static void chk_arg_len(char *argv, uint_t len);
static void chk_event_num(int etype, au_event_t event);
static void chk_event_str(int etype, char *event_str);
static void chk_known_plugin(char *plugin_str);
static void chk_retval(char *retval_str);
static void chk_sorf(char *sorf_str);
static void do_aconf(void);
static void do_args(char **argv, au_mask_t *mask);
static void do_audit(char *, char, int, char *);
static void do_chkaconf(void);
static void do_chkconf(void);
static void do_conf(void);
static void do_getasid(void);
static void do_getaudit(void);
static void do_getkaudit(void);
static void do_setkaudit(char *t, char *s);
static void do_getauid(void);
static void do_getcar(void);
static void do_getclass(char *event_str);
static void do_getcond(void);
static void do_getcwd(void);
static void do_getflags(void);
static void do_getkmask(void);
static void do_getnaflags(void);
static void do_getpinfo(char *pid_str);
static void do_getplugin(char *plugin_str);
static void do_getpolicy(void);
static void do_getqbufsz(void);
static void do_getqctrl(void);
static void do_getqdelay(void);
static void do_getqhiwater(void);
static void do_getqlowater(void);
static void do_getstat(void);
static void do_gettermid(void);
static void do_lsevent(void);
static void do_lspolicy(void);
static void do_setasid(char *sid_str, char **argv);
static void do_setaudit(char *user_str, char *mask_str, char *tid_str,
char *sid_str, char **argv);
static void do_setauid(char *user, char **argv);
static void do_setclass(char *event_str, au_mask_t *mask);
static void do_setflags(char *audit_flags, au_mask_t *amask);
static void do_setkmask(au_mask_t *pmask);
static void do_setnaflags(char *audit_naflags, au_mask_t *namask);
static void do_setpmask(char *pid_str, au_mask_t *mask);
static void do_setsmask(char *asid_str, au_mask_t *mask);
static void do_setumask(char *auid_str, au_mask_t *mask);
static void do_setplugin(char *plugin_str, boolean_t plugin_state,
char *plugin_attr, int plugin_qsize);
static void do_setpolicy(char *policy_str);
static void do_setqbufsz(char *bufsz);
static void do_setqctrl(char *hiwater, char *lowater, char *bufsz, char *delay);
static void do_setqdelay(char *delay);
static void do_setqhiwater(char *hiwater);
static void do_setqlowater(char *lowater);
static void do_setstat(void);
static void str2tid(char *tid_str, au_tid_addr_t *tp);
static void eauditon(int cmd, caddr_t data, int length);
static void echkflags(char *auditflags, au_mask_t *mask);
static void egetaudit(auditinfo_addr_t *ai, int size);
static void egetauditflagsbin(char *auditflags, au_mask_t *pmask);
static void egetauid(au_id_t *auid);
static void egetkaudit(auditinfo_addr_t *ai, int size);
static void esetaudit(auditinfo_addr_t *ai, int size);
static void esetauid(au_id_t *auid);
static void esetkaudit(auditinfo_addr_t *ai, int size);
static void execit(char **argv);
static void exit_error(char *fmt, ...);
static void exit_usage(int status);
static void parse_args(int argc, char **argv, au_mask_t *mask);
static void print_asid(au_asid_t asid);
static void print_auid(au_id_t auid);
static void print_mask(char *desc, au_mask_t *pmp);
static void print_plugin(char *plugin_name, kva_t *plugin_kva);
static void print_tid_ex(au_tid_addr_t *tidp);
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SUNW_OST_OSCMD"
#endif
int
main(int argc, char **argv)
{
au_mask_t mask; /* for options manipulating flags */
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
if (argc == 1) {
exit_usage(0);
}
if (argc == 2 &&
(argv[1][0] == '?' ||
strcmp(argv[1], "-h") == 0 ||
strcmp(argv[1], "-?") == 0)) {
exit_usage(0);
}
parse_args(argc, argv, &mask);
do_args(argv, &mask);
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(int argc, char **argv, au_mask_t *mask)
{
arg_entry_t *ae;
uint_t type;
uint_t addr[4];
for (++argv; *argv; argv++) {
if ((ae = get_arg_ent(*argv)) == NULL) {
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:
case AC_ARG_CONF:
case AC_ARG_ACONF:
case AC_ARG_CHKACONF:
case AC_ARG_GETASID:
case AC_ARG_GETAUID:
case AC_ARG_GETAUDIT:
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:
case AC_ARG_GETCOND:
case AC_ARG_GETCWD:
case AC_ARG_GETFLAGS:
case AC_ARG_GETKMASK:
case AC_ARG_GETNAFLAGS:
break;
case AC_ARG_GETPLUGIN:
if (*++argv == NULL) {
--argv;
break;
}
if (get_arg_ent(*argv) != NULL) {
--argv;
} else {
chk_arg_len(*argv, PLUGIN_MAXBUF);
chk_known_plugin(*argv);
}
break;
case AC_ARG_GETPOLICY:
case AC_ARG_GETQBUFSZ:
case AC_ARG_GETQCTRL:
case AC_ARG_GETQDELAY:
case AC_ARG_GETQHIWATER:
case AC_ARG_GETQLOWATER:
case AC_ARG_GETSTAT:
case AC_ARG_GETTERMID:
case AC_ARG_LSEVENT:
case AC_ARG_LSPOLICY:
break;
case AC_ARG_SETASID:
case AC_ARG_SETAUID:
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:
++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);
echkflags(*argv, mask);
break;
case AC_ARG_SETFLAGS:
++argv;
if (!*argv)
exit_usage(1);
chk_arg_len(*argv, PRESELECTION_MAXBUF);
echkflags(*argv, mask);
break;
case AC_ARG_SETKMASK:
++argv;
if (!*argv)
exit_usage(1);
echkflags(*argv, mask);
break;
case AC_ARG_SETNAFLAGS:
++argv;
if (!*argv)
exit_usage(1);
chk_arg_len(*argv, PRESELECTION_MAXBUF);
echkflags(*argv, mask);
break;
case AC_ARG_SETPLUGIN:
if (*++argv == NULL || get_arg_ent(*argv) != NULL) {
exit_usage(1);
}
chk_known_plugin(*argv);
chk_arg_len(*argv, PLUGIN_MAXBUF);
if (*++argv == NULL || strcmp(*argv, "active") != 0 &&
strcmp(*argv, "inactive") != 0) {
exit_usage(1);
}
if (*++argv == NULL || get_arg_ent(*argv) != NULL) {
--argv;
break;
}
chk_arg_len(*argv, PLUGIN_MAXATT);
if (*++argv == NULL || get_arg_ent(*argv) != NULL) {
--argv;
break;
}
if (atoi(*argv) < 0) {
exit_error(gettext("Incorrect qsize specified "
"(%s)."), *argv);
}
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);
echkflags(*argv, mask);
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("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_SETSMASK:
case AC_ARG_SETUMASK:
++argv;
if (!*argv)
exit_usage(1);
++argv;
if (!*argv)
exit_usage(1);
echkflags(*argv, mask);
break;
case AC_ARG_SET_TEMPORARY:
/* Do not accept single -t option. */
if (argc == 2) {
exit_error(
gettext("Only the -t option specified "
"(it is not a standalone option)."));
}
temporary_set = B_TRUE;
break;
default:
exit_error(gettext("Internal error #1."));
break;
}
}
}
/*
* do_args() - do command line arguments in the order in which they appear.
* Function return values returned by the underlying functions; the semantics
* they should follow is to return B_TRUE on successful execution, B_FALSE
* otherwise.
*/
static void
do_args(char **argv, au_mask_t *mask)
{
arg_entry_t *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:
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_GETFLAGS:
do_getflags();
break;
case AC_ARG_GETKMASK:
do_getkmask();
break;
case AC_ARG_GETNAFLAGS:
do_getnaflags();
break;
case AC_ARG_GETPLUGIN:
{
char *plugin_str = NULL;
++argv;
if (*argv != NULL) {
if (get_arg_ent(*argv) != NULL) {
--argv;
} else {
plugin_str = *argv;
}
} else {
--argv;
}
do_getplugin(plugin_str);
}
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_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:
{
char *event_str;
++argv;
event_str = *argv;
do_setclass(event_str, mask);
++argv;
}
break;
case AC_ARG_SETFLAGS:
++argv;
do_setflags(*argv, mask);
break;
case AC_ARG_SETKMASK:
++argv;
do_setkmask(mask);
break;
case AC_ARG_SETNAFLAGS:
++argv;
do_setnaflags(*argv, mask);
break;
case AC_ARG_SETPLUGIN:
{
char *plugin_str = NULL;
boolean_t plugin_state = B_FALSE;
char *plugin_att = NULL;
int plugin_qsize = -1;
plugin_str = *++argv;
if (strcmp(*++argv, "active") == 0) {
plugin_state = B_TRUE;
}
if (*++argv != NULL &&
get_arg_ent(*argv) == NULL) {
plugin_att = *argv;
if (*++argv != NULL &&
get_arg_ent(*argv) == NULL) {
plugin_qsize = atoi(*argv);
} else {
--argv;
}
} else {
--argv;
}
do_setplugin(plugin_str, plugin_state,
plugin_att, plugin_qsize);
}
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;
++argv;
pid_str = *argv;
do_setpmask(pid_str, mask);
++argv;
}
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_SETSMASK:
{
char *asid_str;
++argv;
asid_str = *argv;
do_setsmask(asid_str, mask);
++argv;
}
break;
case AC_ARG_SETUMASK:
{
char *auid_str;
++argv;
auid_str = *argv;
do_setumask(auid_str, mask);
++argv;
}
break;
case AC_ARG_SET_TEMPORARY:
break;
default:
exit_error(gettext("Internal error #2."));
break;
}
}
}
/*
* do_chkconf() - the returned value is for the global zone unless AUDIT_PERZONE
* is set.
*/
static void
do_chkconf(void)
{
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 (getauevent() == NULL) {
exit_error(gettext("NO AUDIT EVENTS: Could not read %s\n."),
AUDITEVENTFILE);
}
setauevent();
while ((evp = getauevent()) != 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(%hu):%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(%hu): CLASS MISMATCH: "
"runtime class (%s) != "
"configured class (%s)\n"),
evp->ae_name, evp->ae_number,
NONE(run_aflags),
NONE(conf_aflags));
}
}
}
}
endauevent();
}
/*
* do_conf() - configure the kernel events. The value returned to the user is
* for the global zone unless AUDIT_PERZONE is set.
*/
static void
do_conf(void)
{
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()) != 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, sizeof (ec));
}
}
endauevent();
(void) printf(gettext("Configured %d kernel events.\n"), i);
}
/*
* do_chkaconf() - report a mismatch if the runtime class mask of a kernel audit
* event does not match the configured class mask. The value returned to the
* user is for the global zone unless AUDIT_PERZONE is set.
*/
static void
do_chkaconf(void)
{
char *namask_cfg;
au_mask_t pmask, kmask;
if (!do_getnaflags_scf(&namask_cfg) || namask_cfg == NULL) {
exit_error(gettext("Could not get configured value."));
}
egetauditflagsbin(namask_cfg, &pmask);
eauditon(A_GETKMASK, (caddr_t)&kmask, sizeof (kmask));
if ((pmask.am_success != kmask.am_success) ||
(pmask.am_failure != kmask.am_failure)) {
char kbuf[2048];
if (getauditflagschar(kbuf, &kmask, 0) < 0) {
free(namask_cfg);
(void) fprintf(stderr,
gettext("bad kernel non-attributable mask\n"));
exit(1);
}
(void) printf(
gettext("non-attributable event flags mismatch:\n"));
(void) printf(gettext("active non-attributable audit flags "
"= %s\n"), kbuf);
(void) printf(gettext("configured non-attributable audit flags "
"= %s\n"), namask_cfg);
}
free(namask_cfg);
}
/*
* do_aconf - configures the non-attributable events. The value returned to the
* user is for the global zone unless AUDIT_PERZONE is set.
*/
static void
do_aconf(void)
{
au_mask_t namask;
char *namask_cfg;
if (!do_getnaflags_scf(&namask_cfg) || namask_cfg == NULL) {
exit_error(gettext("Could not get configured value."));
}
egetauditflagsbin(namask_cfg, &namask);
free(namask_cfg);
eauditon(A_SETKMASK, (caddr_t)&namask, sizeof (namask));
(void) printf(gettext("Configured non-attributable event mask.\n"));
}
/*
* do_audit() - construct an audit record for audit event event using the
* process's audit characteristics containing a text token string audit_str. The
* return token is constructed from the success/failure flag sort. Returned
* value retval is an errno value.
*/
static void
do_audit(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 %hu\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()) == 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 (is_system_labeled()) {
if ((tokp = au_to_mylabel()) == NULL) {
exit_error(gettext(
"Could not allocate label token\n"));
}
if (au_write(rd, tokp) == -1) {
exit_error(gettext("Could not "
"construct label token of audit record\n"));
}
}
if ((tokp = au_to_text(audit_str)) == 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)) == NULL)
#else
if ((tokp = au_to_return32(sorf, retval)) == 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));
}
}
}
/*
* do_getauid() - print the audit id of the current process.
*/
static void
do_getauid(void)
{
au_id_t auid;
egetauid(&auid);
print_auid(auid);
}
/*
* do_getaudit() - print the audit characteristics of the current process.
*/
static void
do_getaudit(void)
{
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);
}
/*
* do_getkaudit() - print the audit characteristics of the current zone.
*/
static void
do_getkaudit(void)
{
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);
}
/*
* do_setkaudit() - set IP address_type/address of machine to specified values;
* valid per zone if AUDIT_PERZONE is set, else only in global zone.
*/
static void
do_setkaudit(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));
}
/*
* do_getcar() - print the zone-relative root
*/
static void
do_getcar(void)
{
char path[MAXPATHLEN];
eauditon(A_GETCAR, (caddr_t)path, sizeof (path));
(void) printf(gettext("current active root = %s\n"), path);
}
/*
* do_getclass() - print the preselection mask associated with the specified
* kernel audit event. The displayed value is for the global zone unless
* AUDIT_PERZONE is set.
*/
static void
do_getclass(char *event_str)
{
au_evclass_map_t ec;
au_event_ent_t *evp;
au_event_t event_number;
char *event_name;
if (strisnum(event_str)) {
event_number = atol(event_str);
if ((evp = egetauevnum(event_number)) != 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)) != NULL) {
event_number = evp->ae_number;
}
}
ec.ec_number = event_number;
eauditon(A_GETCLASS, (caddr_t)&ec, 0);
(void) printf(gettext("audit class mask for event %s(%hu) = 0x%x\n"),
event_name, event_number, ec.ec_class);
}
/*
* do_getcond() - the printed 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(void)
{
(void) printf(gettext("audit condition = %s\n"), cond2str());
}
/*
* do_getcwd() - the printed path is relative to the current zone root
*/
static void
do_getcwd(void)
{
char path[MAXPATHLEN];
eauditon(A_GETCWD, (caddr_t)path, sizeof (path));
(void) printf(gettext("current working directory = %s\n"), path);
}
/*
* do_getflags() - the printed value is for the global zone unless AUDIT_PERZONE
* is set.
*/
static void
do_getflags(void)
{
au_mask_t amask;
char *amask_cfg;
eauditon(A_GETAMASK, (caddr_t)&amask, sizeof (amask));
print_mask(gettext("active user default audit flags"), &amask);
if (!do_getflags_scf(&amask_cfg) || amask_cfg == NULL) {
exit_error(gettext("Could not get configured value."));
}
egetauditflagsbin(amask_cfg, &amask);
print_mask(gettext("configured user default audit flags"), &amask);
free(amask_cfg);
}
/*
* do_getkmask() - the printed value is for the global zone unless AUDIT_PERZONE
* is set.
*/
static void
do_getkmask(void)
{
au_mask_t pmask;
eauditon(A_GETKMASK, (caddr_t)&pmask, sizeof (pmask));
print_mask(gettext("active non-attributable audit flags"), &pmask);
}
/*
* do_getnaflags() - the printed value is for the global zone unless
* AUDIT_PERZONE is set.
*/
static void
do_getnaflags(void)
{
au_mask_t namask;
char *namask_cfg;
eauditon(A_GETKMASK, (caddr_t)&namask, sizeof (namask));
print_mask(gettext("active non-attributable audit flags"), &namask);
if (!do_getnaflags_scf(&namask_cfg) || namask_cfg == NULL) {
exit_error(gettext("Could not get configured value."));
}
egetauditflagsbin(namask_cfg, &namask);
print_mask(gettext("configured non-attributable audit flags"), &namask);
free(namask_cfg);
}
/*
* do_getpolicy() - print active and configured kernel audit policy relative to
* the current zone.
*/
static void
do_getpolicy(void)
{
char policy_str[1024];
uint32_t policy;
if (!temporary_set) {
if (!do_getpolicy_scf(&policy)) {
exit_error(gettext("Could not get configured values."));
}
(void) policy2str(policy, policy_str, sizeof (policy_str));
(void) printf(gettext("configured audit policies = %s\n"),
policy_str);
}
eauditon(A_GETPOLICY, (caddr_t)&policy, 0);
(void) policy2str(policy, policy_str, sizeof (policy_str));
(void) printf(gettext("active audit policies = %s\n"), policy_str);
}
/*
* do_getpinfo() - print the audit ID, preselection mask, terminal ID, and
* audit session ID for the specified process.
*/
static void
do_getpinfo(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);
}
/*
* do_getplugin() - print plugin configuration.
*/
static void
do_getplugin(char *plugin_str)
{
scf_plugin_kva_node_t *plugin_kva_ll;
scf_plugin_kva_node_t *plugin_kva_ll_head;
if (!do_getpluginconfig_scf(plugin_str, &plugin_kva_ll)) {
exit_error(gettext("Could not get plugin configuration."));
}
plugin_kva_ll_head = plugin_kva_ll;
while (plugin_kva_ll != NULL) {
print_plugin(plugin_kva_ll->plugin_name,
plugin_kva_ll->plugin_kva);
plugin_kva_ll = plugin_kva_ll->next;
if (plugin_kva_ll != NULL) {
(void) printf("\n");
}
}
plugin_kva_ll_free(plugin_kva_ll_head);
}
/*
* do_getqbufsz() - print the active and configured audit queue write buffer
* size relative to the current zone.
*/
static void
do_getqbufsz(void)
{
struct au_qctrl qctrl;
if (!temporary_set) {
if (!do_getqbufsz_scf(&qctrl.aq_bufsz)) {
exit_error(gettext("Could not get configured value."));
}
if (qctrl.aq_bufsz == 0) {
(void) printf(gettext(
"no configured audit queue buffer size\n"));
} else {
(void) printf(gettext("configured audit queue "
"buffer size (bytes) = %d\n"), qctrl.aq_bufsz);
}
}
eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
(void) printf(gettext("active audit queue buffer size (bytes) = %d\n"),
qctrl.aq_bufsz);
}
/*
* do_getqctrl() - print the configured and active audit queue write buffer
* size, audit queue hiwater mark, audit queue lowater mark, audit queue prod
* interval (ticks) relative to the current zone.
*/
static void
do_getqctrl(void)
{
struct au_qctrl qctrl;
if (!temporary_set) {
if (!do_getqctrl_scf(&qctrl)) {
exit_error(gettext("Could not get configured values."));
}
if (qctrl.aq_hiwater == 0) {
(void) printf(gettext(
"no configured audit queue hiwater mark\n"));
} else {
(void) printf(gettext("configured audit queue "
"hiwater mark (records) = %d\n"), qctrl.aq_hiwater);
}
if (qctrl.aq_lowater == 0) {
(void) printf(gettext(
"no configured audit queue lowater mark\n"));
} else {
(void) printf(gettext("configured audit queue "
"lowater mark (records) = %d\n"), qctrl.aq_lowater);
}
if (qctrl.aq_bufsz == 0) {
(void) printf(gettext(
"no configured audit queue buffer size\n"));
} else {
(void) printf(gettext("configured audit queue "
"buffer size (bytes) = %d\n"), qctrl.aq_bufsz);
}
if (qctrl.aq_delay == 0) {
(void) printf(gettext(
"no configured audit queue delay\n"));
} else {
(void) printf(gettext("configured audit queue "
"delay (ticks) = %ld\n"), qctrl.aq_delay);
}
}
eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
(void) printf(gettext("active audit queue hiwater mark "
"(records) = %d\n"), qctrl.aq_hiwater);
(void) printf(gettext("active audit queue lowater mark "
"(records) = %d\n"), qctrl.aq_lowater);
(void) printf(gettext("active audit queue buffer size (bytes) = %d\n"),
qctrl.aq_bufsz);
(void) printf(gettext("active audit queue delay (ticks) = %ld\n"),
qctrl.aq_delay);
}
/*
* do_getqdelay() - print, relative to the current zone, the configured and
* active interval at which audit queue is prodded to start output.
*/
static void
do_getqdelay(void)
{
struct au_qctrl qctrl;
if (!temporary_set) {
if (!do_getqdelay_scf(&qctrl.aq_delay)) {
exit_error(gettext("Could not get configured value."));
}
if (qctrl.aq_delay == 0) {
(void) printf(gettext(
"no configured audit queue delay\n"));
} else {
(void) printf(gettext("configured audit queue "
"delay (ticks) = %ld\n"), qctrl.aq_delay);
}
}
eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
(void) printf(gettext("active audit queue delay (ticks) = %ld\n"),
qctrl.aq_delay);
}
/*
* do_getqhiwater() - print, relative to the current zone, the high water
* point in undelivered audit records when audit generation will block.
*/
static void
do_getqhiwater(void)
{
struct au_qctrl qctrl;
if (!temporary_set) {
if (!do_getqhiwater_scf(&qctrl.aq_hiwater)) {
exit_error(gettext("Could not get configured value."));
}
if (qctrl.aq_hiwater == 0) {
(void) printf(gettext(
"no configured audit queue hiwater mark\n"));
} else {
(void) printf(gettext("configured audit queue "
"hiwater mark (records) = %d\n"), qctrl.aq_hiwater);
}
}
eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
(void) printf(gettext("active audit queue hiwater mark "
"(records) = %d\n"), qctrl.aq_hiwater);
}
/*
* do_getqlowater() - print, relative to the current zone, the low water point
* in undelivered audit records where blocked processes will resume.
*/
static void
do_getqlowater(void)
{
struct au_qctrl qctrl;
if (!temporary_set) {
if (!do_getqlowater_scf(&qctrl.aq_lowater)) {
exit_error(gettext("Could not get configured value."));
}
if (qctrl.aq_lowater == 0) {
(void) printf(gettext(
"no configured audit queue lowater mark\n"));
} else {
(void) printf(gettext("configured audit queue "
"lowater mark (records) = %d\n"), qctrl.aq_lowater);
}
}
eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
(void) printf(gettext("active audit queue lowater mark "
"(records) = %d\n"), qctrl.aq_lowater);
}
/*
* do_getasid() - print out the audit session-ID.
*/
static void
do_getasid(void)
{
auditinfo_addr_t ai;
if (getaudit_addr(&ai, sizeof (ai))) {
exit_error(gettext("getaudit_addr(2) failed"));
}
print_asid(ai.ai_asid);
}
/*
* do_getstat() - the printed statistics are for the entire system unless
* AUDIT_PERZONE is set.
*/
static void
do_getstat(void)
{
au_stat_t as;
int offset[12]; /* used to line the header up correctly */
char buf[512];
eauditon(A_GETSTAT, (caddr_t)&as, 0);
(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)as.as_generated, &(offset[0]),
(ulong_t)as.as_nonattrib, &(offset[1]),
(ulong_t)as.as_kernel, &(offset[2]),
(ulong_t)as.as_audit, &(offset[3]),
(ulong_t)as.as_auditctl, &(offset[4]),
(ulong_t)as.as_enqueue, &(offset[5]),
(ulong_t)as.as_written, &(offset[6]),
(ulong_t)as.as_wblocked, &(offset[7]),
(ulong_t)as.as_rblocked, &(offset[8]),
(ulong_t)as.as_dropped, &(offset[9]),
(ulong_t)as.as_totalsize / ONEK, &(offset[10]),
(ulong_t)as.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) printf("%s\n", buf);
}
/*
* do_gettermid() - print audit terminal ID for current process.
*/
static void
do_gettermid(void)
{
auditinfo_addr_t ai;
if (getaudit_addr(&ai, sizeof (ai))) {
exit_error(gettext("getaudit_addr(2) failed"));
}
print_tid_ex(&ai.ai_termid);
}
/*
* do_lsevent() - display the active kernel and user level audit event
* information. The printed events are for the global zone unless AUDIT_PERZONE
* is set.
*/
static void
do_lsevent(void)
{
register au_event_ent_t *evp;
au_mask_t pmask;
char auflags[256];
setauevent();
if (getauevent() == NULL) {
exit_error(gettext("NO AUDIT EVENTS: Could not read %s\n."),
AUDITEVENTFILE);
}
setauevent();
while ((evp = getauevent()) != NULL) {
pmask.am_success = pmask.am_failure = evp->ae_class;
if (getauditflagschar(auflags, &pmask, 0) == -1)
(void) strcpy(auflags, "unknown");
(void) printf("%-30s %5hu %s %s\n",
evp->ae_name, evp->ae_number, auflags, evp->ae_desc);
}
endauevent();
}
/*
* do_lspolicy() - display the kernel audit policies with a description of each
* policy. The printed value is for the global zone unless AUDIT_PERZONE is set.
*/
static void
do_lspolicy(void)
{
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));
}
}
/*
* do_setasid() - execute shell or cmd with specified session-ID.
*/
static void
do_setasid(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);
}
/*
* do_setaudit() - execute shell or cmd with specified audit characteristics.
*/
static void
do_setaudit(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);
egetauditflagsbin(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);
}
/*
* do_setauid() - execute shell or cmd with specified audit-ID.
*/
static void
do_setauid(char *user, char **argv)
{
au_id_t auid;
auid = get_user_id(user);
esetauid(&auid);
execit(argv);
}
/*
* do_setpmask() - set the preselection mask of the specified process; valid
* per zone if AUDIT_PERZONE is set, else only in global zone.
*/
static void
do_setpmask(char *pid_str, au_mask_t *mask)
{
struct auditpinfo ap;
if (strisnum(pid_str)) {
ap.ap_pid = (pid_t)atoi(pid_str);
} else {
exit_usage(1);
}
ap.ap_mask.am_success = mask->am_success;
ap.ap_mask.am_failure = mask->am_failure;
eauditon(A_SETPMASK, (caddr_t)&ap, sizeof (ap));
}
/*
* do_setsmask() - set the preselection mask of all processes with the specified
* audit session-ID; valid per zone if AUDIT_PERZONE is set, else only in global
* zone.
*/
static void
do_setsmask(char *asid_str, au_mask_t *mask)
{
struct auditinfo ainfo;
if (strisnum(asid_str)) {
ainfo.ai_asid = (au_asid_t)atoi(asid_str);
} else {
exit_usage(1);
}
ainfo.ai_mask.am_success = mask->am_success;
ainfo.ai_mask.am_failure = mask->am_failure;
eauditon(A_SETSMASK, (caddr_t)&ainfo, sizeof (ainfo));
}
/*
* do_setumask() - set the preselection mask of all processes with the
* specified audit-ID; valid per zone if AUDIT_PERZONE is set, else only in
* global zone.
*/
static void
do_setumask(char *auid_str, au_mask_t *mask)
{
struct auditinfo ainfo;
if (strisnum(auid_str)) {
ainfo.ai_auid = (au_id_t)atoi(auid_str);
} else {
exit_usage(1);
}
ainfo.ai_mask.am_success = mask->am_success;
ainfo.ai_mask.am_failure = mask->am_failure;
eauditon(A_SETUMASK, (caddr_t)&ainfo, sizeof (ainfo));
}
/*
* do_setstat() - reset audit statistics counters; local zone use is valid if
* AUDIT_PERZONE is set, otherwise the syscall returns EPERM.
*/
static void
do_setstat(void)
{
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, sizeof (as));
(void) printf("%s\n", gettext("audit stats reset"));
}
/*
* do_setclass() - map the kernel event event_str to the classes specified by
* audit flags (mask); valid per zone if AUDIT_PERZONE is set, else only in
* global zone.
*/
static void
do_setclass(char *event_str, au_mask_t *mask)
{
au_event_t event;
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)) != NULL) {
event = evp->ae_number;
}
}
ec.ec_number = event;
ec.ec_class = (mask->am_success | mask->am_failure);
eauditon(A_SETCLASS, (caddr_t)&ec, sizeof (ec));
}
/*
* do_setflags() - set configured and active default user preselection masks;
* valid per zone if AUDIT_PERZONE is set, else only in global zone.
*/
static void
do_setflags(char *audit_flags, au_mask_t *amask)
{
eauditon(A_SETAMASK, (caddr_t)amask, sizeof (*amask));
if (!do_setflags_scf(audit_flags)) {
print_mask(gettext("active user default audit flags"), amask);
exit_error(gettext("Could not store configuration value."));
}
print_mask(gettext("user default audit flags"), amask);
}
/*
* do_setkmask() - set non-attributable audit flags of machine; valid per zone
* if AUDIT_PERZONE is set, else only in global zone.
*/
static void
do_setkmask(au_mask_t *pmask)
{
eauditon(A_SETKMASK, (caddr_t)pmask, sizeof (*pmask));
print_mask(gettext("active non-attributable audit flags"), pmask);
}
/*
* do_setnaflags() - set configured and active non-attributable selection flags
* of machine; valid per zone if AUDIT_PERZONE is set, else only in global zone.
*/
static void
do_setnaflags(char *audit_naflags, au_mask_t *namask)
{
eauditon(A_SETKMASK, (caddr_t)namask, sizeof (*namask));
if (!do_setnaflags_scf(audit_naflags)) {
print_mask(
gettext("active non-attributable audit flags"), namask);
exit_error(gettext("Could not store configuration value."));
}
print_mask(gettext("non-attributable audit flags"), namask);
}
/*
* do_setplugin() - set the given plugin plugin_str configuration values.
*/
static void
do_setplugin(char *plugin_str, boolean_t plugin_state, char *plugin_attr,
int plugin_qsize)
{
if (!do_setpluginconfig_scf(plugin_str, plugin_state, plugin_attr,
plugin_qsize)) {
exit_error(gettext("Could not set plugin configuration."));
}
}
/*
* do_setpolicy() - set the active and configured kernel audit policy; active
* values can be changed per zone if AUDIT_PERZONE is set, else only in global
* zone.
*
* ahlt and perzone are global zone only. The kernel ensures that a local zone
* can't change ahlt and perzone (EINVAL).
*/
static void
do_setpolicy(char *policy_str)
{
uint32_t policy = 0;
switch (str2policy(policy_str, &policy)) {
case 0:
if (!temporary_set) {
if (!do_getpolicy_scf(&policy)) {
exit_error(gettext("Unable to get current "
"policy values from the SMF repository"));
}
(void) str2policy(policy_str, &policy);
if (!do_setpolicy_scf(policy)) {
exit_error(gettext("Could not store "
"configuration values."));
}
}
eauditon(A_SETPOLICY, (caddr_t)&policy, 0);
break;
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;
}
}
/*
* do_setqbufsz() - set the active and configured audit queue write buffer size
* (bytes); active values can be changed per zone if AUDIT_PERZONE is set, else
* only in global zone.
*/
static void
do_setqbufsz(char *bufsz)
{
struct au_qctrl qctrl;
if (!temporary_set) {
qctrl.aq_bufsz = (size_t)atol(bufsz);
if (!do_setqbufsz_scf(&qctrl.aq_bufsz)) {
exit_error(gettext(
"Could not store configuration value."));
}
if (qctrl.aq_bufsz == 0) {
return;
}
}
eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
qctrl.aq_bufsz = (size_t)atol(bufsz);
eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
}
/*
* do_setqctrl() - set the active and configured audit queue write buffer size
* (bytes), hiwater audit record count, lowater audit record count, and wakeup
* interval (ticks); active values can be changed per zone if AUDIT_PERZONE is
* set, else only in global zone.
*/
static void
do_setqctrl(char *hiwater, char *lowater, char *bufsz, char *delay)
{
struct au_qctrl qctrl;
qctrl.aq_hiwater = (size_t)atol(hiwater);
qctrl.aq_lowater = (size_t)atol(lowater);
qctrl.aq_bufsz = (size_t)atol(bufsz);
qctrl.aq_delay = (clock_t)atol(delay);
if (!temporary_set) {
struct au_qctrl qctrl_act;
if (!do_setqctrl_scf(&qctrl)) {
exit_error(gettext(
"Could not store configuration values."));
}
eauditon(A_GETQCTRL, (caddr_t)&qctrl_act, 0);
if (qctrl.aq_hiwater == 0) {
qctrl.aq_hiwater = qctrl_act.aq_hiwater;
}
if (qctrl.aq_lowater == 0) {
qctrl.aq_lowater = qctrl_act.aq_lowater;
}
if (qctrl.aq_bufsz == 0) {
qctrl.aq_bufsz = qctrl_act.aq_bufsz;
}
if (qctrl.aq_delay == 0) {
qctrl.aq_delay = qctrl_act.aq_delay;
}
}
eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
}
/*
* do_setqdelay() - set the active and configured audit queue wakeup interval
* (ticks); active values can be changed per zone if AUDIT_PERZONE is set, else
* only in global zone.
*/
static void
do_setqdelay(char *delay)
{
struct au_qctrl qctrl;
if (!temporary_set) {
qctrl.aq_delay = (clock_t)atol(delay);
if (!do_setqdelay_scf(&qctrl.aq_delay)) {
exit_error(gettext(
"Could not store configuration value."));
}
if (qctrl.aq_delay == 0) {
return;
}
}
eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
qctrl.aq_delay = (clock_t)atol(delay);
eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
}
/*
* do_setqhiwater() - sets the active and configured number of undelivered audit
* records in the audit queue at which audit record generation blocks; active
* values can be changed per zone if AUDIT_PERZONE is set, else only in global
* zone.
*/
static void
do_setqhiwater(char *hiwater)
{
struct au_qctrl qctrl;
if (!temporary_set) {
qctrl.aq_hiwater = (size_t)atol(hiwater);
if (!do_setqhiwater_scf(&qctrl.aq_hiwater)) {
exit_error(gettext(
"Could not store configuration value."));
}
if (qctrl.aq_hiwater == 0) {
return;
}
}
eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
qctrl.aq_hiwater = (size_t)atol(hiwater);
eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
}
/*
* do_setqlowater() - set the active and configured number of undelivered audit
* records in the audit queue at which blocked auditing processes unblock;
* active values can be changed per zone if AUDIT_PERZONE is set, else only in
* global zone.
*/
static void
do_setqlowater(char *lowater)
{
struct au_qctrl qctrl;
if (!temporary_set) {
qctrl.aq_lowater = (size_t)atol(lowater);
if (!do_setqlowater_scf(&qctrl.aq_lowater)) {
exit_error(gettext(
"Could not store configuration value."));
}
if (qctrl.aq_lowater == 0) {
return;
}
}
eauditon(A_GETQCTRL, (caddr_t)&qctrl, 0);
qctrl.aq_lowater = (size_t)atol(lowater);
eauditon(A_SETQCTRL, (caddr_t)&qctrl, 0);
}
static void
eauditon(int cmd, caddr_t data, int length)
{
if (auditon(cmd, data, length) == -1)
exit_error(gettext("auditon(2) failed."));
}
static void
egetauid(au_id_t *auid)
{
if (getauid(auid) == -1)
exit_error(gettext("getauid(2) failed."));
}
static void
egetaudit(auditinfo_addr_t *ai, int size)
{
if (getaudit_addr(ai, size) == -1)
exit_error(gettext("getaudit_addr(2) failed."));
}
static void
egetkaudit(auditinfo_addr_t *ai, int size)
{
if (auditon(A_GETKAUDIT, (char *)ai, size) < 0)
exit_error(gettext("auditon: A_GETKAUDIT failed."));
}
static void
esetkaudit(auditinfo_addr_t *ai, int size)
{
if (auditon(A_SETKAUDIT, (char *)ai, size) < 0)
exit_error(gettext("auditon: A_SETKAUDIT failed."));
}
static void
egetauditflagsbin(char *auditflags, au_mask_t *pmask)
{
if (strcmp(auditflags, "none") == 0) {
pmask->am_success = pmask->am_failure = 0;
return;
}
if (getauditflagsbin(auditflags, pmask) < 0) {
exit_error(gettext("Could not get audit flags (%s)"),
auditflags);
}
}
static void
echkflags(char *auditflags, au_mask_t *mask)
{
char *err = "";
char *err_ptr;
if (!__chkflags(auditflags, mask, B_FALSE, &err)) {
err_ptr = err;
while (*err_ptr != ',' && *err_ptr != '\0') {
err_ptr++;
}
*err_ptr = '\0';
exit_error(gettext("Unknown audit flags and/or prefixes "
"encountered: %s"), err);
}
}
static au_event_ent_t *
egetauevnum(au_event_t event_number)
{
au_event_ent_t *evp;
if ((evp = getauevnum(event_number)) == NULL) {
exit_error(gettext("Could not get audit event %hu"),
event_number);
}
return (evp);
}
static au_event_ent_t *
egetauevnam(char *event_name)
{
register au_event_ent_t *evp;
if ((evp = getauevnam(event_name)) == NULL)
exit_error(gettext("Could not get audit event %s"), event_name);
return (evp);
}
static void
esetauid(au_id_t *auid)
{
if (setauid(auid) == -1)
exit_error(gettext("setauid(2) failed."));
}
static void
esetaudit(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(char *user)
{
struct passwd *pwd;
uid_t uid;
if (isdigit(*user)) {
uid = atoi(user);
if ((pwd = getpwuid(uid)) == NULL) {
exit_error(gettext("Invalid user: %s"), user);
}
} else {
if ((pwd = getpwnam(user)) == NULL) {
exit_error(gettext("Invalid user: %s"), user);
}
}
return (pwd->pw_uid);
}
/*
* get_arg_ent()
* Inputs: command line argument string
* Returns ptr to struct arg_entry if found; null, if not found
*/
static arg_entry_t *
get_arg_ent(char *arg_str)
{
arg_entry_t key;
key.arg_str = arg_str;
return ((arg_entry_t *)bsearch((char *)&key, (char *)arg_table,
ARG_TBL_SZ, sizeof (arg_entry_t), 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(const void *aep1, const void *aep2)
{
return (strcmp(((arg_entry_t *)aep1)->arg_str,
((arg_entry_t *)aep2)->arg_str));
}
/*
* 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 *minor_str;
char *host_str = 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 char *
cond2str(void)
{
uint_t cond;
eauditon(A_GETCOND, (caddr_t)&cond, sizeof (cond));
switch (cond) {
case AUC_AUDITING:
return ("auditing");
case AUC_NOAUDIT:
case AUC_INIT_AUDIT:
return ("noaudit");
case AUC_UNSET:
return ("unset");
case AUC_NOSPACE:
return ("nospace");
default:
return ("");
}
}
/*
* exit = 0, success
* 1, error
* 2, bad zone
*/
static int
str2policy(char *policy_str, uint32_t *policy_mask)
{
char *buf;
char *tok;
char pfix;
boolean_t is_all = B_FALSE;
uint32_t pm = 0;
uint32_t curp;
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, ",")) {
uint32_t tok_pm;
if (((tok_pm = get_policy(tok)) == 0) &&
((strcasecmp(tok, "none") != 0))) {
free(buf);
return (1);
} else {
pm |= tok_pm;
if (tok_pm == ALL_POLICIES) {
is_all = B_TRUE;
}
}
}
free(buf);
/* reuse policy mask if already set to some value */
if (*policy_mask != 0) {
curp = *policy_mask;
} else {
(void) auditon(A_GETPOLICY, (caddr_t)&curp, 0);
}
if (pfix == '-') {
if (!is_all &&
(getzoneid() != GLOBAL_ZONEID) &&
(pm & ~AUDIT_LOCAL)) {
return (2);
}
if (getzoneid() != GLOBAL_ZONEID)
curp &= AUDIT_LOCAL;
*policy_mask = curp & ~pm;
} else if (pfix == '+') {
/*
* In a local zone, accept specifying "all", but not
* individually specifying global-zone only policies.
* Limit to all locally allowed, so system call doesn't
* fail.
*/
if (!is_all &&
(getzoneid() != GLOBAL_ZONEID) &&
(pm & ~AUDIT_LOCAL)) {
return (2);
}
if (getzoneid() != GLOBAL_ZONEID) {
curp &= AUDIT_LOCAL;
if (is_all) {
pm &= AUDIT_LOCAL;
}
}
*policy_mask = curp | pm;
} else {
/*
* In a local zone, accept specifying "all", but not
* individually specifying global-zone only policies.
* Limit to all locally allowed, so system call doesn't
* fail.
*/
if (!is_all &&
(getzoneid() != GLOBAL_ZONEID) &&
(pm & ~AUDIT_LOCAL)) {
return (2);
}
if (is_all && (getzoneid() != GLOBAL_ZONEID)) {
pm &= AUDIT_LOCAL;
}
*policy_mask = pm;
}
return (0);
}
static int
policy2str(uint32_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(char *s)
{
if (s == NULL || !*s)
return (0);
for (; *s == '-' || *s == '+'; s++)
if (!*s)
return (0);
for (; *s; s++)
if (!isdigit(*s))
return (0);
return (1);
}
static int
strisipaddr(char *s)
{
int dot = 0;
int colon = 0;
/* no string */
if ((s == 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
chk_arg_len(char *argv, uint_t len)
{
if ((strlen(argv) + 1) > len) {
*(argv + len - 1) = '\0';
exit_error(gettext("Argument too long (%s..)."), argv);
}
}
static void
chk_event_num(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%hu 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 %hu."), event);
}
}
}
static void
chk_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_known_plugin(char *plugin_str)
{
if ((strlen(plugin_str) + 1) > PLUGIN_MAXBUF) {
exit_error(gettext("Plugin name too long.\n"));
}
if (!plugin_avail_scf(plugin_str)) {
exit_error(gettext("No such plugin configured: %s"),
plugin_str);
}
}
static void
chk_sorf(char *sorf_str)
{
if (!strisnum(sorf_str))
exit_error(gettext("Invalid sorf specified: %s"), sorf_str);
}
static void
chk_retval(char *retval_str)
{
if (!strisnum(retval_str))
exit_error(gettext("Invalid retval specified: %s"), retval_str);
}
static void
execit(char **argv)
{
char *args, *args_pos;
size_t len = 0;
size_t n = 0;
char **argv_pos;
if (*argv) {
/* concatenate argument array to be passed to sh -c "..." */
for (argv_pos = argv; *argv_pos; argv_pos++)
len += strlen(*argv_pos) + 1;
if ((args = malloc(len + 1)) == NULL)
exit_error(
gettext("Allocation for command/arguments failed"));
args_pos = args;
for (argv_pos = argv; *argv_pos; argv_pos++) {
n += snprintf(args_pos, len - n, "%s ", *argv_pos);
args_pos = args + n;
}
/* strip the last space */
args[strlen(args)] = '\0';
(void) execl("/bin/sh", "sh", "-c", args, NULL);
} else {
(void) execl("/bin/sh", "sh", NULL);
}
exit_error(gettext("exec(2) failed"));
}
static void
exit_usage(int status)
{
FILE *fp;
int i;
fp = (status ? stderr : stdout);
(void) fprintf(fp, gettext("usage: %s option ...\n"), progname);
for (i = 0; i < ARG_TBL_SZ; i++) {
/* skip the -t option; it's not a standalone option */
if (arg_table[i].auditconfig_cmd == AC_ARG_SET_TEMPORARY) {
continue;
}
(void) fprintf(fp, " %s%s%s\n",
arg_table[i].arg_str, arg_table[i].arg_opts,
(arg_table[i].temporary_allowed ? " [-t]" : ""));
}
exit(status);
}
static void
print_asid(au_asid_t asid)
{
(void) printf(gettext("audit session id = %u\n"), asid);
}
static void
print_auid(au_id_t auid)
{
struct passwd *pwd;
char *username;
if ((pwd = getpwuid((uid_t)auid)) != NULL)
username = pwd->pw_name;
else
username = gettext("unknown");
(void) printf(gettext("audit id = %s(%d)\n"), username, auid);
}
static void
print_mask(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_plugin(char *plugin_name, kva_t *plugin_kva)
{
char att_str[PLUGIN_MAXATT];
boolean_t plugin_active;
char *active_str;
char *qsize_ptr;
int qsize;
if ((active_str = kva_match(plugin_kva, "active")) == NULL) {
(void) printf(gettext("Audit service configuration error: "
"\"active\" property not found\n"));
return;
}
plugin_active = (boolean_t)atoi(active_str);
qsize_ptr = kva_match(plugin_kva, "qsize");
qsize = atoi(qsize_ptr == NULL ? "-1" : qsize_ptr);
(void) printf(gettext("Plugin: %s (%s)\n"), plugin_name,
plugin_active ? "active" : "inactive");
free_static_att_kva(plugin_kva);
switch (_kva2str(plugin_kva, att_str, PLUGIN_MAXATT, "=", ";")) {
case 0:
(void) printf(gettext("\tAttributes: %s\n"), att_str);
break;
case 1:
exit_error(gettext("Internal error - buffer size too small."));
break;
default:
exit_error(gettext("Internal error."));
break;
}
if (qsize != 0) {
(void) printf(gettext("\tQueue size: %d %s\n"), qsize,
qsize == -1 ? "(internal error: value not available)" : "");
}
}
static void
print_tid_ex(au_tid_addr_t *tidp)
{
struct hostent *phe;
char *hostname;
struct in_addr ia;
uint32_t *addr;
int err;
char buf[INET6_ADDRSTRLEN];
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)) != NULL) {
hostname = phe->h_name;
} else {
hostname = gettext("unknown");
}
ia.s_addr = tidp->at_addr[0];
(void) printf(gettext(
"terminal id (maj,min,host) = %lu,%lu,%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 == NULL) {
bufp = gettext("unknown");
} else {
bufp = phe->h_name;
}
(void) printf(gettext(
"terminal id (maj,min,host) = %lu,%lu,%s(%s)\n"),
major(tidp->at_port), minor(tidp->at_port),
bufp, buf);
if (phe) {
freehostent(phe);
}
}
}
static int
str2ipaddr(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);
} else 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);
} else 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(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);
}
/*
* exit_error() - print an error message along with corresponding system error
* number and error message, then exit. Inputs - program error format and
* message.
*/
/*PRINTFLIKE1*/
static void
exit_error(char *fmt, ...)
{
va_list args;
va_start(args, fmt);
prt_error_va(fmt, args);
va_end(args);
exit(1);
}