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
68static 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
81static 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
106static CFStringRef SecTaskCopyApplicationIdentifier(SecTaskRef task) {
107    return SecTaskCopyStringForEntitlement(task,
108        kSecEntitlementApplicationIdentifier);
109}
110
111static CFArrayRef SecTaskCopySharedWebCredentialDomains(SecTaskRef task) {
112    return SecTaskCopyArrayOfStringsForEntitlement(task,
113        kSecEntitlementAssociatedDomains);
114}
115
116static 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
147static 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
159static 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
174static 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
186static 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
200static 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
208static 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
218static 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
229static 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
239static 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
247static 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
883static 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
912int 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: */
934