]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSViews.m
Security-59754.41.1.tar.gz
[apple/security.git] / keychain / SecureObjectSync / SOSViews.m
1 /*
2 * Copyright (c) 2015 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 * SOSViews.c - Implementation of views
26 */
27
28 #include <AssertMacros.h>
29 #include <TargetConditionals.h>
30
31 #include "SOSViews.h"
32 #include <utilities/SecCFWrappers.h>
33 #include <utilities/SecCFRelease.h>
34 #include <utilities/SecXPCError.h>
35
36 #include <utilities/SecCFError.h>
37 #include <utilities/der_set.h>
38 #include "keychain/SecureObjectSync/SOSInternal.h"
39
40 #include <Security/SecureObjectSync/SOSPeerInfo.h>
41 #include "keychain/SecureObjectSync/SOSPeerInfoV2.h"
42 #include "keychain/SecureObjectSync/SOSPeerInfoPriv.h"
43 #include <Security/SecureObjectSync/SOSCloudCircle.h>
44
45 #include <utilities/array_size.h>
46 #include "keychain/SecureObjectSync/SOSAccount.h"
47 #include "keychain/SecureObjectSync/SOSAccountPriv.h"
48
49 #define viewMemError CFSTR("Failed to get memory for views in PeerInfo")
50 #define viewUnknownError CFSTR("Unknown view(%@) (ViewResultCode=%d)")
51 #define viewInvalidError CFSTR("Peer is invalid for this view(%@) (ViewResultCode=%d)")
52
53 // Internal Views:
54 const CFStringRef kSOSViewKeychainV0_tomb = CFSTR("KeychainV0-tomb"); // iCloud Keychain backup for v0 peers (no tombstones)
55 const CFStringRef kSOSViewBackupBagV0_tomb = CFSTR("BackupBagV0-tomb"); // iCloud Keychain backup bag for v0 peers (no tombstones)
56 const CFStringRef kSOSViewWiFi_tomb = CFSTR("WiFi-tomb");
57 const CFStringRef kSOSViewAutofillPasswords_tomb = CFSTR("Passwords-tomb");
58 const CFStringRef kSOSViewSafariCreditCards_tomb = CFSTR("CreditCards-tomb");
59 const CFStringRef kSOSViewiCloudIdentity_tomb = CFSTR("iCloudIdentity-tomb");
60 const CFStringRef kSOSViewOtherSyncable_tomb = CFSTR("OtherSyncable-tomb");
61
62 // Views
63 const CFStringRef kSOSViewKeychainV0 = CFSTR("KeychainV0"); // iCloud Keychain syncing for v0 peers
64
65 #undef DOVIEWMACRO
66 #define DOVIEWMACRO(VIEWNAME, DEFSTRING, CMDSTRING, SYSTEM, DEFAULTSETTING, INITIALSYNCSETTING, ALWAYSONSETTING, BACKUPSETTING, V0SETTING) \
67 const CFStringRef k##SYSTEM##View##VIEWNAME = CFSTR(DEFSTRING);
68 #include "keychain/SecureObjectSync/ViewList.list"
69
70 // View Hints
71 // Note that by definition, there cannot be a V0 view hint
72 // These will be deprecated for new constants found in SecItemPriv.h
73 const CFStringRef kSOSViewHintPCSMasterKey = CFSTR("PCS-MasterKey");
74 const CFStringRef kSOSViewHintPCSiCloudDrive = CFSTR("PCS-iCloudDrive");
75 const CFStringRef kSOSViewHintPCSPhotos = CFSTR("PCS-Photos");
76 const CFStringRef kSOSViewHintPCSCloudKit = CFSTR("PCS-CloudKit");
77 const CFStringRef kSOSViewHintPCSEscrow = CFSTR("PCS-Escrow");
78 const CFStringRef kSOSViewHintPCSFDE = CFSTR("PCS-FDE");
79 const CFStringRef kSOSViewHintPCSMailDrop = CFSTR("PCS-Maildrop");
80 const CFStringRef kSOSViewHintPCSiCloudBackup = CFSTR("PCS-Backup");
81 const CFStringRef kSOSViewHintPCSNotes = CFSTR("PCS-Notes");
82 const CFStringRef kSOSViewHintPCSiMessage = CFSTR("PCS-iMessage");
83 const CFStringRef kSOSViewHintPCSFeldspar = CFSTR("PCS-Feldspar");
84
85 const CFStringRef kSOSViewHintAppleTV = CFSTR("AppleTV");
86 const CFStringRef kSOSViewHintHomeKit = CFSTR("HomeKit");
87
88 CFSetRef sTestViewSet = NULL;
89
90
91 CFMutableSetRef SOSViewCopyViewSet(ViewSetKind setKind) {
92 CFMutableSetRef result = CFSetCreateMutableForCFTypes(kCFAllocatorDefault);
93
94 // Only return views in the SOS system, unless they asked for kViewSetCKKS
95 #undef DOVIEWMACRO
96 #define __TYPE_MEMBER_ false
97 #define __TYPE_MEMBER_D true
98 #define __TYPE_MEMBER_I true
99 #define __TYPE_MEMBER_A true
100 #define __TYPE_MEMBER_V true
101 #define __TYPE_MEMBER_B true
102 #define __SYSTEM_SOS true
103 #define __SYSTEM_CKKS false
104
105 #define DOVIEWMACRO_SOS(VIEWNAME, DEFSTRING, CMDSTRING, SYSTEM, DEFAULT, INITIAL, ALWAYSON, BACKUP, V0) \
106 if(((setKind == kViewSetAll) || \
107 ((setKind == kViewSetDefault) && __TYPE_MEMBER_##DEFAULT) || \
108 ((setKind == kViewSetInitial) && __TYPE_MEMBER_##INITIAL) || \
109 ((setKind == kViewSetAlwaysOn) && __TYPE_MEMBER_##ALWAYSON) || \
110 ((setKind == kViewSetRequiredForBackup) && __TYPE_MEMBER_##BACKUP) || \
111 ((setKind == kViewSetV0) && __TYPE_MEMBER_##V0) )) { \
112 CFSetAddValue(result, k##SYSTEM##View##VIEWNAME); \
113 }
114
115 #define DOVIEWMACRO_CKKS(VIEWNAME, DEFSTRING, CMDSTRING, SYSTEM, DEFAULT, INITIAL, ALWAYSON, BACKUP, V0) \
116 if(setKind == kViewSetCKKS) { \
117 CFSetAddValue(result, k##SYSTEM##View##VIEWNAME); \
118 }
119
120 #define DOVIEWMACRO(VIEWNAME, DEFSTRING, CMDSTRING, SYSTEM, DEFAULT, INITIAL, ALWAYSON, BACKUP, V0) \
121 DOVIEWMACRO_##SYSTEM(VIEWNAME, DEFSTRING, CMDSTRING, SYSTEM, DEFAULT, INITIAL, ALWAYSON, BACKUP, V0)
122 #include "keychain/SecureObjectSync/ViewList.list"
123 if(setKind == kViewSetAlwaysOn && sTestViewSet != NULL) {
124 CFReleaseNull(result);
125 result = CFSetCreateMutableForCFTypes(kCFAllocatorDefault);
126 }
127 if(setKind == kViewSetAll && sTestViewSet != NULL) {
128 CFSetUnion(result, sTestViewSet);
129 }
130 return result;
131 }
132
133 bool SOSViewInSOSSystem(CFStringRef view) {
134
135 if(CFEqualSafe(view, kSOSViewKeychainV0)) {
136 return true;
137 }
138
139 #undef DOVIEWMACRO
140 #define DOVIEWMACRO(VIEWNAME, DEFSTRING, CMDSTRING, SYSTEM, DEFAULT, INITIAL, ALWAYSON, BACKUP, V0) \
141 if(CFEqualSafe(view, k##SYSTEM##View##VIEWNAME)) { \
142 return __SYSTEM_##SYSTEM; \
143 }
144 #include "keychain/SecureObjectSync/ViewList.list"
145
146 return false;
147 }
148
149 bool SOSViewHintInSOSSystem(CFStringRef viewHint) {
150 #undef DOVIEWMACRO
151 #define CHECK_VIEWHINT_(VIEWNAME, SYSTEM) \
152 if(CFEqualSafe(viewHint, kSecAttrViewHint##VIEWNAME)) { \
153 return __SYSTEM_##SYSTEM; \
154 }
155 #define CHECK_VIEWHINT_V(VIEWNAME, SYSTEM)
156
157 #define DOVIEWMACRO(VIEWNAME, DEFSTRING, CMDSTRING, SYSTEM, DEFAULT, INITIAL, ALWAYSON, BACKUP, V0) \
158 CHECK_VIEWHINT_##V0(VIEWNAME, SYSTEM)
159 #include "keychain/SecureObjectSync/ViewList.list"
160
161 return false;
162 }
163
164 bool SOSViewHintInCKKSSystem(CFStringRef viewHint) {
165
166 #undef DOVIEWMACRO_SOS
167 #undef DOVIEWMACRO_CKKS
168 #undef DOVIEWMACRO
169
170 #define DOVIEWMACRO_SOS(VIEWNAME, DEFSTRING, CMDSTRING, SYSTEM, DEFAULT, INITIAL, ALWAYSON, BACKUP, V0)
171 #define DOVIEWMACRO_CKKS(VIEWNAME, DEFSTRING, CMDSTRING, SYSTEM, DEFAULT, INITIAL, ALWAYSON, BACKUP, V0) \
172 if(CFEqualSafe(viewHint, kSecAttrViewHint##VIEWNAME)) { \
173 return true; \
174 }
175 #define DOVIEWMACRO(VIEWNAME, DEFSTRING, CMDSTRING, SYSTEM, DEFAULT, INITIAL, ALWAYSON, BACKUP, V0) \
176 DOVIEWMACRO_##SYSTEM(VIEWNAME, DEFSTRING, CMDSTRING, SYSTEM, DEFAULT, INITIAL, ALWAYSON, BACKUP, V0)
177
178 #include "keychain/SecureObjectSync/ViewList.list"
179
180 return false;
181 }
182
183
184 CFGiblisGetSingleton(CFSetRef, SOSViewsGetV0ViewSet, defaultViewSet, ^{
185 // Since peer->views must never be NULL, fill in with a default
186 const void *values[] = { kSOSViewKeychainV0 };
187 *defaultViewSet = CFSetCreate(kCFAllocatorDefault, values, array_size(values), &kCFTypeSetCallBacks);
188 });
189
190 CFGiblisGetSingleton(CFSetRef, SOSViewsGetV0SubviewSet, subViewSet, (^{
191 // Since peer->views must never be NULL, fill in with a default
192 *subViewSet = SOSViewCopyViewSet(kViewSetV0);
193 }));
194
195 CFGiblisGetSingleton(CFSetRef, SOSViewsGetV0BackupViewSet, defaultViewSet, ^{
196 const void *values[] = { kSOSViewKeychainV0_tomb };
197 *defaultViewSet = CFSetCreate(kCFAllocatorDefault, values, array_size(values), &kCFTypeSetCallBacks);
198 });
199
200 CFGiblisGetSingleton(CFSetRef, SOSViewsGetV0BackupBagViewSet, defaultViewSet, ^{
201 const void *values[] = { kSOSViewBackupBagV0_tomb };
202 *defaultViewSet = CFSetCreate(kCFAllocatorDefault, values, array_size(values), &kCFTypeSetCallBacks);
203 });
204
205
206 CFGiblisGetSingleton(CFSetRef, SOSViewsGetInitialSyncSubviewSet, subViewSet, (^{
207 *subViewSet = SOSViewCopyViewSet(kViewSetInitial);
208 }));
209
210
211 bool SOSViewsIsV0Subview(CFStringRef viewName) {
212 return CFSetContainsValue(SOSViewsGetV0SubviewSet(), viewName);
213 }
214
215 static CFMutableSetRef sosAllViews = NULL;
216
217 void SOSViewsSetTestViewsSet(CFSetRef testViewNames) {
218 CFReleaseNull(sTestViewSet);
219 if(testViewNames) {
220 CFRetainAssign(sTestViewSet, testViewNames);
221 }
222
223 CFReleaseNull(sosAllViews);
224 sosAllViews = SOSViewCopyViewSet(kViewSetAll);
225 CFSetAddValue(sosAllViews, kSOSViewKeychainV0);
226 if(sTestViewSet) CFSetUnion(sosAllViews, sTestViewSet);
227 }
228
229
230 CFSetRef SOSViewsGetAllCurrent(void) {
231 static dispatch_once_t dot;
232 dispatch_once(&dot, ^{
233 sosAllViews = SOSViewCopyViewSet(kViewSetAll);
234
235 CFSetAddValue(sosAllViews, kSOSViewKeychainV0);
236 if(sTestViewSet) CFSetUnion(sosAllViews, sTestViewSet);
237 });
238 return sosAllViews;
239 }
240
241 static CFDictionaryRef SOSViewsGetBitmasks(void) {
242 static dispatch_once_t once;
243 static CFMutableDictionaryRef masks = NULL;
244
245 dispatch_once(&once, ^{
246 CFSetRef views = SOSViewsGetAllCurrent();
247 CFMutableArrayRef viewArray = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
248 CFSetForEach(views, ^(const void *value) {
249 CFStringRef viewName = (CFStringRef) value;
250 CFArrayAppendValue(viewArray, viewName);
251 });
252 CFIndex viewCount = CFArrayGetCount(viewArray);
253 if(viewCount > 32) {
254 secnotice("views", "Too many views defined, can't make bitmask (%d)", (int) viewCount);
255 } else {
256 __block uint32_t maskValue = 1;
257 CFRange all = CFRangeMake(0, viewCount);
258 CFArraySortValues(viewArray, all, (CFComparatorFunction)CFStringCompare, NULL);
259 masks = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, NULL);
260 CFArrayForEach(viewArray, ^(const void *value) {
261 CFDictionaryAddValue(masks, value, (const void *) (uintptr_t) maskValue);
262 maskValue <<= 1;
263 });
264 }
265 CFReleaseNull(viewArray);
266 });
267 return masks;
268 }
269
270 uint64_t SOSViewBitmaskFromSet(CFSetRef views) {
271 __block uint64_t retval = 0;
272 if(!views) return retval;
273 CFDictionaryRef masks = SOSViewsGetBitmasks();
274 if(masks) {
275 CFSetForEach(views, ^(const void *viewName) {
276 uint64_t viewMask = (uint64_t) CFDictionaryGetValue(masks, viewName);
277 retval |= viewMask;
278 });
279 }
280 return retval;
281 }
282
283 uint64_t SOSPeerInfoViewBitMask(SOSPeerInfoRef pi) {
284 __block uint64_t retval = 0;
285 CFSetRef views = SOSPeerInfoCopyEnabledViews(pi);
286 if(views) {
287 retval = SOSViewBitmaskFromSet(views);
288 CFReleaseNull(views);
289 }
290 return retval;
291 }
292
293 CFSetRef SOSViewCreateSetFromBitmask(uint64_t bitmask) {
294 CFMutableSetRef retval = NULL;
295 CFDictionaryRef masks = SOSViewsGetBitmasks();
296 if(masks) {
297 retval = CFSetCreateMutableForCFTypes(kCFAllocatorDefault);
298 CFDictionaryForEach(masks, ^(const void *key, const void *value) {
299 CFStringRef viewName = (CFStringRef) key;
300 uint64_t viewMask = (uint64_t) value;
301 if(bitmask & viewMask) {
302 CFSetAddValue(retval, viewName);
303 }
304 });
305 }
306 return retval;
307 }
308
309 bool SOSPeerInfoSupportsCKKSForAll(SOSPeerInfoRef peerInfo) {
310 if(!peerInfo) {
311 return false;
312 }
313
314 bool ret = false;
315 CFBooleanRef value = SOSPeerInfoV2DictionaryCopyBoolean(peerInfo, sCKKSForAll);
316
317 if(value) {
318 ret = CFBooleanGetValue(value) ? true : false;
319 }
320
321 CFReleaseNull(value);
322 return ret;
323 }
324
325 void SOSPeerInfoSetSupportsCKKSForAll(SOSPeerInfoRef peerInfo, bool supports) {
326 return SOSPeerInfoV2DictionarySetValue(peerInfo, sCKKSForAll, supports ? kCFBooleanTrue : kCFBooleanFalse);
327 }
328
329 const char *SOSViewsXlateAction(SOSViewActionCode action) {
330 switch(action) {
331 case kSOSCCViewEnable: return "kSOSCCViewEnable";
332 case kSOSCCViewDisable: return "kSOSCCViewDisable";
333 case kSOSCCViewQuery: return "kSOSCCViewQuery";
334 default: return "unknownViewAction";
335 }
336 }
337
338
339 // Eventually this will want to know the gestalt or security properties...
340 void SOSViewsForEachDefaultEnabledViewName(void (^operation)(CFStringRef viewName)) {
341 CFMutableSetRef defaultViews = SOSViewCopyViewSet(kViewSetDefault);
342
343 CFSetForEach(defaultViews, ^(const void *value) {
344 CFStringRef name = asString(value, NULL);
345
346 if (name) {
347 operation(name);
348 }
349 });
350
351 CFReleaseNull(defaultViews);
352 }
353
354 static bool SOSViewsIsKnownView(CFStringRef viewname) {
355 if(!viewname) return false;
356 CFSetRef allViews = SOSViewsGetAllCurrent();
357 if(CFSetContainsValue(allViews, viewname)) return true;
358 secnotice("views","Not a known view");
359 return false;
360 }
361
362 static bool SOSViewsRequireIsKnownView(CFStringRef viewname, CFErrorRef* error) {
363 return SOSViewsIsKnownView(viewname) || SOSCreateErrorWithFormat(kSOSErrorNameMismatch, NULL, error, NULL, viewUnknownError, viewname, kSOSCCNoSuchView);
364 }
365
366 bool SOSPeerInfoIsEnabledView(SOSPeerInfoRef pi, CFStringRef viewName) {
367 if (pi->version < kSOSPeerV2BaseVersion) {
368 return CFSetContainsValue(SOSViewsGetV0ViewSet(), viewName);
369 } else {
370 return SOSPeerInfoV2DictionaryHasSetContaining(pi, sViewsKey, viewName);
371 }
372 }
373
374 void SOSPeerInfoWithEnabledViewSet(SOSPeerInfoRef pi, void (^operation)(CFSetRef enabled)) {
375 if (pi->version < kSOSPeerV2BaseVersion) {
376 operation(SOSViewsGetV0ViewSet());
377 } else {
378 SOSPeerInfoV2DictionaryWithSet(pi, sViewsKey, operation);
379 }
380 }
381
382 CFMutableSetRef SOSPeerInfoCopyEnabledViews(SOSPeerInfoRef pi) {
383 if (pi->version < kSOSPeerV2BaseVersion) {
384 return CFSetCreateMutableCopy(kCFAllocatorDefault, CFSetGetCount(SOSViewsGetV0ViewSet()), SOSViewsGetV0ViewSet());
385 } else {
386 CFMutableSetRef views = SOSPeerInfoV2DictionaryCopySet(pi, sViewsKey);
387 if (!views) {
388 // This is unexpected: log and return an empty set to prevent <rdar://problem/21938868>
389 secerror("%@ v2 peer has no views", SOSPeerInfoGetPeerID(pi));
390 views = CFSetCreateMutableForCFTypes(kCFAllocatorDefault);
391 }
392 return views;
393 }
394 }
395
396 CFSetRef SOSPeerInfoGetPermittedViews(SOSPeerInfoRef pi) {
397 return SOSViewsGetAllCurrent();
398 }
399
400 static void SOSPeerInfoSetViews(SOSPeerInfoRef pi, CFSetRef newviews) {
401 if(!newviews) {
402 secnotice("views","Asked to swap to NULL views");
403 return;
404 }
405 SOSPeerInfoV2DictionarySetValue(pi, sViewsKey, newviews);
406 }
407
408 static bool SOSPeerInfoViewIsValid(SOSPeerInfoRef pi, CFStringRef viewname) {
409 return true;
410 }
411
412 SOSViewResultCode SOSViewsEnable(SOSPeerInfoRef pi, CFStringRef viewname, CFErrorRef *error) {
413 SOSViewResultCode retval = kSOSCCGeneralViewError;
414
415 CFMutableSetRef newviews = SOSPeerInfoCopyEnabledViews(pi);
416 require_action_quiet(newviews, fail,
417 SOSCreateError(kSOSErrorAllocationFailure, viewMemError, NULL, error));
418 require_action_quiet(SOSViewsRequireIsKnownView(viewname, error), fail,
419 retval = kSOSCCNoSuchView);
420 require_action_quiet(SOSPeerInfoViewIsValid(pi, viewname), fail,
421 SOSCreateErrorWithFormat(kSOSErrorNameMismatch, NULL, error, NULL, viewInvalidError, viewname, retval = kSOSCCViewNotQualified));
422 CFSetAddValue(newviews, viewname);
423 SOSPeerInfoSetViews(pi, newviews);
424 CFReleaseSafe(newviews);
425 return kSOSCCViewMember;
426
427 fail:
428 CFReleaseNull(newviews);
429 secnotice("views","Failed to enable view(%@): %@", viewname, error ? *error : NULL);
430 return retval;
431 }
432
433 bool SOSViewSetEnable(SOSPeerInfoRef pi, CFSetRef viewSet) {
434 __block bool addedView = false;
435 CFMutableSetRef newviews = SOSPeerInfoCopyEnabledViews(pi);
436 require_action_quiet(newviews, errOut, secnotice("views", "failed to copy enabled views"));
437
438 CFSetForEach(viewSet, ^(const void *value) {
439 CFStringRef viewName = (CFStringRef) value;
440 if(SOSViewsIsKnownView(viewName) && SOSPeerInfoViewIsValid(pi, viewName)) {
441 if (!CFSetContainsValue(newviews, viewName)) {
442 addedView = true;
443 CFSetAddValue(newviews, viewName);
444 }
445 } else {
446 secnotice("views", "couldn't add view %@", viewName);
447 }
448 });
449 require_quiet(addedView, errOut);
450
451 SOSPeerInfoSetViews(pi, newviews);
452
453 errOut:
454 CFReleaseNull(newviews);
455 return addedView;
456 }
457
458
459 SOSViewResultCode SOSViewsDisable(SOSPeerInfoRef pi, CFStringRef viewname, CFErrorRef *error) {
460 SOSViewResultCode retval = kSOSCCGeneralViewError;
461 CFMutableSetRef newviews = SOSPeerInfoCopyEnabledViews(pi);
462 require_action_quiet(newviews, fail,
463 SOSCreateError(kSOSErrorAllocationFailure, viewMemError, NULL, error));
464 require_action_quiet(SOSViewsRequireIsKnownView(viewname, error), fail, retval = kSOSCCNoSuchView);
465
466 CFSetRemoveValue(newviews, viewname);
467 SOSPeerInfoSetViews(pi, newviews);
468 CFReleaseSafe(newviews);
469 return kSOSCCViewNotMember;
470
471 fail:
472 CFReleaseNull(newviews);
473 secnotice("views","Failed to disable view(%@): %@", viewname, error ? *error : NULL);
474 return retval;
475 }
476
477
478 bool SOSViewSetDisable(SOSPeerInfoRef pi, CFSetRef viewSet) {
479 __block bool removed = false;
480 CFMutableSetRef newviews = SOSPeerInfoCopyEnabledViews(pi);
481 require_action_quiet(newviews, errOut, secnotice("views", "failed to copy enabled views"));
482
483 CFSetForEach(viewSet, ^(const void *value) {
484 CFStringRef viewName = (CFStringRef) value;
485 if(SOSViewsIsKnownView(viewName) && CFSetContainsValue(newviews, viewName)) {
486 removed = true;
487 CFSetRemoveValue(newviews, viewName);
488 } else {
489 secnotice("views", "couldn't delete view %@", viewName);
490 }
491 });
492
493 require_quiet(removed, errOut);
494
495 SOSPeerInfoSetViews(pi, newviews);
496
497 errOut:
498 CFReleaseNull(newviews);
499 return removed;
500 }
501
502
503 SOSViewResultCode SOSViewsQuery(SOSPeerInfoRef pi, CFStringRef viewname, CFErrorRef *error) {
504 SOSViewResultCode retval = kSOSCCNoSuchView;
505 CFSetRef views = NULL;
506 require_quiet(SOSViewsRequireIsKnownView(viewname, error), fail);
507
508 views = SOSPeerInfoCopyEnabledViews(pi);
509 if(!views){
510 retval = kSOSCCViewNotMember;
511 CFReleaseNull(views);
512 return retval;
513 }
514
515 // kSOSViewKeychainV0 is set if there is a V0 PeerInfo in the circle. It represents all of the subviews in
516 // SOSViewsGetV0SubviewSet() so we return kSOSCCViewMember for that case. kSOSViewKeychainV0 and the subviews
517 // are mutually exclusive.
518 else if(CFSetContainsValue(views, kSOSViewKeychainV0) && CFSetContainsValue(SOSViewsGetV0SubviewSet(), viewname)) {
519 retval = kSOSCCViewMember;
520 } else {
521 retval = (CFSetContainsValue(views, viewname)) ? kSOSCCViewMember: kSOSCCViewNotMember;
522 }
523
524 CFReleaseNull(views);
525 return retval;
526
527 fail:
528 secnotice("views","Failed to query view(%@): %@", viewname, error ? *error : NULL);
529 CFReleaseNull(views);
530 return retval;
531 }
532
533
534 /* Need XPC way to carry CFSets of views */
535
536
537
538 xpc_object_t CreateXPCObjectWithCFSetRef(CFSetRef setref, CFErrorRef *error) {
539 xpc_object_t result = NULL;
540 size_t data_size = 0;
541 uint8_t *data = NULL;
542 require_action_quiet(setref, errOut, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedNull, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Unexpected Null Set to encode")));
543 require_quiet((data_size = der_sizeof_set(setref, error)) != 0, errOut);
544 require_quiet((data = (uint8_t *)malloc(data_size)) != NULL, errOut);
545
546 der_encode_set(setref, error, data, data + data_size);
547 result = xpc_data_create(data, data_size);
548 free(data);
549 errOut:
550 return result;
551 }
552