2 * Copyright (c) 2009-2013 Todd C. Miller <Todd.Miller@courtesan.com>
3 * Copyright (c) 2009 Christian S.J. Peron
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <sys/types.h>
22 #include <bsm/audit.h>
23 #include <bsm/libbsm.h>
24 #include <bsm/audit_uevents.h>
35 #include "sudo_debug.h"
36 #include "bsm_audit.h"
39 * Solaris auditon() returns EINVAL if BSM audit not configured.
40 * OpenBSM returns ENOSYS for unimplemented options.
43 # define AUDIT_NOT_CONFIGURED EINVAL
45 # define AUDIT_NOT_CONFIGURED ENOSYS
49 audit_sudo_selected(int sf)
51 auditinfo_addr_t ainfo_addr;
55 debug_decl(audit_sudo_selected, SUDO_DEBUG_AUDIT)
57 if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0) {
58 if (errno == ENOSYS) {
59 if (getaudit(&ainfo) < 0)
61 mask = &ainfo.ai_mask;
65 mask = &ainfo_addr.ai_mask;
66 sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE;
67 rc = au_preselect(AUE_sudo, mask, sorf, AU_PRS_REREAD);
72 bsm_audit_success(char **exec_args)
74 auditinfo_addr_t ainfo_addr;
81 debug_decl(bsm_audit_success, SUDO_DEBUG_AUDIT)
85 * If we are not auditing, don't cut an audit record; just return.
87 if (auditon(A_GETCOND, (caddr_t)&au_cond, sizeof(long)) < 0) {
88 if (errno == AUDIT_NOT_CONFIGURED)
90 fatal(_("Could not determine audit condition"));
92 if (au_cond == AUC_NOAUDIT)
95 * Check to see if the preselection masks are interested in seeing
98 if (!audit_sudo_selected(0))
100 if (getauid(&auid) < 0)
102 if ((aufd = au_open()) == -1)
104 if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) {
105 tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(),
106 getuid(), pid, pid, &ainfo_addr.ai_termid);
107 } else if (errno == ENOSYS) {
109 * NB: We should probably watch out for ERANGE here.
111 if (getaudit(&ainfo) < 0)
113 tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
114 getuid(), pid, pid, &ainfo.ai_termid);
118 fatal("au_to_subject");
120 tok = au_to_exec_args(exec_args);
122 fatal("au_to_exec_args");
124 tok = au_to_return32(0, 0);
126 fatal("au_to_return32");
128 if (au_close(aufd, 1, AUE_sudo) == -1)
129 fatal(_("unable to commit audit record"));
134 bsm_audit_failure(char **exec_args, char const *const fmt, va_list ap)
136 auditinfo_addr_t ainfo_addr;
144 debug_decl(bsm_audit_success, SUDO_DEBUG_AUDIT)
148 * If we are not auditing, don't cut an audit record; just return.
150 if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) {
151 if (errno == AUDIT_NOT_CONFIGURED)
153 fatal(_("Could not determine audit condition"));
155 if (au_cond == AUC_NOAUDIT)
157 if (!audit_sudo_selected(1))
159 if (getauid(&auid) < 0)
161 if ((aufd = au_open()) == -1)
163 if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) {
164 tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(),
165 getuid(), pid, pid, &ainfo_addr.ai_termid);
166 } else if (errno == ENOSYS) {
167 if (getaudit(&ainfo) < 0)
169 tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
170 getuid(), pid, pid, &ainfo.ai_termid);
174 fatal("au_to_subject");
176 tok = au_to_exec_args(exec_args);
178 fatal("au_to_exec_args");
180 (void) vsnprintf(text, sizeof(text), fmt, ap);
181 tok = au_to_text(text);
185 tok = au_to_return32(EPERM, 1);
187 fatal("au_to_return32");
189 if (au_close(aufd, 1, AUE_sudo) == -1)
190 fatal(_("unable to commit audit record"));