]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPeers.c
Security-57740.31.2.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSAccountPeers.c
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
25 #include <stdio.h>
26 #include "SOSAccountPriv.h"
27 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
28 #include <Security/SecureObjectSync/SOSTransportMessage.h>
29 #include <Security/SecureObjectSync/SOSPeerInfoV2.h>
30
31
32 bool SOSAccountIsMyPeerActive(SOSAccountRef account, CFErrorRef* error) {
33 SOSPeerInfoRef me = SOSFullPeerInfoGetPeerInfo(account->my_identity);
34 return me ? SOSCircleHasActivePeer(account->trusted_circle, me, error) : false;
35 }
36
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;
40 }
41
42 //
43 // MARK: Peer Querying
44 //
45
46
47 static void sosArrayAppendPeerCopy(CFMutableArrayRef appendPeersTo, SOSPeerInfoRef peer) {
48 SOSPeerInfoRef peerInfo = SOSPeerInfoCreateCopy(kCFAllocatorDefault, peer, NULL);
49 CFArrayAppendValue(appendPeersTo, peerInfo);
50 CFRelease(peerInfo);
51 }
52
53 static CFArrayRef SOSAccountCopySortedPeerArray(SOSAccountRef account,
54 CFErrorRef *error,
55 void (^action)(SOSCircleRef circle, CFMutableArrayRef appendPeersTo)) {
56 if (!SOSAccountHasPublicKey(account, error))
57 return NULL;
58
59 CFMutableArrayRef peers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
60
61 action(account->trusted_circle, peers);
62
63 CFArrayOfSOSPeerInfosSortByID(peers);
64
65 return peers;
66 }
67
68
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);
74 }
75 });
76 });
77 }
78
79
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);
85 }
86 });
87 });
88 }
89
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)) {
97 action(peer);
98 }
99 });
100 }
101 }
102
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);
112 }
113 });
114 });
115 }
116
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);
121 });
122 });
123 }
124
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);
130 } else {
131 CFSetRef peerEnabledViews = SOSPeerInfoCopyEnabledViews(peer);
132 CFSetRef enabledV0Views = CFSetCreateIntersection(kCFAllocatorDefault, peerEnabledViews, SOSViewsGetV0ViewSet());
133 if(CFSetGetCount(enabledV0Views) != 0) {
134 sosArrayAppendPeerCopy(appendPeersTo, peer);
135 }
136 CFReleaseNull(peerEnabledViews);
137 CFReleaseNull(enabledV0Views);
138 }
139 });
140 });
141 }
142
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);
147 });
148 });
149 }
150
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);
155 });
156 });
157 }
158
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);
168
169 SecItemCopyMatching(query, &result);
170
171 if(!isData(result)){
172 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result);
173 CFReleaseNull(result);
174 return NULL;
175 }
176 return result;
177 }
178
179 bool SOSAccountDeleteAccountStateFromKeychain(CFErrorRef *error){
180 CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
181 bool result = false;
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);
187
188 result = SecItemDelete(query);
189 return result;
190 }
191
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);
203
204 SecItemCopyMatching(query, &result);
205
206 if(!isData(result)){
207 SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result);
208 CFReleaseNull(result);
209 return NULL;
210 }
211 return result;
212 }
213
214 bool SOSAccountDeleteEngineStateFromKeychain(CFErrorRef *error){
215 CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
216 bool result = false;
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);
224
225 result = SecItemDelete(query);
226 return result;
227 }
228
229
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);
234 });
235 });
236 }
237
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);
242 });
243 });
244 }
245
246 CFArrayRef SOSAccountCopyConcurringPeers(SOSAccountRef account, CFErrorRef *error)
247 {
248 return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
249 SOSCircleAppendConcurringPeers(circle, appendPeersTo, NULL);
250 });
251 }
252
253 SOSPeerInfoRef SOSAccountCopyPeerWithID(SOSAccountRef account, CFStringRef peerid, CFErrorRef *error) {
254 if(!account->trusted_circle) return NULL;
255 return SOSCircleCopyPeerWithID(account->trusted_circle, peerid, error);
256 }
257
258 CFBooleanRef SOSAccountPeersHaveViewsEnabled(SOSAccountRef account, CFArrayRef viewNames, CFErrorRef *error) {
259 CFBooleanRef result = NULL;
260 CFMutableSetRef viewsRemaining = NULL;
261 CFSetRef viewsToLookFor = NULL;
262
263 require_quiet(SOSAccountHasPublicKey(account, error), done);
264 require_quiet(SOSAccountIsInCircle(account, error), done);
265
266 viewsToLookFor = CFSetCreateCopyOfArrayForCFTypes(viewNames);
267 viewsRemaining = CFSetCreateMutableCopy(kCFAllocatorDefault, 0, viewsToLookFor);
268 CFReleaseNull(viewsToLookFor);
269
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);
275 }
276 });
277
278 result = CFSetIsEmpty(viewsRemaining) ? kCFBooleanTrue : kCFBooleanFalse;
279
280 done:
281 CFReleaseNull(viewsToLookFor);
282 CFReleaseNull(viewsRemaining);
283
284 return result;
285 }
286