]> git.saurik.com Git - apple/security.git/blob - OSX/authd/ccaudit.c
Security-58286.20.16.tar.gz
[apple/security.git] / OSX / authd / ccaudit.c
1 /* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */
2
3 #include "ccaudit.h"
4 #include "debugging.h"
5 #include "process.h"
6 #include "authtoken.h"
7
8 #include <Security/Authorization.h>
9 #include <Security/AuthorizationPlugin.h>
10 #include <bsm/libbsm.h>
11
12 AUTHD_DEFINE_LOG
13
14
15 struct _ccaudit_s {
16 __AUTH_BASE_STRUCT_HEADER__;
17
18 int fd;
19 int32_t event;
20
21 auth_token_t auth;
22 process_t proc;
23 audit_info_s auditInfo;
24 au_tid_t tid;
25 };
26
27 static void
28 _ccaudit_finalizer(CFTypeRef value)
29 {
30 ccaudit_t ccaudit = (ccaudit_t)value;
31
32 CFReleaseNull(ccaudit->auth);
33 CFReleaseNull(ccaudit->proc);
34 }
35
36 AUTH_TYPE_INSTANCE(ccaudit,
37 .init = NULL,
38 .copy = NULL,
39 .finalize = _ccaudit_finalizer,
40 .equal = NULL,
41 .hash = NULL,
42 .copyFormattingDesc = NULL,
43 .copyDebugDesc = NULL
44 );
45
46 static CFTypeID ccaudit_get_type_id() {
47 static CFTypeID type_id = _kCFRuntimeNotATypeID;
48 static dispatch_once_t onceToken;
49
50 dispatch_once(&onceToken, ^{
51 type_id = _CFRuntimeRegisterClass(&_auth_type_ccaudit);
52 });
53
54 return type_id;
55 }
56
57 ccaudit_t
58 ccaudit_create(process_t proc, auth_token_t auth, int32_t event)
59 {
60 ccaudit_t ccaudit = NULL;
61
62 require(auth != NULL, done);
63
64 ccaudit = (ccaudit_t)_CFRuntimeCreateInstance(kCFAllocatorDefault, ccaudit_get_type_id(), AUTH_CLASS_SIZE(ccaudit), NULL);
65 require(ccaudit != NULL, done);
66
67 ccaudit->auth = (auth_token_t)CFRetain(auth);
68 ccaudit->proc = (process_t)CFRetain(proc);
69 ccaudit->fd = -1;
70 ccaudit->event = event;
71
72 ccaudit->auditInfo = *auth_token_get_audit_info(auth);
73 ccaudit->tid.port = ccaudit->auditInfo.tid;
74
75 done:
76 return ccaudit;
77 }
78
79 static bool _enabled()
80 {
81 static dispatch_once_t onceToken;
82 static bool enabled = false;
83
84 dispatch_once(&onceToken, ^{
85 int acond = au_get_state();
86 switch (acond) {
87 case AUC_NOAUDIT:
88 break;
89 case AUC_AUDITING:
90 enabled = true;
91 break;
92 default:
93 os_log_error(AUTHD_LOG, "ccaudit: error checking auditing status (%d)", acond);
94 }
95 });
96
97 return enabled;
98 }
99
100 static bool _open(ccaudit_t ccaudit)
101 {
102 if (!_enabled()) {
103 return false;
104 }
105
106 if (-1 != ccaudit->fd)
107 return true;
108
109 if ((ccaudit->fd = au_open()) < 0) {
110 os_log_error(AUTHD_LOG, "ccaudit: au_open() failed (%{public}s)", strerror(errno));
111 return false;
112 }
113
114 return true;
115 }
116
117 static void _close(ccaudit_t ccaudit)
118 {
119 if (-1 != ccaudit->fd) {
120 int err = au_close(ccaudit->fd, AU_TO_WRITE, (short)ccaudit->event);
121 ccaudit->fd = -1;
122 if (err < 0) {
123 os_log_error(AUTHD_LOG, "ccaudit: au_close() failed; record not committed");
124 }
125 }
126 }
127
128 static bool _write(ccaudit_t ccaudit, token_t * token, const char * name)
129 {
130 const char *tokenName = name ? name : "<unidentified>";
131 if (NULL == token)
132 {
133 os_log_error(AUTHD_LOG, "ccaudit: invalid '%{public}s' token", tokenName);
134 return false;
135 }
136 if (au_write(ccaudit->fd, token) < 0) {
137 os_log_error(AUTHD_LOG, "ccaudit: error writing '%{public}s' token (%{public}s)", tokenName, strerror(errno));
138 return false;
139 }
140 return true;
141 }
142
143 static bool _subject(ccaudit_t ccaudit)
144 {
145 token_t * token = au_to_subject32(ccaudit->auditInfo.auid, ccaudit->auditInfo.euid, ccaudit->auditInfo.egid,
146 ccaudit->auditInfo.ruid, ccaudit->auditInfo.rgid, ccaudit->auditInfo.pid, ccaudit->auditInfo.asid, &ccaudit->tid);
147 return _write(ccaudit, token, "subject");
148 }
149
150 void ccaudit_log_authorization(ccaudit_t ccaudit, const char * right, OSStatus err)
151 {
152
153 if (!_open(ccaudit)) {
154 return;
155 }
156 char buf[PATH_MAX+1];
157
158 _subject(ccaudit);
159 _write(ccaudit, au_to_text(right), "right");
160 snprintf(buf, sizeof(buf), "client %s", process_get_code_url(ccaudit->proc));
161 _write(ccaudit, au_to_text(buf), "Authorization client");
162 snprintf(buf, sizeof(buf), "creator %s", auth_token_get_code_url(ccaudit->auth));
163 _write(ccaudit, au_to_text(buf), "Authorization creator");
164
165 if (auth_token_least_privileged(ccaudit->auth)) {
166 _write(ccaudit, au_to_text("least-privilege"), "least-privilege");
167 }
168
169 if (err == errAuthorizationSuccess) {
170 _write(ccaudit, au_to_return32(0, 0), "return");
171 } else {
172 _write(ccaudit, au_to_return32(EPERM, (uint32_t)err), "return");
173 }
174
175 _close(ccaudit);
176 }
177
178 void ccaudit_log_success(ccaudit_t ccaudit, credential_t cred, const char * right)
179 {
180
181 if (!_open(ccaudit)) {
182 return;
183 }
184 char buf[PATH_MAX+1];
185
186 _subject(ccaudit);
187 _write(ccaudit, au_to_text(right), "right");
188 _write(ccaudit, au_to_arg32(1, "known UID ", auth_token_get_uid(ccaudit->auth)), "authenticator");
189 snprintf(buf, sizeof(buf), "authenticated as %s", credential_get_name(cred));
190 _write(ccaudit, au_to_arg32(2, buf, credential_get_uid(cred)), "target");
191 _write(ccaudit, au_to_return32(0, 0), "return");
192
193 _close(ccaudit);
194 }
195
196 #pragma clang diagnostic push
197 #pragma clang diagnostic ignored "-Wunused-parameter"
198
199 void ccaudit_log_failure(ccaudit_t ccaudit, const char * credName, const char * right)
200 {
201
202 if (!_open(ccaudit)) {
203 return;
204 }
205 _subject(ccaudit);
206 _write(ccaudit, au_to_text(right), "right");
207 _write(ccaudit, au_to_arg32(1, "authenticated as ", auth_token_get_uid(ccaudit->auth)), "authenticator");
208
209 _write(ccaudit, au_to_text("<unknown user>"), "target username");
210 _write(ccaudit, au_to_return32(EPERM, (uint32_t)errAuthorizationDenied), "return");
211
212 _close(ccaudit);
213 }
214
215 #pragma clang diagnostic pop
216
217 void ccaudit_log_mechanism(ccaudit_t ccaudit, const char * right, const char * mech, uint32_t status, const char * interrupted)
218 {
219
220 if (!_open(ccaudit)) {
221 return;
222 }
223 char buf[PATH_MAX+1];
224
225 _subject(ccaudit);
226 _write(ccaudit, au_to_text(right), "right");
227 snprintf(buf, sizeof(buf), "mechanism %s", mech);
228 _write(ccaudit, au_to_text(buf), "mechanism");
229
230 if (interrupted) {
231 _write(ccaudit, au_to_text(interrupted), "interrupt");
232 }
233
234 if (status == kAuthorizationResultAllow) {
235 _write(ccaudit, au_to_return32(0, 0), "return");
236 } else {
237 _write(ccaudit, au_to_return32(EPERM, (uint32_t)status), "return");
238 }
239
240 _close(ccaudit);
241 }
242
243 void ccaudit_log(ccaudit_t ccaudit, const char * right, const char * msg, OSStatus err)
244 {
245 if (!_open(ccaudit)) {
246 return;
247 }
248
249 _subject(ccaudit);
250 _write(ccaudit, au_to_text(right), "right");
251
252 if (msg) {
253 _write(ccaudit, au_to_text(msg), "evaluation error");
254 }
255
256 if (err == errAuthorizationSuccess) {
257 _write(ccaudit, au_to_return32(0, 0), "return");
258 } else {
259 _write(ccaudit, au_to_return32(EPERM, (uint32_t)err), "return");
260 }
261
262 _close(ccaudit);
263 }