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