]> git.saurik.com Git - apple/security.git/blob - Security/sec/ipc/server.c
Security-57031.1.35.tar.gz
[apple/security.git] / Security / sec / ipc / server.c
1 /*
2 * Copyright (c) 2007-2014 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 <SecureObjectSync/SOSCloudCircle.h>
25 #include <SecureObjectSync/SOSCloudCircleInternal.h>
26 #include <SecureObjectSync/SOSInternal.h>
27 #include <SecureObjectSync/SOSPeerInfoCollections.h>
28 #include <Security/SecBasePriv.h>
29 #include <Security/SecCertificatePriv.h>
30 #include <Security/SecEntitlements.h>
31 #include <Security/SecInternal.h>
32 #include <Security/SecItemPriv.h> /* For SecItemDeleteAll */
33 #include <Security/SecPolicyInternal.h>
34 #include <Security/SecTask.h>
35 #include <Security/SecuritydXPC.h>
36 #include <securityd/OTATrustUtilities.h>
37 #include <securityd/SOSCloudCircleServer.h>
38 #include <securityd/SecItemServer.h>
39 #include <securityd/SecLogSettingsServer.h>
40 #include <securityd/SecOTRRemote.h>
41 #include <securityd/SecTrustServer.h>
42 #include <securityd/SecTrustStoreServer.h>
43 #include <securityd/iCloudTrace.h>
44 #include <securityd/spi.h>
45 #include <utilities/SecCFError.h>
46 #include <utilities/SecCFWrappers.h>
47 #include <utilities/SecDb.h>
48 #include <utilities/SecIOFormat.h>
49 #include <utilities/SecXPCError.h>
50 #include <utilities/debugging.h>
51
52 #include <AssertMacros.h>
53 #include <CoreFoundation/CFXPCBridge.h>
54 #include <CoreFoundation/CoreFoundation.h>
55 #include <asl.h>
56 #include <bsm/libbsm.h>
57 #include <ipc/securityd_client.h>
58 #include <libkern/OSAtomic.h>
59 #include <mach/mach.h>
60 #include <mach/message.h>
61 #include <stdlib.h>
62 #include <sys/queue.h>
63 #include <sys/sysctl.h>
64 #include <syslog.h>
65 #include <xpc/private.h>
66 #include <xpc/xpc.h>
67
68 static CFStringRef SecTaskCopyStringForEntitlement(SecTaskRef task,
69 CFStringRef entitlement)
70 {
71 CFStringRef value = (CFStringRef)SecTaskCopyValueForEntitlement(task,
72 entitlement, NULL);
73 if (value && CFGetTypeID(value) != CFStringGetTypeID()) {
74 CFRelease(value);
75 value = NULL;
76 }
77
78 return value;
79 }
80
81 static CFArrayRef SecTaskCopyArrayOfStringsForEntitlement(SecTaskRef task,
82 CFStringRef entitlement)
83 {
84 CFArrayRef value = (CFArrayRef)SecTaskCopyValueForEntitlement(task,
85 entitlement, NULL);
86 if (value) {
87 if (CFGetTypeID(value) == CFArrayGetTypeID()) {
88 CFIndex ix, count = CFArrayGetCount(value);
89 for (ix = 0; ix < count; ++ix) {
90 CFStringRef string = (CFStringRef)CFArrayGetValueAtIndex(value, ix);
91 if (CFGetTypeID(string) != CFStringGetTypeID()) {
92 CFRelease(value);
93 value = NULL;
94 break;
95 }
96 }
97 } else {
98 CFRelease(value);
99 value = NULL;
100 }
101 }
102
103 return value;
104 }
105
106 static CFStringRef SecTaskCopyApplicationIdentifier(SecTaskRef task) {
107 return SecTaskCopyStringForEntitlement(task,
108 kSecEntitlementApplicationIdentifier);
109 }
110
111 static CFArrayRef SecTaskCopySharedWebCredentialDomains(SecTaskRef task) {
112 return SecTaskCopyArrayOfStringsForEntitlement(task,
113 kSecEntitlementAssociatedDomains);
114 }
115
116 static CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) {
117 CFMutableArrayRef groups = NULL;
118 CFArrayRef keychainAccessGroups = SecTaskCopyArrayOfStringsForEntitlement(task,
119 kSecEntitlementKeychainAccessGroups);
120 CFArrayRef appleSecurityApplicationGroups = SecTaskCopyArrayOfStringsForEntitlement(task,
121 kSecEntitlementAppleSecurityApplicationGroups);
122 CFStringRef appID = SecTaskCopyApplicationIdentifier(task);
123 CFIndex kagLen = keychainAccessGroups ? CFArrayGetCount(keychainAccessGroups) : 0;
124 CFIndex asagLen = appleSecurityApplicationGroups ? CFArrayGetCount(appleSecurityApplicationGroups) : 0;
125 CFIndex len = kagLen + asagLen + (appID ? 1 : 0);
126 if (len) {
127 groups = CFArrayCreateMutable(kCFAllocatorDefault, len, &kCFTypeArrayCallBacks);
128 if (kagLen)
129 CFArrayAppendArray(groups, keychainAccessGroups, CFRangeMake(0, kagLen));
130 if (appID)
131 CFArrayAppendValue(groups, appID);
132 if (asagLen)
133 CFArrayAppendArray(groups, appleSecurityApplicationGroups, CFRangeMake(0, asagLen));
134 #if TARGET_IPHONE_SIMULATOR
135 } else {
136 secwarning("No keychain access group specified whilst running in simulator, falling back to default set");
137 groups = (CFMutableArrayRef)CFRetainSafe(SecAccessGroupsGetCurrent());
138 #endif
139 }
140
141 CFReleaseSafe(appID);
142 CFReleaseSafe(keychainAccessGroups);
143 CFReleaseSafe(appleSecurityApplicationGroups);
144 return groups;
145 }
146
147 static bool SecTaskGetBooleanValueForEntitlement(SecTaskRef task,
148 CFStringRef entitlement) {
149 CFStringRef canModify = (CFStringRef)SecTaskCopyValueForEntitlement(task,
150 entitlement, NULL);
151 if (!canModify)
152 return false;
153 CFTypeID canModifyType = CFGetTypeID(canModify);
154 bool ok = (CFBooleanGetTypeID() == canModifyType) && CFBooleanGetValue((CFBooleanRef)canModify);
155 CFRelease(canModify);
156 return ok;
157 }
158
159 static void with_label_and_password(xpc_object_t message, void (^action)(CFStringRef label, CFDataRef password)) {
160 const char *label_utf8 = xpc_dictionary_get_string(message, kSecXPCKeyUserLabel);
161
162 size_t password_length = 0;
163 const void *password_data = xpc_dictionary_get_data(message, kSecXPCKeyUserPassword, &password_length);
164
165 CFDataRef user_password = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, password_data, password_length, kCFAllocatorNull);
166 CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8);
167
168 action(user_label, user_password);
169
170 CFReleaseNull(user_password);
171 CFReleaseNull(user_label);
172 }
173
174 static bool SecXPCDictionarySetChainOptional(xpc_object_t message, const char *key, SecCertificatePathRef path, CFErrorRef *error) {
175 if (!path)
176 return true;
177 xpc_object_t xpc_chain = SecCertificatePathCopyXPCArray(path, error);
178 if (!xpc_chain)
179 return false;
180
181 xpc_dictionary_set_value(message, key, xpc_chain);
182 xpc_release(xpc_chain);
183 return true;
184 }
185
186 static SecCertificateRef SecXPCDictionaryCopyCertificate(xpc_object_t message, const char *key, CFErrorRef *error) {
187 size_t length = 0;
188 const void *bytes = xpc_dictionary_get_data(message, key, &length);
189 if (bytes) {
190 SecCertificateRef certificate = SecCertificateCreateWithBytes(kCFAllocatorDefault, bytes, length);
191 if (certificate)
192 return certificate;
193 SecError(errSecDecode, error, CFSTR("object for key %s failed to create certificate from data"), key);
194 } else {
195 SecError(errSecParam, error, CFSTR("object for key %s missing"), key);
196 }
197 return NULL;
198 }
199
200 static bool SecXPCDictionaryCopyCertificates(xpc_object_t message, const char *key, CFArrayRef *certificates, CFErrorRef *error) {
201 xpc_object_t xpc_certificates = xpc_dictionary_get_value(message, key);
202 if (!xpc_certificates)
203 return SecError(errSecAllocate, error, CFSTR("no certs for key %s"), key);
204 *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error);
205 return *certificates;
206 }
207
208 static bool SecXPCDictionaryCopyCertificatesOptional(xpc_object_t message, const char *key, CFArrayRef *certificates, CFErrorRef *error) {
209 xpc_object_t xpc_certificates = xpc_dictionary_get_value(message, key);
210 if (!xpc_certificates) {
211 *certificates = NULL;
212 return true;
213 }
214 *certificates = SecCertificateXPCArrayCopyArray(xpc_certificates, error);
215 return *certificates;
216 }
217
218 static bool SecXPCDictionaryCopyPoliciesOptional(xpc_object_t message, const char *key, CFArrayRef *policies, CFErrorRef *error) {
219 xpc_object_t xpc_policies = xpc_dictionary_get_value(message, key);
220 if (!xpc_policies) {
221 if (policies)
222 *policies = NULL;
223 return true;
224 }
225 *policies = SecPolicyXPCArrayCopyArray(xpc_policies, error);
226 return *policies != NULL;
227 }
228
229 static SecTrustStoreRef SecXPCDictionaryGetTrustStore(xpc_object_t message, const char *key, CFErrorRef *error) {
230 SecTrustStoreRef ts = NULL;
231 CFStringRef domain = SecXPCDictionaryCopyString(message, key, error);
232 if (domain) {
233 ts = SecTrustStoreForDomainName(domain, error);
234 CFRelease(domain);
235 }
236 return ts;
237 }
238
239 static bool SecXPCDictionaryGetDouble(xpc_object_t message, const char *key, double *pvalue, CFErrorRef *error) {
240 *pvalue = xpc_dictionary_get_double(message, key);
241 if (*pvalue == NAN) {
242 return SecError(errSecParam, error, CFSTR("object for key %s bad double"), key);
243 }
244 return true;
245 }
246
247 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_object_t event) {
248 xpc_type_t type = xpc_get_type(event);
249 __block CFErrorRef error = NULL;
250 xpc_object_t xpcError = NULL;
251 xpc_object_t replyMessage = NULL;
252 SecTaskRef clientTask = NULL;
253 CFArrayRef accessGroups = NULL;
254 CFArrayRef domains = NULL;
255
256 secdebug("serverxpc", "entering");
257 if (type == XPC_TYPE_DICTIONARY) {
258 // TODO: Find out what we're dispatching.
259 replyMessage = xpc_dictionary_create_reply(event);
260
261 uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation);
262 secdebug("serverxpc", "operation: %@ (%" PRIu64 ")", SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation);
263
264 bool hasEntitlement;
265 audit_token_t auditToken = {};
266 xpc_connection_get_audit_token(connection, &auditToken);
267
268 clientTask = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken);
269 accessGroups = SecTaskCopyAccessGroups(clientTask);
270 if (operation == sec_add_shared_web_credential_id || operation == sec_copy_shared_web_credential_id) {
271 domains = SecTaskCopySharedWebCredentialDomains(clientTask);
272 }
273
274 // operations before kSecXPCOpTryUserCredentials don't need this entitlement.
275 hasEntitlement = (operation < kSecXPCOpTryUserCredentials) ||
276 (clientTask && SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementKeychainCloudCircle));
277
278 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
279 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
280
281 if (!hasEntitlement) {
282 CFErrorRef entitlementError = NULL;
283 SecError(errSecMissingEntitlement, &entitlementError, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)operation), clientTask, kSecEntitlementKeychainCloudCircle);
284 secnotice("serverxpc", "MissingEntitlement: %@", entitlementError);
285 CFReleaseSafe(entitlementError);
286 }
287
288 if (true) {
289 switch (operation)
290 {
291 case sec_item_add_id:
292 {
293 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
294 if (query) {
295 CFTypeRef result = NULL;
296 if (_SecItemAdd(query, accessGroups, &result, &error) && result) {
297 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
298 CFRelease(result);
299 }
300 CFRelease(query);
301 }
302 break;
303 }
304 case sec_item_copy_matching_id:
305 {
306 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
307 if (query) {
308 CFTypeRef result = NULL;
309 if (_SecItemCopyMatching(query, accessGroups, &result, &error) && result) {
310 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
311 CFRelease(result);
312 }
313 CFRelease(query);
314 }
315 break;
316 }
317 case sec_item_update_id:
318 {
319 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
320 if (query) {
321 CFDictionaryRef attributesToUpdate = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyAttributesToUpdate, &error);
322 if (attributesToUpdate) {
323 bool result = _SecItemUpdate(query, attributesToUpdate, accessGroups, &error);
324 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
325 CFRelease(attributesToUpdate);
326 }
327 CFRelease(query);
328 }
329 break;
330 }
331 case sec_item_delete_id:
332 {
333 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
334 if (query) {
335 bool result = _SecItemDelete(query, accessGroups, &error);
336 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
337 CFRelease(query);
338 }
339 break;
340 }
341 case sec_trust_store_contains_id:
342 {
343 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
344 if (ts) {
345 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error);
346 if (digest) {
347 bool contains;
348 if (SecTrustStoreContainsCertificateWithDigest(ts, digest, &contains, &error))
349 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, contains);
350 CFRelease(digest);
351 }
352 }
353 break;
354 }
355 case sec_trust_store_set_trust_settings_id:
356 {
357 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
358 if (ts) {
359 SecCertificateRef certificate = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, &error);
360 if (certificate) {
361 CFTypeRef trustSettingsDictOrArray = NULL;
362 if (SecXPCDictionaryCopyPListOptional(event, kSecXPCKeySettings, &trustSettingsDictOrArray, &error)) {
363 bool result = _SecTrustStoreSetTrustSettings(ts, certificate, trustSettingsDictOrArray, &error);
364 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
365 CFReleaseSafe(trustSettingsDictOrArray);
366 }
367 CFRelease(certificate);
368 }
369 }
370 break;
371 }
372 case sec_trust_store_remove_certificate_id:
373 {
374 SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error);
375 if (ts) {
376 CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error);
377 if (digest) {
378 bool result = SecTrustStoreRemoveCertificateWithDigest(ts, digest, &error);
379 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
380 CFRelease(digest);
381 }
382 }
383 break;
384 }
385 case sec_delete_all_id:
386 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, _SecItemDeleteAll(&error));
387 break;
388 case sec_trust_evaluate_id:
389 {
390 CFArrayRef certificates = NULL, anchors = NULL, policies = NULL;
391 bool anchorsOnly = xpc_dictionary_get_bool(event, kSecTrustAnchorsOnlyKey);
392 double verifyTime;
393 if (SecXPCDictionaryCopyCertificates(event, kSecTrustCertificatesKey, &certificates, &error) &&
394 SecXPCDictionaryCopyCertificatesOptional(event, kSecTrustAnchorsKey, &anchors, &error) &&
395 SecXPCDictionaryCopyPoliciesOptional(event, kSecTrustPoliciesKey, &policies, &error) &&
396 SecXPCDictionaryGetDouble(event, kSecTrustVerifyDateKey, &verifyTime, &error)) {
397 // If we have no error yet, capture connection and reply in block and properly retain them.
398 xpc_retain(connection);
399 CFRetainSafe(clientTask);
400
401 // Clear replyMessage so we don't send a synchronous reply.
402 xpc_object_t asyncReply = replyMessage;
403 replyMessage = NULL;
404
405 SecTrustServerEvaluateBlock(certificates, anchors, anchorsOnly, policies, verifyTime, accessGroups, ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, SecCertificatePathRef chain, CFErrorRef replyError) {
406 // Send back reply now
407 if (replyError) {
408 CFRetain(replyError);
409 } else {
410 xpc_dictionary_set_int64(asyncReply, kSecTrustResultKey, tr);
411 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustDetailsKey, details, &replyError) &&
412 SecXPCDictionarySetPListOptional(asyncReply, kSecTrustInfoKey, info, &replyError) &&
413 SecXPCDictionarySetChainOptional(asyncReply, kSecTrustChainKey, chain, &replyError);
414 }
415 if (replyError) {
416 secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyError);
417 xpc_object_t xpcReplyError = SecCreateXPCObjectWithCFError(replyError);
418 if (xpcReplyError) {
419 xpc_dictionary_set_value(asyncReply, kSecXPCKeyError, xpcReplyError);
420 xpc_release(xpcReplyError);
421 }
422 CFRelease(replyError);
423 } else {
424 secdebug("ipc", "%@ %@ reponding %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), asyncReply);
425 }
426
427 xpc_connection_send_message(connection, asyncReply);
428 xpc_release(asyncReply);
429 xpc_release(connection);
430 CFReleaseSafe(clientTask);
431 });
432 }
433 CFReleaseSafe(policies);
434 CFReleaseSafe(anchors);
435 CFReleaseSafe(certificates);
436 break;
437 }
438 case sec_keychain_backup_id:
439 {
440 CFDataRef keybag = NULL, passcode = NULL;
441 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybag, &error)) {
442 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
443 CFDataRef backup = _SecServerKeychainBackup(keybag, passcode, &error);
444 if (backup) {
445 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, backup, &error);
446 CFRelease(backup);
447 }
448 CFReleaseSafe(passcode);
449 }
450 CFReleaseSafe(keybag);
451 }
452 break;
453 }
454 case sec_keychain_restore_id:
455 {
456 CFDataRef backup = SecXPCDictionaryCopyData(event, kSecXPCKeyBackup, &error);
457 if (backup) {
458 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
459 if (keybag) {
460 CFDataRef passcode = NULL;
461 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
462 bool result = _SecServerKeychainRestore(backup, keybag, passcode, &error);
463 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
464 CFReleaseSafe(passcode);
465 }
466 CFRelease(keybag);
467 }
468 CFRelease(backup);
469 }
470 break;
471 }
472 case sec_keychain_sync_update_key_parameter_id:
473 {
474 CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
475 if (updates) {
476 CFArrayRef result = _SecServerKeychainSyncUpdateKeyParameter(updates, &error);
477 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
478 CFReleaseNull(result);
479 }
480 CFReleaseNull(updates);
481 break;
482 }
483 case sec_keychain_sync_update_circle_id:
484 {
485 CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
486 if (updates) {
487 CFArrayRef result = _SecServerKeychainSyncUpdateCircle(updates, &error);
488 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
489 CFReleaseNull(result);
490 }
491 CFReleaseNull(updates);
492 break;
493 }
494 case sec_keychain_sync_update_message_id:
495 {
496 CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
497 if (updates) {
498 CFArrayRef result = _SecServerKeychainSyncUpdateMessage(updates, &error);
499 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
500 CFReleaseNull(result);
501 }
502 CFReleaseNull(updates);
503 break;
504 }
505 case sec_keychain_backup_syncable_id:
506 {
507 CFDictionaryRef oldbackup = NULL;
508 if (SecXPCDictionaryCopyDictionaryOptional(event, kSecXPCKeyBackup, &oldbackup, &error)) {
509 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
510 if (keybag) {
511 CFDataRef passcode = NULL;
512 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
513 CFDictionaryRef newbackup = _SecServerBackupSyncable(oldbackup, keybag, passcode, &error);
514 if (newbackup) {
515 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, newbackup, &error);
516 CFRelease(newbackup);
517 }
518 CFReleaseSafe(passcode);
519 }
520 CFRelease(keybag);
521 }
522 CFReleaseSafe(oldbackup);
523 }
524 break;
525 }
526 case sec_keychain_restore_syncable_id:
527 {
528 CFDictionaryRef backup = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyBackup, &error);
529 if (backup) {
530 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
531 if (keybag) {
532 CFDataRef passcode = NULL;
533 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
534 bool result = _SecServerRestoreSyncable(backup, keybag, passcode, &error);
535 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
536 CFReleaseSafe(passcode);
537 }
538 CFRelease(keybag);
539 }
540 CFRelease(backup);
541 }
542 break;
543 }
544 case sec_ota_pki_asset_version_id:
545 {
546 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
547 SecOTAPKIGetCurrentAssetVersion(&error));
548 break;
549 }
550 case sec_add_shared_web_credential_id:
551 {
552 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
553 if (query) {
554 CFTypeRef result = NULL;
555 CFStringRef appID = (clientTask) ? SecTaskCopyApplicationIdentifier(clientTask) : NULL;
556 if (_SecAddSharedWebCredential(query, &auditToken, appID, domains, &result, &error) && result) {
557 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
558 CFRelease(result);
559 }
560 CFReleaseSafe(appID);
561 CFRelease(query);
562 }
563 break;
564 }
565 case sec_copy_shared_web_credential_id:
566 {
567 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
568 if (query) {
569 CFTypeRef result = NULL;
570 CFStringRef appID = (clientTask) ? SecTaskCopyApplicationIdentifier(clientTask) : NULL;
571 if (_SecCopySharedWebCredential(query, &auditToken, appID, domains, &result, &error) && result) {
572 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
573 CFRelease(result);
574 }
575 CFReleaseSafe(appID);
576 CFRelease(query);
577 }
578 break;
579 }
580 case sec_get_log_settings_id:
581 {
582 CFPropertyListRef currentList = SecCopyLogSettings_Server(&error);
583 if (currentList) {
584 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, currentList, &error);
585 }
586 CFReleaseSafe(currentList);
587 break;
588 }
589 case sec_set_xpc_log_settings_id:
590 {
591 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error);
592 if (newSettings) {
593 SecSetXPCLogSettings_Server(newSettings, &error);
594 }
595 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
596 CFReleaseNull(newSettings);
597 break;
598 }
599 case sec_otr_session_create_remote_id:
600 {
601 CFDataRef publicPeerId = NULL;
602 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCPublicPeerId, &publicPeerId, &error)) {
603 CFDataRef otrSession = _SecOTRSessionCreateRemote(publicPeerId, &error);
604 if (otrSession) {
605 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, otrSession, &error);
606 CFRelease(otrSession);
607 }
608 CFReleaseSafe(publicPeerId);
609 }
610 break;
611 }
612 case sec_otr_session_process_packet_remote_id:
613 {
614 CFDataRef sessionData = NULL, inputPacket = NULL, outputSessionData = NULL, outputPacket = NULL;
615 bool readyForMessages = false;
616 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCOTRSession, &sessionData, &error)) {
617 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &inputPacket, &error)) {
618 bool result = _SecOTRSessionProcessPacketRemote(sessionData, inputPacket, &outputSessionData, &outputPacket, &readyForMessages, &error);
619 if (result) {
620 SecXPCDictionarySetData(replyMessage, kSecXPCOTRSession, outputSessionData, &error);
621 SecXPCDictionarySetData(replyMessage, kSecXPCData, outputPacket, &error);
622 xpc_dictionary_set_bool(replyMessage, kSecXPCOTRReady, readyForMessages);
623 CFRelease(outputSessionData);
624 CFRelease(outputPacket);
625 }
626 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
627
628 CFReleaseSafe(inputPacket);
629 }
630 CFReleaseSafe(sessionData);
631 }
632 break;
633 }
634 case kSecXPCOpTryUserCredentials:
635 with_label_and_password(event, ^(CFStringRef label, CFDataRef password) {
636 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
637 SOSCCTryUserCredentials_Server(label, password, &error));
638 });
639 break;
640 case kSecXPCOpSetUserCredentials:
641 with_label_and_password(event, ^(CFStringRef label, CFDataRef password) {
642 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
643 SOSCCSetUserCredentials_Server(label, password, &error));
644 });
645 break;
646 case kSecXPCOpCanAuthenticate:
647 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
648 SOSCCCanAuthenticate_Server(&error));
649 break;
650 case kSecXPCOpPurgeUserCredentials:
651 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
652 SOSCCPurgeUserCredentials_Server(&error));
653 break;
654 case kSecXPCOpDeviceInCircle:
655 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
656 SOSCCThisDeviceIsInCircle_Server(&error));
657 break;
658 case kSecXPCOpRequestToJoin:
659 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
660 SOSCCRequestToJoinCircle_Server(&error));
661 break;
662 case kSecXPCOpRequestToJoinAfterRestore:
663 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
664 SOSCCRequestToJoinCircleAfterRestore_Server(&error));
665 break;
666 case kSecXPCOpRequestEnsureFreshParameters:
667 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
668 SOSCCRequestEnsureFreshParameters_Server(&error));
669 break;
670 case kSecXPCOpRequestDeviceID:
671 {
672 CFStringRef deviceID = SOSCCRequestDeviceID_Server(&error);
673 if (deviceID) {
674 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, deviceID, &error);
675 }
676 }
677 break;
678 case kSecXPCOpSetDeviceID:
679 {
680 secerror("securityd_xpc_dictionary_handler!");
681 CFStringRef IDS = SecXPCDictionaryCopyString(event, kSecXPCKeyDeviceID, &error);
682 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCSetDeviceID_Server(IDS, &error));
683 CFReleaseNull(IDS);
684 }
685 break;
686 case kSecXPCOpResetToOffering:
687 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
688 SOSCCResetToOffering_Server(&error));
689 break;
690 case kSecXPCOpResetToEmpty:
691 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
692 SOSCCResetToEmpty_Server(&error));
693 break;
694 case kSecXPCOpRemoveThisDeviceFromCircle:
695 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
696 SOSCCRemoveThisDeviceFromCircle_Server(&error));
697 break;
698 case kSecXPCOpBailFromCircle:
699 {
700 uint64_t limit_in_seconds = xpc_dictionary_get_uint64(event, kSecXPCLimitInMinutes);
701 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
702 SOSCCBailFromCircle_Server(limit_in_seconds, &error));
703 }
704 break;
705 case kSecXPCOpAcceptApplicants:
706 {
707 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos);
708 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
709 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
710 (applicants && SOSCCAcceptApplicants_Server(applicants, &error)));
711 CFReleaseSafe(applicants);
712 }
713 break;
714 case kSecXPCOpRejectApplicants:
715 {
716 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfos);
717 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
718 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
719 (applicants && SOSCCRejectApplicants_Server(applicants, &error)));
720 CFReleaseSafe(applicants);
721 }
722 break;
723 case kSecXPCOpCopyApplicantPeerInfo:
724 {
725 CFArrayRef array = SOSCCCopyApplicantPeerInfo_Server(&error);
726 if (array) {
727 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error);
728 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
729 xpc_release(xpc_array);
730 }
731 CFReleaseNull(array);
732 }
733 break;
734 case kSecXPCOpCopyValidPeerPeerInfo:
735 {
736 CFArrayRef array = SOSCCCopyValidPeerPeerInfo_Server(&error);
737 if (array) {
738 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error);
739 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
740 xpc_release(xpc_array);
741 }
742 CFReleaseNull(array);
743 }
744 break;
745 case kSecXPCOpValidateUserPublic:
746 {
747 bool trusted = SOSCCValidateUserPublic_Server(&error);
748 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, trusted);
749 }
750 break;
751 case kSecXPCOpCopyNotValidPeerPeerInfo:
752 {
753 CFArrayRef array = SOSCCCopyNotValidPeerPeerInfo_Server(&error);
754 if (array) {
755 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error);
756 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
757 xpc_release(xpc_array);
758 }
759 CFReleaseNull(array);
760 }
761 break;
762 case kSecXPCOpCopyGenerationPeerInfo:
763 {
764 CFArrayRef array = SOSCCCopyGenerationPeerInfo_Server(&error);
765 if (array) {
766 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
767 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
768 xpc_release(xpc_array);
769 }
770 CFReleaseNull(array);
771 }
772 break;
773 case kSecXPCOpCopyRetirementPeerInfo:
774 {
775 CFArrayRef array = SOSCCCopyRetirementPeerInfo_Server(&error);
776 if (array) {
777 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error);
778 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
779 xpc_release(xpc_array);
780 }
781 CFReleaseNull(array);
782 }
783 break;
784 case kSecXPCOpCopyPeerPeerInfo:
785 {
786 CFArrayRef array = SOSCCCopyPeerPeerInfo_Server(&error);
787 if (array) {
788 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error);
789 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
790 xpc_release(xpc_array);
791 }
792 CFReleaseNull(array);
793 }
794 break;
795 case kSecXPCOpCopyConcurringPeerPeerInfo:
796 {
797 CFArrayRef array = SOSCCCopyConcurringPeerPeerInfo_Server(&error);
798 if (array) {
799 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(array, &error);
800 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
801 xpc_release(xpc_array);
802 }
803 CFReleaseNull(array);
804 }
805 break;
806 case kSecXPCOpGetLastDepartureReason:
807 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
808 SOSCCGetLastDepartureReason_Server(&error));
809 break;
810 case kSecXPCOpProcessSyncWithAllPeers:
811 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
812 SOSCCProcessSyncWithAllPeers_Server(&error));
813 break;
814 case soscc_EnsurePeerRegistration_id:
815 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
816 SOSCCProcessEnsurePeerRegistration_Server(&error));
817 break;
818 case kSecXPCOpCopyIncompatibilityInfo: {
819 CFStringRef iis = SOSCCCopyIncompatibilityInfo_Server(&error);
820 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, iis, &error);
821 CFReleaseSafe(iis);
822 break;
823 }
824 case kSecXPCOpOTAGetEscrowCertificates:
825 {
826 uint32_t escrowRootType = (uint32_t)xpc_dictionary_get_uint64(event, "escrowType");
827 CFArrayRef array = SecOTAPKICopyCurrentEscrowCertificates(escrowRootType, &error);
828 if (array) {
829 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
830 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
831 xpc_release(xpc_array);
832 }
833 CFReleaseNull(array);
834 }
835 break;
836 case kSecXPCOpOTAPKIGetNewAsset:
837 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
838 SecOTAPKISignalNewAsset(&error));
839 break;
840 case kSecXPCOpRollKeys:
841 {
842 bool force = xpc_dictionary_get_bool(event, "force");
843 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
844 _SecServerRollKeys(force, &error));
845 }
846 break;
847 default:
848 break;
849 }
850 }
851
852 if (error)
853 {
854 if(SecErrorGetOSStatus(error) == errSecItemNotFound || isSOSErrorCoded(error, kSOSErrorPublicKeyAbsent))
855 secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
856 else
857 secerror("%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
858
859 xpcError = SecCreateXPCObjectWithCFError(error);
860 xpc_dictionary_set_value(replyMessage, kSecXPCKeyError, xpcError);
861 } else if (replyMessage) {
862 secdebug("ipc", "%@ %@ responding %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyMessage);
863 }
864 } else {
865 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &error, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event);
866 secerror("%@: returning error: %@", clientTask, error);
867 xpcError = SecCreateXPCObjectWithCFError(error);
868 replyMessage = xpc_create_reply_with_format(event, "{%string: %value}", kSecXPCKeyError, xpcError);
869 }
870
871 if (replyMessage) {
872 xpc_connection_send_message(connection, replyMessage);
873 xpc_release(replyMessage);
874 }
875 if (xpcError)
876 xpc_release(xpcError);
877 CFReleaseSafe(error);
878 CFReleaseSafe(accessGroups);
879 CFReleaseSafe(domains);
880 CFReleaseSafe(clientTask);
881 }
882
883 static void securityd_xpc_init()
884 {
885 secdebug("serverxpc", "start");
886
887 xpc_connection_t listener = xpc_connection_create_mach_service(kSecuritydXPCServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
888 if (!listener) {
889 seccritical("security failed to register xpc listener, exiting");
890 abort();
891 }
892
893 xpc_connection_set_event_handler(listener, ^(xpc_object_t connection) {
894 if (xpc_get_type(connection) == XPC_TYPE_CONNECTION) {
895 xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
896 if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) {
897 xpc_retain(connection);
898 xpc_retain(event);
899 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
900 securityd_xpc_dictionary_handler(connection, event);
901 xpc_release(event);
902 xpc_release(connection);
903 });
904 }
905 });
906 xpc_connection_resume(connection);
907 }
908 });
909 xpc_connection_resume(listener);
910 }
911
912 int main(int argc, char *argv[])
913 {
914 char *wait4debugger = getenv("WAIT4DEBUGGER");
915 if (wait4debugger && !strcasecmp("YES", wait4debugger)) {
916 seccritical("SIGSTOPing self, awaiting debugger");
917 kill(getpid(), SIGSTOP);
918 asl_log(NULL, NULL, ASL_LEVEL_CRIT,
919 "Again, for good luck (or bad debuggers)");
920 kill(getpid(), SIGSTOP);
921 }
922
923 securityd_init_server();
924 securityd_xpc_init();
925 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (NSEC_PER_SEC * 10)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
926 ^{
927 InitializeCloudKeychainTracing();
928 });
929 dispatch_main();
930 return 0;
931 }
932
933 /* vi:set ts=4 sw=4 et: */