Imported Upstream version 1.8.7
[debian/sudo] / plugins / sudoers / bsm_audit.c
1 /*
2  * Copyright (c) 2009-2013 Todd C. Miller <Todd.Miller@courtesan.com>
3  * Copyright (c) 2009 Christian S.J. Peron
4  *
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.
8  *
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.
16  */
17
18 #include <config.h>
19
20 #include <sys/types.h>
21
22 #include <bsm/audit.h>
23 #include <bsm/libbsm.h>
24 #include <bsm/audit_uevents.h>
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdarg.h>
29 #include <pwd.h>
30 #include <errno.h>
31 #include <unistd.h>
32
33 #include "gettext.h"
34 #include "error.h"
35 #include "sudo_debug.h"
36 #include "bsm_audit.h"
37
38 /*
39  * Solaris auditon() returns EINVAL if BSM audit not configured.
40  * OpenBSM returns ENOSYS for unimplemented options.
41  */
42 #ifdef __sun
43 # define AUDIT_NOT_CONFIGURED   EINVAL
44 #else
45 # define AUDIT_NOT_CONFIGURED   ENOSYS
46 #endif
47
48 static int
49 audit_sudo_selected(int sf)
50 {
51         auditinfo_addr_t ainfo_addr;
52         struct au_mask *mask;
53         auditinfo_t ainfo;
54         int rc, sorf;
55         debug_decl(audit_sudo_selected, SUDO_DEBUG_AUDIT)
56
57         if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0) {
58                 if (errno == ENOSYS) {
59                         if (getaudit(&ainfo) < 0)
60                                 fatal("getaudit");
61                         mask = &ainfo.ai_mask;
62                 } else
63                         fatal("getaudit");
64         } else
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);
68         debug_return_int(rc);
69 }
70
71 void
72 bsm_audit_success(char **exec_args)
73 {
74         auditinfo_addr_t ainfo_addr;
75         auditinfo_t ainfo;
76         token_t *tok;
77         au_id_t auid;
78         long au_cond;
79         int aufd;
80         pid_t pid;
81         debug_decl(bsm_audit_success, SUDO_DEBUG_AUDIT)
82
83         pid = getpid();
84         /*
85          * If we are not auditing, don't cut an audit record; just return.
86          */
87         if (auditon(A_GETCOND, (caddr_t)&au_cond, sizeof(long)) < 0) {
88                 if (errno == AUDIT_NOT_CONFIGURED)
89                         return;
90                 fatal(_("Could not determine audit condition"));
91         }
92         if (au_cond == AUC_NOAUDIT)
93                 debug_return;
94         /*
95          * Check to see if the preselection masks are interested in seeing
96          * this event.
97          */
98         if (!audit_sudo_selected(0))
99                 debug_return;
100         if (getauid(&auid) < 0)
101                 fatal("getauid");
102         if ((aufd = au_open()) == -1)
103                 fatal("au_open");
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) {
108                 /*
109                  * NB: We should probably watch out for ERANGE here.
110                  */
111                 if (getaudit(&ainfo) < 0)
112                         fatal("getaudit");
113                 tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
114                     getuid(), pid, pid, &ainfo.ai_termid);
115         } else
116                 fatal("getaudit");
117         if (tok == NULL)
118                 fatal("au_to_subject");
119         au_write(aufd, tok);
120         tok = au_to_exec_args(exec_args);
121         if (tok == NULL)
122                 fatal("au_to_exec_args");
123         au_write(aufd, tok);
124         tok = au_to_return32(0, 0);
125         if (tok == NULL)
126                 fatal("au_to_return32");
127         au_write(aufd, tok);
128         if (au_close(aufd, 1, AUE_sudo) == -1)
129                 fatal(_("unable to commit audit record"));
130         debug_return;
131 }
132
133 void
134 bsm_audit_failure(char **exec_args, char const *const fmt, va_list ap)
135 {
136         auditinfo_addr_t ainfo_addr;
137         auditinfo_t ainfo;
138         char text[256];
139         token_t *tok;
140         long au_cond;
141         au_id_t auid;
142         pid_t pid;
143         int aufd;
144         debug_decl(bsm_audit_success, SUDO_DEBUG_AUDIT)
145
146         pid = getpid();
147         /*
148          * If we are not auditing, don't cut an audit record; just return.
149          */
150         if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) {
151                 if (errno == AUDIT_NOT_CONFIGURED)
152                         debug_return;
153                 fatal(_("Could not determine audit condition"));
154         }
155         if (au_cond == AUC_NOAUDIT)
156                 debug_return;
157         if (!audit_sudo_selected(1))
158                 debug_return;
159         if (getauid(&auid) < 0)
160                 fatal("getauid");
161         if ((aufd = au_open()) == -1)
162                 fatal("au_open");
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) 
168                         fatal("getaudit");
169                 tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
170                     getuid(), pid, pid, &ainfo.ai_termid);
171         } else
172                 fatal("getaudit");
173         if (tok == NULL)
174                 fatal("au_to_subject");
175         au_write(aufd, tok);
176         tok = au_to_exec_args(exec_args);
177         if (tok == NULL)
178                 fatal("au_to_exec_args");
179         au_write(aufd, tok);
180         (void) vsnprintf(text, sizeof(text), fmt, ap);
181         tok = au_to_text(text);
182         if (tok == NULL)
183                 fatal("au_to_text");
184         au_write(aufd, tok);
185         tok = au_to_return32(EPERM, 1);
186         if (tok == NULL)
187                 fatal("au_to_return32");
188         au_write(aufd, tok);
189         if (au_close(aufd, 1, AUE_sudo) == -1)
190                 fatal(_("unable to commit audit record"));
191         debug_return;
192 }