]> git.saurik.com Git - apple/security.git/blob - OSX/sec/ipc/server.c
796da15ba03ad247bf5df40f3be863782f48e997
[apple/security.git] / OSX / sec / ipc / server.c
1 /*
2 * Copyright (c) 2007-2015 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <Security/SecureObjectSync/SOSPeerInfoDER.h>
25 #include <Security/SecureObjectSync/SOSCloudCircle.h>
26 #include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
27 #include <Security/SecureObjectSync/SOSInternal.h>
28 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
29 #include <Security/SecBasePriv.h>
30 #include <Security/SecCertificatePriv.h>
31 #include <Security/SecEntitlements.h>
32 #include <Security/SecInternal.h>
33 #include <Security/SecItemPriv.h> /* For SecItemDeleteAll */
34 #include <Security/SecPolicyInternal.h>
35 #include <Security/SecTask.h>
36 #include <Security/SecuritydXPC.h>
37 #include <securityd/OTATrustUtilities.h>
38 #include <securityd/SOSCloudCircleServer.h>
39 #include <securityd/SecItemBackupServer.h>
40 #include <securityd/SecItemServer.h>
41 #include <securityd/SecLogSettingsServer.h>
42 #include <securityd/SecOTRRemote.h>
43 #include <securityd/SecTrustServer.h>
44 #include <securityd/SecTrustStoreServer.h>
45 #include <securityd/iCloudTrace.h>
46 #include <securityd/spi.h>
47 #include <utilities/SecCFError.h>
48 #include <utilities/SecCFWrappers.h>
49 #include <utilities/SecDb.h>
50 #include <utilities/SecIOFormat.h>
51 #include <utilities/SecXPCError.h>
52 #include <utilities/debugging.h>
53
54 #include <AssertMacros.h>
55 #include <CoreFoundation/CFXPCBridge.h>
56 #include <CoreFoundation/CoreFoundation.h>
57 #include <asl.h>
58 #include <bsm/libbsm.h>
59 #include <ipc/securityd_client.h>
60 #include <libkern/OSAtomic.h>
61 #include <mach/mach.h>
62 #include <mach/message.h>
63 #include <stdlib.h>
64 #include <sys/queue.h>
65 #include <sys/sysctl.h>
66 #include <syslog.h>
67 #include <xpc/private.h>
68 #include <xpc/xpc.h>
69
70 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
71 #include <Security/SecTaskPriv.h>
72 #endif
73
74 static CFStringRef SecTaskCopyStringForEntitlement(SecTaskRef task,
75 CFStringRef entitlement)
76 {
77 CFStringRef value = (CFStringRef)SecTaskCopyValueForEntitlement(task,
78 entitlement, NULL);
79 if (value && CFGetTypeID(value) != CFStringGetTypeID()) {
80 CFRelease(value);
81 value = NULL;
82 }
83
84 return value;
85 }
86
87 static CFArrayRef SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task,
88 CFStringRef entitlement)
89 {
90 CFArrayRef value = (CFArrayRef)SecTaskCopyValueForEntitlement(task,
91 entitlement, NULL);
92 if (value) {
93 if (CFGetTypeID(value) == CFArrayGetTypeID()) {
94 CFIndex ix, count = CFArrayGetCount(value);
95 for (ix = 0; ix < count; ++ix) {
96 CFStringRef string = (CFStringRef)CFArrayGetValueAtIndex(value, ix);
97 if (CFGetTypeID(string) != CFStringGetTypeID()) {
98 CFRelease(value);
99 value = NULL;
100 break;
101 }
102 }
103 } else {
104 CFRelease(value);
105 value = NULL;
106 }
107 }
108
109 return value;
110 }
111
112 static CFStringRef SecTaskCopyApplicationIdentifier(SecTaskRef task) {
113 return SecTaskCopyStringForEntitlement(task,
114 kSecEntitlementApplicationIdentifier);
115 }
116
117 static CFArrayRef SecTaskCopySharedWebCredentialDomains(SecTaskRef task) {
118 return SecTaskCopyArrayOfStringsForEntitlement(task,
119 kSecEntitlementAssociatedDomains);
120 }
121
122 static CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) {
123 CFMutableArrayRef groups = NULL;
124 CFArrayRef keychainAccessGroups = SecTaskCopyArrayOfStringsForEntitlement(task,
125 kSecEntitlementKeychainAccessGroups);
126 CFArrayRef appleSecurityApplicationGroups = SecTaskCopyArrayOfStringsForEntitlement(task,
127 kSecEntitlementAppleSecurityApplicationGroups);
128 CFStringRef appID = SecTaskCopyApplicationIdentifier(task);
129 CFIndex kagLen = keychainAccessGroups ? CFArrayGetCount(keychainAccessGroups) : 0;
130 CFIndex asagLen = appleSecurityApplicationGroups ? CFArrayGetCount(appleSecurityApplicationGroups) : 0;
131 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
132 if ((appID || asagLen) && !SecTaskEntitlementsValidated(task)) {
133 CFReleaseNull(appID);
134 asagLen = 0;
135 }
136 #endif
137 CFIndex len = kagLen + asagLen + (appID ? 1 : 0);
138 if (len) {
139 groups = CFArrayCreateMutable(kCFAllocatorDefault, len, &kCFTypeArrayCallBacks);
140 if (kagLen)
141 CFArrayAppendArray(groups, keychainAccessGroups, CFRangeMake(0, kagLen));
142 if (appID)
143 CFArrayAppendValue(groups, appID);
144 if (asagLen)
145 CFArrayAppendArray(groups, appleSecurityApplicationGroups, CFRangeMake(0, asagLen));
146 #if TARGET_IPHONE_SIMULATOR
147 } else {
148 secwarning("No keychain access group specified whilst running in simulator, falling back to default set");
149 groups = (CFMutableArrayRef)CFRetainSafe(SecAccessGroupsGetCurrent());
150 #endif
151 }
152
153 CFReleaseSafe(appID);
154 CFReleaseSafe(keychainAccessGroups);
155 CFReleaseSafe(appleSecurityApplicationGroups);
156 return groups;
157 }
158
159 static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task,
160 CFStringRef entitlement) {
161 CFStringRef canModify = (CFStringRef)SecTaskCopyValueForEntitlement(task,
162 entitlement, NULL);
163 if (!canModify)
164 return false;
165 CFTypeID canModifyType = CFGetTypeID(canModify);
166 bool ok = (CFBooleanGetTypeID() == canModifyType) && CFBooleanGetValue((CFBooleanRef)canModify);
167 CFRelease(canModify);
168 return ok;
169 }
170
171 static void with_label_and_password(xpc_object_t message, void (^action)(CFStringRef label, CFDataRef password)) {
172 const char *label_utf8 = xpc_dictionary_get_string(message, kSecXPCKeyUserLabel);
173
174 if (label_utf8) { // Anything we would do here requires a user label
175 size_t password_length = 0;
176 const void *password_data = xpc_dictionary_get_data(message, kSecXPCKeyUserPassword, &password_length);
177
178 CFDataRef user_password = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, password_data, password_length, kCFAllocatorNull);
179 CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8);
180
181 action(user_label, user_password);
182
183 CFReleaseNull(user_password);
184 CFReleaseNull(user_label);
185 }
186 }
187
188 static void with_label_and_password_and_dsid(xpc_object_t message, void (^action)(CFStringRef label, CFDataRef password, CFStringRef dsid)) {
189 const char *label_utf8 = xpc_dictionary_get_string(message, kSecXPCKeyUserLabel);
190
191 if (label_utf8) { // Anything we would do here requires a user label
192 size_t password_length = 0;
193 const void *password_data = xpc_dictionary_get_data(message, kSecXPCKeyUserPassword, &password_length);
194 const char *xdsid = xpc_dictionary_get_string(message, kSecXPCKeyDSID);
195
196 CFDataRef user_password = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, password_data, password_length, kCFAllocatorNull);
197 CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8);
198 CFStringRef dsid = CFStringCreateWithCString(kCFAllocatorDefault, xdsid, kCFStringEncodingUTF8);
199
200 action(user_label, user_password, dsid);
201
202 CFReleaseNull(dsid);
203 CFReleaseNull(user_password);
204 CFReleaseNull(user_label);
205 }
206 }
207
208 static void with_label_and_number(xpc_object_t message, void (^action)(CFStringRef label, uint64_t number)) {
209 const char *label_utf8 = xpc_dictionary_get_string(message, kSecXPCKeyViewName);
210 const int64_t number = xpc_dictionary_get_int64(message, kSecXPCKeyViewActionCode);
211 secnotice("views", "Action Code Raw is %d", (int) number);
212 CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8);
213
214 action(user_label, number);
215 CFReleaseNull(user_label);
216 }
217
218 static bool SecXPCDictionarySetChainOptional(xpc_object_t message, const char *key, SecCertificatePathRef path, CFErrorRef *error) {
219 if (!path)
220 return true;
221 xpc_object_t xpc_chain = SecCertificatePathCopyXPCArray(path, error);
222 if (!xpc_chain)
223 return false;
224
225 xpc_dictionary_set_value(message, key, xpc_chain);
226 xpc_release(xpc_chain);
227 return true;
228 }
229
230 static SecCertificateRef SecXPCDictionaryCopyCertificate(xpc_object_t message, const char *key, CFErrorRef *error) {
231 size_t length = 0;
232 const void *bytes = xpc_dictionary_get_data(message, key, &length);
233 if (bytes) {
234 SecCertificateRef certificate = SecCertificateCreateWithBytes(kCFAllocatorDefault, bytes, length);
235 if (certificate)
236 return certificate;
237 SecError(errSecDecode, error, CFSTR("object for key %s failed to create certificate from data"), key);
238 } else {
239 SecError(errSecParam, error, CFSTR("object for key %s missing"), key);
240 }
241 return NULL;
242 }
243
244 static bool SecXPCDictionaryCopyCertificates(xpc_object_t message, const char *key, CFArrayRef *certificates, CFErrorRef *error) {
245 xpc_object_t xpc_certificates = xpc_dictionary_get_value(message, key);
246 if (!xpc_certificates)
247 return SecError(errSecAllocate, error, CFSTR("no certs for key %s"), key);
248 *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error);
249 return *certificates;
250 }
251
252 static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message, const char *key, CFArrayRef *certificates, CFErrorRef *error) {
253 xpc_object_t xpc_certificates = xpc_dictionary_get_value(message, key);
254 if (!xpc_certificates) {
255 *certificates = NULL;
256 return true;
257 }
258 *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error);
259 return *certificates;
260 }
261
262 static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message, const char *key, CFArrayRef *policies, CFErrorRef *error) {
263 xpc_object_t xpc_policies = xpc_dictionary_get_value(message, key);
264 if (!xpc_policies) {
265 if (policies)
266 *policies = NULL;
267 return true;
268 }
269 *policies = SecPolicyXPCArrayCopyArray(xpc_policies, error);
270 return *policies != NULL;
271 }
272
273 static SecTrustStoreRef SecXPCDictionaryGetTrustStore(xpc_object_t message, const char *key, CFErrorRef *error) {
274 SecTrustStoreRef ts = NULL;
275 CFStringRef domain = SecXPCDictionaryCopyString(message, key, error);
276 if (domain) {
277 ts = SecTrustStoreForDomainName(domain, error);
278 CFRelease(domain);
279 }
280 return ts;
281 }
282
283 static bool SecXPCDictionaryGetDouble(xpc_object_t message, const char *key, double *pvalue, CFErrorRef *error) {
284 *pvalue = xpc_dictionary_get_double(message, key);
285 if (*pvalue == NAN) {
286 return SecError(errSecParam, error, CFSTR("object for key %s bad double"), key);
287 }
288 return true;
289 }
290
291 static CFDataRef CFDataCreateWithXPCArrayAtIndex(xpc_object_t xpc_data_array, size_t index, CFErrorRef *error) {
292 CFDataRef data = NULL;
293 size_t length = 0;
294 const uint8_t *bytes = xpc_array_get_data(xpc_data_array, index, &length);
295 if (bytes) {
296 data = CFDataCreate(kCFAllocatorDefault, bytes, length);
297 }
298 if (!data)
299 SecError(errSecParam, error, CFSTR("data_array[%zu] failed to decode"), index);
300
301 return data;
302 }
303
304 static CFArrayRef CFDataXPCArrayCopyArray(xpc_object_t xpc_data_array, CFErrorRef *error) {
305 CFMutableArrayRef data_array = NULL;
306 require_action_quiet(xpc_get_type(xpc_data_array) == XPC_TYPE_ARRAY, exit,
307 SecError(errSecParam, error, CFSTR("data_array xpc value is not an array")));
308 size_t count = xpc_array_get_count(xpc_data_array);
309 require_action_quiet(data_array = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks), exit,
310 SecError(errSecAllocate, error, CFSTR("failed to create CFArray of capacity %zu"), count));
311
312 size_t ix;
313 for (ix = 0; ix < count; ++ix) {
314 CFDataRef data = CFDataCreateWithXPCArrayAtIndex(xpc_data_array, ix, error);
315 if (!data) {
316 CFRelease(data_array);
317 return NULL;
318 }
319 CFArraySetValueAtIndex(data_array, ix, data);
320 CFRelease(data);
321 }
322
323 exit:
324 return data_array;
325 }
326
327 static bool SecXPCDictionaryCopyCFDataArrayOptional(xpc_object_t message, const char *key, CFArrayRef *data_array, CFErrorRef *error) {
328 xpc_object_t xpc_data_array = xpc_dictionary_get_value(message, key);
329 if (!xpc_data_array) {
330 if (data_array)
331 *data_array = NULL;
332 return true;
333 }
334 *data_array = CFDataXPCArrayCopyArray(xpc_data_array, error);
335 return *data_array != NULL;
336 }
337
338 static CFSetRef SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event, const char *key) {
339 CFErrorRef error = NULL;
340 xpc_object_t object = xpc_dictionary_get_value(event, key);
341 CFSetRef retval = NULL;
342 if(object) retval = CreateCFSetRefFromXPCObject(object, &error);
343 CFReleaseNull(error);
344 return retval;
345 }
346
347
348 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_object_t event) {
349 xpc_type_t type = xpc_get_type(event);
350 __block CFErrorRef error = NULL;
351 xpc_object_t xpcError = NULL;
352 xpc_object_t replyMessage = NULL;
353 SecTaskRef clientTask = NULL;
354 CFDataRef clientAuditToken = NULL;
355 CFArrayRef accessGroups = NULL;
356 CFArrayRef domains = NULL;
357
358 secdebug("serverxpc", "entering");
359 if (type == XPC_TYPE_DICTIONARY) {
360 // TODO: Find out what we're dispatching.
361 replyMessage = xpc_dictionary_create_reply(event);
362
363 uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation);
364
365 bool hasEntitlement;
366 audit_token_t auditToken = {};
367 xpc_connection_get_audit_token(connection, &auditToken);
368
369 clientTask = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken);
370 clientAuditToken = CFDataCreate(kCFAllocatorDefault, (const UInt8*)&auditToken, sizeof(auditToken));
371 accessGroups = SecTaskCopyAccessGroups(clientTask);
372 if (operation == sec_add_shared_web_credential_id || operation == sec_copy_shared_web_credential_id) {
373 domains = SecTaskCopySharedWebCredentialDomains(clientTask);
374 }
375
376 // TODO: change back to secdebug
377 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64 ")", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation);
378
379 if (true) {
380 // Ensure that we remain dirty for a minimum of two seconds to avoid jetsam loops.
381 // Refer to rdar://problem/18615626&18616300 for more details.
382 int64_t minimumDirtyInterval = (int64_t) (2 * NSEC_PER_SEC);
383 xpc_transaction_begin();
384 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, minimumDirtyInterval), dispatch_get_main_queue(), ^{
385 xpc_transaction_end();
386 });
387 }
388
389 // operations before kSecXPCOpTryUserCredentials don't need this entitlement.
390 hasEntitlement = (operation < kSecXPCOpTryUserCredentials) ||
391 (clientTask && SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementKeychainCloudCircle));
392
393 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
394 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
395
396 if (!hasEntitlement) {
397 CFErrorRef entitlementError = NULL;
398 SecError(errSecMissingEntitlement, &entitlementError, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)operation), clientTask, kSecEntitlementKeychainCloudCircle);
399 secnotice("serverxpc", "MissingEntitlement: %@", entitlementError);
400 CFReleaseSafe(entitlementError);
401 }
402
403 if (true) {
404 switch (operation)
405 {
406 case sec_item_add_id:
407 {
408 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
409 if (query) {
410 CFTypeRef result = NULL;
411 if (_SecItemAdd(query, accessGroups, &result, &error) && result) {
412 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
413 CFRelease(result);
414 }
415 CFRelease(query);
416 }
417 break;
418 }
419 case sec_item_copy_matching_id:
420 {
421 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
422 if (query) {
423 CFTypeRef result = NULL;
424 if (_SecItemCopyMatching(query, accessGroups, &result, &error) && result) {
425 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
426 CFRelease(result);
427 }
428 CFRelease(query);
429 }
430 break;
431 }
432 case sec_item_update_id:
433 {
434 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
435 if (query) {
436 CFDictionaryRef attributesToUpdate = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyAttributesToUpdate, &error);
437 if (attributesToUpdate) {
438 bool result = _SecItemUpdate(query, attributesToUpdate, accessGroups, &error);
439 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
440 CFRelease(attributesToUpdate);
441 }
442 CFRelease(query);
443 }
444 break;
445 }
446 case sec_item_delete_id:
447 {
448 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
449 if (query) {
450 bool result = _SecItemDelete(query, accessGroups, &error);
451 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
452 CFRelease(query);
453 }
454 break;
455 }
456 case sec_trust_store_contains_id:
457 {
458 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
459 if (ts) {
460 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error);
461 if (digest) {
462 bool contains;
463 if (SecTrustStoreContainsCertificateWithDigest(ts, digest, &contains, &error))
464 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, contains);
465 CFRelease(digest);
466 }
467 }
468 break;
469 }
470 case sec_trust_store_set_trust_settings_id:
471 {
472 if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementModifyAnchorCertificates)) {
473 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
474 if (ts) {
475 SecCertificateRef certificate = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, &error);
476 if (certificate) {
477 CFTypeRef trustSettingsDictOrArray = NULL;
478 if (SecXPCDictionaryCopyPListOptional(event, kSecXPCKeySettings, &trustSettingsDictOrArray, &error)) {
479 bool result = _SecTrustStoreSetTrustSettings(ts, certificate, trustSettingsDictOrArray, &error);
480 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
481 CFReleaseSafe(trustSettingsDictOrArray);
482 }
483 CFRelease(certificate);
484 }
485 }
486 } else {
487 SecError(errSecMissingEntitlement, &error, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)operation), clientTask, kSecEntitlementModifyAnchorCertificates);
488 }
489 break;
490 }
491 case sec_trust_store_remove_certificate_id:
492 {
493 if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementModifyAnchorCertificates)) {
494 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
495 if (ts) {
496 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error);
497 if (digest) {
498 bool result = SecTrustStoreRemoveCertificateWithDigest(ts, digest, &error);
499 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
500 CFRelease(digest);
501 }
502 }
503 } else {
504 SecError(errSecMissingEntitlement, &error, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)operation), clientTask, kSecEntitlementModifyAnchorCertificates);
505 }
506 break;
507 }
508 case sec_delete_all_id:
509 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, _SecItemDeleteAll(&error));
510 break;
511 case sec_trust_evaluate_id:
512 {
513 CFArrayRef certificates = NULL, anchors = NULL, policies = NULL, responses = NULL, scts = NULL, trustedLogs = NULL;
514 bool anchorsOnly = xpc_dictionary_get_bool(event, kSecTrustAnchorsOnlyKey);
515 double verifyTime;
516 if (SecXPCDictionaryCopyCertificates(event, kSecTrustCertificatesKey, &certificates, &error) &&
517 SecXPCDictionaryCopyCertificatesOptional(event, kSecTrustAnchorsKey, &anchors, &error) &&
518 SecXPCDictionaryCopyPoliciesOptional(event, kSecTrustPoliciesKey, &policies, &error) &&
519 SecXPCDictionaryCopyCFDataArrayOptional(event, kSecTrustResponsesKey, &responses, &error) &&
520 SecXPCDictionaryCopyCFDataArrayOptional(event, kSecTrustSCTsKey, &scts, &error) &&
521 SecXPCDictionaryCopyArrayOptional(event, kSecTrustTrustedLogsKey, &trustedLogs, &error) &&
522 SecXPCDictionaryGetDouble(event, kSecTrustVerifyDateKey, &verifyTime, &error)) {
523 // If we have no error yet, capture connection and reply in block and properly retain them.
524 xpc_retain(connection);
525 CFRetainSafe(clientTask);
526 CFRetainSafe(clientAuditToken);
527
528 // Clear replyMessage so we don't send a synchronous reply.
529 xpc_object_t asyncReply = replyMessage;
530 replyMessage = NULL;
531
532 SecTrustServerEvaluateBlock(clientAuditToken,
533 certificates, anchors, anchorsOnly, policies, responses, scts, trustedLogs, verifyTime, accessGroups,
534 ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, SecCertificatePathRef chain, CFErrorRef replyError) {
535 // Send back reply now
536 if (replyError) {
537 CFRetain(replyError);
538 } else {
539 xpc_dictionary_set_int64(asyncReply, kSecTrustResultKey, tr);
540 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustDetailsKey, details, &replyError) &&
541 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustInfoKey, info, &replyError) &&
542 SecXPCDictionarySetChainOptional(asyncReply, kSecTrustChainKey, chain, &replyError);
543 }
544 if (replyError) {
545 secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyError);
546 xpc_object_t xpcReplyError = SecCreateXPCObjectWithCFError(replyError);
547 if (xpcReplyError) {
548 xpc_dictionary_set_value(asyncReply, kSecXPCKeyError, xpcReplyError);
549 xpc_release(xpcReplyError);
550 }
551 CFRelease(replyError);
552 } else {
553 secdebug("ipc", "%@ %@ reponding %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), asyncReply);
554 }
555
556 xpc_connection_send_message(connection, asyncReply);
557 xpc_release(asyncReply);
558 xpc_release(connection);
559 CFReleaseSafe(clientTask);
560 CFReleaseSafe(clientAuditToken);
561 });
562 }
563 CFReleaseSafe(policies);
564 CFReleaseSafe(anchors);
565 CFReleaseSafe(certificates);
566 CFReleaseSafe(responses);
567 CFReleaseSafe(scts);
568 CFReleaseSafe(trustedLogs);
569 break;
570 }
571 case sec_keychain_backup_id:
572 {
573 CFDataRef keybag = NULL, passcode = NULL;
574 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybag, &error)) {
575 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
576 CFDataRef backup = _SecServerKeychainBackup(keybag, passcode, &error);
577 if (backup) {
578 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, backup, &error);
579 CFRelease(backup);
580 }
581 CFReleaseSafe(passcode);
582 }
583 CFReleaseSafe(keybag);
584 }
585 break;
586 }
587 case sec_keychain_restore_id:
588 {
589 CFDataRef backup = SecXPCDictionaryCopyData(event, kSecXPCKeyBackup, &error);
590 if (backup) {
591 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
592 if (keybag) {
593 CFDataRef passcode = NULL;
594 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
595 bool result = _SecServerKeychainRestore(backup, keybag, passcode, &error);
596 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
597 CFReleaseSafe(passcode);
598 }
599 CFRelease(keybag);
600 }
601 CFRelease(backup);
602 }
603 break;
604 }
605 case sec_keychain_sync_update_message_id:
606 {
607 CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
608 if (updates) {
609 CFArrayRef result = _SecServerKeychainSyncUpdateMessage(updates, &error);
610 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
611 CFReleaseNull(result);
612 }
613 CFReleaseNull(updates);
614 break;
615 }
616 case sec_keychain_backup_syncable_id:
617 {
618 CFDictionaryRef oldbackup = NULL;
619 if (SecXPCDictionaryCopyDictionaryOptional(event, kSecXPCKeyBackup, &oldbackup, &error)) {
620 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
621 if (keybag) {
622 CFDataRef passcode = NULL;
623 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
624 CFDictionaryRef newbackup = _SecServerBackupSyncable(oldbackup, keybag, passcode, &error);
625 if (newbackup) {
626 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, newbackup, &error);
627 CFRelease(newbackup);
628 }
629 CFReleaseSafe(passcode);
630 }
631 CFRelease(keybag);
632 }
633 CFReleaseSafe(oldbackup);
634 }
635 break;
636 }
637 case sec_keychain_restore_syncable_id:
638 {
639 CFDictionaryRef backup = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyBackup, &error);
640 if (backup) {
641 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
642 if (keybag) {
643 CFDataRef passcode = NULL;
644 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
645 bool result = _SecServerRestoreSyncable(backup, keybag, passcode, &error);
646 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
647 CFReleaseSafe(passcode);
648 }
649 CFRelease(keybag);
650 }
651 CFRelease(backup);
652 }
653 break;
654 }
655 case sec_item_backup_copy_names_id:
656 {
657 CFArrayRef names = SecServerItemBackupCopyNames(&error);
658 SecXPCDictionarySetPListOptional(replyMessage, kSecXPCKeyResult, names, &error);
659 CFReleaseSafe(names);
660 break;
661 }
662 case sec_item_backup_handoff_fd_id:
663 {
664 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
665 int fd = -1;
666 if (backupName) {
667 fd = SecServerItemBackupHandoffFD(backupName, &error);
668 CFRelease(backupName);
669 }
670 SecXPCDictionarySetFileDescriptor(replyMessage, kSecXPCKeyResult, fd, &error);
671 if (fd != -1)
672 close(fd);
673 break;
674 }
675 case sec_item_backup_set_confirmed_manifest_id:
676 {
677 CFDataRef keybagDigest = NULL;
678 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybagDigest, &error)) {
679 CFDataRef manifest = NULL;
680 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &manifest, &error)) {
681 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
682 if (backupName) {
683 bool result = SecServerItemBackupSetConfirmedManifest(backupName, keybagDigest, manifest, &error);
684 CFRelease(backupName);
685 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
686 }
687 CFReleaseSafe(manifest);
688 }
689 CFRelease(keybagDigest);
690 }
691 break;
692 }
693 case sec_item_backup_restore_id:
694 {
695 bool result = false;
696 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
697 if (backupName) {
698 CFStringRef peerID = NULL;
699 if (SecXPCDictionaryCopyStringOptional(event, kSecXPCKeyDigest, &peerID, &error)) {
700 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
701 if (keybag) {
702 CFDataRef secret = SecXPCDictionaryCopyData(event, kSecXPCKeyUserPassword, &error);
703 if (secret) {
704 CFDataRef backup = SecXPCDictionaryCopyData(event, kSecXPCData, &error);
705 if (backup) {
706 result = SecServerItemBackupRestore(backupName, peerID, keybag, secret, backup, &error);
707 CFRelease(backup);
708 }
709 CFRelease(secret);
710 }
711 CFRelease(keybag);
712 }
713 CFReleaseSafe(peerID);
714 }
715 CFRelease(backupName);
716 }
717 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
718 break;
719 }
720 case sec_ota_pki_asset_version_id:
721 {
722 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
723 SecOTAPKIGetCurrentAssetVersion(&error));
724 break;
725 }
726 case sec_add_shared_web_credential_id:
727 {
728 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
729 if (query) {
730 CFTypeRef result = NULL;
731 CFStringRef appID = (clientTask) ? SecTaskCopyApplicationIdentifier(clientTask) : NULL;
732 if (_SecAddSharedWebCredential(query, &auditToken, appID, domains, &result, &error) && result) {
733 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
734 CFRelease(result);
735 }
736 CFReleaseSafe(appID);
737 CFRelease(query);
738 }
739 break;
740 }
741 case sec_copy_shared_web_credential_id:
742 {
743 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
744 if (query) {
745 CFTypeRef result = NULL;
746 CFStringRef appID = (clientTask) ? SecTaskCopyApplicationIdentifier(clientTask) : NULL;
747 if (_SecCopySharedWebCredential(query, &auditToken, appID, domains, &result, &error) && result) {
748 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
749 CFRelease(result);
750 }
751 CFReleaseSafe(appID);
752 CFRelease(query);
753 }
754 break;
755 }
756 case sec_get_log_settings_id:
757 {
758 CFPropertyListRef currentList = SecCopyLogSettings_Server(&error);
759 if (currentList) {
760 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, currentList, &error);
761 }
762 CFReleaseSafe(currentList);
763 break;
764 }
765 case sec_set_xpc_log_settings_id:
766 {
767 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error);
768 if (newSettings) {
769 SecSetXPCLogSettings_Server(newSettings, &error);
770 }
771 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
772 CFReleaseNull(newSettings);
773 break;
774 }
775 case sec_set_circle_log_settings_id:
776 {
777 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error);
778 if (newSettings) {
779 SecSetCircleLogSettings_Server(newSettings, &error);
780 }
781 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
782 CFReleaseNull(newSettings);
783 break;
784 }
785 case sec_otr_session_create_remote_id:
786 {
787 CFDataRef publicPeerId = NULL;
788 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCPublicPeerId, &publicPeerId, &error)) {
789 CFDataRef otrSession = _SecOTRSessionCreateRemote(publicPeerId, &error);
790 if (otrSession) {
791 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, otrSession, &error);
792 CFRelease(otrSession);
793 }
794 CFReleaseSafe(publicPeerId);
795 }
796 break;
797 }
798 case sec_otr_session_process_packet_remote_id:
799 {
800 CFDataRef sessionData = NULL, inputPacket = NULL, outputSessionData = NULL, outputPacket = NULL;
801 bool readyForMessages = false;
802 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCOTRSession, &sessionData, &error)) {
803 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &inputPacket, &error)) {
804 bool result = _SecOTRSessionProcessPacketRemote(sessionData, inputPacket, &outputSessionData, &outputPacket, &readyForMessages, &error);
805 if (result) {
806 SecXPCDictionarySetData(replyMessage, kSecXPCOTRSession, outputSessionData, &error);
807 SecXPCDictionarySetData(replyMessage, kSecXPCData, outputPacket, &error);
808 xpc_dictionary_set_bool(replyMessage, kSecXPCOTRReady, readyForMessages);
809 CFRelease(outputSessionData);
810 CFRelease(outputPacket);
811 }
812 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
813
814 CFReleaseSafe(inputPacket);
815 }
816 CFReleaseSafe(sessionData);
817 }
818 break;
819 }
820 case kSecXPCOpTryUserCredentials:
821 with_label_and_password(event, ^(CFStringRef label, CFDataRef password) {
822 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
823 SOSCCTryUserCredentials_Server(label, password, &error));
824 });
825 break;
826 case kSecXPCOpSetUserCredentials:
827 with_label_and_password(event, ^(CFStringRef label, CFDataRef password) {
828 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
829 SOSCCSetUserCredentials_Server(label, password, &error));
830 });
831 break;
832 case kSecXPCOpSetUserCredentialsAndDSID:
833 with_label_and_password_and_dsid(event, ^(CFStringRef label, CFDataRef password, CFStringRef dsid) {
834 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
835 SOSCCSetUserCredentialsAndDSID_Server(label, password, dsid, &error));
836 });
837 break;
838 case kSecXPCOpView:
839 with_label_and_number(event, ^(CFStringRef view, uint64_t actionCode) {
840 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
841 SOSCCView_Server(view, (SOSViewActionCode)actionCode, &error));
842 });
843 break;
844 case kSecXPCOpViewSet:
845 {
846 CFSetRef enabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyEnabledViewsKey);
847 CFSetRef disabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyDisabledViewsKey);
848 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCViewSet_Server(enabledViews, disabledViews));
849 CFReleaseNull(enabledViews);
850 CFReleaseNull(disabledViews);
851 }
852 break;
853 case kSecXPCOpSecurityProperty:
854 with_label_and_number(event, ^(CFStringRef property, uint64_t actionCode) {
855 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
856 SOSCCSecurityProperty_Server(property, (SOSSecurityPropertyActionCode)actionCode, &error));
857 });
858 break;
859 case kSecXPCOpCanAuthenticate:
860 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
861 SOSCCCanAuthenticate_Server(&error));
862 break;
863 case kSecXPCOpPurgeUserCredentials:
864 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
865 SOSCCPurgeUserCredentials_Server(&error));
866 break;
867 case kSecXPCOpDeviceInCircle:
868 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
869 SOSCCThisDeviceIsInCircle_Server(&error));
870 break;
871 case kSecXPCOpRequestToJoin:
872 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
873 SOSCCRequestToJoinCircle_Server(&error));
874 break;
875 case kSecXPCOpRequestToJoinAfterRestore:
876 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
877 SOSCCRequestToJoinCircleAfterRestore_Server(&error));
878 break;
879 case kSecXPCOpRequestEnsureFreshParameters:
880 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
881 SOSCCRequestEnsureFreshParameters_Server(&error));
882 break;
883 case kSecXPCOpGetAllTheRings:
884 {
885 CFStringRef ringDescriptions = SOSCCGetAllTheRings_Server(&error);
886 xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(ringDescriptions);
887 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_dictionary);
888 xpc_release(xpc_dictionary);
889 }
890 break;
891 case kSecXPCOpApplyToARing:
892 {
893 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
894 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCApplyToARing_Server(ringName, &error));
895 CFReleaseNull(ringName);
896 }
897 break;
898 case kSecXPCOpWithdrawlFromARing:
899 {
900 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
901 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCWithdrawlFromARing_Server(ringName, &error));
902 CFReleaseNull(ringName);
903 }
904 break;
905 case kSecXPCOpRingStatus:
906 {
907 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
908 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRingStatus_Server(ringName, &error));
909 CFReleaseNull(ringName);
910 }
911 break;
912 case kSecXPCOpEnableRing:
913 {
914 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
915 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCEnableRing_Server(ringName, &error));
916 CFReleaseNull(ringName);
917 }
918 break;
919 case kSecXPCOpRequestDeviceID:
920 {
921 CFStringRef deviceID = SOSCCRequestDeviceID_Server(&error);
922 if (deviceID) {
923 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, deviceID, &error);
924 }
925 }
926 break;
927 case kSecXPCOpSetDeviceID:
928 {
929 CFStringRef IDS = SecXPCDictionaryCopyString(event, kSecXPCKeyDeviceID, &error);
930 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCSetDeviceID_Server(IDS, &error));
931 CFReleaseNull(IDS);
932 }
933 break;
934 case kSecXPCOpHandleIDSMessage:
935 {
936 CFDictionaryRef IDS = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyIDSMessage, &error);
937 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult, SOSCCHandleIDSMessage_Server(IDS, &error));
938 CFReleaseNull(IDS);
939 }
940 break;
941
942 case kSecXPCOpSendIDSMessage:
943 {
944 CFStringRef message = SecXPCDictionaryCopyString(event, kSecXPCKeySendIDSMessage, &error);
945 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCIDSServiceRegistrationTest_Server(message, &error));
946 CFReleaseNull(message);
947 }
948 break;
949 case kSecXPCOpPingTest:
950 {
951 CFStringRef message = SecXPCDictionaryCopyString(event, kSecXPCKeySendIDSMessage, &error);
952 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCIDSPingTest_Server(message, &error));
953 CFReleaseNull(message);
954 }
955 break;
956 case kSecXPCOpIDSDeviceID:
957 {
958 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCIDSDeviceIDIsAvailableTest_Server(&error));
959 }
960 break;
961 case kSecXPCOpAccountSetToNew:
962 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCAccountSetToNew_Server(&error));
963 break;
964 case kSecXPCOpResetToOffering:
965 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
966 SOSCCResetToOffering_Server(&error));
967 break;
968 case kSecXPCOpResetToEmpty:
969 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
970 SOSCCResetToEmpty_Server(&error));
971 break;
972 case kSecXPCOpRemoveThisDeviceFromCircle:
973 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
974 SOSCCRemoveThisDeviceFromCircle_Server(&error));
975 break;
976 case kSecXPCOpLoggedOutOfAccount:
977 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
978 SOSCCLoggedOutOfAccount_Server(&error));
979 break;
980 case kSecXPCOpBailFromCircle:
981 {
982 uint64_t limit_in_seconds = xpc_dictionary_get_uint64(event, kSecXPCLimitInMinutes);
983 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
984 SOSCCBailFromCircle_Server(limit_in_seconds, &error));
985 }
986 break;
987 case kSecXPCOpAcceptApplicants:
988 {
989 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos);
990 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
991 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
992 (applicants && SOSCCAcceptApplicants_Server(applicants, &error)));
993 CFReleaseSafe(applicants);
994 }
995 break;
996 case kSecXPCOpRejectApplicants:
997 {
998 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos);
999 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1000 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1001 (applicants && SOSCCRejectApplicants_Server(applicants, &error)));
1002 CFReleaseSafe(applicants);
1003 }
1004 break;
1005 case kSecXPCOpSetNewPublicBackupKey:
1006 {
1007 CFDataRef publicBackupKey = SecXPCDictionaryCopyData(event, kSecXPCKeyNewPublicBackupKey, &error);
1008 SOSPeerInfoRef peerInfo = SOSCCSetNewPublicBackupKey_Server(publicBackupKey, &error);
1009 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1010 CFReleaseNull(peerInfo);
1011 if (peerInfoData) {
1012 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1013 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1014 xpc_release(xpc_object);
1015 }
1016 CFReleaseNull(peerInfoData);
1017 CFReleaseSafe(publicBackupKey);
1018
1019 }
1020 break;
1021 case kSecXPCOpSetBagForAllSlices:
1022 {
1023 CFDataRef backupSlice = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
1024 bool includeV0 = xpc_dictionary_get_bool(event, kSecXPCKeyIncludeV0);
1025 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, backupSlice && SOSCCRegisterSingleRecoverySecret_Server(backupSlice, includeV0, &error));
1026 CFReleaseSafe(backupSlice);
1027 }
1028 break;
1029 case kSecXPCOpCopyApplicantPeerInfo:
1030 {
1031 CFArrayRef array = SOSCCCopyApplicantPeerInfo_Server(&error);
1032 if (array) {
1033 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error);
1034 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1035 xpc_release(xpc_array);
1036 }
1037 CFReleaseNull(array);
1038 }
1039 break;
1040 case kSecXPCOpCopyValidPeerPeerInfo:
1041 {
1042 CFArrayRef array = SOSCCCopyValidPeerPeerInfo_Server(&error);
1043 if (array) {
1044 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error);
1045 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1046 xpc_release(xpc_array);
1047 }
1048 CFReleaseNull(array);
1049 }
1050 break;
1051 case kSecXPCOpValidateUserPublic:
1052 {
1053 bool trusted = SOSCCValidateUserPublic_Server(&error);
1054 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, trusted);
1055 }
1056 break;
1057 case kSecXPCOpCopyNotValidPeerPeerInfo:
1058 {
1059 CFArrayRef array = SOSCCCopyNotValidPeerPeerInfo_Server(&error);
1060 if (array) {
1061 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error);
1062 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1063 xpc_release(xpc_array);
1064 }
1065 CFReleaseNull(array);
1066 }
1067 break;
1068 case kSecXPCOpCopyGenerationPeerInfo:
1069 {
1070 CFArrayRef array = SOSCCCopyGenerationPeerInfo_Server(&error);
1071 if (array) {
1072 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1073 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1074 xpc_release(xpc_array);
1075 }
1076 CFReleaseNull(array);
1077 }
1078 break;
1079 case kSecXPCOpCopyRetirementPeerInfo:
1080 {
1081 CFArrayRef array = SOSCCCopyRetirementPeerInfo_Server(&error);
1082 if (array) {
1083 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error);
1084 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1085 xpc_release(xpc_array);
1086 }
1087 CFReleaseNull(array);
1088 }
1089 break;
1090 case kSecXPCOpCopyEngineState:
1091 {
1092 CFArrayRef array = SOSCCCopyEngineState_Server(&error);
1093 if (array) {
1094 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1095 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1096 xpc_release(xpc_array);
1097 }
1098 CFReleaseNull(array);
1099 }
1100 break;
1101 case kSecXPCOpCopyPeerPeerInfo:
1102 {
1103 CFArrayRef array = SOSCCCopyPeerPeerInfo_Server(&error);
1104 if (array) {
1105 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error);
1106 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1107 xpc_release(xpc_array);
1108 }
1109 CFReleaseNull(array);
1110 }
1111 break;
1112 case kSecXPCOpCopyConcurringPeerPeerInfo:
1113 {
1114 CFArrayRef array = SOSCCCopyConcurringPeerPeerInfo_Server(&error);
1115 if (array) {
1116 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error);
1117 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1118 xpc_release(xpc_array);
1119 }
1120 CFReleaseNull(array);
1121 }
1122 break;
1123 case kSecXPCOpCopyMyPeerInfo:
1124 {
1125 SOSPeerInfoRef peerInfo = SOSCCCopyMyPeerInfo_Server(&error);
1126 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1127 CFReleaseNull(peerInfo);
1128 if (peerInfoData) {
1129 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1130 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1131 xpc_release(xpc_object);
1132 }
1133 CFReleaseNull(peerInfoData);
1134 }
1135 break;
1136 case kSecXPCOpGetLastDepartureReason:
1137 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1138 SOSCCGetLastDepartureReason_Server(&error));
1139 break;
1140 case kSecXPCOpSetLastDepartureReason:
1141 {
1142 int32_t reason = (int32_t) xpc_dictionary_get_int64(event, kSecXPCKeyReason);
1143 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1144 SOSCCSetLastDepartureReason_Server(reason, &error));
1145 break;
1146 }
1147 case kSecXPCOpProcessSyncWithAllPeers:
1148 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1149 SOSCCProcessSyncWithAllPeers_Server(&error));
1150 break;
1151 case soscc_EnsurePeerRegistration_id:
1152 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1153 SOSCCProcessEnsurePeerRegistration_Server(&error));
1154 break;
1155 case kSecXPCOpCopyIncompatibilityInfo: {
1156 CFStringRef iis = SOSCCCopyIncompatibilityInfo_Server(&error);
1157 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, iis, &error);
1158 CFReleaseSafe(iis);
1159 break;
1160 }
1161 case kSecXPCOpOTAGetEscrowCertificates:
1162 {
1163 uint32_t escrowRootType = (uint32_t)xpc_dictionary_get_uint64(event, "escrowType");
1164 CFArrayRef array = SecOTAPKICopyCurrentEscrowCertificates(escrowRootType, &error);
1165 if (array) {
1166 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1167 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1168 xpc_release(xpc_array);
1169 }
1170 CFReleaseNull(array);
1171 }
1172 break;
1173 case kSecXPCOpOTAPKIGetNewAsset:
1174 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1175 SecOTAPKISignalNewAsset(&error));
1176 break;
1177 case kSecXPCOpRollKeys:
1178 {
1179 bool force = xpc_dictionary_get_bool(event, "force");
1180 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1181 _SecServerRollKeys(force, &error));
1182 }
1183 break;
1184 case kSecXPCOpSetHSA2AutoAcceptInfo:
1185 {
1186 CFDataRef cfbytes = NULL;
1187 const uint8_t *bytes = NULL;
1188 size_t len = 0;
1189
1190 bytes = xpc_dictionary_get_data(event,
1191 kSecXPCKeyHSA2AutoAcceptInfo, &len);
1192 if (!bytes) {
1193 SOSCreateError(kSOSErrorBadKey,
1194 CFSTR("missing autoaccept info"), NULL, &error);
1195 break;
1196 }
1197
1198 cfbytes = CFDataCreate(NULL, bytes, len);
1199 if (!cfbytes) {
1200 SOSCreateError(kSOSErrorAllocationFailure,
1201 CFSTR("could not allocate autoaccept info"),
1202 NULL, &error);
1203 break;
1204 }
1205
1206 xpc_dictionary_set_bool(replyMessage,
1207 kSecXPCKeyResult,
1208 SOSCCSetHSA2AutoAcceptInfo_Server(cfbytes, &error));
1209 CFRelease(cfbytes);
1210 }
1211 break;
1212 case kSecXPCOpWaitForInitialSync:
1213 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1214 SOSCCWaitForInitialSync_Server(&error));
1215 break;
1216
1217 case kSecXPCOpCopyYetToSyncViews:
1218 {
1219 CFArrayRef array = SOSCCCopyYetToSyncViewsList_Server(&error);
1220 if (array) {
1221 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1222 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1223 xpc_release(xpc_array);
1224 }
1225 CFReleaseNull(array);
1226 }
1227 break;
1228
1229 default:
1230 break;
1231 }
1232
1233
1234 }
1235
1236 if (error)
1237 {
1238 if(SecErrorGetOSStatus(error) == errSecItemNotFound || isSOSErrorCoded(error, kSOSErrorPublicKeyAbsent))
1239 secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1240 else if (SecErrorGetOSStatus(error) == errSecAuthNeeded)
1241 secwarning("Authentication is needed %@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1242 else
1243 secerror("%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
1244
1245 xpcError = SecCreateXPCObjectWithCFError(error);
1246 if (replyMessage) {
1247 xpc_dictionary_set_value(replyMessage, kSecXPCKeyError, xpcError);
1248 }
1249 } else if (replyMessage) {
1250 secdebug("ipc", "%@ %@ responding %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyMessage);
1251 }
1252 } else {
1253 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &error, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event);
1254 secerror("%@: returning error: %@", clientTask, error);
1255 xpcError = SecCreateXPCObjectWithCFError(error);
1256 replyMessage = xpc_create_reply_with_format(event, "{%string: %value}", kSecXPCKeyError, xpcError);
1257 }
1258
1259 if (replyMessage) {
1260 xpc_connection_send_message(connection, replyMessage);
1261 xpc_release(replyMessage);
1262 }
1263 if (xpcError)
1264 xpc_release(xpcError);
1265 CFReleaseSafe(error);
1266 CFReleaseSafe(accessGroups);
1267 CFReleaseSafe(domains);
1268 CFReleaseSafe(clientTask);
1269 CFReleaseSafe(clientAuditToken);
1270 }
1271
1272 static void securityd_xpc_init(const char *service_name)
1273 {
1274 secdebug("serverxpc", "start");
1275 xpc_connection_t listener = xpc_connection_create_mach_service(service_name, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
1276 if (!listener) {
1277 seccritical("security failed to register xpc listener for %s, exiting", service_name);
1278 abort();
1279 }
1280
1281 xpc_connection_set_event_handler(listener, ^(xpc_object_t connection) {
1282 if (xpc_get_type(connection) == XPC_TYPE_CONNECTION) {
1283 xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
1284 if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) {
1285 xpc_retain(connection);
1286 xpc_retain(event);
1287 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
1288 securityd_xpc_dictionary_handler(connection, event);
1289 xpc_release(event);
1290 xpc_release(connection);
1291 });
1292 }
1293 });
1294 xpc_connection_resume(connection);
1295 }
1296 });
1297 xpc_connection_resume(listener);
1298 }
1299
1300
1301
1302 int main(int argc, char *argv[])
1303 {
1304 char *wait4debugger = getenv("WAIT4DEBUGGER");
1305 if (wait4debugger && !strcasecmp("YES", wait4debugger)) {
1306 seccritical("SIGSTOPing self, awaiting debugger");
1307 kill(getpid(), SIGSTOP);
1308 asl_log(NULL, NULL, ASL_LEVEL_CRIT,
1309 "Again, for good luck (or bad debuggers)");
1310 kill(getpid(), SIGSTOP);
1311 }
1312
1313 const char *serviceName = kSecuritydXPCServiceName;
1314 #if TRUSTD_SERVER
1315 serviceName = kTrustdXPCServiceName;
1316 if (argc > 1 && (!strcmp(argv[1], "--agent"))) {
1317 serviceName = kTrustdAgentXPCServiceName;
1318 }
1319 #endif
1320 securityd_init_server();
1321 securityd_xpc_init(serviceName);
1322
1323 dispatch_main();
1324
1325 return 0;
1326 }
1327
1328 /* vi:set ts=4 sw=4 et: */