]> git.saurik.com Git - apple/security.git/blob - sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c
Security-55471.14.18.tar.gz
[apple/security.git] / sec / SOSCircle / SecureObjectSync / SOSCloudCircle.c
1 /*
2 * Copyright (c) 2012 Apple Computer, 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 //
25 // SOSCloudCircle.m
26 //
27
28 #include <stdio.h>
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>
39
40 #include "Imported/SecItemServer.h"
41
42 #include <utilities/SecDispatchRelease.h>
43 #include <utilities/SecCFRelease.h>
44 #include <utilities/SecCFWrappers.h>
45 #include <utilities/SecXPCError.h>
46
47 #include <utilities/debugging.h>
48
49 #include <CoreFoundation/CoreFoundation.h>
50
51 #include <xpc/xpc.h>
52 #define MINIMIZE_INCLUDES MINIMIZE_INCLUDES
53 #include "Imported/securityd_client.h"
54 #include "Imported/spi.h"
55
56 #include "SOSRegressionUtilities.h"
57
58
59 const char * kSOSCCCircleChangedNotification = "com.apple.security.secureobjectsync.circlechanged";
60
61 #define do_if_registered(sdp, ...) if (gSecurityd && gSecurityd->sdp) { return gSecurityd->sdp(__VA_ARGS__); }
62
63 static bool xpc_dictionary_entry_is_type(xpc_object_t dictionary, const char *key, xpc_type_t type)
64 {
65 xpc_object_t value = xpc_dictionary_get_value(dictionary, key);
66
67 return value && (xpc_get_type(value) == type);
68 }
69
70 SOSCCStatus SOSCCThisDeviceIsInCircle(CFErrorRef *error)
71 {
72 sec_trace_enter_api(NULL);
73 sec_trace_return_api(SOSCCStatus, ^{
74 SOSCCStatus result = kSOSCCError;
75
76 do_if_registered(soscc_ThisDeviceIsInCircle, error);
77
78 xpc_object_t message = securityd_create_message(kSecXPCOpDeviceInCircle, error);
79 if (message) {
80 xpc_object_t response = securityd_message_with_reply_sync(message, error);
81
82 if (response && xpc_dictionary_entry_is_type(response, kSecXPCKeyResult, XPC_TYPE_INT64)) {
83 result = (SOSCCStatus) xpc_dictionary_get_int64(response, kSecXPCKeyResult);
84 } else {
85 result = kSOSCCError;
86 }
87
88 if (result < 0) {
89 if (response && securityd_message_no_error(response, error))
90 {
91 char *desc = xpc_copy_description(response);
92 SecCFCreateErrorWithFormat(0, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Remote error occurred/no info: %s"), desc);
93 free((void *)desc);
94 }
95 }
96 if(response)
97 xpc_release(response);
98 if(message)
99 xpc_release(message);
100 }
101
102
103 return result;
104 }, CFSTR("SOSCCStatus=%d"))
105 }
106
107 static CFStringRef simple_cfstring_error_request(enum SecXPCOperation op, CFErrorRef* error)
108 {
109 __block CFStringRef result = NULL;
110
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);
114
115 if (c_string) {
116 result = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)c_string, strlen(c_string), kCFStringEncodingUTF8, false);
117 }
118
119 return c_string != NULL;
120 });
121 return result;
122 }
123
124 static bool simple_bool_error_request(enum SecXPCOperation op, CFErrorRef* error)
125 {
126 __block bool result = false;
127
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);
131 return result;
132 });
133 return result;
134 }
135
136 static int simple_int_error_request(enum SecXPCOperation op, CFErrorRef* error)
137 {
138 __block int result = 0;
139
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;
145 }
146 return result;
147 });
148 return result;
149 }
150
151 static CFArrayRef array_of_info_error_request(enum SecXPCOperation op, CFErrorRef* error)
152 {
153 __block CFArrayRef result = NULL;
154
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);
160 }
161 return result != NULL;
162 });
163
164 return result;
165 }
166
167 static bool info_array_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFErrorRef* error)
168 {
169 __block bool result = false;
170
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);
174 if (encoded_peers)
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);
179 return result;
180 });
181 return result;
182 }
183
184 static bool uint64_t_to_bool_error_request(enum SecXPCOperation op,
185 uint64_t number,
186 CFErrorRef* error)
187 {
188 __block bool result = false;
189
190 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
191 xpc_dictionary_set_uint64(message, kSecXPCLimitInMinutes, number);
192 return true;
193 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
194 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
195 return result;
196 });
197
198 return result;
199 }
200
201 bool SOSCCRequestToJoinCircle(CFErrorRef* error)
202 {
203 sec_trace_enter_api(NULL);
204 sec_trace_return_bool_api(^{
205 do_if_registered(soscc_RequestToJoinCircle, error);
206
207 return simple_bool_error_request(kSecXPCOpRequestToJoin, error);
208 }, NULL)
209 }
210
211 bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error)
212 {
213 sec_trace_enter_api(NULL);
214 sec_trace_return_bool_api(^{
215 do_if_registered(soscc_RequestToJoinCircleAfterRestore, error);
216
217 return simple_bool_error_request(kSecXPCOpRequestToJoinAfterRestore, error);
218 }, NULL)
219 }
220
221 bool SOSCCResetToOffering(CFErrorRef* error)
222 {
223 sec_trace_enter_api(NULL);
224 sec_trace_return_bool_api(^{
225 do_if_registered(soscc_ResetToOffering, error);
226
227 return simple_bool_error_request(kSecXPCOpResetToOffering, error);
228 }, NULL)
229 }
230
231 bool SOSCCResetToEmpty(CFErrorRef* error)
232 {
233 sec_trace_enter_api(NULL);
234 sec_trace_return_bool_api(^{
235 do_if_registered(soscc_ResetToEmpty, error);
236
237 return simple_bool_error_request(kSecXPCOpResetToEmpty, error);
238 }, NULL)
239 }
240
241 bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error)
242 {
243 sec_trace_enter_api(NULL);
244 sec_trace_return_bool_api(^{
245 do_if_registered(soscc_RemoveThisDeviceFromCircle, error);
246
247 return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle, error);
248 }, NULL)
249 }
250
251 bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error)
252 {
253 sec_trace_enter_api(NULL);
254 sec_trace_return_bool_api(^{
255 do_if_registered(soscc_BailFromCircle, limit_in_seconds, error);
256
257 return uint64_t_to_bool_error_request(kSecXPCOpBailFromCircle, limit_in_seconds, error);
258 }, NULL)
259 }
260
261
262 CFArrayRef SOSCCCopyPeerPeerInfo(CFErrorRef* error)
263 {
264 sec_trace_enter_api(NULL);
265 sec_trace_return_api(CFArrayRef, ^{
266 do_if_registered(soscc_CopyPeerInfo, error);
267
268 return array_of_info_error_request(kSecXPCOpCopyPeerPeerInfo, error);
269 }, CFSTR("return=%@"));
270 }
271
272 CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error)
273 {
274 sec_trace_enter_api(NULL);
275 sec_trace_return_api(CFArrayRef, ^{
276 do_if_registered(soscc_CopyConcurringPeerInfo, error);
277
278 return array_of_info_error_request(kSecXPCOpCopyConcurringPeerPeerInfo, error);
279 }, CFSTR("return=%@"));
280 }
281
282 CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error)
283 {
284 sec_trace_enter_api(NULL);
285 sec_trace_return_api(CFArrayRef, ^{
286 do_if_registered(soscc_CopyApplicantPeerInfo, error);
287
288 return array_of_info_error_request(kSecXPCOpCopyApplicantPeerInfo, error);
289 }, CFSTR("return=%@"))
290 }
291
292 bool SOSCCAcceptApplicants(CFArrayRef applicants, CFErrorRef* error)
293 {
294 sec_trace_enter_api(NULL);
295 sec_trace_return_bool_api(^{
296 do_if_registered(soscc_AcceptApplicants, applicants, error);
297
298 return info_array_to_bool_error_request(kSecXPCOpAcceptApplicants, applicants, error);
299 }, NULL)
300 }
301
302 bool SOSCCRejectApplicants(CFArrayRef applicants, CFErrorRef *error)
303 {
304 sec_trace_enter_api(CFSTR("applicants=%@"), applicants);
305 sec_trace_return_bool_api(^{
306 do_if_registered(soscc_RejectApplicants, applicants, error);
307
308 return info_array_to_bool_error_request(kSecXPCOpRejectApplicants, applicants, error);
309 }, NULL)
310 }
311
312 static bool label_and_password_to_bool_error_request(enum SecXPCOperation op,
313 CFStringRef user_label, CFDataRef user_password,
314 CFErrorRef* error)
315 {
316 __block bool result = false;
317
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);
321 });
322 xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password));
323 return true;
324 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
325 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
326 return result;
327 });
328
329 return result;
330 }
331
332 bool SOSCCRegisterUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
333 {
334 return SOSCCSetUserCredentials(user_label, user_password, error);
335 }
336
337 bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
338 {
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);
342
343 return label_and_password_to_bool_error_request(kSecXPCOpSetUserCredentials, user_label, user_password, error);
344 }, NULL)
345 }
346
347 bool SOSCCTryUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
348 {
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);
352
353 return label_and_password_to_bool_error_request(kSecXPCOpTryUserCredentials, user_label, user_password, error);
354 }, NULL)
355 }
356
357
358 bool SOSCCCanAuthenticate(CFErrorRef* error) {
359 sec_trace_enter_api(NULL);
360 sec_trace_return_bool_api(^{
361 do_if_registered(soscc_CanAuthenticate, error);
362
363 return simple_bool_error_request(kSecXPCOpCanAuthenticate, error);
364 }, NULL)
365 }
366
367 bool SOSCCPurgeUserCredentials(CFErrorRef* error) {
368 sec_trace_enter_api(NULL);
369 sec_trace_return_bool_api(^{
370 do_if_registered(soscc_PurgeUserCredentials, error);
371
372 return simple_bool_error_request(kSecXPCOpPurgeUserCredentials, error);
373 }, NULL)
374 }
375
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);
380
381 return (enum DepartureReason) simple_int_error_request(kSecXPCOpGetLastDepartureReason, error);
382 }, NULL)
383 }
384
385 CFStringRef SOSCCCopyIncompatibilityInfo(CFErrorRef* error) {
386 sec_trace_enter_api(NULL);
387 sec_trace_return_api(CFStringRef, ^{
388 do_if_registered(soscc_CopyIncompatibilityInfo, error);
389
390 return simple_cfstring_error_request(kSecXPCOpCopyIncompatibilityInfo, error);
391 }, NULL)
392 }
393
394 SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error)
395 {
396 sec_trace_enter_api(NULL);
397 sec_trace_return_api(SyncWithAllPeersReason, ^{
398 do_if_registered(soscc_ProcessSyncWithAllPeers, error);
399
400 return (SyncWithAllPeersReason) simple_int_error_request(kSecXPCOpProcessSyncWithAllPeers, error);
401 }, NULL)
402 }
403
404 CFStringRef SOSCCGetStatusDescription(SOSCCStatus status)
405 {
406 switch (status) {
407 case kSOSCCInCircle:
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");
415 case kSOSCCError:
416 return CFSTR("InternalError");
417 case kSOSCCParamErr:
418 return CFSTR("ParamError");
419 case kSOSCCMemoryErr:
420 return CFSTR("MemoryError");
421
422 default:
423 return CFSTR("WTF? Unknown Status");
424 };
425 }