X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/c38e3ce98599a410a47dc10253faa4d5830f13b2..427c49bcad63d042b29ada2ac27e3dfc4845c779:/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c?ds=sidebyside diff --git a/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c b/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c new file mode 100644 index 00000000..2e5c4427 --- /dev/null +++ b/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +// +// SOSCloudCircle.m +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Imported/SecItemServer.h" + +#include +#include +#include +#include + +#include + +#include + +#include +#define MINIMIZE_INCLUDES MINIMIZE_INCLUDES +#include "Imported/securityd_client.h" +#include "Imported/spi.h" + +#include "SOSRegressionUtilities.h" + + +const char * kSOSCCCircleChangedNotification = "com.apple.security.secureobjectsync.circlechanged"; + +#define do_if_registered(sdp, ...) if (gSecurityd && gSecurityd->sdp) { return gSecurityd->sdp(__VA_ARGS__); } + +static bool xpc_dictionary_entry_is_type(xpc_object_t dictionary, const char *key, xpc_type_t type) +{ + xpc_object_t value = xpc_dictionary_get_value(dictionary, key); + + return value && (xpc_get_type(value) == type); +} + +SOSCCStatus SOSCCThisDeviceIsInCircle(CFErrorRef *error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(SOSCCStatus, ^{ + SOSCCStatus result = kSOSCCError; + + do_if_registered(soscc_ThisDeviceIsInCircle, error); + + xpc_object_t message = securityd_create_message(kSecXPCOpDeviceInCircle, error); + if (message) { + xpc_object_t response = securityd_message_with_reply_sync(message, error); + + if (response && xpc_dictionary_entry_is_type(response, kSecXPCKeyResult, XPC_TYPE_INT64)) { + result = (SOSCCStatus) xpc_dictionary_get_int64(response, kSecXPCKeyResult); + } else { + result = kSOSCCError; + } + + if (result < 0) { + if (response && securityd_message_no_error(response, error)) + { + char *desc = xpc_copy_description(response); + SecCFCreateErrorWithFormat(0, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Remote error occurred/no info: %s"), desc); + free((void *)desc); + } + } + if(response) + xpc_release(response); + if(message) + xpc_release(message); + } + + + return result; + }, CFSTR("SOSCCStatus=%d")) +} + +static CFStringRef simple_cfstring_error_request(enum SecXPCOperation op, CFErrorRef* error) +{ + __block CFStringRef result = NULL; + + secdebug("sosops","enter - operation: %d", op); + securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + const char *c_string = xpc_dictionary_get_string(response, kSecXPCKeyResult); + + if (c_string) { + result = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)c_string, strlen(c_string), kCFStringEncodingUTF8, false); + } + + return c_string != NULL; + }); + return result; +} + +static bool simple_bool_error_request(enum SecXPCOperation op, CFErrorRef* error) +{ + __block bool result = false; + + secdebug("sosops","enter - operation: %d", op); + securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); + return result; + }); + return result; +} + +static int simple_int_error_request(enum SecXPCOperation op, CFErrorRef* error) +{ + __block int result = 0; + + secdebug("sosops","enter - operation: %d", op); + securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + int64_t temp_result = xpc_dictionary_get_int64(response, kSecXPCKeyResult); + if ((temp_result >= INT32_MIN) && (temp_result <= INT32_MAX)) { + result = (int)temp_result; + } + return result; + }); + return result; +} + +static CFArrayRef array_of_info_error_request(enum SecXPCOperation op, CFErrorRef* error) +{ + __block CFArrayRef result = NULL; + + secdebug("sosops","enter - operation: %d", op); + securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) { + xpc_object_t encoded_array = xpc_dictionary_get_value(response, kSecXPCKeyResult); + if (response && (NULL != encoded_array)) { + result = CreateArrayOfPeerInfoWithXPCObject(encoded_array, error); + } + return result != NULL; + }); + + return result; +} + +static bool info_array_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFErrorRef* error) +{ + __block bool result = false; + + secdebug("sosops", "enter - operation: %d", op); + securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { + xpc_object_t encoded_peers = CreateXPCObjectWithArrayOfPeerInfo(peer_infos, error); + if (encoded_peers) + xpc_dictionary_set_value(message, kSecXPCKeyPeerInfos, encoded_peers); + return encoded_peers != NULL; + }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); + return result; + }); + return result; +} + +static bool uint64_t_to_bool_error_request(enum SecXPCOperation op, + uint64_t number, + CFErrorRef* error) +{ + __block bool result = false; + + securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { + xpc_dictionary_set_uint64(message, kSecXPCLimitInMinutes, number); + return true; + }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); + return result; + }); + + return result; +} + +bool SOSCCRequestToJoinCircle(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_RequestToJoinCircle, error); + + return simple_bool_error_request(kSecXPCOpRequestToJoin, error); + }, NULL) +} + +bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_RequestToJoinCircleAfterRestore, error); + + return simple_bool_error_request(kSecXPCOpRequestToJoinAfterRestore, error); + }, NULL) +} + +bool SOSCCResetToOffering(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_ResetToOffering, error); + + return simple_bool_error_request(kSecXPCOpResetToOffering, error); + }, NULL) +} + +bool SOSCCResetToEmpty(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_ResetToEmpty, error); + + return simple_bool_error_request(kSecXPCOpResetToEmpty, error); + }, NULL) +} + +bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_RemoveThisDeviceFromCircle, error); + + return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle, error); + }, NULL) +} + +bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_BailFromCircle, limit_in_seconds, error); + + return uint64_t_to_bool_error_request(kSecXPCOpBailFromCircle, limit_in_seconds, error); + }, NULL) +} + + +CFArrayRef SOSCCCopyPeerPeerInfo(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(CFArrayRef, ^{ + do_if_registered(soscc_CopyPeerInfo, error); + + return array_of_info_error_request(kSecXPCOpCopyPeerPeerInfo, error); + }, CFSTR("return=%@")); +} + +CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(CFArrayRef, ^{ + do_if_registered(soscc_CopyConcurringPeerInfo, error); + + return array_of_info_error_request(kSecXPCOpCopyConcurringPeerPeerInfo, error); + }, CFSTR("return=%@")); +} + +CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(CFArrayRef, ^{ + do_if_registered(soscc_CopyApplicantPeerInfo, error); + + return array_of_info_error_request(kSecXPCOpCopyApplicantPeerInfo, error); + }, CFSTR("return=%@")) +} + +bool SOSCCAcceptApplicants(CFArrayRef applicants, CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_AcceptApplicants, applicants, error); + + return info_array_to_bool_error_request(kSecXPCOpAcceptApplicants, applicants, error); + }, NULL) +} + +bool SOSCCRejectApplicants(CFArrayRef applicants, CFErrorRef *error) +{ + sec_trace_enter_api(CFSTR("applicants=%@"), applicants); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_RejectApplicants, applicants, error); + + return info_array_to_bool_error_request(kSecXPCOpRejectApplicants, applicants, error); + }, NULL) +} + +static bool label_and_password_to_bool_error_request(enum SecXPCOperation op, + CFStringRef user_label, CFDataRef user_password, + CFErrorRef* error) +{ + __block bool result = false; + + securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { + CFStringPerformWithCString(user_label, ^(const char *utf8Str) { + xpc_dictionary_set_string(message, kSecXPCKeyUserLabel, utf8Str); + }); + xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password)); + return true; + }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); + return result; + }); + + return result; +} + +bool SOSCCRegisterUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) +{ + return SOSCCSetUserCredentials(user_label, user_password, error); +} + +bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) +{ + sec_trace_enter_api(CFSTR("user_label=%@"), user_label); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_SetUserCredentials, user_label, user_password, error); + + return label_and_password_to_bool_error_request(kSecXPCOpSetUserCredentials, user_label, user_password, error); + }, NULL) +} + +bool SOSCCTryUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error) +{ + sec_trace_enter_api(CFSTR("user_label=%@"), user_label); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_TryUserCredentials, user_label, user_password, error); + + return label_and_password_to_bool_error_request(kSecXPCOpTryUserCredentials, user_label, user_password, error); + }, NULL) +} + + +bool SOSCCCanAuthenticate(CFErrorRef* error) { + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_CanAuthenticate, error); + + return simple_bool_error_request(kSecXPCOpCanAuthenticate, error); + }, NULL) +} + +bool SOSCCPurgeUserCredentials(CFErrorRef* error) { + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(soscc_PurgeUserCredentials, error); + + return simple_bool_error_request(kSecXPCOpPurgeUserCredentials, error); + }, NULL) +} + +enum DepartureReason SOSCCGetLastDepartureReason(CFErrorRef *error) { + sec_trace_enter_api(NULL); + sec_trace_return_api(enum DepartureReason, ^{ + do_if_registered(soscc_GetLastDepartureReason, error); + + return (enum DepartureReason) simple_int_error_request(kSecXPCOpGetLastDepartureReason, error); + }, NULL) +} + +CFStringRef SOSCCCopyIncompatibilityInfo(CFErrorRef* error) { + sec_trace_enter_api(NULL); + sec_trace_return_api(CFStringRef, ^{ + do_if_registered(soscc_CopyIncompatibilityInfo, error); + + return simple_cfstring_error_request(kSecXPCOpCopyIncompatibilityInfo, error); + }, NULL) +} + +SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(SyncWithAllPeersReason, ^{ + do_if_registered(soscc_ProcessSyncWithAllPeers, error); + + return (SyncWithAllPeersReason) simple_int_error_request(kSecXPCOpProcessSyncWithAllPeers, error); + }, NULL) +} + +CFStringRef SOSCCGetStatusDescription(SOSCCStatus status) +{ + switch (status) { + case kSOSCCInCircle: + return CFSTR("InCircle"); + case kSOSCCNotInCircle: + return CFSTR("NotInCircle"); + case kSOSCCRequestPending: + return CFSTR("RequestPending"); + case kSOSCCCircleAbsent: + return CFSTR("CircleAbsent"); + case kSOSCCError: + return CFSTR("InternalError"); + case kSOSCCParamErr: + return CFSTR("ParamError"); + case kSOSCCMemoryErr: + return CFSTR("MemoryError"); + + default: + return CFSTR("WTF? Unknown Status"); + }; +}