2 * Copyright (c) 2009 Christian S.J. Peron
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
21 #include <bsm/audit.h>
22 #include <bsm/libbsm.h>
23 #include <bsm/audit_uevents.h>
32 #include "bsm_audit.h"
35 * Solaris auditon() returns EINVAL if BSM audit not configured.
36 * OpenBSM returns ENOSYS for unimplemented options.
39 # define AUDIT_NOT_CONFIGURED EINVAL
41 # define AUDIT_NOT_CONFIGURED ENOSYS
44 void log_error(int flags, const char *fmt, ...) __attribute__((__noreturn__));
47 audit_sudo_selected(int sf)
49 auditinfo_addr_t ainfo_addr;
54 if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0) {
55 if (errno == ENOSYS) {
56 if (getaudit(&ainfo) < 0)
57 log_error(0, "getaudit: failed");
58 mask = &ainfo.ai_mask;
60 log_error(0, "getaudit: failed");
62 mask = &ainfo_addr.ai_mask;
63 sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE;
64 rc = au_preselect(AUE_sudo, mask, sorf, AU_PRS_REREAD);
69 bsm_audit_success(char **exec_args)
71 auditinfo_addr_t ainfo_addr;
81 * If we are not auditing, don't cut an audit record; just return.
83 if (auditon(A_GETCOND, (caddr_t)&au_cond, sizeof(long)) < 0) {
84 if (errno == AUDIT_NOT_CONFIGURED)
86 log_error(0, "Could not determine audit condition");
88 if (au_cond == AUC_NOAUDIT)
91 * Check to see if the preselection masks are interested in seeing
94 if (!audit_sudo_selected(0))
96 if (getauid(&auid) < 0)
97 log_error(0, "getauid failed");
98 if ((aufd = au_open()) == -1)
99 log_error(0, "au_open: failed");
100 if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) {
101 tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(),
102 getuid(), pid, pid, &ainfo_addr.ai_termid);
103 } else if (errno == ENOSYS) {
105 * NB: We should probably watch out for ERANGE here.
107 if (getaudit(&ainfo) < 0)
108 log_error(0, "getaudit: failed");
109 tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
110 getuid(), pid, pid, &ainfo.ai_termid);
112 log_error(0, "getaudit: failed");
114 log_error(0, "au_to_subject: failed");
116 tok = au_to_exec_args(exec_args);
118 log_error(0, "au_to_exec_args: failed");
120 tok = au_to_return32(0, 0);
122 log_error(0, "au_to_return32: failed");
124 if (au_close(aufd, 1, AUE_sudo) == -1)
125 log_error(0, "unable to commit audit record");
129 bsm_audit_failure(char **exec_args, char const *const fmt, va_list ap)
131 auditinfo_addr_t ainfo_addr;
142 * If we are not auditing, don't cut an audit record; just return.
144 if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) {
145 if (errno == AUDIT_NOT_CONFIGURED)
147 log_error(0, "Could not determine audit condition");
149 if (au_cond == AUC_NOAUDIT)
151 if (!audit_sudo_selected(1))
153 if (getauid(&auid) < 0)
154 log_error(0, "getauid: failed");
155 if ((aufd = au_open()) == -1)
156 log_error(0, "au_open: failed");
157 if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) {
158 tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(),
159 getuid(), pid, pid, &ainfo_addr.ai_termid);
160 } else if (errno == ENOSYS) {
161 if (getaudit(&ainfo) < 0)
162 log_error(0, "getaudit: failed");
163 tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
164 getuid(), pid, pid, &ainfo.ai_termid);
166 log_error(0, "getaudit: failed");
168 log_error(0, "au_to_subject: failed");
170 tok = au_to_exec_args(exec_args);
172 log_error(0, "au_to_exec_args: failed");
174 (void) vsnprintf(text, sizeof(text), fmt, ap);
175 tok = au_to_text(text);
177 log_error(0, "au_to_text: failed");
179 tok = au_to_return32(EPERM, 1);
181 log_error(0, "au_to_return32: failed");
183 if (au_close(aufd, 1, AUE_sudo) == -1)
184 log_error(0, "unable to commit audit record");