]> git.saurik.com Git - apple/security.git/blob - Security/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c
Security-57031.1.35.tar.gz
[apple/security.git] / Security / sec / SOSCircle / SecureObjectSync / SOSCloudCircle.c
1 /*
2 * Copyright (c) 2012-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 //
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/SOSPeerInfoCollections.h>
36 #include <SecureObjectSync/SOSInternal.h>
37 #include <Security/SecKeyPriv.h>
38 #include <Security/SecFramework.h>
39 #include <CoreFoundation/CFXPCBridge.h>
40
41 #include <securityd/SecItemServer.h>
42
43 #include <utilities/SecDispatchRelease.h>
44 #include <utilities/SecCFRelease.h>
45 #include <utilities/SecCFWrappers.h>
46 #include <utilities/SecXPCError.h>
47
48 #include <utilities/debugging.h>
49
50 #include <CoreFoundation/CoreFoundation.h>
51
52 #include <xpc/xpc.h>
53 #define MINIMIZE_INCLUDES MINIMIZE_INCLUDES
54 #include <ipc/securityd_client.h>
55 #include <securityd/spi.h>
56
57 #include "SOSRegressionUtilities.h"
58
59
60 const char * kSOSCCCircleChangedNotification = "com.apple.security.secureobjectsync.circlechanged";
61
62 #define do_if_registered(sdp, ...) if (gSecurityd && gSecurityd->sdp) { return gSecurityd->sdp(__VA_ARGS__); }
63
64 static bool xpc_dictionary_entry_is_type(xpc_object_t dictionary, const char *key, xpc_type_t type)
65 {
66 xpc_object_t value = xpc_dictionary_get_value(dictionary, key);
67
68 return value && (xpc_get_type(value) == type);
69 }
70
71 SOSCCStatus SOSCCThisDeviceIsInCircle(CFErrorRef *error)
72 {
73 static int counter = 0;
74 if(counter++ > 5) secerror("SOSCCThisDeviceIsInCircle!! %d\n", counter);
75 sec_trace_enter_api(NULL);
76 sec_trace_return_api(SOSCCStatus, ^{
77 SOSCCStatus result = kSOSCCError;
78
79 do_if_registered(soscc_ThisDeviceIsInCircle, error);
80
81 xpc_object_t message = securityd_create_message(kSecXPCOpDeviceInCircle, error);
82 if (message) {
83 xpc_object_t response = securityd_message_with_reply_sync(message, error);
84
85 if (response && xpc_dictionary_entry_is_type(response, kSecXPCKeyResult, XPC_TYPE_INT64)) {
86 result = (SOSCCStatus) xpc_dictionary_get_int64(response, kSecXPCKeyResult);
87 } else {
88 result = kSOSCCError;
89 }
90
91 if (result < 0) {
92 if (response && securityd_message_no_error(response, error))
93 {
94 char *desc = xpc_copy_description(response);
95 SecCFCreateErrorWithFormat(0, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Remote error occurred/no info: %s"), desc);
96 free((void *)desc);
97 }
98 }
99 if(response)
100 xpc_release(response);
101 if(message)
102 xpc_release(message);
103 }
104
105
106 return result;
107 }, CFSTR("SOSCCStatus=%d"))
108 }
109
110 static CFStringRef simple_cfstring_error_request(enum SecXPCOperation op, CFErrorRef* error)
111 {
112 __block CFStringRef result = NULL;
113
114 secdebug("sosops","enter - operation: %d", op);
115 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
116 const char *c_string = xpc_dictionary_get_string(response, kSecXPCKeyResult);
117
118 if (c_string) {
119 result = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)c_string, strlen(c_string), kCFStringEncodingUTF8, false);
120 }
121
122 return c_string != NULL;
123 });
124 return result;
125 }
126
127 static bool simple_bool_error_request(enum SecXPCOperation op, CFErrorRef* error)
128 {
129 __block bool result = false;
130
131 secdebug("sosops","enter - operation: %d", op);
132 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
133 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
134 return result;
135 });
136 return result;
137 }
138
139 static CFArrayRef simple_array_error_request(enum SecXPCOperation op, CFErrorRef* error)
140 {
141 __block CFArrayRef result = false;
142
143 secdebug("sosops","enter - operation: %d", op);
144 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
145 xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult);
146 result = _CFXPCCreateCFObjectFromXPCObject(temp_result);
147 return result != NULL;
148 });
149 return result;
150 }
151
152 static int simple_int_error_request(enum SecXPCOperation op, CFErrorRef* error)
153 {
154 __block int result = 0;
155
156 secdebug("sosops","enter - operation: %d", op);
157 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
158 int64_t temp_result = xpc_dictionary_get_int64(response, kSecXPCKeyResult);
159 if ((temp_result >= INT32_MIN) && (temp_result <= INT32_MAX)) {
160 result = (int)temp_result;
161 }
162 return result;
163 });
164 return result;
165 }
166
167 static CFArrayRef array_of_info_error_request(enum SecXPCOperation op, CFErrorRef* error)
168 {
169 __block CFArrayRef result = NULL;
170
171 secdebug("sosops","enter - operation: %d", op);
172 securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) {
173 xpc_object_t encoded_array = xpc_dictionary_get_value(response, kSecXPCKeyResult);
174 if (response && (NULL != encoded_array)) {
175 result = CreateArrayOfPeerInfoWithXPCObject(encoded_array, error);
176 }
177 return result != NULL;
178 });
179
180 return result;
181 }
182
183 static bool info_array_to_bool_error_request(enum SecXPCOperation op, CFArrayRef peer_infos, CFErrorRef* error)
184 {
185 __block bool result = false;
186
187 secdebug("sosops", "enter - operation: %d", op);
188 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
189 xpc_object_t encoded_peers = CreateXPCObjectWithArrayOfPeerInfo(peer_infos, error);
190 if (encoded_peers)
191 xpc_dictionary_set_value(message, kSecXPCKeyPeerInfos, encoded_peers);
192 return encoded_peers != NULL;
193 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
194 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
195 return result;
196 });
197 return result;
198 }
199
200 static bool uint64_t_to_bool_error_request(enum SecXPCOperation op,
201 uint64_t number,
202 CFErrorRef* error)
203 {
204 __block bool result = false;
205
206 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
207 xpc_dictionary_set_uint64(message, kSecXPCLimitInMinutes, number);
208 return true;
209 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
210 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
211 return result;
212 });
213
214 return result;
215 }
216
217 bool SOSCCRequestToJoinCircle(CFErrorRef* error)
218 {
219 sec_trace_enter_api(NULL);
220 sec_trace_return_bool_api(^{
221 do_if_registered(soscc_RequestToJoinCircle, error);
222
223 return simple_bool_error_request(kSecXPCOpRequestToJoin, error);
224 }, NULL)
225 }
226
227 bool SOSCCRequestToJoinCircleAfterRestore(CFErrorRef* error)
228 {
229 sec_trace_enter_api(NULL);
230 sec_trace_return_bool_api(^{
231 do_if_registered(soscc_RequestToJoinCircleAfterRestore, error);
232
233 return simple_bool_error_request(kSecXPCOpRequestToJoinAfterRestore, error);
234 }, NULL)
235 }
236
237 bool SOSCCRequestEnsureFreshParameters(CFErrorRef* error)
238 {
239 sec_trace_enter_api(NULL);
240 sec_trace_return_bool_api(^{
241 do_if_registered(soscc_RequestEnsureFreshParameters, error);
242
243 return simple_bool_error_request(kSecXPCOpRequestEnsureFreshParameters, error);
244 }, NULL)
245 }
246
247 bool SOSCCResetToOffering(CFErrorRef* error)
248 {
249 secwarning("SOSCCResetToOffering called");
250 sec_trace_enter_api(NULL);
251 sec_trace_return_bool_api(^{
252 do_if_registered(soscc_ResetToOffering, error);
253
254 return simple_bool_error_request(kSecXPCOpResetToOffering, error);
255 }, NULL)
256 }
257
258 bool SOSCCResetToEmpty(CFErrorRef* error)
259 {
260 secwarning("SOSCCResetToEmpty called");
261 sec_trace_enter_api(NULL);
262 sec_trace_return_bool_api(^{
263 do_if_registered(soscc_ResetToEmpty, error);
264
265 return simple_bool_error_request(kSecXPCOpResetToEmpty, error);
266 }, NULL)
267 }
268
269 bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error)
270 {
271 sec_trace_enter_api(NULL);
272 sec_trace_return_bool_api(^{
273 do_if_registered(soscc_RemoveThisDeviceFromCircle, error);
274
275 return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle, error);
276 }, NULL)
277 }
278
279 bool SOSCCBailFromCircle_BestEffort(uint64_t limit_in_seconds, CFErrorRef* error)
280 {
281 sec_trace_enter_api(NULL);
282 sec_trace_return_bool_api(^{
283 do_if_registered(soscc_BailFromCircle, limit_in_seconds, error);
284
285 return uint64_t_to_bool_error_request(kSecXPCOpBailFromCircle, limit_in_seconds, error);
286 }, NULL)
287 }
288
289 bool SOSCCSignedOut(bool immediate, CFErrorRef* error)
290 {
291 uint64_t limit = strtoul(optarg, NULL, 10);
292
293 if(immediate)
294 return SOSCCRemoveThisDeviceFromCircle(error);
295 else
296 return SOSCCBailFromCircle_BestEffort(limit, error);
297
298 }
299
300 CFArrayRef SOSCCCopyPeerPeerInfo(CFErrorRef* error)
301 {
302 sec_trace_enter_api(NULL);
303 sec_trace_return_api(CFArrayRef, ^{
304 do_if_registered(soscc_CopyPeerInfo, error);
305
306 return array_of_info_error_request(kSecXPCOpCopyPeerPeerInfo, error);
307 }, CFSTR("return=%@"));
308 }
309
310 CFArrayRef SOSCCCopyConcurringPeerPeerInfo(CFErrorRef* error)
311 {
312 sec_trace_enter_api(NULL);
313 sec_trace_return_api(CFArrayRef, ^{
314 do_if_registered(soscc_CopyConcurringPeerInfo, error);
315
316 return array_of_info_error_request(kSecXPCOpCopyConcurringPeerPeerInfo, error);
317 }, CFSTR("return=%@"));
318 }
319
320 CFArrayRef SOSCCCopyGenerationPeerInfo(CFErrorRef* error)
321 {
322 sec_trace_enter_api(NULL);
323 sec_trace_return_api(CFArrayRef, ^{
324 do_if_registered(soscc_CopyGenerationPeerInfo, error);
325
326 return simple_array_error_request(kSecXPCOpCopyGenerationPeerInfo, error);
327 }, CFSTR("return=%@"));
328 }
329
330 CFArrayRef SOSCCCopyApplicantPeerInfo(CFErrorRef* error)
331 {
332 sec_trace_enter_api(NULL);
333 sec_trace_return_api(CFArrayRef, ^{
334 do_if_registered(soscc_CopyApplicantPeerInfo, error);
335
336 return array_of_info_error_request(kSecXPCOpCopyApplicantPeerInfo, error);
337 }, CFSTR("return=%@"));
338 }
339 bool SOSCCValidateUserPublic(CFErrorRef* error){
340 sec_trace_enter_api(NULL);
341 sec_trace_return_api(bool, ^{
342 do_if_registered(soscc_ValidateUserPublic, error);
343
344 return simple_bool_error_request(kSecXPCOpValidateUserPublic, error);
345 }, NULL);
346 }
347
348 CFArrayRef SOSCCCopyValidPeerPeerInfo(CFErrorRef* error)
349 {
350 sec_trace_enter_api(NULL);
351 sec_trace_return_api(CFArrayRef, ^{
352 do_if_registered(soscc_CopyValidPeerPeerInfo, error);
353
354 return array_of_info_error_request(kSecXPCOpCopyValidPeerPeerInfo, error);
355 }, CFSTR("return=%@"));
356 }
357
358 CFArrayRef SOSCCCopyNotValidPeerPeerInfo(CFErrorRef* error)
359 {
360 sec_trace_enter_api(NULL);
361 sec_trace_return_api(CFArrayRef, ^{
362 do_if_registered(soscc_CopyNotValidPeerPeerInfo, error);
363
364 return array_of_info_error_request(kSecXPCOpCopyNotValidPeerPeerInfo, error);
365 }, CFSTR("return=%@"));
366 }
367
368 CFArrayRef SOSCCCopyRetirementPeerInfo(CFErrorRef* error)
369 {
370 sec_trace_enter_api(NULL);
371 sec_trace_return_api(CFArrayRef, ^{
372 do_if_registered(soscc_CopyRetirementPeerInfo, error);
373
374 return array_of_info_error_request(kSecXPCOpCopyRetirementPeerInfo, error);
375 }, CFSTR("return=%@"));
376 }
377
378 bool SOSCCAcceptApplicants(CFArrayRef applicants, CFErrorRef* error)
379 {
380 sec_trace_enter_api(NULL);
381 sec_trace_return_bool_api(^{
382 do_if_registered(soscc_AcceptApplicants, applicants, error);
383
384 return info_array_to_bool_error_request(kSecXPCOpAcceptApplicants, applicants, error);
385 }, NULL)
386 }
387
388 bool SOSCCRejectApplicants(CFArrayRef applicants, CFErrorRef *error)
389 {
390 sec_trace_enter_api(CFSTR("applicants=%@"), applicants);
391 sec_trace_return_bool_api(^{
392 do_if_registered(soscc_RejectApplicants, applicants, error);
393
394 return info_array_to_bool_error_request(kSecXPCOpRejectApplicants, applicants, error);
395 }, NULL)
396 }
397
398 static bool label_and_password_to_bool_error_request(enum SecXPCOperation op,
399 CFStringRef user_label, CFDataRef user_password,
400 CFErrorRef* error)
401 {
402 __block bool result = false;
403
404 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
405 CFStringPerformWithCString(user_label, ^(const char *utf8Str) {
406 xpc_dictionary_set_string(message, kSecXPCKeyUserLabel, utf8Str);
407 });
408 xpc_dictionary_set_data(message, kSecXPCKeyUserPassword, CFDataGetBytePtr(user_password), CFDataGetLength(user_password));
409 return true;
410 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
411 result = xpc_dictionary_get_bool(response, kSecXPCKeyResult);
412 return result;
413 });
414
415 return result;
416 }
417
418 static bool deviceid_to_bool_error_request(enum SecXPCOperation op,
419 CFStringRef IDS,
420 CFErrorRef* error)
421 {
422 __block bool result = false;
423
424 securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
425 CFStringPerformWithCString(IDS, ^(const char *utf8Str) {
426 xpc_dictionary_set_string(message, kSecXPCKeyDeviceID, utf8Str);
427 });
428 return true;
429 }, ^bool(xpc_object_t response, __unused CFErrorRef *error) {
430 result = xpc_dictionary_get_bool(response, kSecXPCKeyDeviceID);
431 return result;
432 });
433
434 return result;
435 }
436
437 bool SOSCCRegisterUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
438 {
439 secerror("SOSCCRegisterUserCredentials - calling SOSCCSetUserCredentials!! %@\n", user_label);
440 return SOSCCSetUserCredentials(user_label, user_password, error);
441 }
442
443 bool SOSCCSetUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
444 {
445 secerror("SOSCCSetUserCredentials!! %@\n", user_label);
446 sec_trace_enter_api(CFSTR("user_label=%@"), user_label);
447 sec_trace_return_bool_api(^{
448 do_if_registered(soscc_SetUserCredentials, user_label, user_password, error);
449
450 return label_and_password_to_bool_error_request(kSecXPCOpSetUserCredentials, user_label, user_password, error);
451 }, NULL)
452 }
453 bool SOSCCSetDeviceID(CFStringRef IDS, CFErrorRef* error)
454 {
455 secerror("SOSCCSetDeviceID!! %@\n", IDS);
456 sec_trace_enter_api(NULL);
457 sec_trace_return_bool_api(^{
458 do_if_registered(soscc_SetDeviceID, IDS, error);
459 return deviceid_to_bool_error_request(kSecXPCOpSetDeviceID, IDS, error);
460 }, NULL)
461 }
462 bool SOSCCTryUserCredentials(CFStringRef user_label, CFDataRef user_password, CFErrorRef* error)
463 {
464 sec_trace_enter_api(CFSTR("user_label=%@"), user_label);
465 sec_trace_return_bool_api(^{
466 do_if_registered(soscc_TryUserCredentials, user_label, user_password, error);
467
468 return label_and_password_to_bool_error_request(kSecXPCOpTryUserCredentials, user_label, user_password, error);
469 }, NULL)
470 }
471
472
473 bool SOSCCCanAuthenticate(CFErrorRef* error) {
474 sec_trace_enter_api(NULL);
475 sec_trace_return_bool_api(^{
476 do_if_registered(soscc_CanAuthenticate, error);
477
478 return simple_bool_error_request(kSecXPCOpCanAuthenticate, error);
479 }, NULL)
480 }
481
482 bool SOSCCPurgeUserCredentials(CFErrorRef* error) {
483 sec_trace_enter_api(NULL);
484 sec_trace_return_bool_api(^{
485 do_if_registered(soscc_PurgeUserCredentials, error);
486
487 return simple_bool_error_request(kSecXPCOpPurgeUserCredentials, error);
488 }, NULL)
489 }
490
491 enum DepartureReason SOSCCGetLastDepartureReason(CFErrorRef *error) {
492 sec_trace_enter_api(NULL);
493 sec_trace_return_api(enum DepartureReason, ^{
494 do_if_registered(soscc_GetLastDepartureReason, error);
495
496 return (enum DepartureReason) simple_int_error_request(kSecXPCOpGetLastDepartureReason, error);
497 }, NULL)
498 }
499
500 CFStringRef SOSCCCopyIncompatibilityInfo(CFErrorRef* error) {
501 sec_trace_enter_api(NULL);
502 sec_trace_return_api(CFStringRef, ^{
503 do_if_registered(soscc_CopyIncompatibilityInfo, error);
504
505 return simple_cfstring_error_request(kSecXPCOpCopyIncompatibilityInfo, error);
506 }, NULL)
507 }
508
509 CFStringRef SOSCCRequestDeviceID(CFErrorRef* error)
510 {
511 sec_trace_enter_api(NULL);
512 sec_trace_return_api(CFStringRef, ^{
513 do_if_registered(soscc_RequestDeviceID, error);
514 CFStringRef deviceID = simple_cfstring_error_request(kSecXPCOpRequestDeviceID, error);
515 return deviceID;
516 }, NULL)
517 }
518
519 bool SOSCCProcessEnsurePeerRegistration(CFErrorRef* error){
520 secnotice("updates", "enter SOSCCProcessEnsurePeerRegistration");
521 sec_trace_enter_api(NULL);
522 sec_trace_return_bool_api(^{
523 do_if_registered(soscc_EnsurePeerRegistration, error);
524
525 return simple_bool_error_request(soscc_EnsurePeerRegistration_id, error);
526 }, NULL)
527 }
528
529
530 SyncWithAllPeersReason SOSCCProcessSyncWithAllPeers(CFErrorRef* error)
531 {
532 sec_trace_enter_api(NULL);
533 sec_trace_return_api(SyncWithAllPeersReason, ^{
534 do_if_registered(soscc_ProcessSyncWithAllPeers, error);
535
536 return (SyncWithAllPeersReason) simple_int_error_request(kSecXPCOpProcessSyncWithAllPeers, error);
537 }, NULL)
538 }
539
540 CFStringRef SOSCCGetStatusDescription(SOSCCStatus status)
541 {
542 switch (status) {
543 case kSOSCCInCircle:
544 return CFSTR("InCircle");
545 case kSOSCCNotInCircle:
546 return CFSTR("NotInCircle");
547 case kSOSCCRequestPending:
548 return CFSTR("RequestPending");
549 case kSOSCCCircleAbsent:
550 return CFSTR("CircleAbsent");
551 case kSOSCCError:
552 return CFSTR("InternalError");
553 default:
554 return CFSTR("Unknown Status (%d)");
555 };
556 }