]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSAccountBackup.c
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSAccountBackup.c
1 //
2 // SOSAccountCircles.c
3 // sec
4 //
5
6 #include "SOSAccountPriv.h"
7 #include "SOSCloudKeychainClient.h"
8
9 #include <Security/SecureObjectSync/SOSBackupSliceKeyBag.h>
10 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
11 #include <Security/SecureObjectSync/SOSViews.h>
12
13 #include "SOSInternal.h"
14
15 //
16 // MARK: V0 Keybag keychain stuff
17 //
18 static bool SecItemUpdateOrAdd(CFDictionaryRef query, CFDictionaryRef update, CFErrorRef *error)
19 {
20 OSStatus saveStatus = SecItemUpdate(query, update);
21
22 if (errSecItemNotFound == saveStatus) {
23 CFMutableDictionaryRef add = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, query);
24 CFDictionaryForEach(update, ^(const void *key, const void *value) {
25 CFDictionaryAddValue(add, key, value);
26 });
27 saveStatus = SecItemAdd(add, NULL);
28 CFReleaseNull(add);
29 }
30
31 return SecError(saveStatus, error, CFSTR("Error saving %@"), query);
32 }
33
34 static CFDictionaryRef SOSCopyV0Attributes() {
35 return CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
36 kSecClass, kSecClassGenericPassword,
37 kSecAttrAccessGroup, CFSTR("com.apple.sbd"),
38 kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked,
39 kSecAttrAccount, CFSTR("SecureBackupPublicKeybag"),
40 kSecAttrService, CFSTR("SecureBackupService"),
41 kSecAttrSynchronizable, kCFBooleanTrue,
42 NULL);
43 }
44
45 static bool SOSDeleteV0Keybag(CFErrorRef *error) {
46 CFDictionaryRef attributes = SOSCopyV0Attributes();
47
48 OSStatus result = SecItemDelete(attributes);
49
50 CFReleaseNull(attributes);
51
52 return SecError(result != errSecItemNotFound ? result : errSecSuccess, error, CFSTR("Deleting V0 Keybag failed - %ld"), result);
53 }
54
55 static bool SOSSaveV0Keybag(CFDataRef v0Keybag, CFErrorRef *error) {
56 CFDictionaryRef attributes = SOSCopyV0Attributes();
57
58 CFDictionaryRef update = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
59 kSecValueData, v0Keybag,
60 NULL);
61
62
63 bool result = SecItemUpdateOrAdd(attributes, update, error);
64 CFReleaseNull(attributes);
65 CFReleaseNull(update);
66
67 return result;
68 }
69
70
71 static bool SOSPeerInfoIsViewBackupEnabled(SOSPeerInfoRef peerInfo, CFStringRef viewName) {
72 if (CFEqualSafe(kSOSViewKeychainV0, viewName))
73 return false;
74
75 return SOSPeerInfoHasBackupKey(peerInfo) && SOSPeerInfoIsViewPermitted(peerInfo, viewName);
76 }
77
78 static CFSetRef SOSAccountCopyBackupPeersForView(SOSAccountRef account, CFStringRef viewName) {
79 CFMutableSetRef backupPeers = CFSetCreateMutableForSOSPeerInfosByID(kCFAllocatorDefault);
80
81 SOSCircleRef circle = SOSAccountGetCircle(account, NULL);
82
83 require_quiet(circle, exit);
84
85 SOSCircleForEachValidPeer(circle, account->user_public, ^(SOSPeerInfoRef peer) {
86 if (SOSPeerInfoIsViewBackupEnabled(peer, viewName))
87 CFSetAddValue(backupPeers, peer);
88 });
89
90 exit:
91 return backupPeers;
92 }
93
94 static void SOSAccountWithBackupPeersForView(SOSAccountRef account, CFStringRef viewName, void (^action)(CFSetRef peers)) {
95 CFSetRef backupPeersForView = SOSAccountCopyBackupPeersForView(account, viewName);
96
97 action(backupPeersForView);
98
99 CFReleaseNull(backupPeersForView);
100 }
101
102 static bool SOSAccountWithBSKBForView(SOSAccountRef account, CFStringRef viewName, CFErrorRef *error,
103 bool (^action)(SOSBackupSliceKeyBagRef bskb, CFErrorRef *error)) {
104 __block SOSBackupSliceKeyBagRef bskb = NULL;
105 bool result = false;
106
107 SOSAccountWithBackupPeersForView(account, viewName, ^(CFSetRef peers) {
108 bskb = SOSBackupSliceKeyBagCreate(kCFAllocatorDefault, peers, error);
109 });
110
111 require_quiet(bskb, exit);
112
113 action(bskb, error);
114
115 result = true;
116
117 exit:
118 CFReleaseNull(bskb);
119 return result;
120 }
121
122 CFStringRef SOSBackupCopyRingNameForView(CFStringRef viewName) {
123 return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@-tomb"), viewName);
124 }
125
126 static bool SOSAccountUpdateNamedRing(SOSAccountRef account, CFStringRef ringName, CFErrorRef *error,
127 SOSRingRef (^create)(CFStringRef ringName, CFErrorRef *error),
128 SOSRingRef (^copyModified)(SOSRingRef existing, CFErrorRef *error)) {
129 bool result = false;
130 SOSRingRef newRing = NULL;
131 SOSRingRef found = (SOSRingRef) CFDictionaryGetValue(account->trusted_rings, ringName);
132 if (isSOSRing(found)) {
133 found = SOSRingCopyRing(found, error);
134 } else {
135 if (found) {
136 secerror("Non ring in ring table: %@, purging!", found);
137 CFDictionaryRemoveValue(account->trusted_rings, ringName);
138 }
139 found = create(ringName, error);
140 }
141
142 require_quiet(found, exit);
143 newRing = copyModified(found, error);
144 CFReleaseNull(found);
145
146 require_quiet(newRing, exit);
147
148 result = SOSAccountHandleUpdateRing(account, newRing, true, error);
149
150 exit:
151 CFReleaseNull(found);
152 CFReleaseNull(newRing);
153 return result;
154 }
155
156 static bool SOSAccountUpdateBackupRing(SOSAccountRef account, CFStringRef viewName, CFErrorRef *error,
157 SOSRingRef (^modify)(SOSRingRef existing, CFErrorRef *error)) {
158
159 CFStringRef ringName = SOSBackupCopyRingNameForView(viewName);
160
161 bool result = SOSAccountUpdateNamedRing(account, ringName, error, ^SOSRingRef(CFStringRef ringName, CFErrorRef *error) {
162 return SOSRingCreate(ringName, SOSAccountGetMyPeerID(account), kSOSRingBackup, error);
163 }, modify);
164
165 CFReleaseNull(ringName);
166
167 return result;
168 }
169
170 static CFSetRef SOSAccountCopyPeerSetForView(SOSAccountRef account, CFStringRef viewName) {
171 CFMutableSetRef result = CFSetCreateMutableForSOSPeerInfosByID(kCFAllocatorDefault);
172
173 if (account->trusted_circle) {
174 SOSCircleForEachPeer(account->trusted_circle, ^(SOSPeerInfoRef peer) {
175 if (CFSetContainsValue(SOSPeerInfoGetPermittedViews(peer), viewName)) {
176 CFSetAddValue(result, peer);
177 }
178 });
179 }
180
181 return result;
182 }
183
184 static bool SOSAccountSetKeybagForViewBackupRing(SOSAccountRef account, CFStringRef viewName, SOSBackupSliceKeyBagRef keyBag, CFErrorRef *error) {
185 CFMutableSetRef backupViewSet = CFSetCreateMutableForCFTypes(NULL);
186 bool result = false;
187 require_quiet(SecAllocationError(backupViewSet, error, CFSTR("No backup view set created")), errOut);
188 CFSetAddValue(backupViewSet, viewName);
189
190 result = SOSAccountUpdateBackupRing(account, viewName, error, ^SOSRingRef(SOSRingRef existing, CFErrorRef *error) {
191 SOSRingRef newRing = NULL;
192 CFSetRef viewPeerSet = SOSAccountCopyPeerSetForView(account, viewName);
193 CFMutableSetRef cleared = CFSetCreateMutableForCFTypes(NULL);
194
195 SOSRingSetPeerIDs(existing, cleared);
196 SOSRingAddAll(existing, viewPeerSet);
197
198 require_quiet(SOSRingSetBackupKeyBag(existing, SOSAccountGetMyFullPeerInfo(account), backupViewSet, keyBag, error), exit);
199
200 newRing = CFRetainSafe(existing);
201 exit:
202 CFReleaseNull(viewPeerSet);
203 CFReleaseNull(cleared);
204 return newRing;
205 });
206
207 errOut:
208
209 if (result && NULL != error && NULL != *error) {
210 secerror("Got Success and Error (dropping error): %@", *error);
211 CFReleaseNull(*error);
212 }
213
214 if (!result) {
215 secnotice("backupring", "Got error setting keybag for backup view '%@': %@", viewName, error ? (CFTypeRef) *error : (CFTypeRef) CFSTR("No error space."));
216 }
217
218 CFReleaseNull(backupViewSet);
219 return result;
220 }
221
222 bool SOSAccountStartNewBackup(SOSAccountRef account, CFStringRef viewName, CFErrorRef *error)
223 {
224 return SOSAccountWithBSKBForView(account, viewName, error, ^(SOSBackupSliceKeyBagRef bskb, CFErrorRef *error) {
225 bool result = SOSAccountSetKeybagForViewBackupRing(account, viewName, bskb, error);
226 return result;
227 });
228 }
229
230 bool SOSAccountIsBackupRingEmpty(SOSAccountRef account, CFStringRef viewName) {
231 CFStringRef backupRing = SOSBackupCopyRingNameForView(viewName);
232 SOSRingRef ring = SOSAccountGetRing(account, backupRing, NULL);
233 CFReleaseNull(backupRing);
234 int peercnt = 0;
235 if(ring) peercnt = SOSRingCountPeers(ring);
236 return peercnt == 0;
237 }
238
239 static bool SOSAccountUpdatePeerInfo(SOSAccountRef account, CFStringRef updateDescription, CFErrorRef *error, bool (^update)(SOSFullPeerInfoRef fpi, CFErrorRef *error)) {
240 if (account->my_identity == NULL)
241 return true;
242
243 bool result = update(account->my_identity, error);
244
245 if (result && SOSAccountHasCircle(account, NULL)) {
246 return SOSAccountModifyCircle(account, error, ^(SOSCircleRef circle_to_change) {
247 secnotice("circleChange", "Calling SOSCircleUpdatePeerInfo for %@", updateDescription);
248 return SOSCircleUpdatePeerInfo(circle_to_change, SOSAccountGetMyPeerInfo(account));
249 });
250 }
251
252 return result;
253 }
254
255 bool SOSAccountIsMyPeerInBackupAndCurrentInView(SOSAccountRef account, CFStringRef viewname){
256 bool result = false;
257 CFErrorRef bsError = NULL;
258 CFDataRef backupSliceData = NULL;
259 SOSBackupSliceKeyBagRef backupSlice = NULL;
260
261 require_quiet(SOSPeerInfoIsViewBackupEnabled(SOSAccountGetMyPeerInfo(account), viewname), exit);
262
263 CFMutableDictionaryRef trusted_rings = SOSAccountGetRings(account, &bsError);
264 require_quiet(trusted_rings, exit);
265
266 CFStringRef ringName = SOSBackupCopyRingNameForView(viewname);
267 SOSRingRef ring = (SOSRingRef)CFDictionaryGetValue(trusted_rings, ringName);
268 CFReleaseNull(ringName);
269
270 require_quiet(ring, exit);
271
272 //grab the backup slice from the ring
273 backupSliceData = SOSRingGetPayload(ring, &bsError);
274 require_quiet(backupSliceData, exit);
275
276 backupSlice = SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault, backupSliceData, &bsError);
277 require_quiet(backupSlice, exit);
278
279 CFSetRef peers = SOSBSKBGetPeers(backupSlice);
280 SOSPeerInfoRef myPeer = SOSAccountGetMyPeerInfo(account);
281
282 SOSPeerInfoRef myPeerInBSKB = (SOSPeerInfoRef) CFSetGetValue(peers, myPeer);
283 require_quiet(isSOSPeerInfo(myPeerInBSKB), exit);
284
285 CFDataRef myBK = SOSPeerInfoCopyBackupKey(myPeer);
286 CFDataRef myPeerInBSKBBK = SOSPeerInfoCopyBackupKey(myPeerInBSKB);
287 result = CFEqualSafe(myBK, myPeerInBSKBBK);
288 CFReleaseNull(myBK);
289 CFReleaseNull(myPeerInBSKBBK);
290
291 exit:
292 if (bsError) {
293 secnotice("backup", "Failed to find BKSB: %@, %@ (%@)", backupSliceData, backupSlice, bsError);
294 }
295 CFReleaseNull(bsError);
296 return result;
297 }
298
299 bool SOSAccountIsPeerInBackupAndCurrentInView(SOSAccountRef account, SOSPeerInfoRef testPeer, CFStringRef viewname){
300 bool result = false;
301 CFErrorRef bsError = NULL;
302 CFDataRef backupSliceData = NULL;
303 SOSBackupSliceKeyBagRef backupSlice = NULL;
304
305 require_quiet(testPeer, exit);
306
307 CFMutableDictionaryRef trusted_rings = SOSAccountGetRings(account, &bsError);
308 require_quiet(trusted_rings, exit);
309
310 CFStringRef ringName = SOSBackupCopyRingNameForView(viewname);
311 SOSRingRef ring = (SOSRingRef)CFDictionaryGetValue(trusted_rings, ringName);
312 CFReleaseNull(ringName);
313
314 require_quiet(ring, exit);
315
316 //grab the backup slice from the ring
317 backupSliceData = SOSRingGetPayload(ring, &bsError);
318 require_quiet(backupSliceData, exit);
319
320 backupSlice = SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault, backupSliceData, &bsError);
321 require_quiet(backupSlice, exit);
322
323 CFSetRef peers = SOSBSKBGetPeers(backupSlice);
324
325 SOSPeerInfoRef peerInBSKB = (SOSPeerInfoRef) CFSetGetValue(peers, testPeer);
326 require_quiet(isSOSPeerInfo(peerInBSKB), exit);
327
328 result = CFEqualSafe(testPeer, peerInBSKB);
329
330 exit:
331 if (bsError) {
332 secnotice("backup", "Failed to find BKSB: %@, %@ (%@)", backupSliceData, backupSlice, bsError);
333 }
334 CFReleaseNull(bsError);
335 return result;
336
337 }
338
339 bool SOSAccountUpdateOurPeerInBackup(SOSAccountRef account, SOSRingRef oldRing, CFErrorRef *error){
340 bool result = false;
341 CFSetRef viewNames = SOSBackupRingGetViews(oldRing, error);
342 __block CFStringRef viewName = NULL;
343 require_quiet(viewNames, fail);
344 require_quiet(SecRequirementError(1 == CFSetGetCount(viewNames), error, CFSTR("Only support single view backup rings")), fail);
345
346 CFSetForEach(viewNames, ^(const void *value) {
347 if (isString(value)) {
348 viewName = CFRetainSafe((CFStringRef) value);
349 }
350 });
351
352 result = SOSAccountStartNewBackup(account, viewName, error);
353
354 fail:
355 CFReleaseNull(viewName);
356 return result;
357 }
358
359 void SOSAccountForEachBackupRingName(SOSAccountRef account, void (^operation)(CFStringRef value)) {
360 SOSPeerInfoRef myPeer = SOSAccountGetMyPeerInfo(account);
361 if (myPeer) {
362 CFMutableSetRef myBackupViews = CFSetCreateMutableCopy(kCFAllocatorDefault, 0, SOSPeerInfoGetPermittedViews(myPeer));
363
364 CFSetRemoveValue(myBackupViews, kSOSViewKeychainV0);
365
366 CFSetForEach(myBackupViews, ^(const void *value) {
367 CFStringRef viewName = asString(value, NULL);
368
369 if (viewName) {
370 CFStringRef ringName = SOSBackupCopyRingNameForView(viewName);
371 operation(ringName);
372 CFReleaseNull(ringName);
373 }
374 });
375
376 CFReleaseNull(myBackupViews);
377 }
378 }
379
380 static
381 void SOSAccountForEachBackupView(SOSAccountRef account, void (^operation)(const void *value)) {
382 SOSPeerInfoRef myPeer = SOSAccountGetMyPeerInfo(account);
383
384 if (myPeer) {
385 CFMutableSetRef myBackupViews = CFSetCreateMutableCopy(kCFAllocatorDefault, 0, SOSPeerInfoGetPermittedViews(myPeer));
386
387 CFSetRemoveValue(myBackupViews, kSOSViewKeychainV0);
388
389 CFSetForEach(myBackupViews, operation);
390
391 CFReleaseNull(myBackupViews);
392 }
393 }
394
395 bool SOSAccountSetBackupPublicKey(SOSAccountRef account, CFDataRef backupKey, CFErrorRef *error)
396 {
397 __block bool result = false;
398
399 require_quiet(SOSAccountIsInCircle(account, error), exit);
400
401 if (CFEqualSafe(backupKey, account->backup_key))
402 return true;
403
404 require_quiet(SOSBSKBIsGoodBackupPublic(backupKey, error), exit);
405 require_quiet(SOSAccountUpdatePeerInfo(account, CFSTR("Backup public key"), error,
406 ^bool(SOSFullPeerInfoRef fpi, CFErrorRef *error) {
407 return SOSFullPeerInfoUpdateBackupKey(fpi, backupKey, error);
408 }), exit);
409
410 CFRetainAssign(account->backup_key, backupKey);
411
412 CFErrorRef localError = NULL;
413 if (!SOSDeleteV0Keybag(&localError)) {
414 secerror("Failed to delete v0 keybag: %@", localError);
415 }
416 CFReleaseNull(localError);
417
418 result = true;
419
420 SOSAccountForEachBackupView(account, ^(const void *value) {
421 CFStringRef viewName = (CFStringRef)value;
422 result &= SOSAccountStartNewBackup(account, viewName, error);
423 });
424
425 exit:
426 if (!result) {
427 secnotice("backupkey", "Failed to setup backup public key: %@", error ? (CFTypeRef) *error : (CFTypeRef) CFSTR("No error space provided"));
428 }
429 return result;
430 }
431
432 static bool SOSAccountWithBSKBAndPeerInfosForView(SOSAccountRef account, CFArrayRef retiree, CFStringRef viewName, CFErrorRef *error,
433 bool (^action)(SOSBackupSliceKeyBagRef bskb, CFErrorRef *error)) {
434 __block SOSBackupSliceKeyBagRef bskb = NULL;
435 bool result = false;
436
437 SOSAccountWithBackupPeersForView(account, viewName, ^(CFSetRef peers) {
438 CFMutableSetRef newPeerList = CFSetCreateMutableCopy(kCFAllocatorDefault, CFSetGetCount(peers), peers);
439 CFArrayForEach(retiree, ^(const void *value) {
440 if (!isSOSPeerInfo(value)) {
441 secerror("Peer list contains a non-peerInfo element");
442 } else {
443 SOSPeerInfoRef retiringPeer = (SOSPeerInfoRef)value;
444 CFStringRef retiringPeerID = SOSPeerInfoGetPeerID(retiringPeer);
445
446 CFSetForEach(newPeerList, ^(const void *peerFromAccount) {
447 CFStringRef peerFromAccountID = SOSPeerInfoGetPeerID((SOSPeerInfoRef)peerFromAccount);
448 if (peerFromAccountID && retiringPeerID && CFStringCompare(peerFromAccountID, retiringPeerID, 0) == 0){
449 CFSetRemoveValue(newPeerList, peerFromAccount);
450 }
451 });
452 }
453 });
454 bskb = SOSBackupSliceKeyBagCreate(kCFAllocatorDefault, newPeerList, error);
455 CFReleaseNull(newPeerList);
456 });
457
458 require_quiet(bskb, exit);
459
460 action(bskb, error);
461
462 result = true;
463
464 exit:
465 CFReleaseNull(bskb);
466 return result;
467 }
468
469 bool SOSAccountRemoveBackupPublickey(SOSAccountRef account, CFErrorRef *error)
470 {
471 __block bool result = false;
472 __block CFMutableArrayRef removals = NULL;
473
474 require_quiet(SOSAccountUpdatePeerInfo(account, CFSTR("Backup public key"), error,
475 ^bool(SOSFullPeerInfoRef fpi, CFErrorRef *error) {
476 return SOSFullPeerInfoUpdateBackupKey(fpi, NULL, error);
477 }), exit);
478
479 CFReleaseNull(account->backup_key);
480
481 removals = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
482 CFArrayAppendValue(removals, SOSAccountGetMyPeerInfo(account));
483
484 SOSAccountForEachBackupView(account, ^(const void *value) {
485 CFStringRef viewName = (CFStringRef)value;
486 result = SOSAccountWithBSKBAndPeerInfosForView(account, removals, viewName, error, ^(SOSBackupSliceKeyBagRef bskb, CFErrorRef *error) {
487 bool result = SOSAccountSetKeybagForViewBackupRing(account, viewName, bskb, error);
488 return result;
489 });
490 });
491
492
493 result = true;
494
495 exit:
496 return result;
497
498 }
499
500 bool SOSAccountSetBSKBagForAllSlices(SOSAccountRef account, CFDataRef aks_bag, bool setupV0Only, CFErrorRef *error){
501 __block bool result = false;
502 SOSBackupSliceKeyBagRef backup_slice = NULL;
503
504 require_quiet(SOSAccountIsInCircle(account, error), exit);
505
506 if (setupV0Only) {
507 result = SOSSaveV0Keybag(aks_bag, error);
508 require_action_quiet(result, exit, secnotice("keybag", "failed to set V0 keybag (%@)", *error));
509 } else {
510 result = true;
511
512 backup_slice = SOSBackupSliceKeyBagCreateDirect(kCFAllocatorDefault, aks_bag, error);
513
514 SOSAccountForEachBackupView(account, ^(const void *value) {
515 CFStringRef viewname = (CFStringRef) value;
516 result &= SOSAccountSetKeybagForViewBackupRing(account, viewname, backup_slice, error);
517 });
518 }
519
520 exit:
521 CFReleaseNull(backup_slice);
522 return result;
523 }
524
525 static CFMutableArrayRef SOSAccountIsRetiredPeerIDInBackupPeerList(SOSAccountRef account, CFArrayRef peers, CFSetRef peersInBackup){
526 CFMutableArrayRef removals = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
527
528 CFSetForEach(peersInBackup, ^(const void *value) {
529 SOSPeerInfoRef peer = (SOSPeerInfoRef)value;
530 CFArrayForEach(peers, ^(const void *value) {
531 CFStringRef peerID = SOSPeerInfoGetPeerID((SOSPeerInfoRef)value);
532 CFStringRef piPeerID = SOSPeerInfoGetPeerID(peer);
533 if (peerID && piPeerID && CFStringCompare(piPeerID, peerID, 0) == 0){
534 CFArrayAppendValue(removals, peer);
535 }
536 });
537
538 });
539
540 return removals;
541
542 }
543
544 bool SOSAccountRemoveBackupPeers(SOSAccountRef account, CFArrayRef peers, CFErrorRef *error){
545 __block bool result = true;
546
547 SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInfo(account);
548 SOSPeerInfoRef myPeer = SOSFullPeerInfoGetPeerInfo(fpi);
549
550 CFSetRef permittedViews = SOSPeerInfoGetPermittedViews(myPeer);
551 CFSetForEach(permittedViews, ^(const void *value) {
552 CFStringRef viewName = (CFStringRef)value;
553 if(SOSPeerInfoIsViewBackupEnabled(myPeer, viewName)){
554 //grab current peers list
555 CFSetRef peersInBackup = SOSAccountCopyBackupPeersForView(account, viewName);
556 //get peer infos that have retired but are still in the backup peer list
557 CFMutableArrayRef removals = SOSAccountIsRetiredPeerIDInBackupPeerList(account, peers, peersInBackup);
558 result = SOSAccountWithBSKBAndPeerInfosForView(account, removals, viewName, error, ^(SOSBackupSliceKeyBagRef bskb, CFErrorRef *error) {
559 bool result = SOSAccountSetKeybagForViewBackupRing(account, viewName, bskb, error);
560 return result;
561 });
562 }
563 });
564
565 return result;
566
567 }
568