add doc about interaction with RAMRUN to README.Debian in response to #581393
[debian/sudo] / bsm_audit.c
1 /*
2  * Copyright (c) 2009 Christian S.J. Peron
3  *
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.
7  *
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.
15  */
16
17 #include <config.h>
18
19 #include <sys/types.h>
20
21 #include <bsm/audit.h>
22 #include <bsm/libbsm.h>
23 #include <bsm/audit_uevents.h>
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include <pwd.h>
29 #include <errno.h>
30 #include <unistd.h>
31
32 void log_error(int flags, const char *fmt, ...) __attribute__((__noreturn__));
33
34 static int
35 audit_sudo_selected(int sf)
36 {
37         auditinfo_addr_t ainfo_addr;
38         struct au_mask *mask;
39         auditinfo_t ainfo;
40         int rc, sorf;
41
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;
47                 } else
48                         log_error(0, "getaudit: failed");
49         } else
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);
53         return (rc);
54 }
55
56 void
57 bsm_audit_success(char **exec_args)
58 {
59         auditinfo_addr_t ainfo_addr;
60         auditinfo_t ainfo;
61         token_t *tok;
62         au_id_t auid;
63         long au_cond;
64         int aufd;
65         pid_t pid;
66
67         pid = getpid();
68         /*
69          * If we are not auditing, don't cut an audit record; just return.
70          */
71         if (auditon(A_GETCOND, (caddr_t)&au_cond, sizeof(long)) < 0) {
72                 if (errno == ENOSYS)
73                         return;
74                 log_error(0, "Could not determine audit condition");
75         }
76         if (au_cond == AUC_NOAUDIT)
77                 return;
78         /*
79          * Check to see if the preselection masks are interested in seeing
80          * this event.
81          */
82         if (!audit_sudo_selected(0))
83                 return;
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) {
92                 /*
93                  * NB: We should probably watch out for ERANGE here.
94                  */
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);
99         } else
100                 log_error(0, "getaudit: failed");
101         if (tok == NULL)
102                 log_error(0, "au_to_subject: failed");
103         au_write(aufd, tok);
104         tok = au_to_exec_args(exec_args);
105         if (tok == NULL)
106                 log_error(0, "au_to_exec_args: failed");
107         au_write(aufd, tok);
108         tok = au_to_return32(0, 0);
109         if (tok == NULL)
110                 log_error(0, "au_to_return32: failed");
111         au_write(aufd, tok);
112         if (au_close(aufd, 1, AUE_sudo) == -1)
113                 log_error(0, "unable to commit audit record");
114 }
115
116 void
117 bsm_audit_failure(char **exec_args, char const *const fmt, va_list ap)
118 {
119         auditinfo_addr_t ainfo_addr;
120         auditinfo_t ainfo;
121         char text[256];
122         token_t *tok;
123         long au_cond;
124         au_id_t auid;
125         pid_t pid;
126         int aufd;
127
128         pid = getpid();
129         /*
130          * If we are not auditing, don't cut an audit record; just return.
131          */
132         if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) {
133                 if (errno == ENOSYS)
134                         return;
135                 log_error(0, "Could not determine audit condition");
136         }
137         if (au_cond == AUC_NOAUDIT)
138                 return;
139         if (!audit_sudo_selected(1))
140                 return;
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);
153         } else
154                 log_error(0, "getaudit: failed");
155         if (tok == NULL)
156                 log_error(0, "au_to_subject: failed");
157         au_write(aufd, tok);
158         tok = au_to_exec_args(exec_args);
159         if (tok == NULL)
160                 log_error(0, "au_to_exec_args: failed");
161         au_write(aufd, tok);
162         (void) vsnprintf(text, sizeof(text), fmt, ap);
163         tok = au_to_text(text);
164         if (tok == NULL)
165                 log_error(0, "au_to_text: failed");
166         au_write(aufd, tok);
167         tok = au_to_return32(EPERM, 1);
168         if (tok == NULL)
169                 log_error(0, "au_to_return32: failed");
170         au_write(aufd, tok);
171         if (au_close(aufd, 1, AUE_sudo) == -1)
172                 log_error(0, "unable to commit audit record");
173 }