]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSAccountTrustClassic+Retirement.m
Security-59306.11.20.tar.gz
[apple/security.git] / keychain / SecureObjectSync / SOSAccountTrustClassic+Retirement.m
1 //
2 // SOSAccountTrustClassicRetirement.m
3 // Security
4 //
5 // Created by Michelle Auricchio on 12/27/16.
6 //
7 //
8
9 #import <Foundation/Foundation.h>
10 #import "keychain/SecureObjectSync/SOSAccountTrustClassic.h"
11 #import "keychain/SecureObjectSync/SOSAccountTrustClassic+Retirement.h"
12 #import "keychain/SecureObjectSync/SOSPeerInfoCollections.h"
13 #import "keychain/SecureObjectSync/SOSTransportMessageKVS.h"
14
15 @implementation SOSAccountTrustClassic (Retirement)
16
17 -(bool) cleanupRetirementTickets:(SOSAccount*)account circle:(SOSCircleRef)circle time:(size_t) seconds err:(CFErrorRef*) error
18 {
19 CFMutableSetRef retirees_to_remove = CFSetCreateMutableForSOSPeerInfosByID(kCFAllocatorDefault);
20
21 __block bool success = true;
22
23 CFSetForEach((__bridge CFSetRef)(self.retirees), ^(const void *value) {
24 SOSPeerInfoRef retiree = (SOSPeerInfoRef) value;
25
26 if (retiree) {
27 // Remove the entry if it's not a retired peer or if it's retirment ticket has expired AND he's no longer in the circle.
28 if (!SOSPeerInfoIsRetirementTicket(retiree) ||
29 (SOSPeerInfoRetireRetirementTicket(seconds, retiree) && !SOSCircleHasActivePeer(circle, retiree, NULL))) {
30 CFSetAddValue(retirees_to_remove, retiree);
31 };
32 }
33 });
34
35 CFMutableArrayRef retirees_to_cleanup = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
36 CFSetForEach(retirees_to_remove, ^(const void *value) {
37 CFArrayAppendValue(retirees_to_cleanup, value);
38 CFSetRemoveValue((__bridge CFMutableSetRef)self.retirees, value);
39 });
40
41 CFReleaseNull(retirees_to_remove);
42
43 CFDictionaryRef retirements_to_remove = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
44 SOSCircleGetName(circle), retirees_to_cleanup,
45 NULL);
46
47 CFReleaseNull(retirees_to_cleanup);
48
49 success = [account.circle_transport expireRetirementRecords:retirements_to_remove err:error];
50
51 CFReleaseNull(retirements_to_remove);
52
53 return success;
54 }
55
56 static inline CFMutableArrayRef CFDictionaryEnsureCFArrayAndGetCurrentValue(CFMutableDictionaryRef dict, CFTypeRef key)
57 {
58 CFMutableArrayRef result = (CFMutableArrayRef) CFDictionaryGetValue(dict, key);
59
60 if (!isArray(result)) {
61 result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
62 CFDictionarySetValue(dict, key, result);
63 CFReleaseSafe(result);
64 }
65
66 return result;
67 }
68
69
70 -(bool) cleanupAfterPeer:(SOSMessageKVS*)kvsTransport circleTransport:(SOSCircleStorageTransport*)circleTransport seconds:(size_t) seconds circle:(SOSCircleRef) circle cleanupPeer:(SOSPeerInfoRef) cleanupPeer err:(CFErrorRef*) error
71 {
72 bool success = true;
73
74 SOSPeerInfoRef myPeerInfo = self.peerInfo;
75 require_action_quiet(self.fullPeerInfo && myPeerInfo, xit, SOSErrorCreate(kSOSErrorPeerNotFound, error, NULL, CFSTR("I have no peer")));
76 require_quiet(SOSCircleHasActivePeer(circle, self.peerInfo, error), xit);
77
78 CFStringRef cleanupPeerID = SOSPeerInfoGetPeerID(cleanupPeer);
79
80 CFStringRef circle_name = SOSCircleGetName(circle);
81
82 CFMutableDictionaryRef circleToPeerIDs = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
83 CFArrayAppendValue(CFDictionaryEnsureCFArrayAndGetCurrentValue(circleToPeerIDs, circle_name), cleanupPeerID);
84
85 CFErrorRef localError = NULL;
86
87 if (!(success &= [kvsTransport SOSTransportMessageCleanupAfterPeerMessages:kvsTransport peers:circleToPeerIDs err:&localError])) {
88 secnotice("account", "Failed to cleanup after peer %@ messages: %@", cleanupPeerID, localError);
89 }
90
91 CFReleaseNull(localError);
92
93 if((success &= SOSPeerInfoRetireRetirementTicket(seconds, cleanupPeer))) {
94
95 if (!(success &= [circleTransport expireRetirementRecords:circleToPeerIDs err:&localError])) {
96 secnotice("account", "Failed to cleanup after peer %@ retirement: %@", cleanupPeerID, localError);
97 }
98 }
99 CFReleaseNull(localError);
100 CFReleaseNull(circleToPeerIDs);
101
102 xit:
103 return success;
104 }
105
106 @end