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