audit.c revision 7883e825152992a0f20c3f52f7c4bb902a56205c
/*
* 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
* 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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <fcntl.h>
#include <libscf.h>
#include <secdb.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <locale.h>
#include <audit_sig_infc.h>
#include <zone.h>
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SUNW_OST_OSCMD"
#endif
#define VERIFY -1
/* GLOBALS */
static char *auditdatafile = AUDITDATAFILE;
static char *progname = "audit";
static char *usage = "audit [-n] | [-s] | [-t] | [-v filepath]";
static int silent = 0;
static char *instance_name = "svc:/system/auditd:default";
static int get_auditd_pid();
static void display_smf_error();
static void start_auditd(); /* start audit daemon */
/*
* audit() - This program serves as a general administrator's interface to
* the audit trail. Only one option is valid at a time.
*
* input:
* audit -s
* - signal audit daemon to read audit_control file and
* start auditd if needed.
* audit -n
* - signal audit daemon to use next audit_control audit directory.
* audit -t
* - signal audit daemon to disable auditing.
* audit -T
* - signal audit daemon to disable auditing report no errors.
* audit -v filepath
* - validate audit_control parameters but use filepath for
* the name. Emit errors or "syntax ok"
*
*
* output:
*
* returns: 0 - command successful
* >0 - command failed
*/
int
{
int sig = 0; /* signal to send auditd */
char c;
char *first_option;
/* Internationalization */
(void) textdomain(TEXT_DOMAIN);
if (getuid() != 0) {
progname);
exit(2);
}
/* first option required */
exit(3);
}
/* second or more options not allowed; please pick one */
exit(5);
}
switch (c) {
case 'n':
exit(10);
break;
case 's':
exit(10);
else if (!is_audit_control_ok(NULL))
exit(7);
start_auditd();
break;
case 't':
if (!is_valid_zone(0)) /* 0 == no error message display */
exit(0);
/* use bmsunconv to permanently disable, -t for temporary */
break;
case 'T':
if (!is_valid_zone(0)) /* 0 == no error message display */
exit(0);
silent = 1;
break;
case 'v':
if (is_audit_control_ok(first_option)) {
exit(0);
} else {
exit(8);
}
break;
default:
exit(6);
}
if (get_auditd_pid(&pid) != 0) {
if (silent) {
exit(0);
} else {
"can't get process id of auditd from audit_data(4)"));
exit(4);
}
}
if (silent) {
exit(0);
} else {
exit(1);
}
}
return (0);
}
/*
* get_auditd_pid(&pid):
*
* reads PID from audit_data
*
* returns: 0 - successful
* 1 - error
*/
static int
{
int retstat;
if (!silent)
return (1);
}
return (retstat);
}
/*
* perform reasonableness check on audit_control or its standin; goal
* actually generates data.
*
* A NULL input is ok -- it is used to tell _openac() to use the
* real audit_control file, not a substitute.
*/
#define TRADITIONAL_MAX 1024
static boolean_t
is_audit_control_ok(char *filename) {
char buf[TRADITIONAL_MAX];
int outputs = 0;
int rc;
int min;
char *value;
exit(9);
}
/*
* There must be at least one directory or one plugin
* defined.
*/
outputs++;
gettext("%s: audit_control \"dir:\" spec invalid\n"),
progname);
state = 0; /* is_not_ok */
}
/*
* _getacplug -- all that is of interest is the return code.
*/
"\"plugin:\" missing name\n"), progname);
state = 0; /* is_not_ok */
}
else
outputs++;
} else if (rc < -1) {
gettext("%s: audit_control \"plugin:\" spec invalid\n"),
progname);
state = 0; /* is_not_ok */
}
if (outputs == 0) {
gettext("%s: audit_control must have either a "
"\"dir:\" or a \"plugin:\" specified.\n"),
progname);
state = 0; /* is_not_ok */
}
/* minfree is not required */
"%s: audit_control \"minfree:\" spec invalid\n"),
progname);
state = 0; /* is_not_ok */
}
/* flags is not required */
gettext("%s: audit_control \"flags:\" spec invalid\n"),
progname);
state = 0; /* is_not_ok */
}
/* naflags is not required */
"%s: audit_control \"naflags:\" spec invalid\n"),
progname);
state = 0; /* is_not_ok */
}
return (state);
}
/*
* The operations that call this function are only valid in the global
* zone unless the perzone audit policy is set.
*
* "!silent" and "show_err" are slightly different; silent is from
* -T for which no error messages should be displayed and show_err
* applies to more options (including -T)
*
*/
static boolean_t
{
long policy;
if (!silent)
"%s: Cannot read audit policy: %s\n"),
return (0);
}
if (policy & AUDIT_PERZONE)
return (1);
if (getzoneid() != GLOBAL_ZONEID) {
if (show_err)
gettext("%s: Not valid in a local zone.\n"),
progname);
return (0);
} else {
return (1);
}
}
/*
* if auditd isn't running, start it. Otherwise refresh.
* First check to see if c2audit is loaded via the auditon()
* system call, then check SMF state.
*/
static void
{
int audit_state;
char *state;
sizeof (audit_state)) != 0)
return;
return;
}
if (smf_enable_instance(instance_name, 0) != 0)
} else {
if (smf_refresh_instance(instance_name) != 0)
}
}
static void
{
switch (rc) {
case SCF_ERROR_NOT_FOUND:
"SMF error: \"%s\" not found.\n",
break;
default:
break;
}
}