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;
37 SOSTransportMessageRef
SOSAccountGetMessageTransportFor(SOSAccountRef account
, SOSPeerInfoRef peerInfo
) {
38 // Returns the transport to use to talk to that peer. if he's a member of the circle.
39 return (SOSPeerInfoHasDeviceID(peerInfo
) && (false)) ? account
->ids_message_transport
: account
->kvs_message_transport
;
43 // MARK: Peer Querying
47 static void sosArrayAppendPeerCopy(CFMutableArrayRef appendPeersTo
, SOSPeerInfoRef peer
) {
48 SOSPeerInfoRef peerInfo
= SOSPeerInfoCreateCopy(kCFAllocatorDefault
, peer
, NULL
);
49 CFArrayAppendValue(appendPeersTo
, peerInfo
);
53 static CFArrayRef
SOSAccountCopySortedPeerArray(SOSAccountRef account
,
55 void (^action
)(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
)) {
56 if (!SOSAccountHasPublicKey(account
, error
))
59 CFMutableArrayRef peers
= CFArrayCreateMutableForCFTypes(kCFAllocatorDefault
);
61 action(account
->trusted_circle
, peers
);
63 CFArrayOfSOSPeerInfosSortByID(peers
);
69 CFArrayRef
SOSAccountCopyNotValidPeers(SOSAccountRef account
, CFErrorRef
*error
) {
70 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
71 SOSCircleForEachPeer(circle
, ^(SOSPeerInfoRef peer
) {
72 if(!SOSPeerInfoApplicationVerify(peer
, account
->user_public
, NULL
)) {
73 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
80 CFArrayRef
SOSAccountCopyValidPeers(SOSAccountRef account
, CFErrorRef
*error
) {
81 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
82 SOSCircleForEachPeer(circle
, ^(SOSPeerInfoRef peer
) {
83 if(SOSPeerInfoApplicationVerify(peer
, account
->user_public
, NULL
)) {
84 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
90 void SOSAccountForEachCirclePeerExceptMe(SOSAccountRef account
, void (^action
)(SOSPeerInfoRef peer
)) {
91 SOSPeerInfoRef myPi
= SOSAccountGetMyPeerInfo(account
);
92 if (account
->trusted_circle
&& myPi
) {
93 CFStringRef myPi_id
= SOSPeerInfoGetPeerID(myPi
);
94 SOSCircleForEachPeer(account
->trusted_circle
, ^(SOSPeerInfoRef peer
) {
95 CFStringRef peerID
= SOSPeerInfoGetPeerID(peer
);
96 if (peerID
&& !CFEqual(peerID
, myPi_id
)) {
103 CFArrayRef
SOSAccountCopyPeersToListenTo(SOSAccountRef account
, CFErrorRef
*error
) {
104 SOSPeerInfoRef myPeerInfo
= SOSFullPeerInfoGetPeerInfo(account
->my_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
->user_public
, NULL
) &&
110 !SOSPeerInfoIsRetirementTicket(peer
)) {
111 CFArrayAppendValue(appendPeersTo
, peer
);
117 CFArrayRef
SOSAccountCopyRetired(SOSAccountRef account
, CFErrorRef
*error
) {
118 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
119 SOSCircleForEachRetiredPeer(circle
, ^(SOSPeerInfoRef peer
) {
120 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
125 CFArrayRef
SOSAccountCopyViewUnaware(SOSAccountRef 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(SOSAccountRef account
, CFErrorRef
*error
) {
144 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
145 SOSCircleForEachApplicant(circle
, ^(SOSPeerInfoRef peer
) {
146 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
151 CFArrayRef
SOSAccountCopyPeers(SOSAccountRef 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(SOSAccountRef account
, CFErrorRef
*error
) {
231 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
232 SOSCircleForEachActivePeer(circle
, ^(SOSPeerInfoRef peer
) {
233 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
238 CFArrayRef
SOSAccountCopyActiveValidPeers(SOSAccountRef account
, CFErrorRef
*error
) {
239 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
240 SOSCircleForEachActiveValidPeer(circle
, account
->user_public
, ^(SOSPeerInfoRef peer
) {
241 sosArrayAppendPeerCopy(appendPeersTo
, peer
);
246 CFArrayRef
SOSAccountCopyConcurringPeers(SOSAccountRef account
, CFErrorRef
*error
)
248 return SOSAccountCopySortedPeerArray(account
, error
, ^(SOSCircleRef circle
, CFMutableArrayRef appendPeersTo
) {
249 SOSCircleAppendConcurringPeers(circle
, appendPeersTo
, NULL
);
253 SOSPeerInfoRef
SOSAccountCopyPeerWithID(SOSAccountRef account
, CFStringRef peerid
, CFErrorRef
*error
) {
254 if(!account
->trusted_circle
) return NULL
;
255 return SOSCircleCopyPeerWithID(account
->trusted_circle
, peerid
, error
);
258 CFBooleanRef
SOSAccountPeersHaveViewsEnabled(SOSAccountRef account
, CFArrayRef viewNames
, CFErrorRef
*error
) {
259 CFBooleanRef result
= NULL
;
260 CFMutableSetRef viewsRemaining
= NULL
;
261 CFSetRef viewsToLookFor
= NULL
;
263 require_quiet(SOSAccountHasPublicKey(account
, error
), done
);
264 require_quiet(SOSAccountIsInCircle(account
, error
), done
);
266 viewsToLookFor
= CFSetCreateCopyOfArrayForCFTypes(viewNames
);
267 viewsRemaining
= CFSetCreateMutableCopy(kCFAllocatorDefault
, 0, viewsToLookFor
);
268 CFReleaseNull(viewsToLookFor
);
270 SOSAccountForEachCirclePeerExceptMe(account
, ^(SOSPeerInfoRef peer
) {
271 if (SOSPeerInfoApplicationVerify(peer
, account
->user_public
, NULL
)) {
272 CFSetRef peerViews
= SOSPeerInfoCopyEnabledViews(peer
);
273 CFSetSubtract(viewsRemaining
, peerViews
);
274 CFReleaseNull(peerViews
);
278 result
= CFSetIsEmpty(viewsRemaining
) ? kCFBooleanTrue
: kCFBooleanFalse
;
281 CFReleaseNull(viewsToLookFor
);
282 CFReleaseNull(viewsRemaining
);