2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 #include "SOSAccountPriv.h"
27 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
28 #include <Security/SecureObjectSync/SOSTransportMessage.h>
29 #include <Security/SecureObjectSync/SOSPeerInfoV2.h>
30 #include <Security/SecureObjectSync/SOSPeerInfoSecurityProperties.h>
31 #import <Security/SecureObjectSync/SOSAccountTrust.h>
32 #include <Security/SecureObjectSync/SOSAccountTrustClassic+Circle.h>
34 bool SOSAccountIsMyPeerActive(SOSAccount* account, CFErrorRef* error) {
35 SOSFullPeerInfoRef identity = NULL;
36 SOSCircleRef circle = NULL;
38 SOSAccountTrustClassic *trust = account.trust;
39 identity = trust.fullPeerInfo;
40 circle = trust.trustedCircle;
42 SOSPeerInfoRef me = SOSFullPeerInfoGetPeerInfo(identity);
43 return me ? SOSCircleHasActivePeer(circle, me, error) : false;
47 // MARK: Peer Querying
51 static void sosArrayAppendPeerCopy(CFMutableArrayRef appendPeersTo, SOSPeerInfoRef peer) {
52 SOSPeerInfoRef peerInfo = SOSPeerInfoCreateCopy(kCFAllocatorDefault, peer, NULL);
53 CFArrayAppendValue(appendPeersTo, peerInfo);
57 static CFArrayRef SOSAccountCopySortedPeerArray(SOSAccount* account,
59 void (^action)(SOSCircleRef circle, CFMutableArrayRef appendPeersTo)) {
60 if (!SOSAccountHasPublicKey(account, error))
63 CFMutableArrayRef peers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
64 SOSCircleRef circle = NULL;
66 SOSAccountTrustClassic *trust = account.trust;
67 circle = trust.trustedCircle;
68 action(circle, peers);
70 CFArrayOfSOSPeerInfosSortByID(peers);
76 CFArrayRef SOSAccountCopyNotValidPeers(SOSAccount* account, CFErrorRef *error) {
77 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
78 SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) {
79 if(!SOSPeerInfoApplicationVerify(peer, account.accountKey, NULL)) {
80 sosArrayAppendPeerCopy(appendPeersTo, peer);
87 CFArrayRef SOSAccountCopyValidPeers(SOSAccount* account, CFErrorRef *error) {
88 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
89 SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) {
90 if(SOSPeerInfoApplicationVerify(peer, account.accountKey, NULL)) {
91 sosArrayAppendPeerCopy(appendPeersTo, peer);
99 CFArrayRef SOSAccountCopyPeersToListenTo(SOSAccount* account, CFErrorRef *error) {
100 SOSFullPeerInfoRef identity = NULL;
102 SOSAccountTrustClassic *trust = account.trust;
103 identity = trust.fullPeerInfo;
104 SOSPeerInfoRef myPeerInfo = SOSFullPeerInfoGetPeerInfo(identity);
105 CFStringRef myID = myPeerInfo ? SOSPeerInfoGetPeerID(myPeerInfo) : NULL;
106 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
107 SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) {
108 if(!CFEqualSafe(myID, SOSPeerInfoGetPeerID(peer)) &&
109 SOSPeerInfoApplicationVerify(peer, account.accountKey, NULL) &&
110 !SOSPeerInfoIsRetirementTicket(peer)) {
111 CFArrayAppendValue(appendPeersTo, peer);
117 CFArrayRef SOSAccountCopyRetired(SOSAccount* account, CFErrorRef *error) {
118 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
119 SOSCircleForEachRetiredPeer(circle, ^(SOSPeerInfoRef peer) {
120 sosArrayAppendPeerCopy(appendPeersTo, peer);
125 CFArrayRef SOSAccountCopyViewUnaware(SOSAccount* account, CFErrorRef *error) {
126 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
127 SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) {
128 if (!SOSPeerInfoVersionHasV2Data(peer) ) {
129 sosArrayAppendPeerCopy(appendPeersTo, peer);
131 CFSetRef peerEnabledViews = SOSPeerInfoCopyEnabledViews(peer);
132 CFSetRef enabledV0Views = CFSetCreateIntersection(kCFAllocatorDefault, peerEnabledViews, SOSViewsGetV0ViewSet());
133 if(CFSetGetCount(enabledV0Views) != 0) {
134 sosArrayAppendPeerCopy(appendPeersTo, peer);
136 CFReleaseNull(peerEnabledViews);
137 CFReleaseNull(enabledV0Views);
143 CFArrayRef SOSAccountCopyApplicants(SOSAccount* account, CFErrorRef *error) {
144 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
145 SOSCircleForEachApplicant(circle, ^(SOSPeerInfoRef peer) {
146 sosArrayAppendPeerCopy(appendPeersTo, peer);
151 CFArrayRef SOSAccountCopyPeers(SOSAccount* account, CFErrorRef *error) {
152 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
153 SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) {
154 sosArrayAppendPeerCopy(appendPeersTo, peer);
159 CFDataRef SOSAccountCopyAccountStateFromKeychain(CFErrorRef *error){
160 CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
161 CFTypeRef result = NULL;
162 CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword);
163 CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("com.apple.security.sos"));
164 CFDictionaryAddValue(query, kSecAttrAccessible, CFSTR("dku"));
165 CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanFalse);
166 CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanFalse);
167 CFDictionaryAddValue(query, kSecReturnData, kCFBooleanTrue);
169 SecItemCopyMatching(query, &result);
172 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result);
173 CFReleaseNull(result);
179 bool SOSAccountDeleteAccountStateFromKeychain(CFErrorRef *error){
180 CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
182 CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword);
183 CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("com.apple.security.sos"));
184 CFDictionaryAddValue(query, kSecAttrAccessible, CFSTR("dku"));
185 CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanFalse);
186 CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanFalse);
188 result = SecItemDelete(query);
192 CFDataRef SOSAccountCopyEngineStateFromKeychain(CFErrorRef *error){
193 CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
194 CFTypeRef result = NULL;
195 CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword);
196 CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("engine-state"));
197 CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("com.apple.security.sos"));
198 CFDictionaryAddValue(query, kSecAttrAccessible, CFSTR("dk"));
199 CFDictionaryAddValue(query, kSecAttrService, CFSTR("SOSDataSource-ak"));
200 CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanFalse);
201 CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanFalse);
202 CFDictionaryAddValue(query, kSecReturnData, kCFBooleanTrue);
204 SecItemCopyMatching(query, &result);
207 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result);
208 CFReleaseNull(result);
214 bool SOSAccountDeleteEngineStateFromKeychain(CFErrorRef *error){
215 CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
217 CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword);
218 CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("engine-state"));
219 CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("com.apple.security.sos"));
220 CFDictionaryAddValue(query, kSecAttrAccessible, CFSTR("dk"));
221 CFDictionaryAddValue(query, kSecAttrService, CFSTR("SOSDataSource-ak"));
222 CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanFalse);
223 CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanFalse);
225 result = SecItemDelete(query);
230 CFArrayRef SOSAccountCopyActivePeers(SOSAccount* account, CFErrorRef *error) {
231 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
232 SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) {
233 sosArrayAppendPeerCopy(appendPeersTo, peer);
238 CFArrayRef CF_RETURNS_RETAINED SOSAccountCopyActiveValidPeers(SOSAccount* account, CFErrorRef *error) {
239 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
240 SOSCircleForEachActiveValidPeer(circle, account.accountKey, ^(SOSPeerInfoRef peer) {
241 sosArrayAppendPeerCopy(appendPeersTo, peer);
246 CFArrayRef SOSAccountCopyConcurringPeers(SOSAccount* account, CFErrorRef *error)
248 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
249 SOSCircleAppendConcurringPeers(circle, appendPeersTo, NULL);
253 SOSPeerInfoRef SOSAccountCopyPeerWithID(SOSAccount* account, CFStringRef peerid, CFErrorRef *error) {
254 SOSCircleRef circle = NULL;
256 SOSAccountTrustClassic *trust = account.trust;
257 circle = trust.trustedCircle;
258 if(!circle) return NULL;
259 return SOSCircleCopyPeerWithID(circle, peerid, error);
262 CFBooleanRef SOSAccountPeersHaveViewsEnabled(SOSAccount* account, CFArrayRef viewNames, CFErrorRef *error) {
263 CFBooleanRef result = NULL;
264 CFMutableSetRef viewsRemaining = NULL;
265 CFSetRef viewsToLookFor = NULL;
267 if(!SOSAccountHasPublicKey(account, error))
269 CFReleaseNull(viewsToLookFor);
270 CFReleaseNull(viewsRemaining);
274 if(![account.trust isInCircle:error]){
275 CFReleaseNull(viewsToLookFor);
276 CFReleaseNull(viewsRemaining);
281 viewsToLookFor = CFSetCreateCopyOfArrayForCFTypes(viewNames);
282 viewsRemaining = CFSetCreateMutableCopy(kCFAllocatorDefault, 0, viewsToLookFor);
283 CFReleaseNull(viewsToLookFor);
285 SOSAccountForEachCirclePeerExceptMe(account, ^(SOSPeerInfoRef peer) {
286 if (SOSPeerInfoApplicationVerify(peer, account.accountKey, NULL)) {
287 CFSetRef peerViews = SOSPeerInfoCopyEnabledViews(peer);
288 CFSetSubtract(viewsRemaining, peerViews);
289 CFReleaseNull(peerViews);
293 result = CFSetIsEmpty(viewsRemaining) ? kCFBooleanTrue : kCFBooleanFalse;
295 CFReleaseNull(viewsToLookFor);
296 CFReleaseNull(viewsRemaining);