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>
32 bool SOSAccountIsMyPeerActive(SOSAccountRef account
, CFErrorRef
* error
) {
33 SOSPeerInfoRef me
= SOSFullPeerInfoGetPeerInfo(account
->my_identity
);
34 return me
? SOSCircleHasActivePeer(account
->trusted_circle
, me
, error
) : false;
38 // MARK: Peer Querying
42 static void sosArrayAppendPeerCopy(CFMutableArrayRef appendPeersTo
, SOSPeerInfoRef peer
) {
43 SOSPeerInfoRef peerInfo
= SOSPeerInfoCreateCopy(kCFAllocatorDefault
, peer
, NULL
);
44 CFArrayAppendValue(appendPeersTo
, peerInfo
);
48 static CFArrayRef
SOSAccountCopySortedPeerArray(SOSAccountRef account
,
50 void (^action
)(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
)) {
51 if (!SOSAccountHasPublicKey(account
, error
))
54 CFMutableArrayRef peers
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
56 action(account
->trusted_circle
, peers
);
58 CFArrayOfSOSPeerInfosSortByID(peers
);
64 CFArrayRef
SOSAccountCopyNotValidPeers(SOSAccountRef account
, CFErrorRef
*error
) {
65 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
66 SOSCircleForEachPeer(circle
, ^(SOSPeerInfoRef peer
) {
67 if(!SOSPeerInfoApplicationVerify(peer
, account
->user_public
, NULL
)) {
68 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
75 CFArrayRef
SOSAccountCopyValidPeers(SOSAccountRef account
, CFErrorRef
*error
) {
76 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
77 SOSCircleForEachPeer(circle
, ^(SOSPeerInfoRef peer
) {
78 if(SOSPeerInfoApplicationVerify(peer
, account
->user_public
, NULL
)) {
79 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
85 void SOSAccountForEachCirclePeerExceptMe(SOSAccountRef account
, void (^action
)(SOSPeerInfoRef peer
)) {
86 SOSPeerInfoRef myPi
= SOSAccountGetMyPeerInfo(account
);
87 if (account
->trusted_circle
&& myPi
) {
88 CFStringRef myPi_id
= SOSPeerInfoGetPeerID(myPi
);
89 SOSCircleForEachPeer(account
->trusted_circle
, ^(SOSPeerInfoRef peer
) {
90 CFStringRef peerID
= SOSPeerInfoGetPeerID(peer
);
91 if (peerID
&& !CFEqual(peerID
, myPi_id
)) {
98 CFArrayRef
SOSAccountCopyPeersToListenTo(SOSAccountRef account
, CFErrorRef
*error
) {
99 SOSPeerInfoRef myPeerInfo
= SOSFullPeerInfoGetPeerInfo(account
->my_identity
);
100 CFStringRef myID
= myPeerInfo
? SOSPeerInfoGetPeerID(myPeerInfo
) : NULL
;
101 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
102 SOSCircleForEachPeer(circle
, ^(SOSPeerInfoRef peer
) {
103 if(!CFEqualSafe(myID
, SOSPeerInfoGetPeerID(peer
)) &&
104 SOSPeerInfoApplicationVerify(peer
, account
->user_public
, NULL
) &&
105 !SOSPeerInfoIsRetirementTicket(peer
)) {
106 CFArrayAppendValue(appendPeersTo
, peer
);
112 CFArrayRef
SOSAccountCopyRetired(SOSAccountRef account
, CFErrorRef
*error
) {
113 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
114 SOSCircleForEachRetiredPeer(circle
, ^(SOSPeerInfoRef peer
) {
115 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
120 CFArrayRef
SOSAccountCopyViewUnaware(SOSAccountRef account
, CFErrorRef
*error
) {
121 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
122 SOSCircleForEachPeer(circle
, ^(SOSPeerInfoRef peer
) {
123 if (!SOSPeerInfoVersionHasV2Data(peer
) ) {
124 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
126 CFSetRef peerEnabledViews
= SOSPeerInfoCopyEnabledViews(peer
);
127 CFSetRef enabledV0Views
= CFSetCreateIntersection(kCFAllocatorDefault
, peerEnabledViews
, SOSViewsGetV0ViewSet());
128 if(CFSetGetCount(enabledV0Views
) != 0) {
129 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
131 CFReleaseNull(peerEnabledViews
);
132 CFReleaseNull(enabledV0Views
);
138 CFArrayRef
SOSAccountCopyApplicants(SOSAccountRef account
, CFErrorRef
*error
) {
139 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
140 SOSCircleForEachApplicant(circle
, ^(SOSPeerInfoRef peer
) {
141 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
146 CFArrayRef
SOSAccountCopyPeers(SOSAccountRef account
, CFErrorRef
*error
) {
147 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
148 SOSCircleForEachPeer(circle
, ^(SOSPeerInfoRef peer
) {
149 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
154 CFDataRef
SOSAccountCopyAccountStateFromKeychain(CFErrorRef
*error
){
155 CFMutableDictionaryRef query
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
156 CFTypeRef result
= NULL
;
157 CFDictionaryAddValue(query
, kSecClass
, kSecClassGenericPassword
);
158 CFDictionaryAddValue(query
, kSecAttrAccessGroup
, CFSTR("com.apple.security.sos"));
159 CFDictionaryAddValue(query
, kSecAttrAccessible
, CFSTR("dku"));
160 CFDictionaryAddValue(query
, kSecAttrTombstone
, kCFBooleanFalse
);
161 CFDictionaryAddValue(query
, kSecAttrSynchronizable
, kCFBooleanFalse
);
162 CFDictionaryAddValue(query
, kSecReturnData
, kCFBooleanTrue
);
164 SecItemCopyMatching(query
, &result
);
167 SOSErrorCreate(kSOSErrorUnexpectedType
, error
, NULL
, CFSTR("Expected CFData, got: %@"), result
);
168 CFReleaseNull(result
);
174 bool SOSAccountDeleteAccountStateFromKeychain(CFErrorRef
*error
){
175 CFMutableDictionaryRef query
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
177 CFDictionaryAddValue(query
, kSecClass
, kSecClassGenericPassword
);
178 CFDictionaryAddValue(query
, kSecAttrAccessGroup
, CFSTR("com.apple.security.sos"));
179 CFDictionaryAddValue(query
, kSecAttrAccessible
, CFSTR("dku"));
180 CFDictionaryAddValue(query
, kSecAttrTombstone
, kCFBooleanFalse
);
181 CFDictionaryAddValue(query
, kSecAttrSynchronizable
, kCFBooleanFalse
);
183 result
= SecItemDelete(query
);
187 CFDataRef
SOSAccountCopyEngineStateFromKeychain(CFErrorRef
*error
){
188 CFMutableDictionaryRef query
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
189 CFTypeRef result
= NULL
;
190 CFDictionaryAddValue(query
, kSecClass
, kSecClassGenericPassword
);
191 CFDictionaryAddValue(query
, kSecAttrAccount
, CFSTR("engine-state"));
192 CFDictionaryAddValue(query
, kSecAttrAccessGroup
, CFSTR("com.apple.security.sos"));
193 CFDictionaryAddValue(query
, kSecAttrAccessible
, CFSTR("dk"));
194 CFDictionaryAddValue(query
, kSecAttrService
, CFSTR("SOSDataSource-ak"));
195 CFDictionaryAddValue(query
, kSecAttrTombstone
, kCFBooleanFalse
);
196 CFDictionaryAddValue(query
, kSecAttrSynchronizable
, kCFBooleanFalse
);
197 CFDictionaryAddValue(query
, kSecReturnData
, kCFBooleanTrue
);
199 SecItemCopyMatching(query
, &result
);
202 SOSErrorCreate(kSOSErrorUnexpectedType
, error
, NULL
, CFSTR("Expected CFData, got: %@"), result
);
203 CFReleaseNull(result
);
209 bool SOSAccountDeleteEngineStateFromKeychain(CFErrorRef
*error
){
210 CFMutableDictionaryRef query
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
212 CFDictionaryAddValue(query
, kSecClass
, kSecClassGenericPassword
);
213 CFDictionaryAddValue(query
, kSecAttrAccount
, CFSTR("engine-state"));
214 CFDictionaryAddValue(query
, kSecAttrAccessGroup
, CFSTR("com.apple.security.sos"));
215 CFDictionaryAddValue(query
, kSecAttrAccessible
, CFSTR("dk"));
216 CFDictionaryAddValue(query
, kSecAttrService
, CFSTR("SOSDataSource-ak"));
217 CFDictionaryAddValue(query
, kSecAttrTombstone
, kCFBooleanFalse
);
218 CFDictionaryAddValue(query
, kSecAttrSynchronizable
, kCFBooleanFalse
);
220 result
= SecItemDelete(query
);
225 CFArrayRef
SOSAccountCopyActivePeers(SOSAccountRef account
, CFErrorRef
*error
) {
226 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
227 SOSCircleForEachActivePeer(circle
, ^(SOSPeerInfoRef peer
) {
228 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
233 CFArrayRef
SOSAccountCopyActiveValidPeers(SOSAccountRef account
, CFErrorRef
*error
) {
234 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
235 SOSCircleForEachActiveValidPeer(circle
, account
->user_public
, ^(SOSPeerInfoRef peer
) {
236 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
241 CFArrayRef
SOSAccountCopyConcurringPeers(SOSAccountRef account
, CFErrorRef
*error
)
243 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
244 SOSCircleAppendConcurringPeers(circle
, appendPeersTo
, NULL
);
248 SOSPeerInfoRef
SOSAccountCopyPeerWithID(SOSAccountRef account
, CFStringRef peerid
, CFErrorRef
*error
) {
249 if(!account
->trusted_circle
) return NULL
;
250 return SOSCircleCopyPeerWithID(account
->trusted_circle
, peerid
, error
);
253 CFBooleanRef
SOSAccountPeersHaveViewsEnabled(SOSAccountRef account
, CFArrayRef viewNames
, CFErrorRef
*error
) {
254 CFBooleanRef result
= NULL
;
255 CFMutableSetRef viewsRemaining
= NULL
;
256 CFSetRef viewsToLookFor
= NULL
;
258 require_quiet(SOSAccountHasPublicKey(account
, error
), done
);
259 require_quiet(SOSAccountIsInCircle(account
, error
), done
);
261 viewsToLookFor
= CFSetCreateCopyOfArrayForCFTypes(viewNames
);
262 viewsRemaining
= CFSetCreateMutableCopy(kCFAllocatorDefault
, 0, viewsToLookFor
);
263 CFReleaseNull(viewsToLookFor
);
265 SOSAccountForEachCirclePeerExceptMe(account
, ^(SOSPeerInfoRef peer
) {
266 if (SOSPeerInfoApplicationVerify(peer
, account
->user_public
, NULL
)) {
267 CFSetRef peerViews
= SOSPeerInfoCopyEnabledViews(peer
);
268 CFSetSubtract(viewsRemaining
, peerViews
);
269 CFReleaseNull(peerViews
);
273 result
= CFSetIsEmpty(viewsRemaining
) ? kCFBooleanTrue
: kCFBooleanFalse
;
276 CFReleaseNull(viewsToLookFor
);
277 CFReleaseNull(viewsRemaining
);