SOSAccountPeers.m
1 /* 2 * Copyright (c) 2013-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 #include "SOSAccountPriv.h" 25 #include "SOSAccount.h" 26 #include "keychain/SecureObjectSync/SOSPeerInfoCollections.h" 27 #include "keychain/SecureObjectSync/SOSTransportMessage.h" 28 #include "keychain/SecureObjectSync/SOSPeerInfoV2.h" 29 #import "keychain/SecureObjectSync/SOSAccountTrust.h" 30 #include "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h" 31 32 bool SOSAccountIsMyPeerActive(SOSAccount* account, CFErrorRef* error) { 33 SOSFullPeerInfoRef identity = NULL; 34 SOSCircleRef circle = NULL; 35 36 SOSAccountTrustClassic *trust = account.trust; 37 identity = trust.fullPeerInfo; 38 circle = trust.trustedCircle; 39 40 SOSPeerInfoRef me = SOSFullPeerInfoGetPeerInfo(identity); 41 return me ? SOSCircleHasActivePeer(circle, me, error) : false; 42 } 43 44 // 45 // MARK: Peer Querying 46 // 47 48 49 static void sosArrayAppendPeerCopy(CFMutableArrayRef appendPeersTo, SOSPeerInfoRef peer) { 50 SOSPeerInfoRef peerInfo = SOSPeerInfoCreateCopy(kCFAllocatorDefault, peer, NULL); 51 CFArrayAppendValue(appendPeersTo, peerInfo); 52 CFRelease(peerInfo); 53 } 54 55 static CFArrayRef SOSAccountCopySortedPeerArray(SOSAccount* account, 56 CFErrorRef *error, 57 void (^action)(SOSCircleRef circle, CFMutableArrayRef appendPeersTo)) { 58 if (!SOSAccountHasPublicKey(account, error)) 59 return NULL; 60 61 CFMutableArrayRef peers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); 62 SOSCircleRef circle = NULL; 63 64 SOSAccountTrustClassic *trust = account.trust; 65 circle = trust.trustedCircle; 66 action(circle, peers); 67 68 CFArrayOfSOSPeerInfosSortByID(peers); 69 70 return peers; 71 } 72 73 74 CFArrayRef SOSAccountCopyNotValidPeers(SOSAccount* account, CFErrorRef *error) { 75 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { 76 SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { 77 if(!SOSPeerInfoApplicationVerify(peer, account.accountKey, NULL)) { 78 sosArrayAppendPeerCopy(appendPeersTo, peer); 79 } 80 }); 81 }); 82 } 83 84 85 CFArrayRef SOSAccountCopyValidPeers(SOSAccount* account, CFErrorRef *error) { 86 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { 87 SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { 88 if(SOSPeerInfoApplicationVerify(peer, account.accountKey, NULL)) { 89 sosArrayAppendPeerCopy(appendPeersTo, peer); 90 } 91 }); 92 }); 93 } 94 95 96 97 CFArrayRef SOSAccountCopyPeersToListenTo(SOSAccount* account, CFErrorRef *error) { 98 SOSFullPeerInfoRef identity = NULL; 99 100 SOSAccountTrustClassic *trust = account.trust; 101 identity = trust.fullPeerInfo; 102 SOSPeerInfoRef myPeerInfo = SOSFullPeerInfoGetPeerInfo(identity); 103 CFStringRef myID = myPeerInfo ? SOSPeerInfoGetPeerID(myPeerInfo) : NULL; 104 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { 105 SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { 106 if(!CFEqualSafe(myID, SOSPeerInfoGetPeerID(peer)) && 107 SOSPeerInfoApplicationVerify(peer, account.accountKey, NULL) && 108 !SOSPeerInfoIsRetirementTicket(peer)) { 109 CFArrayAppendValue(appendPeersTo, peer); 110 } 111 }); 112 }); 113 } 114 115 CFArrayRef SOSAccountCopyRetired(SOSAccount* account, CFErrorRef *error) { 116 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { 117 SOSCircleForEachRetiredPeer(circle, ^(SOSPeerInfoRef peer) { 118 sosArrayAppendPeerCopy(appendPeersTo, peer); 119 }); 120 }); 121 } 122 123 CFArrayRef SOSAccountCopyViewUnaware(SOSAccount* account, CFErrorRef *error) { 124 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { 125 SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { 126 if (!SOSPeerInfoVersionHasV2Data(peer) ) { 127 sosArrayAppendPeerCopy(appendPeersTo, peer); 128 } }); 129 }); 130 } 131 132 CFArrayRef SOSAccountCopyApplicants(SOSAccount* account, CFErrorRef *error) { 133 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { 134 SOSCircleForEachApplicant(circle, ^(SOSPeerInfoRef peer) { 135 sosArrayAppendPeerCopy(appendPeersTo, peer); 136 }); 137 }); 138 } 139 140 CFArrayRef SOSAccountCopyPeers(SOSAccount* account, CFErrorRef *error) { 141 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { 142 SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { 143 sosArrayAppendPeerCopy(appendPeersTo, peer); 144 }); 145 }); 146 } 147 148 CFArrayRef SOSAccountCopyActivePeers(SOSAccount* account, CFErrorRef *error) { 149 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { 150 SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { 151 sosArrayAppendPeerCopy(appendPeersTo, peer); 152 }); 153 }); 154 } 155 156 CFArrayRef CF_RETURNS_RETAINED SOSAccountCopyActiveValidPeers(SOSAccount* account, CFErrorRef *error) { 157 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { 158 SOSCircleForEachActiveValidPeer(circle, account.accountKey, ^(SOSPeerInfoRef peer) { 159 sosArrayAppendPeerCopy(appendPeersTo, peer); 160 }); 161 }); 162 } 163 164 CFArrayRef SOSAccountCopyConcurringPeers(SOSAccount* account, CFErrorRef *error) 165 { 166 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { 167 SOSCircleAppendConcurringPeers(circle, appendPeersTo, NULL); 168 }); 169 } 170 171 SOSPeerInfoRef SOSAccountCopyPeerWithID(SOSAccount* account, CFStringRef peerid, CFErrorRef *error) { 172 SOSCircleRef circle = NULL; 173 174 SOSAccountTrustClassic *trust = account.trust; 175 circle = trust.trustedCircle; 176 if(!circle) return NULL; 177 return SOSCircleCopyPeerWithID(circle, peerid, error); 178 } 179 180 CFBooleanRef SOSAccountPeersHaveViewsEnabled(SOSAccount* account, CFArrayRef viewNames, CFErrorRef *error) { 181 CFBooleanRef result = NULL; 182 CFMutableSetRef viewsRemaining = NULL; 183 CFSetRef viewsToLookFor = NULL; 184 185 if(![account isInCircle:error]) { 186 CFReleaseNull(viewsToLookFor); 187 CFReleaseNull(viewsRemaining); 188 return result; 189 } 190 191 viewsToLookFor = CFSetCreateCopyOfArrayForCFTypes(viewNames); 192 viewsRemaining = CFSetCreateMutableCopy(kCFAllocatorDefault, 0, viewsToLookFor); 193 CFReleaseNull(viewsToLookFor); 194 195 SOSAccountForEachCirclePeerExceptMe(account, ^(SOSPeerInfoRef peer) { 196 if (SOSPeerInfoApplicationVerify(peer, account.accountKey, NULL)) { 197 CFSetRef peerViews = SOSPeerInfoCopyEnabledViews(peer); 198 CFSetSubtract(viewsRemaining, peerViews); 199 CFReleaseNull(peerViews); 200 } 201 }); 202 203 result = CFSetIsEmpty(viewsRemaining) ? kCFBooleanTrue : kCFBooleanFalse; 204 205 CFReleaseNull(viewsToLookFor); 206 CFReleaseNull(viewsRemaining); 207 208 return result; 209 } 210 211 bool SOSAccountRemoveV0Clients(SOSAccount *account, CFErrorRef *error) { 212 CFErrorRef localError = NULL; 213 214 CFArrayRef v0Peers = SOSAccountCopyViewUnaware(account, &localError); 215 if (error && localError) { 216 CFTransferRetained(*error, localError); 217 } 218 219 if (v0Peers == NULL || CFArrayGetCount(v0Peers) == 0) { 220 CFReleaseNull(localError); 221 CFReleaseNull(v0Peers); 222 return true; 223 } 224 225 bool result = SOSAccountRemovePeersFromCircle(account, v0Peers, &localError); 226 if (error && localError) { 227 CFTransferRetained(*error, localError); 228 } 229 230 CFReleaseNull(localError); 231 CFReleaseNull(v0Peers); 232 233 return result; 234 }