4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
34 #include <sys/types.h>
37 #include <sys/param.h>
39 #include <bsm/audit.h>
40 #include <bsm/libbsm.h>
43 #include <audit_scf.h>
45 #if !defined(TEXT_DOMAIN)
46 #define TEXT_DOMAIN "SUNW_OST_OSCMD"
52 static char *progname
= "audit";
53 static char *usage
= "audit [-n] | [-s] | [-t] | [-v]";
54 static int silent
= 0;
56 static void display_smf_error();
58 static boolean_t
is_audit_config_ok(); /* config validation */
59 static boolean_t
is_valid_zone(boolean_t
); /* operation ok in this zone? */
60 static boolean_t
contains_valid_dirs(char *); /* p_dir contents validation */
61 static boolean_t
validate_path(char *); /* is it path to dir? */
62 static void start_auditd(); /* start audit daemon */
63 static int sig_auditd(int); /* send signal to auditd */
66 * audit() - This program serves as a general administrator's interface to
67 * the audit trail. Only one option is valid at a time.
71 * - signal audit daemon to read audit configuration and
72 * start auditd if needed.
74 * - signal audit daemon to use next audit_binfile directory.
76 * - signal audit daemon to disable auditing.
78 * - signal audit daemon to temporarily disable auditing reporting
81 * - validate audit configuration parameters;
82 * Print errors or "configuration ok".
87 * returns: 0 - command successful
92 main(int argc
, char *argv
[])
96 /* Internationalization */
97 (void) setlocale(LC_ALL
, "");
98 (void) textdomain(TEXT_DOMAIN
);
100 /* second or more options not allowed; please pick one */
102 (void) fprintf(stderr
, gettext("usage: %s\n"), usage
);
106 /* first option required */
107 if ((c
= getopt(argc
, argv
, "nstTv")) == -1) {
108 (void) fprintf(stderr
, gettext("usage: %s\n"), usage
);
114 if (!is_valid_zone(1)) /* 1 == display error if any */
117 if (sig_auditd(SIGUSR1
) != 0)
121 if (!is_valid_zone(1)) /* 1 == display error if any */
123 else if (!is_audit_config_ok())
129 if (!is_valid_zone(0)) /* 0 == no error message display */
131 if (smf_disable_instance(AUDITD_FMRI
, 0) != 0) {
138 if (!is_valid_zone(0)) /* 0 == no error message display */
140 if (smf_disable_instance(AUDITD_FMRI
, SMF_TEMPORARY
) != 0) {
145 if (is_audit_config_ok()) {
146 (void) fprintf(stderr
, gettext("configuration ok\n"));
153 (void) fprintf(stderr
, gettext("usage: %s\n"), usage
);
163 * send a signal to auditd service
165 * returns: 0 - successful
172 scf_simple_prop_t
*prop
= NULL
;
173 uint64_t *cid
= NULL
;
175 if ((prop
= scf_simple_prop_get(NULL
, AUDITD_FMRI
, SCF_PG_RESTARTER
,
176 SCF_PROPERTY_CONTRACT
)) == NULL
) {
180 if ((scf_simple_prop_numvalues(prop
) < 0) ||
181 (cid
= scf_simple_prop_next_count(prop
)) == NULL
) {
182 scf_simple_prop_free(prop
);
186 if (sigsend(P_CTID
, (ctid_t
)*cid
, sig
) != 0) {
187 perror("audit: can't signal auditd");
188 scf_simple_prop_free(prop
);
191 scf_simple_prop_free(prop
);
196 * perform reasonableness check on audit configuration
200 is_audit_config_ok() {
201 int state
= B_TRUE
; /* B_TRUE/B_FALSE = ok/not_ok */
205 scf_plugin_kva_node_t
*plugin_kva_ll
;
206 scf_plugin_kva_node_t
*plugin_kva_ll_head
;
207 boolean_t one_plugin_enabled
= B_FALSE
;
210 * There must be at least one active plugin configured; if the
211 * configured plugin is audit_binfile(5), then the p_dir must not be
214 if (!do_getpluginconfig_scf(NULL
, &plugin_kva_ll
)) {
215 (void) fprintf(stderr
,
216 gettext("Could not get plugin configuration.\n"));
220 plugin_kva_ll_head
= plugin_kva_ll
;
222 while (plugin_kva_ll
!= NULL
) {
223 kvlist
= plugin_kva_ll
->plugin_kva
;
225 if (!one_plugin_enabled
) {
226 cval_str
= kva_match(kvlist
, "active");
227 if (atoi(cval_str
) == 1) {
228 one_plugin_enabled
= B_TRUE
;
232 if (strcmp((char *)&(*plugin_kva_ll
).plugin_name
,
233 "audit_binfile") == 0) {
234 cval_str
= kva_match(kvlist
, "p_dir");
235 if (*cval_str
== '\0' || cval_str
== NULL
) {
236 (void) fprintf(stderr
,
237 gettext("%s: audit_binfile(5) \"p_dir:\" "
238 "attribute empty\n"), progname
);
240 } else if (!contains_valid_dirs(cval_str
)) {
241 (void) fprintf(stderr
,
242 gettext("%s: audit_binfile(5) \"p_dir:\" "
243 "attribute invalid\n"), progname
);
247 cval_str
= kva_match(kvlist
, "p_minfree");
248 cval_int
= atoi(cval_str
);
249 if (cval_int
< 0 || cval_int
> 100) {
250 (void) fprintf(stderr
,
251 gettext("%s: audit_binfile(5) "
252 "\"p_minfree:\" attribute invalid\n"),
258 plugin_kva_ll
= plugin_kva_ll
->next
;
261 plugin_kva_ll_free(plugin_kva_ll_head
);
263 if (!one_plugin_enabled
) {
264 (void) fprintf(stderr
, gettext("%s: no active plugin found\n"),
273 * The operations that call this function are only valid in the global
274 * zone unless the perzone audit policy is set.
276 * "!silent" and "show_err" are slightly different; silent is from
277 * -T for which no error messages should be displayed and show_err
278 * applies to more options (including -T)
283 is_valid_zone(boolean_t show_err
)
287 if (auditon(A_GETPOLICY
, (char *)&policy
, 0) == -1) {
289 (void) fprintf(stderr
, gettext(
290 "%s: Cannot read audit policy: %s\n"),
291 progname
, strerror(errno
));
295 if (policy
& AUDIT_PERZONE
)
298 if (getzoneid() != GLOBAL_ZONEID
) {
300 (void) fprintf(stderr
,
301 gettext("%s: Not valid in a local zone.\n"),
310 * Verify, whether the dirs_str contains at least one currently valid path to
311 * the directory. All invalid paths are reported. In case no valid directory
312 * path is found function returns B_FALSE, otherwise B_TRUE.
316 contains_valid_dirs(char *dirs_str
)
318 boolean_t rc
= B_FALSE
;
319 boolean_t rc_validate_path
= B_TRUE
;
323 if (dirs_str
== NULL
) {
327 if ((tok_ptr
= strtok_r(dirs_str
, ",", &tok_lasts
)) != NULL
) {
328 if (validate_path(tok_ptr
)) {
331 rc_validate_path
= B_FALSE
;
333 while ((tok_ptr
= strtok_r(NULL
, ",", &tok_lasts
)) != NULL
) {
334 if (validate_path(tok_ptr
)) {
337 rc_validate_path
= B_FALSE
;
342 if (rc
&& !rc_validate_path
) {
343 (void) fprintf(stderr
, gettext("%s: at least one valid "
344 "directory path found\n"), progname
);
351 * Verify, that the dir_path is path to a directory.
355 validate_path(char *dir_path
)
357 boolean_t rc
= B_FALSE
;
360 if (dir_path
== NULL
) {
364 if (stat(dir_path
, &statbuf
) == -1) {
365 (void) fprintf(stderr
, gettext("%s: %s error: %s\n"), progname
,
366 dir_path
, strerror(errno
));
367 } else if (statbuf
.st_mode
& S_IFDIR
) {
370 (void) fprintf(stderr
, gettext("%s: %s is not a directory\n"),
378 * if auditd isn't running, start it. Otherwise refresh.
379 * First check to see if c2audit is loaded via the auditon()
380 * system call, then check SMF state.
388 if (auditon(A_GETCOND
, (caddr_t
)&audit_state
,
389 sizeof (audit_state
)) != 0)
392 if ((state
= smf_get_state(AUDITD_FMRI
)) == NULL
) {
396 if (strcmp(SCF_STATE_STRING_ONLINE
, state
) != 0) {
397 if (smf_enable_instance(AUDITD_FMRI
, 0) != 0) {
403 if (smf_refresh_instance(AUDITD_FMRI
) != 0) {
415 scf_error_t rc
= scf_error();
418 case SCF_ERROR_NOT_FOUND
:
419 (void) fprintf(stderr
,
420 "SMF error: \"%s\" not found.\n",
424 (void) fprintf(stderr
, "SMF error: %s\n", scf_strerror(rc
));