]> git.saurik.com Git - apple/security.git/blob - securityd/securityd_service/securityd_service/main.c
63a2a894c7ddb4dfd3920b470a7cd2612cb26ee5
[apple/security.git] / securityd / securityd_service / securityd_service / main.c
1 /* Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. */
2
3 #include "securityd_service.h"
4 #include "securityd_service_client.h"
5 #include <libaks.h>
6
7 #include <sandbox.h>
8 #include <vproc.h>
9 #include <xpc/xpc.h>
10 #include <xpc/private.h>
11 #include <dispatch/dispatch.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <sys/codesign.h>
15 #include <os/log.h>
16 #include <stdio.h>
17 #include <errno.h>
18 #include <assert.h>
19 #include <unistd.h>
20 #include <pwd.h>
21 #include <uuid/uuid.h>
22 #include <bsm/libbsm.h>
23 #include <copyfile.h>
24 #include <AssertMacros.h>
25 #include <Security/Security.h>
26 #include <Security/SecTask.h>
27 #include <Security/SecTaskPriv.h>
28 #include <Security/SecKeychainPriv.h>
29 #include <MobileKeyBag/MobileKeyBag.h>
30
31 #include <IOKit/IOKitLib.h>
32 #include <Kernel/IOKit/crypto/AppleFDEKeyStoreDefs.h>
33
34 #define LOG(...) os_log_debug(OS_LOG_DEFAULT, ##__VA_ARGS__);
35
36 static bool check_signature(xpc_connection_t connection);
37
38 static pid_t get_caller_pid(audit_token_t * token)
39 {
40 pid_t pid = 0;
41 if (token) {
42 audit_token_to_au32(*token, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL);
43 }
44 return pid;
45 }
46
47 // exported from libaks.a
48 kern_return_t aks_register_for_notifications(mach_port_t server_port, uintptr_t message_id);
49 kern_return_t aks_stash_escrow(keybag_handle_t handle, bool create, const void * secret, int secret_len, const void * in_data, int in_data_len, void ** out_data, int * out_data_len);
50
51 const char * kb_home_path = "Library/Keychains";
52 const char * kb_user_bag = "user.kb";
53 const char * kb_stash_bag = "stash.kb";
54
55 #define HEXBUF_LEN 2048
56
57 typedef struct {
58 uid_t uid;
59 gid_t gid;
60 char * name;
61 char * home;
62 } service_user_record_t;
63
64 typedef enum {
65 kb_bag_type_user,
66 kb_bag_type_stash
67 } kb_bag_type_t;
68
69 static io_connect_t
70 openiodev(void)
71 {
72 io_registry_entry_t service;
73 io_connect_t conn;
74 kern_return_t kr;
75
76 service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kAppleFDEKeyStoreServiceName));
77 if (service == IO_OBJECT_NULL)
78 return IO_OBJECT_NULL;
79
80 kr = IOServiceOpen(service, mach_task_self(), 0, &conn);
81 if (kr != KERN_SUCCESS)
82 return IO_OBJECT_NULL;
83
84 kr = IOConnectCallMethod(conn, kAppleFDEKeyStoreUserClientOpen, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL);
85 if (kr != KERN_SUCCESS) {
86 IOServiceClose(conn);
87 return IO_OBJECT_NULL;
88 }
89
90 return conn;
91 }
92
93 static void
94 closeiodev(io_connect_t conn)
95 {
96 kern_return_t kr;
97 kr = IOConnectCallMethod(conn, kAppleFDEKeyStoreUserClientClose, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL);
98 if (kr != KERN_SUCCESS)
99 return;
100 IOServiceClose(conn);
101 }
102
103 static dispatch_queue_t
104 _kb_service_get_dispatch_queue()
105 {
106 static dispatch_once_t onceToken = 0;
107 static dispatch_queue_t connection_queue = NULL;
108
109 dispatch_once(&onceToken, ^{
110 connection_queue = dispatch_queue_create("kb-service-queue", DISPATCH_QUEUE_SERIAL);
111 });
112
113 return connection_queue;
114 }
115
116 static service_user_record_t * get_user_record(uid_t uid)
117 {
118 service_user_record_t * ur = NULL;
119 long bufsize = 0;
120 if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1) {
121 bufsize = 4096;
122 }
123 char buf[bufsize];
124 struct passwd pwbuf, *pw = NULL;
125 int rc;
126 if (((rc = getpwuid_r(uid, &pwbuf, buf, bufsize, &pw)) == 0) && pw != NULL) {
127 ur = calloc(1u, sizeof(service_user_record_t));
128 require(ur, done);
129 ur->uid = pw->pw_uid;
130 ur->gid = pw->pw_gid;
131 ur->home = strdup(pw->pw_dir);
132 ur->name = strdup(pw->pw_name);
133 } else {
134 os_log(OS_LOG_DEFAULT, "failed (%d) to lookup user record for uid: %d", rc, uid);
135 }
136
137 done:
138 return ur;
139 }
140
141 static void free_user_record(service_user_record_t * ur)
142 {
143 if (ur != NULL) {
144 if (ur->home) {
145 free(ur->home);
146 }
147 if (ur->name) {
148 free(ur->name);
149 }
150 free(ur);
151 }
152 }
153
154 static const char * get_host_uuid()
155 {
156 static uuid_string_t hostuuid = {};
157 static dispatch_once_t onceToken;
158 dispatch_once(&onceToken, ^{
159 struct timespec timeout = {30, 0};
160 uuid_t uuid = {};
161 if (gethostuuid(uuid, &timeout) == 0) {
162 uuid_unparse(uuid, hostuuid);
163 } else {
164 os_log(OS_LOG_DEFAULT, "failed to get host uuid");
165 onceToken = 0;
166 }
167 });
168
169 return hostuuid;
170 }
171
172 static char *
173 _kb_copy_bag_filename(service_user_record_t * ur, kb_bag_type_t type)
174 {
175 char * bag_file = NULL;
176 const char * name = NULL;
177
178 require(ur, done);
179 switch(type) {
180 case kb_bag_type_user:
181 name = kb_user_bag;
182 break;
183 case kb_bag_type_stash:
184 name = kb_stash_bag;
185 break;
186 default:
187 goto done;
188 }
189
190 bag_file = calloc(1u, PATH_MAX);
191 require(bag_file, done);
192
193 snprintf(bag_file, PATH_MAX, "%s/%s/%s/%s", ur->home, kb_home_path, get_host_uuid(), name);
194
195 done:
196 return bag_file;
197 }
198
199 static bool
200 _kb_verify_create_path(service_user_record_t * ur)
201 {
202 bool created = false;
203 struct stat st_info = {};
204 char new_path[PATH_MAX] = {};
205 char kb_path[PATH_MAX] = {};
206 snprintf(kb_path, sizeof(kb_path), "%s/%s/%s", ur->home, kb_home_path, get_host_uuid());
207 if (lstat(kb_path, &st_info) == 0) {
208 if (S_ISDIR(st_info.st_mode)) {
209 created = true;
210 } else {
211 os_log(OS_LOG_DEFAULT, "invalid directory at '%s' moving aside", kb_path);
212 snprintf(new_path, sizeof(new_path), "%s-invalid", kb_path);
213 unlink(new_path);
214 if (rename(kb_path, new_path) != 0) {
215 os_log(OS_LOG_DEFAULT, "failed to rename file: %s (%s)", kb_path, strerror(errno));
216 goto done;
217 }
218 }
219 }
220 if (!created) {
221 require_action(mkpath_np(kb_path, 0700) == 0, done, os_log(OS_LOG_DEFAULT, "could not create path: %s (%s)", kb_path, strerror(errno)));
222 created = true;
223 }
224
225 done:
226 if (!created) {
227 os_log(OS_LOG_DEFAULT, "_kb_verify_create_path failed %s", kb_path);
228 }
229 return created;
230 }
231
232 static void
233 _set_thread_credentials(service_user_record_t * ur)
234 {
235 int rc = pthread_setugid_np(ur->uid, ur->gid);
236 if (rc) { os_log(OS_LOG_DEFAULT, "failed to set thread credential: %i (%s)", errno, strerror(errno)); }
237
238 rc = initgroups(ur->name, ur->gid);
239 if (rc) { os_log(OS_LOG_DEFAULT, "failed to initgroups: %i", rc); }
240 }
241
242 static void
243 _clear_thread_credentials()
244 {
245 int rc = pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE);
246 if (rc) { os_log(OS_LOG_DEFAULT, "failed to reset thread credential: %i (%s)", errno, strerror(errno)); }
247 }
248
249 static bool
250 _kb_bag_exists(service_user_record_t * ur, const char * bag_file)
251 {
252 bool exists = false;
253 struct stat st_info = {};
254 char new_file[PATH_MAX] = {};
255
256 require(ur, done);
257
258 _set_thread_credentials(ur);
259 if (lstat(bag_file, &st_info) == 0) {
260 if (S_ISREG(st_info.st_mode)) {
261 exists = true;
262 } else {
263 os_log(OS_LOG_DEFAULT, "invalid file at '%s' moving aside", bag_file);
264 snprintf(new_file, sizeof(new_file), "%s-invalid", bag_file);
265 unlink(new_file);
266 if (rename(bag_file, new_file) != 0) {
267 os_log(OS_LOG_DEFAULT, "failed to rename file: %s (%s)", bag_file, strerror(errno));
268 }
269 }
270 }
271
272 done:
273 _clear_thread_credentials();
274 return exists;
275 }
276
277 static bool
278 _kb_save_bag_to_disk(service_user_record_t * ur, const char * bag_file, void * data, size_t length)
279 {
280 bool result = false;
281 int fd = -1;
282
283 require(bag_file, done);
284
285 _set_thread_credentials(ur);
286 require(_kb_verify_create_path(ur), done);
287
288 fd = open(bag_file, O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW, 0600);
289 require_action(fd != -1, done, os_log(OS_LOG_DEFAULT, "could not create file: %s (%s)", bag_file, strerror(errno)));
290 require_action(write(fd, data, length) == length, done, os_log(OS_LOG_DEFAULT, "failed to write keybag to disk %s (%s)", bag_file, strerror(errno)));
291
292 result = true;
293
294 done:
295 if (fd != -1) { close(fd); }
296 _clear_thread_credentials();
297 return result;
298 }
299
300 static bool
301 _kb_load_bag_from_disk(service_user_record_t * ur, const char * bag_file, uint8_t ** data, size_t * length)
302 {
303 bool result = false;
304 int fd = -1;
305 uint8_t * buf = NULL;
306 size_t buf_size = 0;
307 struct stat st_info = {};
308
309 require(bag_file, done);
310
311 _set_thread_credentials(ur);
312 require(_kb_verify_create_path(ur), done);
313 require_action_quiet(lstat(bag_file, &st_info) == 0, done, os_log(OS_LOG_DEFAULT, "failed to stat file: %s (%s)", bag_file, strerror(errno)));
314 require_action(S_ISREG(st_info.st_mode), done, os_log(OS_LOG_DEFAULT, "failed to load, not a file: %s", bag_file));
315 buf_size = (size_t)st_info.st_size;
316
317 fd = open(bag_file, O_RDONLY | O_NOFOLLOW);
318 require_action(fd != -1, done, os_log(OS_LOG_DEFAULT, "could not open file: %s (%s)", bag_file, strerror(errno)));
319
320 buf = (uint8_t *)calloc(1u, buf_size);
321 require(buf != NULL, done);
322 require(read(fd, buf, buf_size) == buf_size, done);
323
324 *data = buf;
325 *length = buf_size;
326 buf = NULL;
327 result = true;
328
329 done:
330 if (fd != -1) { close(fd); }
331 if (buf) { free(buf); }
332 _clear_thread_credentials();
333 return result;
334 }
335
336 static void
337 _kb_rename_bag_on_disk(service_user_record_t * ur, const char * bag_file)
338 {
339 char new_file[PATH_MAX] = {};
340 if (bag_file) {
341 _set_thread_credentials(ur);
342 snprintf(new_file, sizeof(new_file), "%s-invalid", bag_file);
343 unlink(new_file);
344 rename(bag_file, new_file);
345 _clear_thread_credentials();
346 }
347 }
348
349 static void
350 _kb_delete_bag_on_disk(service_user_record_t * ur, const char * bag_file)
351 {
352 if (bag_file) {
353 _set_thread_credentials(ur);
354 unlink(bag_file);
355 _clear_thread_credentials();
356 }
357 }
358
359 static int service_kb_load(service_context_t *context);
360 static int service_kb_load_uid(uid_t s_uid);
361
362 #ifndef AKS_MACOS_ROOT_HANDLE
363 #define AKS_MACOS_ROOT_HANDLE 4 //temporary define to avoid dependency on AKS change, filed rdar://problem/30542034
364 #endif /* AKS_MACOS_ROOT_HANDLE */
365
366 static int
367 _service_kb_set_system(keybag_handle_t handle, keybag_handle_t special_handle)
368 {
369 //Use reserved root handle for root sessions, since 0 clashes with device_keybag_handle in AKS
370 return aks_set_system(handle, (special_handle == 0) ? AKS_MACOS_ROOT_HANDLE : special_handle);
371 }
372
373 static int
374 _service_kb_get_system(keybag_handle_t special_handle, keybag_handle_t * handle_out)
375 {
376 //Use reserved root handle for root sessions, since 0 clashes with device_keybag_handle in AKS
377 return aks_get_system((special_handle == 0) ? AKS_MACOS_ROOT_HANDLE : special_handle, handle_out);
378 }
379
380 static int
381 _kb_get_session_handle(service_context_t * context, keybag_handle_t * handle_out)
382 {
383 int rc = KB_BagNotLoaded;
384 require_noerr_quiet(_service_kb_get_system(context->s_uid, handle_out), done);
385
386 rc = KB_Success;
387
388 done:
389 if (rc == KB_BagNotLoaded) {
390 if (service_kb_load(context) == KB_Success) {
391 if (_service_kb_get_system(context->s_uid, handle_out) == kIOReturnSuccess) {
392 rc = KB_Success;
393 }
394 }
395 }
396 return rc;
397 }
398
399 static void update_keybag_handle(keybag_handle_t handle)
400 {
401 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
402 uid_t uid = abs(handle);
403 uint8_t * buf = NULL;
404 size_t buf_size = 0;
405 service_user_record_t * ur = NULL;
406 char * bag_file = NULL;
407
408 require_noerr(aks_save_bag(handle, (void**)&buf, (int*)&buf_size), done);
409 require(ur = get_user_record(uid), done);
410 require(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_user), done);
411 require(_kb_save_bag_to_disk(ur, bag_file, buf, buf_size), done);
412
413 os_log(OS_LOG_DEFAULT, "successfully updated handle %d", handle);
414
415 done:
416 if (buf) free(buf);
417 if (ur) free_user_record(ur);
418 if (bag_file) free(bag_file);
419 });
420 }
421
422 static int
423 _kb_get_options_for_uid(uid_t uid, CFMutableDictionaryRef *options_out)
424 {
425 int result = KB_GeneralError;
426 CFMutableDictionaryRef options = NULL;
427 CFNumberRef cf_uid = NULL;
428
429 require(options_out, out);
430
431 require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), out);
432 require(cf_uid = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &uid), out);
433 CFDictionaryAddValue(options, kKeyBagDeviceHandle, cf_uid);
434
435 *options_out = options;
436 options = NULL;
437
438 result = KB_Success;
439 out:
440 if (options) { CFRelease(options); }
441 if (cf_uid) { CFRelease(cf_uid); }
442
443 return result;
444 }
445
446 static int
447 _kb_set_user_uuid(service_context_t * context, const void * secret, int secret_len)
448 {
449 int result = KB_GeneralError;
450 CFMutableDictionaryRef options = NULL;
451 CFDataRef passcode = NULL;
452
453 require_noerr(_kb_get_options_for_uid(context->s_uid, &options), done);
454
455 /* set user uuid, if not already set */
456 passcode = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, secret, secret_len, kCFAllocatorNull);
457 MKBKeyBagSetUserUUID(options, passcode);
458
459 result = KB_Success;
460 done:
461 if (options) { CFRelease(options); }
462 if (passcode) { CFRelease(passcode); }
463 return result;
464 }
465
466 static int
467 service_kb_create(service_context_t * context, const void * secret, int secret_len)
468 {
469 __block int rc = KB_GeneralError;
470
471 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
472 uint8_t * buf = NULL;
473 size_t buf_size = 0;
474 keybag_handle_t private_handle = bad_keybag_handle, session_handle = bad_keybag_handle;
475 service_user_record_t * ur = get_user_record(context->s_uid);
476 char * bag_file = _kb_copy_bag_filename(ur, kb_bag_type_user);
477
478 require(bag_file, done);
479
480 // check for the existance of the bagfile
481 require_action(!_kb_bag_exists(ur, bag_file), done, rc = KB_BagExists);
482
483 require_noerr(rc = aks_create_bag(secret, secret_len, kAppleKeyStoreDeviceBag, &private_handle), done);
484 require_noerr(rc = aks_save_bag(private_handle, (void**)&buf, (int*)&buf_size), done);
485 require_action(_kb_save_bag_to_disk(ur, bag_file, buf, buf_size), done, rc = KB_BagError);
486 require_noerr(rc = _service_kb_set_system(private_handle, context->s_uid), done);
487 require_noerr(rc = _kb_get_session_handle(context, &session_handle), done);
488
489 if (secret && rc == KB_Success) {
490 aks_unlock_bag(session_handle, secret, secret_len);
491 }
492
493 if (rc == KB_Success) {
494 _kb_set_user_uuid(context, secret, secret_len);
495 }
496
497 done:
498 if (private_handle != bad_keybag_handle) {
499 aks_unload_bag(private_handle);
500 }
501 if (buf) free(buf);
502 if (bag_file) { free(bag_file); }
503 if (ur) free_user_record(ur);
504 });
505
506 return rc;
507 }
508
509 /* Load s_uid's keybag, unless already loaded */
510 static int
511 _service_kb_load_uid(uid_t s_uid)
512 {
513 __block int rc = KB_GeneralError;
514
515 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
516 uint8_t * buf = NULL;
517 size_t buf_size = 0;
518 keybag_handle_t private_handle = bad_keybag_handle, session_handle = bad_keybag_handle;
519 service_user_record_t * ur = NULL;
520 char * bag_file = NULL;
521 int _stage = 0;
522
523 rc = _service_kb_get_system(s_uid, &session_handle);
524 if (rc == kIOReturnNotFound) {
525 require_action(ur = get_user_record(s_uid), done, rc = KB_GeneralError; _stage = 1);
526 require_action(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_user), done, rc = KB_GeneralError; _stage = 2);
527 require_action_quiet(_kb_load_bag_from_disk(ur, bag_file, &buf, &buf_size), done, rc = KB_BagNotFound; _stage = 3);
528 rc = aks_load_bag(buf, (int)buf_size, &private_handle);
529 if (rc == kIOReturnNotPermitted || rc == kAKSReturnBadDeviceKey) {
530 os_log(OS_LOG_DEFAULT, "bag load failed %d for uid (%i)", rc, s_uid);
531 _kb_rename_bag_on_disk(ur, bag_file);
532 rc = KB_BagNotFound;
533 }
534 require_noerr(rc, done; _stage = 4);
535 require_noerr(rc = _service_kb_set_system(private_handle, s_uid), done; _stage = 5);
536 }
537 require(rc == KB_Success, done);
538
539 done:
540 if (private_handle != bad_keybag_handle) {
541 aks_unload_bag(private_handle);
542 }
543 // this function should never fail unless bootstrapping the user for the first time, or rare conditions from aks_load_bag
544 if (rc != KB_Success) {
545 os_log(OS_LOG_DEFAULT, "%d: error %d loading keybag for uid (%i) at path: %s", _stage, rc, s_uid, bag_file);
546 }
547 if (buf) free(buf);
548 if (ur) free_user_record(ur);
549 if (bag_file) free(bag_file);
550 });
551
552 return rc;
553 }
554
555 static int
556 service_kb_load_uid(uid_t s_uid)
557 {
558 return _service_kb_load_uid(s_uid);
559 }
560
561 static int
562 service_kb_load(service_context_t * context)
563 {
564 return _service_kb_load_uid(context->s_uid);
565 }
566
567 static int
568 service_kb_unload(service_context_t *context)
569 {
570 __block int rc = KB_GeneralError;
571
572 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
573 keybag_handle_t session_handle = bad_keybag_handle;
574
575 rc = _service_kb_get_system(context->s_uid, &session_handle);
576 if (rc == kIOReturnNotFound) {
577 // No session bag, nothing to do
578 rc = KB_Success;
579 return;
580 } else if (rc != kIOReturnSuccess) {
581 os_log(OS_LOG_DEFAULT, "error locating session keybag for uid (%i) in session (%i)", context->s_uid, context->s_id);
582 rc = KB_BagError;
583 return;
584 }
585
586 rc = aks_unload_bag(session_handle);
587 if (rc != kAKSReturnSuccess) {
588 os_log(OS_LOG_DEFAULT, "error unloading keybag for uid (%i) in session (%i)", context->s_uid, context->s_id);
589 rc = KB_BagError;
590 } else {
591 os_log(OS_LOG_DEFAULT, "successfully unloaded keybag (%ld) for uid (%i) in session (%i)", (long)session_handle, context->s_uid, context->s_id);
592 }
593 });
594
595 return rc;
596 }
597
598 static int
599 service_kb_save(service_context_t * context)
600 {
601 __block int rc = KB_GeneralError;
602 keybag_handle_t session_handle;
603 require_noerr(rc = _kb_get_session_handle(context, &session_handle), done);
604
605 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
606 uint8_t * buf = NULL;
607 size_t buf_size = 0;
608 service_user_record_t * ur = NULL;
609 char * bag_file = NULL;
610
611 require_noerr(rc = aks_save_bag(session_handle, (void**)&buf, (int*)&buf_size), done);
612 require_action(ur = get_user_record(context->s_uid), done, rc = KB_GeneralError);
613 require_action(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_user), done, rc = KB_GeneralError);
614 require_action(_kb_save_bag_to_disk(ur, bag_file, buf, buf_size), done, rc = KB_BagError);
615
616 rc = KB_Success;
617
618 done:
619 if (buf) free(buf);
620 if (ur) free_user_record(ur);
621 if (bag_file) free(bag_file);
622 return;
623 });
624
625 done:
626 return rc;
627 }
628
629 static int
630 service_kb_unlock(service_context_t * context, const void * secret, int secret_len)
631 {
632 int rc = KB_GeneralError;
633 keybag_handle_t session_handle;
634 CFDataRef passcode = NULL;
635 CFMutableDictionaryRef options = NULL;
636
637 require_noerr(_kb_get_options_for_uid(context->s_uid, &options), done);
638
639 /* technically, session_handle is not needed. Call this to handle lazy keybag loading */
640 require_noerr(rc = _kb_get_session_handle(context, &session_handle), done);
641
642 require(passcode = CFDataCreateWithBytesNoCopy(NULL, secret, secret_len, kCFAllocatorNull), done);
643
644 rc = MKBUnlockDevice(passcode, options);
645 os_log(OS_LOG_DEFAULT, "MKBUnlockDevice result: (%ld)", (long)rc);
646
647 done:
648 if (options) { CFRelease(options); }
649 if (passcode) { CFRelease(passcode); }
650 return rc;
651 }
652
653 static int
654 service_kb_lock(service_context_t * context)
655 {
656 // this call has been disabled
657 return -1;
658 }
659
660 static int
661 service_kb_change_secret(service_context_t * context, const void * secret, int secret_len, const void * new_secret, int new_secret_len)
662 {
663 __block int rc = KB_GeneralError;
664 keybag_handle_t session_handle;
665 require_noerr(rc = _kb_get_session_handle(context, &session_handle), done);
666
667 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
668 uint8_t * buf = NULL;
669 size_t buf_size = 0;
670 service_user_record_t * ur = NULL;
671 char * bag_file = NULL;
672
673 require_noerr(rc = aks_change_secret(session_handle, secret, secret_len, new_secret, new_secret_len, generation_noop, NULL), done);
674 require_noerr(rc = aks_save_bag(session_handle, (void**)&buf, (int*)&buf_size), done);
675 require_action(ur = get_user_record(context->s_uid), done, rc = KB_GeneralError);
676 require_action(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_user), done, rc = KB_GeneralError);
677 require_action(_kb_save_bag_to_disk(ur, bag_file, buf, buf_size), done, rc = KB_BagError);
678
679 rc = KB_Success;
680
681 done:
682 if (buf) free(buf);
683 if (ur) free_user_record(ur);
684 if (bag_file) free(bag_file);
685 return;
686 });
687
688 done:
689 return rc;
690 }
691
692 static int
693 service_kb_reset(service_context_t * context, const void * secret, int secret_len)
694 {
695 __block int rc = KB_GeneralError;
696 service_user_record_t * ur = NULL;
697 char * bag_file = NULL;
698
699 require_action(ur = get_user_record(context->s_uid), done, rc = KB_GeneralError);
700 require_action(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_user), done, rc = KB_GeneralError);
701
702 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
703 uint8_t * buf = NULL;
704 size_t buf_size = 0;
705 keybag_handle_t private_handle = bad_keybag_handle, session_handle = bad_keybag_handle;
706
707 os_log(OS_LOG_DEFAULT, "resetting keybag for uid (%i) in session (%i)", context->s_uid, context->s_id);
708 _kb_rename_bag_on_disk(ur, bag_file);
709
710 require_noerr(rc = aks_create_bag(secret, secret_len, kAppleKeyStoreDeviceBag, &private_handle), done);
711 require_noerr(rc = aks_save_bag(private_handle, (void**)&buf, (int*)&buf_size), done);
712 require_action(_kb_save_bag_to_disk(ur, bag_file, buf, buf_size), done, rc = KB_BagError);
713 require_noerr(rc = _service_kb_set_system(private_handle, context->s_uid), done);
714 require_noerr(rc = _kb_get_session_handle(context, &session_handle), done);
715
716 if (secret && rc == KB_Success) {
717 aks_unlock_bag(session_handle, secret, secret_len);
718 }
719
720 if (rc == KB_Success) {
721 _kb_set_user_uuid(context, secret, secret_len);
722 }
723
724 done:
725 if (private_handle != bad_keybag_handle) {
726 aks_unload_bag(private_handle);
727 }
728 if (buf) free(buf);
729 return;
730 });
731
732 done:
733 if (ur) free_user_record(ur);
734 if (bag_file) free(bag_file);
735 return rc;
736 }
737
738 static int
739 service_kb_is_locked(service_context_t * context, xpc_object_t reply)
740 {
741 int rc = KB_GeneralError;
742 keybag_state_t state;
743 keybag_handle_t session_handle;
744 require_noerr(rc = _kb_get_session_handle(context, &session_handle), done);
745
746 require_noerr(rc = aks_get_lock_state(session_handle, &state), done);
747
748 xpc_dictionary_set_bool(reply, SERVICE_XPC_LOCKED, state & keybag_state_locked);
749 xpc_dictionary_set_bool(reply, SERVICE_XPC_NO_PIN, state & keybag_state_no_pin);
750
751 done:
752 return rc;
753 }
754
755 static int
756 service_kb_wrap_key(service_context_t *context, xpc_object_t event, xpc_object_t reply)
757 {
758 int rc = KB_GeneralError;
759 size_t sz;
760 const void *key;
761 int key_size;
762 keyclass_t key_class;
763 keybag_handle_t session_handle;
764 void *wrapped_key = NULL;
765 int wrapped_key_size;
766 keyclass_t wrapped_key_class;
767
768 require_noerr(rc = _kb_get_session_handle(context, &session_handle), done);
769
770 key = xpc_dictionary_get_data(event, SERVICE_XPC_KEY, &sz);
771 require_action(key != NULL, done, rc = KB_GeneralError);
772 require_action(sz <= APPLE_KEYSTORE_MAX_KEY_LEN, done, rc = KB_GeneralError);
773 key_size = (int)sz;
774 key_class = (keyclass_t)xpc_dictionary_get_int64(event, SERVICE_XPC_KEYCLASS);
775
776 wrapped_key_size = APPLE_KEYSTORE_MAX_ASYM_WRAPPED_KEY_LEN;
777 wrapped_key = calloc(1, wrapped_key_size);
778
779 rc = aks_wrap_key(key, key_size, key_class, session_handle, wrapped_key, &wrapped_key_size, &wrapped_key_class);
780 if (rc == KB_Success) {
781 xpc_dictionary_set_data(reply, SERVICE_XPC_WRAPPED_KEY, wrapped_key, wrapped_key_size);
782 xpc_dictionary_set_int64(reply, SERVICE_XPC_KEYCLASS, wrapped_key_class);
783 }
784
785 done:
786 free(wrapped_key);
787 return rc;
788 }
789
790 static int
791 service_kb_unwrap_key(service_context_t *context, xpc_object_t event, xpc_object_t reply)
792 {
793 int rc = KB_GeneralError;
794 size_t sz;
795 const void *wrapped_key;
796 int wrapped_key_size;
797 keyclass_t wrapped_key_class;
798 keybag_handle_t session_handle;
799 void *key = NULL;
800 int key_size;
801
802 require_noerr(rc = _kb_get_session_handle(context, &session_handle), done);
803
804 wrapped_key = xpc_dictionary_get_data(event, SERVICE_XPC_WRAPPED_KEY, &sz);
805 require_action(wrapped_key != NULL, done, rc = KB_GeneralError);
806 require_action(sz <= APPLE_KEYSTORE_MAX_ASYM_WRAPPED_KEY_LEN, done, rc = KB_GeneralError);
807 wrapped_key_size = (int)sz;
808 wrapped_key_class = (keyclass_t)xpc_dictionary_get_int64(event, SERVICE_XPC_KEYCLASS);
809
810 key_size = APPLE_KEYSTORE_MAX_KEY_LEN;
811 key = calloc(1, key_size);
812
813 rc = aks_unwrap_key(wrapped_key, wrapped_key_size, wrapped_key_class, session_handle, key, &key_size);
814 if (rc == KB_Success) {
815 xpc_dictionary_set_data(reply, SERVICE_XPC_KEY, key, key_size);
816 }
817
818 done:
819 free(key);
820 return rc;
821 }
822
823 static int
824 service_kb_stash_create(service_context_t * context, const void * key, unsigned key_size)
825 {
826 int rc = KB_GeneralError;
827 char * bag_file = NULL;
828 keybag_handle_t session_handle;
829 service_user_record_t * ur = NULL;
830 void * stashbag = NULL;
831 int stashbag_size = 0;
832 __block bool saved = false;
833
834 require(key, done);
835 require_noerr(rc = _kb_get_session_handle(context, &session_handle), done);
836 require_action(ur = get_user_record(context->s_uid), done, rc = KB_GeneralError);
837 require_noerr(rc = aks_stash_escrow(session_handle, true, key, key_size, NULL, 0, (void**)&stashbag, &stashbag_size), done);
838 require_action(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_stash), done, rc = KB_GeneralError);
839
840 // sync writing the bag to disk
841 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
842 saved = _kb_save_bag_to_disk(ur, bag_file, stashbag, stashbag_size);
843 });
844 require_action(saved, done, rc = KB_BagError);
845 rc = KB_Success;
846
847 done:
848 if (stashbag) { free(stashbag); }
849 if (bag_file) { free(bag_file); }
850 if (ur) free_user_record(ur);
851 return rc;
852 }
853
854 static int
855 service_kb_stash_load(service_context_t * context, const void * key, unsigned key_size, bool nondestructive)
856 {
857 __block int rc = KB_GeneralError;
858 char * bag_file = NULL;
859 keybag_handle_t session_handle;
860 service_user_record_t * ur = NULL;
861 __block uint8_t * stashbag = NULL;
862 __block size_t stashbag_size = 0;
863
864 require(key, done);
865 require_noerr(rc = _kb_get_session_handle(context, &session_handle), done);
866 require_action(ur = get_user_record(context->s_uid), done, rc = KB_GeneralError);
867 require_action(bag_file = _kb_copy_bag_filename(ur, kb_bag_type_stash), done, rc = KB_GeneralError);
868
869 // sync loading the bag from disk
870 dispatch_sync(_kb_service_get_dispatch_queue(), ^{
871 if (!_kb_load_bag_from_disk(ur, bag_file, &stashbag, &stashbag_size)) {
872 rc = KB_BagError;
873 }
874 });
875 require_noerr(rc, done);
876
877 require_noerr(rc = aks_stash_escrow(session_handle, false, key, key_size, stashbag, (int)stashbag_size, NULL, NULL), done);
878 rc = KB_Success;
879
880 done:
881 if (stashbag) { free(stashbag); }
882 if ((bag_file) && (!nondestructive)) {
883 _kb_delete_bag_on_disk(ur, bag_file);
884 free(bag_file);
885 }
886 if (ur) free_user_record(ur);
887 return rc;
888 }
889
890 //
891 // Get the keychain master key from the AppleFDEKeyStore.
892 // Note that this is a one-time call - the master key is
893 // removed from the keystore after it is returned.
894 // Requires the entitlement: com.apple.private.securityd.keychain
895 //
896 OSStatus service_stash_get_key(service_context_t * context, xpc_object_t event, xpc_object_t reply)
897 {
898 getStashKey_InStruct_t inStruct;
899 getStashKey_OutStruct_t outStruct;
900 size_t outSize = sizeof(outStruct);
901 kern_return_t kr = KERN_INVALID_ARGUMENT;
902
903 io_connect_t conn = openiodev();
904 require(conn, done);
905 inStruct.type = kAppleFDEKeyStoreStash_master;
906
907 kr = IOConnectCallMethod(conn, kAppleFDEKeyStore_getStashKey,
908 NULL, 0,
909 &inStruct, sizeof(inStruct),
910 NULL, NULL,
911 &outStruct, &outSize);
912
913 if (kr == KERN_SUCCESS) {
914 xpc_dictionary_set_data(reply, SERVICE_XPC_KEY, outStruct.outBuf.key.key, outStruct.outBuf.key.keysize);
915 service_kb_stash_load(context, outStruct.outBuf.key.key, outStruct.outBuf.key.keysize, false);
916 } else {
917 os_log(OS_LOG_DEFAULT, "failed to get stash key: %d", (int)kr);
918 }
919
920 done:
921 if (conn)
922 closeiodev(conn);
923
924 return kr;
925 }
926
927 //
928 // Stash the keychain master key in the AppleFDEKeyStore and
929 // flag it as the keychain master key to be added to the
930 // reboot NVRAM blob.
931 // This requires two calls to the AKS: the first to store the
932 // key and get its uuid. The second uses the uuid to flag the
933 // key for blob inclusion.
934 //
935 OSStatus service_stash_set_key(service_context_t * context, xpc_object_t event, xpc_object_t reply)
936 {
937 kern_return_t kr = KERN_INVALID_ARGUMENT;
938 io_connect_t conn = IO_OBJECT_NULL;
939 size_t keydata_len = 0;
940 size_t len;
941
942 keybag_state_t state;
943 keybag_handle_t session_handle;
944 require_noerr(_kb_get_session_handle(context, &session_handle), done);
945 require_noerr(aks_get_lock_state(session_handle, &state), done);
946 require_action(!(state & keybag_lock_locked), done, kr = CSSMERR_CSP_OS_ACCESS_DENIED; LOG("stash failed keybag locked"));
947
948 conn = openiodev();
949 require(conn, done);
950
951 // Store the key in the keystore and get its uuid
952 setKeyGetUUID_InStruct_t inStruct1;
953 uuid_OutStruct_t outStruct1;
954
955
956 const uint8_t *keydata = xpc_dictionary_get_data(event, SERVICE_XPC_KEY, &keydata_len);
957 require(keydata, done);
958
959 memcpy(&inStruct1.inKey.key.key, keydata, keydata_len);
960 inStruct1.inKey.key.keysize = (cryptosize_t) keydata_len;
961 len = sizeof(outStruct1);
962 kr = IOConnectCallMethod(conn, kAppleFDEKeyStore_setKeyGetUUID,
963 NULL, 0,
964 &inStruct1, sizeof(inStruct1),
965 NULL, NULL,
966 &outStruct1, &len);
967 require(kr == KERN_SUCCESS, done);
968
969 // Now using the uuid stash it as the master key
970 setStashKey_InStruct_t inStruct2;
971 memcpy(&inStruct2.uuid, &outStruct1.uuid, sizeof(outStruct1.uuid));
972 inStruct2.type = kAppleFDEKeyStoreStash_master;
973
974 kr = IOConnectCallMethod(conn, kAppleFDEKeyStore_setStashKey,
975 NULL, 0,
976 &inStruct2, sizeof(inStruct2),
977 NULL, NULL,
978 NULL, NULL);
979
980 if (kr == KERN_SUCCESS) {
981 service_kb_stash_create(context, keydata, (unsigned)keydata_len);
982 }
983 done:
984 os_log(OS_LOG_DEFAULT, "set stashkey %d", (int)kr);
985
986 if (conn)
987 closeiodev(conn);
988
989 return kr;
990 }
991
992 //
993 // Load the master stash key
994 //
995 OSStatus service_stash_load_key(service_context_t * context, xpc_object_t event, xpc_object_t reply)
996 {
997 kern_return_t kr = KERN_SUCCESS;
998 size_t keydata_len = 0;
999
1000 const uint8_t *keydata = xpc_dictionary_get_data(event, SERVICE_XPC_KEY, &keydata_len);
1001 require(keydata, done);
1002
1003 kr = service_kb_stash_load(context, keydata, (cryptosize_t) keydata_len, true);
1004 done:
1005
1006 return kr;
1007 }
1008
1009 //
1010 // Signal the AppleFDEKeyStore to take the tagged FDE key
1011 // and keychain master key, stash them in an encrypted
1012 // blob structure and write the blob to NVRAM. The random
1013 // encryption key is written to the SMC.
1014 //
1015 #if DEBUG
1016 OSStatus service_stash_blob(xpc_object_t event, xpc_object_t reply)
1017 {
1018 kern_return_t kr = KERN_INVALID_ARGUMENT;
1019
1020 io_connect_t conn = openiodev();
1021 require(conn, done);
1022
1023 kr = IOConnectCallMethod(conn, kAppleFDEKeyStore_commitStash,
1024 NULL, 0,
1025 NULL, 0,
1026 NULL, NULL,
1027 NULL, NULL);
1028 done:
1029 if (conn)
1030 closeiodev(conn);
1031
1032 return kr;
1033 }
1034 #endif
1035
1036 bool peer_has_entitlement(xpc_connection_t peer, const char * entitlement)
1037 {
1038 bool entitled = false;
1039
1040 xpc_object_t value = xpc_connection_copy_entitlement_value(peer, entitlement);
1041 if (value && (xpc_get_type(value) == XPC_TYPE_BOOL)) {
1042 entitled = xpc_bool_get_value(value);
1043 }
1044
1045 if (value) xpc_release(value);
1046 return entitled;
1047 }
1048
1049 static char * sel_to_char(uint64_t sel)
1050 {
1051 switch (sel) {
1052 case SERVICE_STASH_SET_KEY:
1053 return "set_key";
1054 case SERVICE_STASH_GET_KEY:
1055 return "get_key";
1056 case SERVICE_STASH_BLOB:
1057 return "stash_blob";
1058 case SERVICE_KB_LOAD:
1059 return "kb_load";
1060 case SERVICE_KB_SAVE:
1061 return "kb_save";
1062 case SERVICE_KB_UNLOCK:
1063 return "kb_unlock";
1064 case SERVICE_KB_LOCK:
1065 return "kb_lock";
1066 case SERVICE_KB_CHANGE_SECRET:
1067 return "kb_change_secret";
1068 case SERVICE_KB_CREATE:
1069 return "kb_create";
1070 case SERVICE_KB_IS_LOCKED:
1071 return "kb_is_locked";
1072 case SERVICE_KB_RESET:
1073 return "kb_reset";
1074 case SERVICE_KB_UNLOAD:
1075 return "kb_unload";
1076 case SERVICE_KB_LOAD_UID:
1077 return "kb_load_uid";
1078 case SERVICE_KB_WRAP_KEY:
1079 return "kb_wrap_key";
1080 case SERVICE_KB_UNWRAP_KEY:
1081 return "kb_unwrap_key";
1082 default:
1083 return "unknown";
1084 }
1085 }
1086
1087 static char * err_to_char(int err)
1088 {
1089 switch (err) {
1090 case KB_Success:
1091 return "success";
1092 case KB_GeneralError:
1093 return "general error";
1094 case KB_BagNotFound:
1095 return "bag not found";
1096 case KB_BagError:
1097 return "bag error";
1098 case KB_BagNotLoaded:
1099 return "bag not loaded";
1100 case KB_BagExists:
1101 return "bag exists";
1102 case KB_InvalidSession:
1103 return "invalid session";
1104 default:
1105 return "";
1106 }
1107 }
1108
1109 void service_peer_event_handler(xpc_connection_t connection, xpc_object_t event)
1110 {
1111 xpc_type_t type = xpc_get_type(event);
1112 uid_t uid;
1113
1114 if (type == XPC_TYPE_ERROR) {
1115 if (event == XPC_ERROR_CONNECTION_INVALID) {
1116 }
1117 } else {
1118 assert(type == XPC_TYPE_DICTIONARY);
1119
1120 int rc = KB_GeneralError;
1121 uint64_t request = 0;
1122 const uint8_t * secret = NULL, * new_secret = NULL;
1123 size_t secret_len = 0, new_secret_len = 0, data_len = 0;
1124 service_context_t * context = NULL;
1125 bool free_context = false;
1126 const void * data;
1127 const char *entitlement;
1128
1129 xpc_object_t reply = xpc_dictionary_create_reply(event);
1130
1131 request = xpc_dictionary_get_uint64(event, SERVICE_XPC_REQUEST);
1132
1133
1134 // For SERVICE_KB_{UNLOAD,LOAD} only, allow non-securityd, non-root but
1135 // entitled callers.
1136 if (request == SERVICE_KB_UNLOAD || request == SERVICE_KB_LOAD_UID) {
1137 switch (request) {
1138 case SERVICE_KB_UNLOAD:
1139 entitlement = "com.apple.private.securityd.keybag-unload";
1140 break;
1141 case SERVICE_KB_LOAD_UID:
1142 entitlement = "com.apple.private.securityd.keybag-load";
1143 break;
1144 }
1145 if (!peer_has_entitlement(connection, entitlement) && !peer_has_entitlement(connection, "com.apple.keystore.device")) {
1146 xpc_connection_cancel(connection);
1147 return;
1148 }
1149 } else {
1150 if (xpc_connection_get_euid(connection) != 0) {
1151 xpc_connection_cancel(connection);
1152 return;
1153 }
1154 if (!check_signature(connection)) {
1155 xpc_connection_cancel(connection);
1156 return;
1157 }
1158 }
1159
1160 data = xpc_dictionary_get_data(event, SERVICE_XPC_CONTEXT, &data_len);
1161 require_action(data || request == SERVICE_KB_UNLOAD || request == SERVICE_KB_LOAD_UID, done, rc = KB_GeneralError);
1162 if (data) {
1163 require(data_len == sizeof(service_context_t), done);
1164 context = (service_context_t*)data;
1165 } else {
1166 audit_token_t audit_token = { 0 };
1167 xpc_connection_get_audit_token(connection, &audit_token);
1168 context = calloc(1, sizeof(service_context_t));
1169 context->s_id = xpc_connection_get_asid(connection);
1170 context->s_uid = xpc_connection_get_euid(connection);
1171 context->procToken = audit_token;
1172 free_context = true;
1173 }
1174
1175 require_action(context->s_id != AU_DEFAUDITSID, done, rc = KB_InvalidSession);
1176 require_action(context->s_uid != AU_DEFAUDITID, done, rc = KB_InvalidSession); // we only want to work in actual user sessions.
1177
1178 switch (request) {
1179 case SERVICE_KB_CREATE:
1180 // if (kb_service_has_entitlement(peer, "com.apple.keystore.device")) {
1181 secret = xpc_dictionary_get_data(event, SERVICE_XPC_SECRET, &secret_len);
1182 rc = service_kb_create(context, secret, (int)secret_len);
1183 // }
1184 break;
1185 case SERVICE_KB_LOAD:
1186 rc = service_kb_load(context);
1187 break;
1188 case SERVICE_KB_UNLOAD:
1189 rc = service_kb_unload(context);
1190 break;
1191 case SERVICE_KB_SAVE:
1192 rc = service_kb_save(context);
1193 break;
1194 case SERVICE_KB_UNLOCK:
1195 secret = xpc_dictionary_get_data(event, SERVICE_XPC_SECRET, &secret_len);
1196 rc = service_kb_unlock(context, secret, (int)secret_len);
1197 break;
1198 case SERVICE_KB_LOCK:
1199 rc = service_kb_lock(context);
1200 break;
1201 case SERVICE_KB_CHANGE_SECRET:
1202 secret = xpc_dictionary_get_data(event, SERVICE_XPC_SECRET, &secret_len);
1203 new_secret = xpc_dictionary_get_data(event, SERVICE_XPC_SECRET_NEW, &new_secret_len);
1204 rc = service_kb_change_secret(context, secret, (int)secret_len, new_secret, (int)new_secret_len);
1205 break;
1206 case SERVICE_KB_RESET:
1207 secret = xpc_dictionary_get_data(event, SERVICE_XPC_SECRET, &secret_len);
1208 rc = service_kb_reset(context, secret, (int)secret_len);
1209 break;
1210 case SERVICE_KB_IS_LOCKED:
1211 rc = service_kb_is_locked(context, reply);
1212 break;
1213 case SERVICE_STASH_GET_KEY:
1214 rc = service_stash_get_key(context, event, reply);
1215 break;
1216 case SERVICE_STASH_SET_KEY:
1217 rc = service_stash_set_key(context, event, reply);
1218 break;
1219 case SERVICE_STASH_LOAD_KEY:
1220 rc = service_stash_load_key(context, event, reply);
1221 break;
1222 case SERVICE_KB_LOAD_UID:
1223 uid = (uid_t)xpc_dictionary_get_uint64(event, SERVICE_XPC_UID);
1224 rc = service_kb_load_uid(uid);
1225 break;
1226 case SERVICE_KB_WRAP_KEY:
1227 rc = service_kb_wrap_key(context, event, reply);
1228 break;
1229 case SERVICE_KB_UNWRAP_KEY:
1230 rc = service_kb_unwrap_key(context, event, reply);
1231 break;
1232 #if DEBUG
1233 case SERVICE_STASH_BLOB:
1234 rc = service_stash_blob(event, reply);
1235 break;
1236 #endif
1237 default:
1238 LOG("unknown service type");
1239 break;
1240 }
1241
1242 done:
1243 #if DEBUG
1244 LOG("selector: %s (%llu), error: %s (%x), sid: %d, suid: %d, pid: %d", sel_to_char(request), request, err_to_char(rc), rc, context ? context->s_id : 0, context ? context->s_uid : 0, context ? get_caller_pid(&context->procToken) : 0);
1245 #else
1246 if (rc != 0) {
1247 os_log(OS_LOG_DEFAULT, "selector: %s (%llu), error: %s (%x), sid: %d, suid: %d, pid: %d", sel_to_char(request), request, err_to_char(rc), rc, context ? context->s_id : 0, context ? context->s_uid : 0, context ? get_caller_pid(&context->procToken) : 0);
1248 }
1249 #endif
1250 xpc_dictionary_set_int64(reply, SERVICE_XPC_RC, rc);
1251 xpc_connection_send_message(connection, reply);
1252 xpc_release(reply);
1253 if (free_context) {
1254 free(context);
1255 }
1256 }
1257 }
1258
1259 bool check_signature(xpc_connection_t connection)
1260 {
1261 #if !(DEBUG || RC_BUILDIT_YES)
1262 audit_token_t token;
1263
1264 xpc_connection_get_audit_token(connection, &token);
1265
1266 SecTaskRef task = SecTaskCreateWithAuditToken(NULL, token);
1267 if (task == NULL) {
1268 os_log(OS_LOG_DEFAULT, "failed getting SecTaskRef of the client");
1269 return false;
1270 }
1271
1272 uint32_t flags = SecTaskGetCodeSignStatus(task);
1273 /* check if valid and platform binary, but not platform path */
1274 if ((flags & (CS_VALID | CS_PLATFORM_BINARY | CS_PLATFORM_PATH)) != (CS_VALID | CS_PLATFORM_BINARY)) {
1275 os_log(OS_LOG_DEFAULT, "client is not a platform binary: %0x08x", flags);
1276 CFRelease(task);
1277 return false;
1278 }
1279
1280 CFStringRef signingIdentity = SecTaskCopySigningIdentifier(task, NULL);
1281 CFRelease(task);
1282 if (signingIdentity == NULL) {
1283 os_log(OS_LOG_DEFAULT, "client have no code sign identity");
1284 return false;
1285 }
1286
1287 bool res = CFEqual(signingIdentity, CFSTR("com.apple.securityd"));
1288 CFRelease(signingIdentity);
1289
1290 if (!res)
1291 os_log(OS_LOG_DEFAULT, "client is not not securityd");
1292
1293 return res;
1294 #else
1295 return true;
1296 #endif
1297 }
1298
1299 static void register_for_notifications()
1300 {
1301 __block kern_return_t kr;
1302 static mach_port_t mp = MACH_PORT_NULL;
1303
1304 static dispatch_once_t onceToken = 0;
1305 dispatch_once(&onceToken, ^{
1306 kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &mp);
1307 if (kr == KERN_SUCCESS) {
1308 dispatch_source_t mach_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, mp, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
1309 dispatch_source_set_event_handler(mach_src, ^{
1310 mach_msg_return_t mr;
1311 uint8_t buf[sizeof(aks_notification_msg_t) + MAX_TRAILER_SIZE] = {};
1312 aks_notification_msg_t * msg = (aks_notification_msg_t*)buf;
1313 mr = mach_msg((mach_msg_header_t*)&buf, MACH_RCV_MSG, 0, sizeof(buf), mp, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
1314 if (mr == MACH_MSG_SUCCESS && msg->hdr.msgh_id == AKS_NOTIFICATION_MSGID) {
1315 // ignored for now
1316 } else if (mr == MACH_MSG_SUCCESS && msg->hdr.msgh_id == AKS_NOTIFICATION_WRITE_SYSTEM_KEYBAG) {
1317 os_log(OS_LOG_DEFAULT, "request to update handle %d", msg->handle);
1318 update_keybag_handle(msg->handle);
1319 } else {
1320 os_log(OS_LOG_DEFAULT, "mach_msg error: %x", mr);
1321 }
1322 });
1323 dispatch_resume(mach_src);
1324 } else {
1325 os_log(OS_LOG_DEFAULT, "failed to create notification port");
1326 }
1327
1328 });
1329
1330 kr = aks_register_for_notifications(mp, AKS_NOTIFICATION_WRITE_SYSTEM_KEYBAG);
1331 if (kr == KERN_SUCCESS) {
1332 os_log(OS_LOG_DEFAULT, "registered for notifications");
1333 } else {
1334 os_log(OS_LOG_DEFAULT, "failed to register for notifications %d", kr);
1335 }
1336 }
1337
1338 int main(int argc, const char * argv[])
1339 {
1340 char * errorbuf;
1341 if (sandbox_init(SECURITYD_SERVICE_NAME, SANDBOX_NAMED, &errorbuf) != 0) {
1342 os_log(OS_LOG_DEFAULT, "sandbox_init failed %s", errorbuf);
1343 sandbox_free_error(errorbuf);
1344 #ifndef DEBUG
1345 abort();
1346 #endif
1347 }
1348
1349 register_for_notifications();
1350
1351 xpc_connection_t listener = xpc_connection_create_mach_service(SECURITYD_SERVICE_NAME, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
1352 xpc_connection_set_event_handler(listener, ^(xpc_object_t peer) {
1353 // It is safe to cast 'peer' to xpc_connection_t assuming
1354 // we have a correct configuration in our launchd.plist.
1355 xpc_connection_set_event_handler(peer, ^(xpc_object_t event) {
1356 vproc_transaction_t transaction = vproc_transaction_begin(NULL);
1357 service_peer_event_handler(peer, event);
1358 vproc_transaction_end(NULL, transaction);
1359 });
1360 xpc_connection_resume(peer);
1361 });
1362 xpc_connection_resume(listener);
1363
1364 dispatch_main();
1365 }
1366