2 * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
29 #include <AssertMacros.h>
30 #include <SecureObjectSync/SOSCloudCircle.h>
31 #include <SecureObjectSync/SOSCloudCircleInternal.h>
32 #include <SecureObjectSync/SOSCircle.h>
33 #include <SecureObjectSync/SOSAccount.h>
34 #include <SecureObjectSync/SOSFullPeerInfo.h>
35 #include <SecureObjectSync/SOSInternal.h>
36 #include <Security/SecKeyPriv.h>
37 #include <Security/SecFramework.h>
38 #include <CoreFoundation/CFXPCBridge.h>
40 #include "Imported/SecItemServer.h"
42 #include <utilities/SecDispatchRelease.h>
43 #include <utilities/SecCFRelease.h>
44 #include <utilities/SecCFWrappers.h>
45 #include <utilities/SecXPCError.h>
47 #include <utilities/debugging.h>
49 #include <CoreFoundation/CoreFoundation.h>
52 #define MINIMIZE_INCLUDES MINIMIZE_INCLUDES
53 #include "Imported/securityd_client.h"
54 #include "Imported/spi.h"
56 #include "SOSRegressionUtilities.h"
59 const char * kSOSCCCircleChangedNotification
= "com.apple.security.secureobjectsync.circlechanged";
61 #define do_if_registered(sdp, ...) if (gSecurityd && gSecurityd->sdp) { return gSecurityd->sdp(__VA_ARGS__); }
63 static bool xpc_dictionary_entry_is_type(xpc_object_t dictionary
, const char *key
, xpc_type_t type
)
65 xpc_object_t value
= xpc_dictionary_get_value(dictionary
, key
);
67 return value
&& (xpc_get_type(value
) == type
);
70 SOSCCStatus
SOSCCThisDeviceIsInCircle(CFErrorRef
*error
)
72 sec_trace_enter_api(NULL
);
73 sec_trace_return_api(SOSCCStatus
, ^{
74 SOSCCStatus result
= kSOSCCError
;
76 do_if_registered(soscc_ThisDeviceIsInCircle
, error
);
78 xpc_object_t message
= securityd_create_message(kSecXPCOpDeviceInCircle
, error
);
80 xpc_object_t response
= securityd_message_with_reply_sync(message
, error
);
82 if (response
&& xpc_dictionary_entry_is_type(response
, kSecXPCKeyResult
, XPC_TYPE_INT64
)) {
83 result
= (SOSCCStatus
) xpc_dictionary_get_int64(response
, kSecXPCKeyResult
);
89 if (response
&& securityd_message_no_error(response
, error
))
91 char *desc
= xpc_copy_description(response
);
92 SecCFCreateErrorWithFormat(0, sSecXPCErrorDomain
, NULL
, error
, NULL
, CFSTR("Remote error occurred/no info: %s"), desc
);
97 xpc_release(response
);
104 }, CFSTR("SOSCCStatus=%d"))
107 static CFStringRef
simple_cfstring_error_request(enum SecXPCOperation op
, CFErrorRef
* error
)
109 __block CFStringRef result
= NULL
;
111 secdebug("sosops","enter - operation: %d", op
);
112 securityd_send_sync_and_do(op
, error
, NULL
, ^bool(xpc_object_t response
, __unused CFErrorRef
*error
) {
113 const char *c_string
= xpc_dictionary_get_string(response
, kSecXPCKeyResult
);
116 result
= CFStringCreateWithBytes(kCFAllocatorDefault
, (const UInt8
*)c_string
, strlen(c_string
), kCFStringEncodingUTF8
, false);
119 return c_string
!= NULL
;
124 static bool simple_bool_error_request(enum SecXPCOperation op
, CFErrorRef
* error
)
126 __block
bool result
= false;
128 secdebug("sosops","enter - operation: %d", op
);
129 securityd_send_sync_and_do(op
, error
, NULL
, ^bool(xpc_object_t response
, __unused CFErrorRef
*error
) {
130 result
= xpc_dictionary_get_bool(response
, kSecXPCKeyResult
);
136 static int simple_int_error_request(enum SecXPCOperation op
, CFErrorRef
* error
)
138 __block
int result
= 0;
140 secdebug("sosops","enter - operation: %d", op
);
141 securityd_send_sync_and_do(op
, error
, NULL
, ^bool(xpc_object_t response
, __unused CFErrorRef
*error
) {
142 int64_t temp_result
= xpc_dictionary_get_int64(response
, kSecXPCKeyResult
);
143 if ((temp_result
>= INT32_MIN
) && (temp_result
<= INT32_MAX
)) {
144 result
= (int)temp_result
;
151 static CFArrayRef
array_of_info_error_request(enum SecXPCOperation op
, CFErrorRef
* error
)
153 __block CFArrayRef result
= NULL
;
155 secdebug("sosops","enter - operation: %d", op
);
156 securityd_send_sync_and_do(op
, error
, NULL
, ^bool(xpc_object_t response
, CFErrorRef
*error
) {
157 xpc_object_t encoded_array
= xpc_dictionary_get_value(response
, kSecXPCKeyResult
);
158 if (response
&& (NULL
!= encoded_array
)) {
159 result
= CreateArrayOfPeerInfoWithXPCObject(encoded_array
, error
);
161 return result
!= NULL
;
167 static bool info_array_to_bool_error_request(enum SecXPCOperation op
, CFArrayRef peer_infos
, CFErrorRef
* error
)
169 __block
bool result
= false;
171 secdebug("sosops", "enter - operation: %d", op
);
172 securityd_send_sync_and_do(op
, error
, ^bool(xpc_object_t message
, CFErrorRef
*error
) {
173 xpc_object_t encoded_peers
= CreateXPCObjectWithArrayOfPeerInfo(peer_infos
, error
);
175 xpc_dictionary_set_value(message
, kSecXPCKeyPeerInfos
, encoded_peers
);
176 return encoded_peers
!= NULL
;
177 }, ^bool(xpc_object_t response
, __unused CFErrorRef
*error
) {
178 result
= xpc_dictionary_get_bool(response
, kSecXPCKeyResult
);
184 static bool uint64_t_to_bool_error_request(enum SecXPCOperation op
,
188 __block
bool result
= false;
190 securityd_send_sync_and_do(op
, error
, ^bool(xpc_object_t message
, CFErrorRef
*error
) {
191 xpc_dictionary_set_uint64(message
, kSecXPCLimitInMinutes
, number
);
193 }, ^bool(xpc_object_t response
, __unused CFErrorRef
*error
) {
194 result
= xpc_dictionary_get_bool(response
, kSecXPCKeyResult
);
201 bool SOSCCRequestToJoinCircle(CFErrorRef
* error
)
203 sec_trace_enter_api(NULL
);
204 sec_trace_return_bool_api(^{
205 do_if_registered(soscc_RequestToJoinCircle
, error
);
207 return simple_bool_error_request(kSecXPCOpRequestToJoin
, error
);
211 bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef
* error
)
213 sec_trace_enter_api(NULL
);
214 sec_trace_return_bool_api(^{
215 do_if_registered(soscc_RequestToJoinCircleAfterRestore
, error
);
217 return simple_bool_error_request(kSecXPCOpRequestToJoinAfterRestore
, error
);
221 bool SOSCCResetToOffering(CFErrorRef
* error
)
223 sec_trace_enter_api(NULL
);
224 sec_trace_return_bool_api(^{
225 do_if_registered(soscc_ResetToOffering
, error
);
227 return simple_bool_error_request(kSecXPCOpResetToOffering
, error
);
231 bool SOSCCResetToEmpty(CFErrorRef
* error
)
233 sec_trace_enter_api(NULL
);
234 sec_trace_return_bool_api(^{
235 do_if_registered(soscc_ResetToEmpty
, error
);
237 return simple_bool_error_request(kSecXPCOpResetToEmpty
, error
);
241 bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef
* error
)
243 sec_trace_enter_api(NULL
);
244 sec_trace_return_bool_api(^{
245 do_if_registered(soscc_RemoveThisDeviceFromCircle
, error
);
247 return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle
, error
);
251 bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds
, CFErrorRef
* error
)
253 sec_trace_enter_api(NULL
);
254 sec_trace_return_bool_api(^{
255 do_if_registered(soscc_BailFromCircle
, limit_in_seconds
, error
);
257 return uint64_t_to_bool_error_request(kSecXPCOpBailFromCircle
, limit_in_seconds
, error
);
262 CFArrayRef
SOSCCCopyPeerPeerInfo(CFErrorRef
* error
)
264 sec_trace_enter_api(NULL
);
265 sec_trace_return_api(CFArrayRef
, ^{
266 do_if_registered(soscc_CopyPeerInfo
, error
);
268 return array_of_info_error_request(kSecXPCOpCopyPeerPeerInfo
, error
);
269 }, CFSTR("return=%@"));
272 CFArrayRef
SOSCCCopyConcurringPeerPeerInfo(CFErrorRef
* error
)
274 sec_trace_enter_api(NULL
);
275 sec_trace_return_api(CFArrayRef
, ^{
276 do_if_registered(soscc_CopyConcurringPeerInfo
, error
);
278 return array_of_info_error_request(kSecXPCOpCopyConcurringPeerPeerInfo
, error
);
279 }, CFSTR("return=%@"));
282 CFArrayRef
SOSCCCopyApplicantPeerInfo(CFErrorRef
* error
)
284 sec_trace_enter_api(NULL
);
285 sec_trace_return_api(CFArrayRef
, ^{
286 do_if_registered(soscc_CopyApplicantPeerInfo
, error
);
288 return array_of_info_error_request(kSecXPCOpCopyApplicantPeerInfo
, error
);
289 }, CFSTR("return=%@"))
292 bool SOSCCAcceptApplicants(CFArrayRef applicants
, CFErrorRef
* error
)
294 sec_trace_enter_api(NULL
);
295 sec_trace_return_bool_api(^{
296 do_if_registered(soscc_AcceptApplicants
, applicants
, error
);
298 return info_array_to_bool_error_request(kSecXPCOpAcceptApplicants
, applicants
, error
);
302 bool SOSCCRejectApplicants(CFArrayRef applicants
, CFErrorRef
*error
)
304 sec_trace_enter_api(CFSTR("applicants=%@"), applicants
);
305 sec_trace_return_bool_api(^{
306 do_if_registered(soscc_RejectApplicants
, applicants
, error
);
308 return info_array_to_bool_error_request(kSecXPCOpRejectApplicants
, applicants
, error
);
312 static bool label_and_password_to_bool_error_request(enum SecXPCOperation op
,
313 CFStringRef user_label
, CFDataRef user_password
,
316 __block
bool result
= false;
318 securityd_send_sync_and_do(op
, error
, ^bool(xpc_object_t message
, CFErrorRef
*error
) {
319 CFStringPerformWithCString(user_label
, ^(const char *utf8Str
) {
320 xpc_dictionary_set_string(message
, kSecXPCKeyUserLabel
, utf8Str
);
322 xpc_dictionary_set_data(message
, kSecXPCKeyUserPassword
, CFDataGetBytePtr(user_password
), CFDataGetLength(user_password
));
324 }, ^bool(xpc_object_t response
, __unused CFErrorRef
*error
) {
325 result
= xpc_dictionary_get_bool(response
, kSecXPCKeyResult
);
332 bool SOSCCRegisterUserCredentials(CFStringRef user_label
, CFDataRef user_password
, CFErrorRef
* error
)
334 return SOSCCSetUserCredentials(user_label
, user_password
, error
);
337 bool SOSCCSetUserCredentials(CFStringRef user_label
, CFDataRef user_password
, CFErrorRef
* error
)
339 sec_trace_enter_api(CFSTR("user_label=%@"), user_label
);
340 sec_trace_return_bool_api(^{
341 do_if_registered(soscc_SetUserCredentials
, user_label
, user_password
, error
);
343 return label_and_password_to_bool_error_request(kSecXPCOpSetUserCredentials
, user_label
, user_password
, error
);
347 bool SOSCCTryUserCredentials(CFStringRef user_label
, CFDataRef user_password
, CFErrorRef
* error
)
349 sec_trace_enter_api(CFSTR("user_label=%@"), user_label
);
350 sec_trace_return_bool_api(^{
351 do_if_registered(soscc_TryUserCredentials
, user_label
, user_password
, error
);
353 return label_and_password_to_bool_error_request(kSecXPCOpTryUserCredentials
, user_label
, user_password
, error
);
358 bool SOSCCCanAuthenticate(CFErrorRef
* error
) {
359 sec_trace_enter_api(NULL
);
360 sec_trace_return_bool_api(^{
361 do_if_registered(soscc_CanAuthenticate
, error
);
363 return simple_bool_error_request(kSecXPCOpCanAuthenticate
, error
);
367 bool SOSCCPurgeUserCredentials(CFErrorRef
* error
) {
368 sec_trace_enter_api(NULL
);
369 sec_trace_return_bool_api(^{
370 do_if_registered(soscc_PurgeUserCredentials
, error
);
372 return simple_bool_error_request(kSecXPCOpPurgeUserCredentials
, error
);
376 enum DepartureReason
SOSCCGetLastDepartureReason(CFErrorRef
*error
) {
377 sec_trace_enter_api(NULL
);
378 sec_trace_return_api(enum DepartureReason
, ^{
379 do_if_registered(soscc_GetLastDepartureReason
, error
);
381 return (enum DepartureReason
) simple_int_error_request(kSecXPCOpGetLastDepartureReason
, error
);
385 CFStringRef
SOSCCCopyIncompatibilityInfo(CFErrorRef
* error
) {
386 sec_trace_enter_api(NULL
);
387 sec_trace_return_api(CFStringRef
, ^{
388 do_if_registered(soscc_CopyIncompatibilityInfo
, error
);
390 return simple_cfstring_error_request(kSecXPCOpCopyIncompatibilityInfo
, error
);
394 SyncWithAllPeersReason
SOSCCProcessSyncWithAllPeers(CFErrorRef
* error
)
396 sec_trace_enter_api(NULL
);
397 sec_trace_return_api(SyncWithAllPeersReason
, ^{
398 do_if_registered(soscc_ProcessSyncWithAllPeers
, error
);
400 return (SyncWithAllPeersReason
) simple_int_error_request(kSecXPCOpProcessSyncWithAllPeers
, error
);
404 CFStringRef
SOSCCGetStatusDescription(SOSCCStatus status
)
408 return CFSTR("InCircle");
409 case kSOSCCNotInCircle
:
410 return CFSTR("NotInCircle");
411 case kSOSCCRequestPending
:
412 return CFSTR("RequestPending");
413 case kSOSCCCircleAbsent
:
414 return CFSTR("CircleAbsent");
416 return CFSTR("InternalError");
418 return CFSTR("ParamError");
419 case kSOSCCMemoryErr
:
420 return CFSTR("MemoryError");
423 return CFSTR("WTF? Unknown Status");