6 #include "SOSAccountPriv.h" 
   7 #include "SOSCloudKeychainClient.h" 
   9 #include <Security/SecureObjectSync/SOSBackupSliceKeyBag.h> 
  10 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h> 
  11 #include <Security/SecureObjectSync/SOSViews.h> 
  13 #include "SOSInternal.h" 
  16 // MARK: V0 Keybag keychain stuff 
  18 static bool SecItemUpdateOrAdd(CFDictionaryRef query
, CFDictionaryRef update
, CFErrorRef 
*error
) 
  20     OSStatus saveStatus 
= SecItemUpdate(query
, update
); 
  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
); 
  27         saveStatus 
= SecItemAdd(add
, NULL
); 
  31     return SecError(saveStatus
, error
, CFSTR("Error saving %@"), query
); 
  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
, 
  45 bool SOSDeleteV0Keybag(CFErrorRef 
*error
) { 
  46     CFDictionaryRef attributes 
= SOSCopyV0Attributes(); 
  48     OSStatus result 
= SecItemDelete(attributes
); 
  50     CFReleaseNull(attributes
); 
  52     return SecError(result 
!= errSecItemNotFound 
? result 
: errSecSuccess
, error
, CFSTR("Deleting V0 Keybag failed - %ld"), result
); 
  55 static bool SOSSaveV0Keybag(CFDataRef v0Keybag
, CFErrorRef 
*error
) { 
  56     CFDictionaryRef attributes 
= SOSCopyV0Attributes(); 
  58     CFDictionaryRef update 
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
, 
  59                                                           kSecValueData
,           v0Keybag
, 
  63     bool result 
= SecItemUpdateOrAdd(attributes
, update
, error
); 
  64     CFReleaseNull(attributes
); 
  65     CFReleaseNull(update
); 
  71 static bool SOSPeerInfoIsViewBackupEnabled(SOSPeerInfoRef peerInfo
, CFStringRef viewName
) { 
  72     if (CFEqualSafe(kSOSViewKeychainV0
, viewName
)) 
  75     return SOSPeerInfoHasBackupKey(peerInfo
) && SOSPeerInfoIsViewPermitted(peerInfo
, viewName
); 
  78 static CFSetRef 
SOSAccountCopyBackupPeersForView(SOSAccountRef account
, CFStringRef viewName
) { 
  79     CFMutableSetRef backupPeers 
= CFSetCreateMutableForSOSPeerInfosByID(kCFAllocatorDefault
); 
  81     SOSCircleRef circle 
= SOSAccountGetCircle(account
, NULL
); 
  83     require_quiet(circle
, exit
); 
  85     SOSCircleForEachValidPeer(circle
, account
->user_public
, ^(SOSPeerInfoRef peer
) { 
  86         if (SOSPeerInfoIsViewBackupEnabled(peer
, viewName
)) 
  87             CFSetAddValue(backupPeers
, peer
); 
  94 static void SOSAccountWithBackupPeersForView(SOSAccountRef account
, CFStringRef viewName
, void (^action
)(CFSetRef peers
)) { 
  95     CFSetRef backupPeersForView 
= SOSAccountCopyBackupPeersForView(account
, viewName
); 
  97     action(backupPeersForView
); 
  99     CFReleaseNull(backupPeersForView
); 
 102 static bool SOSAccountWithBSKBForView(SOSAccountRef account
, CFStringRef viewName
, CFErrorRef 
*error
, 
 103                                       bool (^action
)(SOSBackupSliceKeyBagRef bskb
, CFErrorRef 
*error
)) { 
 104     __block SOSBackupSliceKeyBagRef bskb 
= NULL
; 
 107     SOSAccountWithBackupPeersForView(account
, viewName
, ^(CFSetRef peers
) { 
 108         bskb 
= SOSBackupSliceKeyBagCreate(kCFAllocatorDefault
, peers
, error
); 
 111     require_quiet(bskb
, exit
); 
 122 CFStringRef 
SOSBackupCopyRingNameForView(CFStringRef viewName
) { 
 123     return CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%@-tomb"), viewName
); 
 126 static bool SOSAccountUpdateNamedRing(SOSAccountRef account
, CFStringRef ringName
, CFErrorRef 
*error
, 
 127                                       SOSRingRef (^create
)(CFStringRef ringName
, CFErrorRef 
*error
), 
 128                                       SOSRingRef (^copyModified
)(SOSRingRef existing
, CFErrorRef 
*error
)) { 
 130     SOSRingRef newRing 
= NULL
; 
 131     SOSRingRef found 
= (SOSRingRef
) CFDictionaryGetValue(account
->trusted_rings
, ringName
); 
 132     if (isSOSRing(found
)) { 
 133         found 
= SOSRingCopyRing(found
, error
); 
 136             secerror("Non ring in ring table: %@, purging!", found
); 
 137             CFDictionaryRemoveValue(account
->trusted_rings
, ringName
); 
 139         found 
= create(ringName
, error
); 
 142     require_quiet(found
, exit
); 
 143     newRing 
= copyModified(found
, error
); 
 144     CFReleaseNull(found
); 
 146     require_quiet(newRing
, exit
); 
 148     result 
= SOSAccountHandleUpdateRing(account
, newRing
, true, error
); 
 151     CFReleaseNull(found
); 
 152     CFReleaseNull(newRing
); 
 156 static bool SOSAccountUpdateBackupRing(SOSAccountRef account
, CFStringRef viewName
, CFErrorRef 
*error
, 
 157                                        SOSRingRef (^modify
)(SOSRingRef existing
, CFErrorRef 
*error
)) { 
 159     CFStringRef ringName 
= SOSBackupCopyRingNameForView(viewName
); 
 161     bool result 
= SOSAccountUpdateNamedRing(account
, ringName
, error
, ^SOSRingRef(CFStringRef ringName
, CFErrorRef 
*error
) { 
 162         return SOSRingCreate(ringName
, SOSAccountGetMyPeerID(account
), kSOSRingBackup
, error
); 
 165     CFReleaseNull(ringName
); 
 170 static CFSetRef 
SOSAccountCopyPeerSetForView(SOSAccountRef account
, CFStringRef viewName
) { 
 171     CFMutableSetRef result 
= CFSetCreateMutableForSOSPeerInfosByID(kCFAllocatorDefault
); 
 173     if (account
->trusted_circle
) { 
 174         SOSCircleForEachPeer(account
->trusted_circle
, ^(SOSPeerInfoRef peer
) { 
 175             if (CFSetContainsValue(SOSPeerInfoGetPermittedViews(peer
), viewName
)) { 
 176                 CFSetAddValue(result
, peer
); 
 184 static bool SOSAccountSetKeybagForViewBackupRing(SOSAccountRef account
, CFStringRef viewName
, SOSBackupSliceKeyBagRef keyBag
, CFErrorRef 
*error
) { 
 185     CFMutableSetRef backupViewSet 
= CFSetCreateMutableForCFTypes(NULL
); 
 187     require_quiet(SecAllocationError(backupViewSet
, error
, CFSTR("No backup view set created")), errOut
); 
 188     CFSetAddValue(backupViewSet
, viewName
); 
 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
); 
 195         SOSRingSetPeerIDs(existing
, cleared
); 
 196         SOSRingAddAll(existing
, viewPeerSet
); 
 198         require_quiet(SOSRingSetBackupKeyBag(existing
, SOSAccountGetMyFullPeerInfo(account
), backupViewSet
, keyBag
, error
), exit
); 
 200         newRing 
= CFRetainSafe(existing
); 
 202         CFReleaseNull(viewPeerSet
); 
 203         CFReleaseNull(cleared
); 
 209     if (result 
&& NULL 
!= error 
&& NULL 
!= *error
) { 
 210         secerror("Got Success and Error (dropping error): %@", *error
); 
 211         CFReleaseNull(*error
); 
 215         secnotice("backupring", "Got error setting keybag for backup view '%@': %@", viewName
, error 
? (CFTypeRef
) *error 
: (CFTypeRef
) CFSTR("No error space.")); 
 218     CFReleaseNull(backupViewSet
); 
 222 bool SOSAccountStartNewBackup(SOSAccountRef account
, CFStringRef viewName
, CFErrorRef 
*error
) 
 224     return SOSAccountWithBSKBForView(account
, viewName
, error
, ^(SOSBackupSliceKeyBagRef bskb
, CFErrorRef 
*error
) { 
 225         bool result 
= SOSAccountSetKeybagForViewBackupRing(account
, viewName
, bskb
, error
); 
 230 bool SOSAccountIsBackupRingEmpty(SOSAccountRef account
, CFStringRef viewName
) { 
 231     CFStringRef backupRing 
= SOSBackupCopyRingNameForView(viewName
); 
 232     SOSRingRef ring 
= SOSAccountGetRing(account
, backupRing
, NULL
); 
 233     CFReleaseNull(backupRing
); 
 235     if(ring
) peercnt 
= SOSRingCountPeers(ring
); 
 239 bool SOSAccountUpdatePeerInfo(SOSAccountRef account
, CFStringRef updateDescription
, CFErrorRef 
*error
, bool (^update
)(SOSFullPeerInfoRef fpi
, CFErrorRef 
*error
)) { 
 240     if (account
->my_identity 
== NULL
) 
 243     bool result 
= update(account
->my_identity
, error
); 
 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
)); 
 255 bool SOSAccountIsMyPeerInBackupAndCurrentInView(SOSAccountRef account
, CFStringRef viewname
){ 
 257     CFErrorRef bsError 
= NULL
; 
 258     CFDataRef backupSliceData 
= NULL
; 
 259     SOSBackupSliceKeyBagRef backupSlice 
= NULL
; 
 261     require_quiet(SOSPeerInfoIsViewBackupEnabled(SOSAccountGetMyPeerInfo(account
), viewname
), exit
); 
 263     CFMutableDictionaryRef trusted_rings 
= SOSAccountGetRings(account
, &bsError
); 
 264     require_quiet(trusted_rings
, exit
); 
 266     CFStringRef ringName 
= SOSBackupCopyRingNameForView(viewname
); 
 267     SOSRingRef ring 
= (SOSRingRef
)CFDictionaryGetValue(trusted_rings
, ringName
); 
 268     CFReleaseNull(ringName
); 
 270     require_quiet(ring
, exit
); 
 272     //grab the backup slice from the ring 
 273     backupSliceData 
= SOSRingGetPayload(ring
, &bsError
); 
 274     require_quiet(backupSliceData
, exit
); 
 276     backupSlice 
= SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault
, backupSliceData
, &bsError
); 
 277     require_quiet(backupSlice
, exit
); 
 279     CFSetRef peers 
= SOSBSKBGetPeers(backupSlice
); 
 280     SOSPeerInfoRef myPeer 
= SOSAccountGetMyPeerInfo(account
); 
 282     SOSPeerInfoRef myPeerInBSKB 
= (SOSPeerInfoRef
) CFSetGetValue(peers
, myPeer
); 
 283     require_quiet(isSOSPeerInfo(myPeerInBSKB
), exit
); 
 285     CFDataRef myBK 
= SOSPeerInfoCopyBackupKey(myPeer
); 
 286     CFDataRef myPeerInBSKBBK 
= SOSPeerInfoCopyBackupKey(myPeerInBSKB
); 
 287     result 
= CFEqualSafe(myBK
, myPeerInBSKBBK
); 
 289     CFReleaseNull(myPeerInBSKBBK
); 
 293         secnotice("backup", "Failed to find BKSB: %@, %@ (%@)", backupSliceData
, backupSlice
, bsError
); 
 295     CFReleaseNull(bsError
); 
 299 bool SOSAccountIsPeerInBackupAndCurrentInView(SOSAccountRef account
, SOSPeerInfoRef testPeer
, CFStringRef viewname
){ 
 301     CFErrorRef bsError 
= NULL
; 
 302     CFDataRef backupSliceData 
= NULL
; 
 303     SOSBackupSliceKeyBagRef backupSlice 
= NULL
; 
 305     require_quiet(testPeer
, exit
); 
 307     CFMutableDictionaryRef trusted_rings 
= SOSAccountGetRings(account
, &bsError
); 
 308     require_quiet(trusted_rings
, exit
); 
 310     CFStringRef ringName 
= SOSBackupCopyRingNameForView(viewname
); 
 311     SOSRingRef ring 
= (SOSRingRef
)CFDictionaryGetValue(trusted_rings
, ringName
); 
 312     CFReleaseNull(ringName
); 
 314     require_quiet(ring
, exit
); 
 316     //grab the backup slice from the ring 
 317     backupSliceData 
= SOSRingGetPayload(ring
, &bsError
); 
 318     require_quiet(backupSliceData
, exit
); 
 320     backupSlice 
= SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault
, backupSliceData
, &bsError
); 
 321     require_quiet(backupSlice
, exit
); 
 323     CFSetRef peers 
= SOSBSKBGetPeers(backupSlice
); 
 325     SOSPeerInfoRef peerInBSKB 
= (SOSPeerInfoRef
) CFSetGetValue(peers
, testPeer
); 
 326     require_quiet(isSOSPeerInfo(peerInBSKB
), exit
); 
 328     result 
= CFEqualSafe(testPeer
, peerInBSKB
); 
 332         secnotice("backup", "Failed to find BKSB: %@, %@ (%@)", backupSliceData
, backupSlice
, bsError
); 
 334     CFReleaseNull(bsError
); 
 339 bool SOSAccountUpdateOurPeerInBackup(SOSAccountRef account
, SOSRingRef oldRing
, CFErrorRef 
*error
){ 
 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
); 
 346     CFSetForEach(viewNames
, ^(const void *value
) { 
 347         if (isString(value
)) { 
 348             viewName 
= CFRetainSafe((CFStringRef
) value
); 
 352     result 
= SOSAccountStartNewBackup(account
, viewName
, error
); 
 355     CFReleaseNull(viewName
); 
 359 void SOSAccountForEachBackupRingName(SOSAccountRef account
, void (^operation
)(CFStringRef value
)) { 
 360     SOSPeerInfoRef myPeer 
= SOSAccountGetMyPeerInfo(account
); 
 362         CFMutableSetRef myBackupViews 
= CFSetCreateMutableCopy(kCFAllocatorDefault
, 0, SOSPeerInfoGetPermittedViews(myPeer
)); 
 364         CFSetRemoveValue(myBackupViews
, kSOSViewKeychainV0
); 
 366         CFSetForEach(myBackupViews
, ^(const void *value
) { 
 367             CFStringRef viewName 
= asString(value
, NULL
); 
 370                 CFStringRef ringName 
= SOSBackupCopyRingNameForView(viewName
); 
 372                 CFReleaseNull(ringName
); 
 376         CFReleaseNull(myBackupViews
); 
 380 void SOSAccountForEachBackupView(SOSAccountRef account
,  void (^operation
)(const void *value
)) { 
 381     SOSPeerInfoRef myPeer 
= SOSAccountGetMyPeerInfo(account
); 
 384         CFMutableSetRef myBackupViews 
= CFSetCreateMutableCopy(kCFAllocatorDefault
, 0, SOSPeerInfoGetPermittedViews(myPeer
)); 
 386         CFSetRemoveValue(myBackupViews
, kSOSViewKeychainV0
); 
 388         CFSetForEach(myBackupViews
, operation
); 
 390         CFReleaseNull(myBackupViews
); 
 394 bool SOSAccountSetBackupPublicKey(SOSAccountRef account
, CFDataRef backupKey
, CFErrorRef 
*error
) 
 396     __block 
bool result 
= false; 
 398     secnotice("backup", "setting backup public key"); 
 399     require_quiet(SOSAccountIsInCircle(account
, error
), exit
); 
 401     if (CFEqualSafe(backupKey
, account
->backup_key
)) 
 404     CFRetainAssign(account
->backup_key
, backupKey
); 
 406     SOSAccountEnsureBackupStarts(account
); 
 412         secnotice("backupkey", "Failed to setup backup public key: %@", error 
? (CFTypeRef
) *error 
: (CFTypeRef
) CFSTR("No error space provided")); 
 417 static bool SOSAccountWithBSKBAndPeerInfosForView(SOSAccountRef account
, CFArrayRef retiree
, CFStringRef viewName
, CFErrorRef 
*error
, 
 418                                                   bool (^action
)(SOSBackupSliceKeyBagRef bskb
, CFErrorRef 
*error
)) { 
 419     __block SOSBackupSliceKeyBagRef bskb 
= NULL
; 
 422     SOSAccountWithBackupPeersForView(account
, viewName
, ^(CFSetRef peers
) { 
 423         CFMutableSetRef newPeerList 
= CFSetCreateMutableCopy(kCFAllocatorDefault
, CFSetGetCount(peers
), peers
); 
 424         CFArrayForEach(retiree
, ^(const void *value
) { 
 425             if (!isSOSPeerInfo(value
)) { 
 426                 secerror("Peer list contains a non-peerInfo element"); 
 428                 SOSPeerInfoRef retiringPeer 
= (SOSPeerInfoRef
)value
; 
 429                 CFStringRef retiringPeerID 
= SOSPeerInfoGetPeerID(retiringPeer
); 
 431                 CFSetForEach(newPeerList
, ^(const void *peerFromAccount
) { 
 432                     CFStringRef peerFromAccountID 
= SOSPeerInfoGetPeerID((SOSPeerInfoRef
)peerFromAccount
); 
 433                     if (peerFromAccountID 
&& retiringPeerID 
&& CFStringCompare(peerFromAccountID
, retiringPeerID
, 0) == 0){ 
 434                         CFSetRemoveValue(newPeerList
, peerFromAccount
); 
 439         bskb 
= SOSBackupSliceKeyBagCreate(kCFAllocatorDefault
, newPeerList
, error
); 
 440         CFReleaseNull(newPeerList
); 
 443     require_quiet(bskb
, exit
); 
 454 bool SOSAccountRemoveBackupPublickey(SOSAccountRef account
, CFErrorRef 
*error
) 
 456     __block 
bool result 
= false; 
 457     __block CFMutableArrayRef removals 
= NULL
; 
 459     require_quiet(SOSAccountUpdatePeerInfo(account
, CFSTR("Backup public key"), error
, 
 460                                            ^bool(SOSFullPeerInfoRef fpi
, CFErrorRef 
*error
) { 
 461                                                return SOSFullPeerInfoUpdateBackupKey(fpi
, NULL
, error
); 
 464     CFReleaseNull(account
->backup_key
); 
 466     removals 
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
); 
 467     CFArrayAppendValue(removals
, SOSAccountGetMyPeerInfo(account
)); 
 469     SOSAccountForEachBackupView(account
, ^(const void *value
) { 
 470         CFStringRef viewName 
= (CFStringRef
)value
; 
 471         result 
= SOSAccountWithBSKBAndPeerInfosForView(account
, removals
, viewName
, error
, ^(SOSBackupSliceKeyBagRef bskb
, CFErrorRef 
*error
) { 
 472             bool result 
= SOSAccountSetKeybagForViewBackupRing(account
, viewName
, bskb
, error
); 
 485 bool SOSAccountSetBSKBagForAllSlices(SOSAccountRef account
, CFDataRef aks_bag
, bool setupV0Only
, CFErrorRef 
*error
){ 
 486     __block 
bool result 
= false; 
 487     SOSBackupSliceKeyBagRef backup_slice 
= NULL
; 
 489     require_quiet(SOSAccountIsInCircle(account
, error
), exit
); 
 492         result 
= SOSSaveV0Keybag(aks_bag
, error
); 
 493         require_action_quiet(result
, exit
, secnotice("keybag", "failed to set V0 keybag (%@)", *error
)); 
 497         backup_slice 
= SOSBackupSliceKeyBagCreateDirect(kCFAllocatorDefault
, aks_bag
, error
); 
 499         SOSAccountForEachBackupView(account
, ^(const void *value
) { 
 500             CFStringRef viewname 
= (CFStringRef
) value
; 
 501             result 
&= SOSAccountSetKeybagForViewBackupRing(account
, viewname
, backup_slice
, error
); 
 506     CFReleaseNull(backup_slice
); 
 510 static CFMutableArrayRef 
SOSAccountIsRetiredPeerIDInBackupPeerList(SOSAccountRef account
, CFArrayRef peers
, CFSetRef peersInBackup
){ 
 511     CFMutableArrayRef removals 
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
); 
 513     CFSetForEach(peersInBackup
, ^(const void *value
) { 
 514         SOSPeerInfoRef peer 
= (SOSPeerInfoRef
)value
; 
 515         CFArrayForEach(peers
, ^(const void *value
) { 
 516             CFStringRef peerID 
= SOSPeerInfoGetPeerID((SOSPeerInfoRef
)value
); 
 517             CFStringRef piPeerID 
= SOSPeerInfoGetPeerID(peer
); 
 518             if (peerID 
&& piPeerID 
&& CFStringCompare(piPeerID
, peerID
, 0) == 0){ 
 519                 CFArrayAppendValue(removals
, peer
); 
 529 bool SOSAccountRemoveBackupPeers(SOSAccountRef account
, CFArrayRef peers
, CFErrorRef 
*error
){ 
 530     __block 
bool result 
= true; 
 532     SOSFullPeerInfoRef fpi 
= SOSAccountGetMyFullPeerInfo(account
); 
 533     SOSPeerInfoRef myPeer 
= SOSFullPeerInfoGetPeerInfo(fpi
); 
 535     CFSetRef permittedViews 
= SOSPeerInfoGetPermittedViews(myPeer
); 
 536     CFSetForEach(permittedViews
, ^(const void *value
) { 
 537         CFStringRef viewName 
= (CFStringRef
)value
; 
 538         if(SOSPeerInfoIsViewBackupEnabled(myPeer
, viewName
)){ 
 539             //grab current peers list 
 540             CFSetRef peersInBackup 
= SOSAccountCopyBackupPeersForView(account
, viewName
); 
 541             //get peer infos that have retired but are still in the backup peer list 
 542             CFMutableArrayRef removals 
= SOSAccountIsRetiredPeerIDInBackupPeerList(account
, peers
, peersInBackup
); 
 543             result 
= SOSAccountWithBSKBAndPeerInfosForView(account
, removals
, viewName
, error
, ^(SOSBackupSliceKeyBagRef bskb
, CFErrorRef 
*error
) { 
 544                 bool result 
= SOSAccountSetKeybagForViewBackupRing(account
, viewName
, bskb
, error
); 
 554 SOSBackupSliceKeyBagRef 
SOSAccountBackupSliceKeyBagForView(SOSAccountRef account
, CFStringRef viewName
, CFErrorRef
* error
){ 
 555     CFMutableDictionaryRef trusted_rings 
= NULL
; 
 556     CFDataRef backupSliceData 
= NULL
; 
 557     CFStringRef ringName 
= NULL
; 
 558     SOSRingRef ring 
= NULL
; 
 559     SOSBackupSliceKeyBagRef bskb 
= NULL
; 
 561     trusted_rings 
= SOSAccountGetRings(account
, error
); 
 562     require_action_quiet(trusted_rings
, exit
, secnotice("keybag", "failed to get trusted rings (%@)", *error
)); 
 564     ringName 
= SOSBackupCopyRingNameForView(viewName
); 
 566     ring 
= (SOSRingRef
)CFDictionaryGetValue(trusted_rings
, ringName
); 
 567     require_action_quiet(ring
, exit
, SOSCreateErrorWithFormat(kSOSErrorNoCircle
, NULL
, error
, NULL
, CFSTR("failed to get ring"))); 
 569     //grab the backup slice from the ring 
 570     backupSliceData 
= SOSRingGetPayload(ring
, error
); 
 571     require_action_quiet(backupSliceData
, exit
, secnotice("backup", "failed to get backup slice (%@)", *error
)); 
 573     bskb 
= SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault
, backupSliceData
, error
); 
 576     CFReleaseNull(ringName
);