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 void log_error(int flags, const char *fmt, ...) __attribute__((__noreturn__));
35 audit_sudo_selected(int sf)
37 auditinfo_addr_t ainfo_addr;
42 if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0) {
43 if (errno == ENOSYS) {
44 if (getaudit(&ainfo) < 0)
45 log_error(0, "getaudit: failed");
46 mask = &ainfo.ai_mask;
48 log_error(0, "getaudit: failed");
50 mask = &ainfo_addr.ai_mask;
51 sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE;
52 rc = au_preselect(AUE_sudo, mask, sorf, AU_PRS_REREAD);
57 bsm_audit_success(char **exec_args)
59 auditinfo_addr_t ainfo_addr;
69 * If we are not auditing, don't cut an audit record; just return.
71 if (auditon(A_GETCOND, (caddr_t)&au_cond, sizeof(long)) < 0) {
74 log_error(0, "Could not determine audit condition");
76 if (au_cond == AUC_NOAUDIT)
79 * Check to see if the preselection masks are interested in seeing
82 if (!audit_sudo_selected(0))
84 if (getauid(&auid) < 0)
85 log_error(0, "getauid failed");
86 if ((aufd = au_open()) == -1)
87 log_error(0, "au_open: failed");
88 if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) {
89 tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(),
90 getuid(), pid, pid, &ainfo_addr.ai_termid);
91 } else if (errno == ENOSYS) {
93 * NB: We should probably watch out for ERANGE here.
95 if (getaudit(&ainfo) < 0)
96 log_error(0, "getaudit: failed");
97 tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
98 getuid(), pid, pid, &ainfo.ai_termid);
100 log_error(0, "getaudit: failed");
102 log_error(0, "au_to_subject: failed");
104 tok = au_to_exec_args(exec_args);
106 log_error(0, "au_to_exec_args: failed");
108 tok = au_to_return32(0, 0);
110 log_error(0, "au_to_return32: failed");
112 if (au_close(aufd, 1, AUE_sudo) == -1)
113 log_error(0, "unable to commit audit record");
117 bsm_audit_failure(char **exec_args, char const *const fmt, va_list ap)
119 auditinfo_addr_t ainfo_addr;
130 * If we are not auditing, don't cut an audit record; just return.
132 if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) {
135 log_error(0, "Could not determine audit condition");
137 if (au_cond == AUC_NOAUDIT)
139 if (!audit_sudo_selected(1))
141 if (getauid(&auid) < 0)
142 log_error(0, "getauid: failed");
143 if ((aufd = au_open()) == -1)
144 log_error(0, "au_open: failed");
145 if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) {
146 tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(),
147 getuid(), pid, pid, &ainfo_addr.ai_termid);
148 } else if (errno == ENOSYS) {
149 if (getaudit(&ainfo) < 0)
150 log_error(0, "getaudit: failed");
151 tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
152 getuid(), pid, pid, &ainfo.ai_termid);
154 log_error(0, "getaudit: failed");
156 log_error(0, "au_to_subject: failed");
158 tok = au_to_exec_args(exec_args);
160 log_error(0, "au_to_exec_args: failed");
162 (void) vsnprintf(text, sizeof(text), fmt, ap);
163 tok = au_to_text(text);
165 log_error(0, "au_to_text: failed");
167 tok = au_to_return32(EPERM, 1);
169 log_error(0, "au_to_return32: failed");
171 if (au_close(aufd, 1, AUE_sudo) == -1)
172 log_error(0, "unable to commit audit record");