]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSRingTypes.c
6b807ba83381cb05c318bd19609b07ea1cfd0cd2
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSRingTypes.c
1 //
2 // SOSRingTypes.c
3 // sec
4 //
5 // Created by Richard Murphy on 2/23/15.
6 //
7 //
8
9 #include "SOSRing.h"
10 #include "SOSRingTypes.h"
11 #include "SOSRingBasic.h"
12 #include "SOSRingBackup.h"
13 #include <Security/SecureObjectSync/SOSAccountPriv.h>
14 #include <Security/SecureObjectSync/SOSBackupSliceKeyBag.h>
15
16 static ringFuncs ringTypes[] = {
17 &basic,
18 &backup,
19 };
20 static const size_t typecount = sizeof(ringTypes) / sizeof(ringFuncs);
21
22 static bool SOSRingValidType(SOSRingType type) {
23 return type < typecount;
24 }
25
26 // MARK: Exported Functions
27
28
29 SOSRingRef SOSRingCreate(CFStringRef name, CFStringRef myPeerID, SOSRingType type, CFErrorRef *error) {
30 require(SOSRingValidType(type), errOut);
31 require(ringTypes[type]->sosRingCreate, errOut);
32 return ringTypes[type]->sosRingCreate(name, myPeerID, error);
33 errOut:
34 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
35 return NULL;
36 }
37
38 bool SOSRingResetToEmpty(SOSRingRef ring, CFStringRef myPeerID, CFErrorRef *error) {
39 SOSRingAssertStable(ring);
40 SOSRingType type = SOSRingGetType(ring);
41 require(SOSRingValidType(type), errOut);
42 require(ringTypes[type]->sosRingResetToEmpty, errOut);
43 return ringTypes[type]->sosRingResetToEmpty(ring, myPeerID, error);
44 errOut:
45 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
46 return false;
47 }
48
49 bool SOSRingResetToOffering(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
50 SOSRingAssertStable(ring);
51 SOSRingType type = SOSRingGetType(ring);
52 require(SOSRingValidType(type), errOut);
53 require(ringTypes[type]->sosRingResetToOffering, errOut);
54 return ringTypes[type]->sosRingResetToOffering(ring, user_privkey, requestor, error);
55 errOut:
56 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
57 return false;
58 }
59
60 SOSRingStatus SOSRingDeviceIsInRing(SOSRingRef ring, CFStringRef peerID) {
61 SOSRingAssertStable(ring);
62 SOSRingType type = SOSRingGetType(ring);
63 require(SOSRingValidType(type), errOut);
64 require(ringTypes[type]->sosRingDeviceIsInRing, errOut);
65 return ringTypes[type]->sosRingDeviceIsInRing(ring, peerID);
66 errOut:
67 return kSOSRingError;
68 }
69
70 bool SOSRingApply(SOSRingRef ring, SecKeyRef user_pubkey, SOSFullPeerInfoRef fpi, CFErrorRef *error) {
71 SOSRingAssertStable(ring);
72 SOSRingType type = SOSRingGetType(ring);
73 require(SOSRingValidType(type), errOut);
74 require(ringTypes[type]->sosRingApply, shortCircuit);
75 require_quiet(SOSPeerInfoApplicationVerify(SOSFullPeerInfoGetPeerInfo(fpi), user_pubkey, error), errOut2);
76
77 return ringTypes[type]->sosRingApply(ring, user_pubkey, fpi, error);
78 errOut:
79 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
80 return false;
81 errOut2:
82 SOSCreateError(kSOSErrorBadSignature, CFSTR("FullPeerInfo fails userkey signature check"), NULL, error);
83 return false;
84 shortCircuit:
85 return true;
86 }
87
88 bool SOSRingWithdraw(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
89 SOSRingAssertStable(ring);
90 SOSRingType type = SOSRingGetType(ring);
91 require(SOSRingValidType(type), errOut);
92 require(ringTypes[type]->sosRingWithdraw, shortCircuit);
93 return ringTypes[type]->sosRingWithdraw(ring, user_privkey, requestor, error);
94 errOut:
95 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
96 return false;
97 shortCircuit:
98 return true;
99 }
100
101 bool SOSRingGenerationSign(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
102 SOSRingAssertStable(ring);
103 SOSRingType type = SOSRingGetType(ring);
104 require(SOSRingValidType(type), errOut);
105 require(ringTypes[type]->sosRingGenerationSign, shortCircuit);
106 return ringTypes[type]->sosRingGenerationSign(ring, user_privkey, requestor, error);
107 errOut:
108 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
109 return false;
110 shortCircuit:
111 return true;
112 }
113
114 bool SOSRingConcordanceSign(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
115 SOSRingAssertStable(ring);
116 SOSRingType type = SOSRingGetType(ring);
117 require(SOSRingValidType(type), errOut);
118 require(ringTypes[type]->sosRingConcordanceSign, shortCircuit);
119 return ringTypes[type]->sosRingConcordanceSign(ring, requestor, error);
120 errOut:
121 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
122 return false;
123 shortCircuit:
124 return true;
125 }
126
127 SOSConcordanceStatus SOSRingConcordanceTrust(SOSFullPeerInfoRef me, CFSetRef peers,
128 SOSRingRef knownRing, SOSRingRef proposedRing,
129 SecKeyRef knownPubkey, SecKeyRef userPubkey,
130 CFStringRef excludePeerID, CFErrorRef *error) {
131 SOSRingAssertStable(knownRing);
132 SOSRingAssertStable(proposedRing);
133 SOSRingType type1 = SOSRingGetType(knownRing);
134 SOSRingType type2 = SOSRingGetType(proposedRing);
135 require(SOSRingValidType(type1), errOut);
136 require(SOSRingValidType(type2), errOut);
137 require(type1 == type2, errOut);
138
139 secnotice("ring", "concordance trust (%s) knownRing: %@ proposedRing: %@ knownkey: %@ userkey: %@ excluded: %@",
140 ringTypes[type1]->typeName, knownRing, proposedRing, knownPubkey, userPubkey, excludePeerID);
141
142 require(ringTypes[type1]->sosRingConcordanceTrust, errOut);
143 return ringTypes[type1]->sosRingConcordanceTrust(me, peers, knownRing, proposedRing, knownPubkey, userPubkey, excludePeerID, error);
144 errOut:
145 return kSOSConcordanceError;
146 }
147
148 bool SOSRingAccept(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
149 SOSRingAssertStable(ring);
150 SOSRingType type = SOSRingGetType(ring);
151 require(SOSRingValidType(type), errOut);
152 require(ringTypes[type]->sosRingAccept, shortCircuit);
153 return ringTypes[type]->sosRingAccept(ring, user_privkey, requestor, error);
154 errOut:
155 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
156 return false;
157 shortCircuit:
158 return true;
159 }
160
161 bool SOSRingReject(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
162 SOSRingAssertStable(ring);
163 SOSRingType type = SOSRingGetType(ring);
164 require(SOSRingValidType(type), errOut);
165 require(ringTypes[type]->sosRingReject, shortCircuit);
166 return ringTypes[type]->sosRingReject(ring, user_privkey, requestor, error);
167 errOut:
168 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
169 return false;
170 shortCircuit:
171 return true;
172 }
173
174 bool SOSRingSetPayload(SOSRingRef ring, SecKeyRef user_privkey, CFDataRef payload, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
175 SOSRingAssertStable(ring);
176 SOSRingType type = SOSRingGetType(ring);
177 require(SOSRingValidType(type), errOut);
178 require(ringTypes[type]->sosRingSetPayload, errOut);
179 return ringTypes[type]->sosRingSetPayload(ring, user_privkey, payload, requestor, error);
180 errOut:
181 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
182 return false;
183 }
184
185 CFDataRef SOSRingGetPayload(SOSRingRef ring, CFErrorRef *error) {
186 SOSRingAssertStable(ring);
187 SOSRingType type = SOSRingGetType(ring);
188 require(SOSRingValidType(type), errOut);
189 require(ringTypes[type]->sosRingGetPayload, errOut);
190 return ringTypes[type]->sosRingGetPayload(ring, error);
191 errOut:
192 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
193 return false;
194 }
195
196 CFSetRef SOSRingGetBackupViewset(SOSRingRef ring, CFErrorRef *error) {
197 SOSRingAssertStable(ring);
198 SOSRingType type = SOSRingGetType(ring);
199 require(kSOSRingBackup == type, errOut);
200 return SOSRingGetBackupViewset_Internal(ring);
201 errOut:
202 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not backup ring type"), NULL, error);
203 return false;
204 }
205
206 static bool isBackupRing(SOSRingRef ring, CFErrorRef *error) {
207 SOSRingType type = SOSRingGetType(ring);
208 require_quiet(kSOSRingBackup == type, errOut);
209 return true;
210 errOut:
211 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not backup ring type"), NULL, error);
212 return false;
213 }
214
215 bool SOSRingSetBackupKeyBag(SOSRingRef ring, SOSFullPeerInfoRef fpi, CFSetRef viewSet, SOSBackupSliceKeyBagRef bskb, CFErrorRef *error) {
216 SOSRingAssertStable(ring);
217 CFDataRef bskb_as_data = NULL;
218 bool result = false;
219 require_quiet(isBackupRing(ring, error), errOut);
220
221 bskb_as_data = SOSBSKBCopyEncoded(bskb, error);
222 result = bskb_as_data &&
223 SOSRingSetBackupViewset_Internal(ring, viewSet) &&
224 SOSRingSetPayload(ring, NULL, bskb_as_data, fpi, error);
225 errOut:
226 CFReleaseNull(bskb_as_data);
227 return result;
228 }
229
230 SOSBackupSliceKeyBagRef SOSRingCopyBackupSliceKeyBag(SOSRingRef ring, CFErrorRef *error) {
231 SOSRingAssertStable(ring);
232
233 CFDataRef bskb_as_data = NULL;
234 SOSBackupSliceKeyBagRef result = NULL;
235 require_quiet(isBackupRing(ring, error), errOut);
236
237 bskb_as_data = SOSRingGetPayload(ring, error);
238 require_quiet(bskb_as_data, errOut);
239
240 result = SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault, bskb_as_data, error);
241
242 errOut:
243 return result;
244 }
245
246
247 bool SOSRingPKTrusted(SOSRingRef ring, SecKeyRef pubkey, CFErrorRef *error) {
248 SOSRingAssertStable(ring);
249 SOSRingType type = SOSRingGetType(ring);
250 require(SOSRingValidType(type), errOut);
251 return SOSRingVerify(ring, pubkey, error);
252 errOut:
253 SOSCreateError(kSOSErrorUnexpectedType, CFSTR("Not valid ring type"), NULL, error);
254 return false;
255 }
256
257 bool SOSRingPeerTrusted(SOSRingRef ring, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
258 bool retval = false;
259 SOSPeerInfoRef pi = SOSFullPeerInfoGetPeerInfo(requestor);
260 SecKeyRef pubkey = SOSPeerInfoCopyPubKey(pi, error);
261 require_quiet(pubkey, exit);
262 retval = SOSRingPKTrusted(ring, pubkey, error);
263 exit:
264 CFReleaseNull(pubkey);
265 return retval;
266 }
267
268
269 #if 0
270 static inline
271 bool SOSAccountKnowsRings(SOSAccountRef account, CFErrorRef *error) {
272 if(account->rings) return true;
273 SOSCreateError(kSOSErrorUnsupported, CFSTR("This account doesn't support rings"), NULL, error);
274 return false;
275 }
276
277
278 // ViewRequirements
279 bool SOSRingRequirementKnown(SOSAccountRef account, CFStringRef name, CFErrorRef *error) {
280 bool retval = false;
281 require_quiet(SOSAccountKnowsRings(account, error), errOut);
282 retval = CFDictionaryContainsValue(account->rings, name);
283 errOut:
284 return retval;
285 }
286
287 bool SOSRingRequirementCreate(SOSAccountRef account, CFStringRef name, SOSRingType type, CFErrorRef *error) {
288 if(account->rings) return false;
289 if(CFDictionaryContainsValue(account->rings, name)) return true;
290 if(!SOSRingValidType(type)) return false;
291 SOSRingRef ring = SOSRingCreate(NULL, name, type, error);
292 if(!ring) return false;
293 CFDictionaryAddValue(account->rings, name, ring);
294 return false;
295 }
296
297 static SOSRingRef getRingFromAccount(SOSAccountRef account, CFStringRef name, CFErrorRef* error) {
298 SOSRingRef retval = NULL;
299 require_quiet(SOSAccountKnowsRings(account, error), errOut);
300 retval = (SOSRingRef) CFDictionaryGetValue(account->rings, name);
301
302 errOut:
303 return retval;
304
305 }
306
307 // Admins
308 bool SOSRingRequirementResetToOffering(SOSAccountRef account, CFStringRef name, CFErrorRef* error) {
309 SOSRingRef ring = getRingFromAccount(account, name, error);
310 SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInfo(account);
311 require_action_quiet(ring, errOut,
312 SOSCreateError(kSOSErrorNoCircle, CFSTR("No ring by name specified"), NULL, error));
313 switch(SOSRingGetType(ring)) {
314
315 }
316 SOSRingResetToOffering(ring, account->__user_private, fpi, error);
317
318 errOut:
319 return false;
320 }
321
322
323 bool SOSRingRequirementResetToEmpty(SOSAccountRef account, CFStringRef name, CFErrorRef* error) {
324 return false;
325 }
326
327
328
329 // Clients
330 bool SOSRingRequirementRequestToJoin(SOSAccountRef account, CFStringRef name, CFErrorRef* error) {
331 return false;
332 }
333
334 bool SOSRingRequirementRemoveThisDevice(SOSAccountRef account, CFStringRef name, CFErrorRef* error) {
335 return false;
336 }
337
338 // Approvers
339 CFArrayRef SOSRingRequirementGetApplicants(SOSAccountRef account, CFStringRef name, CFErrorRef* error) {
340 return false;
341 }
342
343
344 bool SOSRingRequirementAcceptApplicants(SOSAccountRef account, CFStringRef name, CFArrayRef applicants, CFErrorRef* error) {
345 return false;
346 }
347
348
349 bool SOSRingRequirementRejectApplicants(SOSAccountRef account, CFStringRef name, CFArrayRef applicants, CFErrorRef *error) {
350 return false;
351 }
352
353
354 bool SOSRingResetToOffering(SOSCircleRef circle, SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error){
355
356 return SOSRingResetToEmpty(ring, error)
357 && SOSRingRequestAdmission(ring, user_privkey, requestor, error)
358 && SOSRingAcceptRequest(ring, user_privkey, requestor, SOSFullPeerInfoGetPeerInfo(requestor), error);
359 }
360
361
362 static bool SOSRingRecordAdmissionRequest(SOSRingRef ring, SecKeyRef user_pubkey, CFStringRef peerID, CFErrorRef *error) {
363 SOSRingAssertStable(ring);
364
365 bool isPeer = SOSRingHasPeerWithID(ring, peerID, error);
366 require_action_quiet(!isPeer, fail, SOSCreateError(kSOSErrorAlreadyPeer, CFSTR("Cannot request admission when already a peer"), NULL, error));
367 CFSetRemoveValue(ring->rejections, requestorPeerInfo); // We remove from rejected list, in case?
368 CFSetSetValue(ring->applicants, requestorPeerInfo);
369
370 return true;
371
372 fail:
373 return false;
374
375 }
376
377 bool SOSRingRequestReadmission(SOSRingRef ring, SecKeyRef user_pubkey, SOSPeerInfoRef peer, CFErrorRef *error) {
378 bool success = false;
379
380 require_quiet(SOSPeerInfoApplicationVerify(peer, user_pubkey, error), fail);
381 success = SOSRingRecordAdmissionRequest(ring, user_pubkey, peer, error);
382 fail:
383 return success;
384 }
385
386 bool SOSRingRequestAdmission(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
387 bool success = false;
388
389 SecKeyRef user_pubkey = SecKeyCreatePublicFromPrivate(user_privkey);
390 require_action_quiet(user_pubkey, fail, SOSCreateError(kSOSErrorBadKey, CFSTR("No public key for key"), NULL, error));
391
392 require(SOSFullPeerInfoPromoteToApplication(requestor, user_privkey, error), fail);
393
394 success = SOSRingRecordAdmissionRequest(ring, user_pubkey, SOSFullPeerInfoGetPeerInfo(requestor), error);
395 fail:
396 CFReleaseNull(user_pubkey);
397 return success;
398 }
399
400
401 bool SOSRingRemovePeer(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, SOSPeerInfoRef peer_to_remove, CFErrorRef *error) {
402 SOSPeerInfoRef requestor_peer_info = SOSFullPeerInfoGetPeerInfo(requestor);
403
404 if (SOSRingHasApplicant(ring, peer_to_remove, error)) {
405 return SOSRingRejectRequest(ring, requestor, peer_to_remove, error);
406 }
407
408 if (!SOSRingHasPeer(ring, requestor_peer_info, error)) {
409 SOSCreateError(kSOSErrorAlreadyPeer, CFSTR("Must be peer to remove peer"), NULL, error);
410 return false;
411 }
412
413 CFSetRemoveValue(ring->peers, peer_to_remove);
414
415 SOSRingGenerationSign(ring, user_privkey, requestor, error);
416
417 return true;
418 }
419
420 bool SOSRingAcceptRequest(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef device_approver, SOSPeerInfoRef peerInfo, CFErrorRef *error) {
421 SOSRingAssertStable(ring);
422
423 SecKeyRef publicKey = NULL;
424 bool result = false;
425
426 require_action_quiet(CFSetContainsValue(ring->applicants, peerInfo), fail,
427 SOSCreateError(kSOSErrorNotApplicant, CFSTR("Cannot accept non-applicant"), NULL, error));
428
429 publicKey = SecKeyCreatePublicFromPrivate(user_privkey);
430 require_quiet(SOSPeerInfoApplicationVerify(peerInfo, publicKey, error), fail);
431
432 CFSetRemoveValue(ring->applicants, peerInfo);
433 CFSetSetValue(ring->peers, peerInfo);
434
435 result = SOSRingGenerationSign(ring, user_privkey, device_approver, error);
436 secnotice("ring", "Accepted %@", peerInfo);
437
438 fail:
439 CFReleaseNull(publicKey);
440 return result;
441 }
442
443 bool SOSRingWithdrawRequest(SOSRingRef ring, SOSPeerInfoRef peerInfo, CFErrorRef *error) {
444 SOSRingAssertStable(ring);
445
446 CFSetRemoveValue(ring->applicants, peerInfo);
447
448 return true;
449 }
450
451 bool SOSRingRemoveRejectedPeer(SOSRingRef ring, SOSPeerInfoRef peerInfo, CFErrorRef *error) {
452 SOSRingAssertStable(ring);
453
454 CFSetRemoveValue(ring->rejected_applicants, peerInfo);
455
456 return true;
457 }
458
459
460 bool SOSRingRejectRequest(SOSRingRef ring, SOSFullPeerInfoRef device_rejector,
461 SOSPeerInfoRef peerInfo, CFErrorRef *error) {
462 SOSRingAssertStable(ring);
463
464 if (CFEqual(SOSPeerInfoGetPeerID(peerInfo), SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(device_rejector))))
465 return SOSRingWithdrawRequest(ring, peerInfo, error);
466
467 if (!CFSetContainsValue(ring->applicants, peerInfo)) {
468 SOSCreateError(kSOSErrorNotApplicant, CFSTR("Cannot reject non-applicant"), NULL, error);
469 return false;
470 }
471
472 CFSetRemoveValue(ring->applicants, peerInfo);
473 CFSetSetValue(ring->rejected_applicants, peerInfo);
474
475 // TODO: Maybe we sign the rejection with device_rejector.
476
477 return true;
478 }
479
480 bool SOSRingAcceptRequests(SOSRingRef ring, SecKeyRef user_privkey, SOSFullPeerInfoRef device_approver,
481 CFErrorRef *error) {
482 // Returns true if we accepted someone and therefore have to post the ring back to KVS
483 __block bool result = false;
484
485 SOSRingForEachApplicant(ring, ^(SOSPeerInfoRef peer) {
486 if (!SOSRingAcceptRequest(ring, user_privkey, device_approver, peer, error))
487 printf("error in SOSRingAcceptRequest\n");
488 else {
489 secnotice("ring", "Accepted peer: %@", peer);
490 result = true;
491 }
492 });
493
494 if (result) {
495 SOSRingGenerationSign(ring, user_privkey, device_approver, error);
496 secnotice("ring", "Countersigned accepted requests");
497 }
498
499 return result;
500 }
501
502 bool SOSRingPeerSigUpdate(SOSRingRef ring, SecKeyRef userPrivKey, SOSFullPeerInfoRef fpi,
503 CFErrorRef *error) {
504 // Returns true if we accepted someone and therefore have to post the ring back to KVS
505 __block bool result = false;
506 SecKeyRef userPubKey = SecKeyCreatePublicFromPrivate(userPrivKey);
507
508 // We're going to remove any applicants using a mismatched user key.
509 SOSRingForEachApplicant(ring, ^(SOSPeerInfoRef peer) {
510 if(!SOSPeerInfoApplicationVerify(peer, userPubKey, NULL)) {
511 if(!SOSRingRejectRequest(ring, fpi, peer, NULL)) {
512 // do we care?
513 }
514 }
515 });
516
517 result = SOSRingUpdatePeerInfo(ring, SOSFullPeerInfoGetPeerInfo(fpi));
518
519 if (result) {
520 SOSRingGenerationSign(ring, userPrivKey, fpi, error);
521 secnotice("ring", "Generation signed updated signatures on peerinfo");
522 }
523
524 return result;
525 }
526
527
528 SOSFullPeerInfoRef SOSRingGetiCloudFullPeerInfoRef(SOSCircleRef circle, SOSRingRef ring) {
529 __block SOSFullPeerInfoRef cloud_full_peer = NULL;
530 SOSRingForEachActivePeer(circle, ring, ^(SOSPeerInfoRef peer) {
531 if (SOSPeerInfoIsCloudIdentity(peer)) {
532 if (cloud_full_peer == NULL) {
533 CFErrorRef localError = NULL;
534 cloud_full_peer = SOSFullPeerInfoCreateCloudIdentity(kCFAllocatorDefault, peer, &localError);
535
536 if (localError) {
537 secerror("Found cloud peer in ring but can't make full peer: %@", localError);
538 CFReleaseNull(localError);
539 }
540
541 } else {
542 secerror("More than one cloud identity found in ring: %@", ring);
543 }
544 }
545 });
546 return cloud_full_peer;
547 }
548
549
550 CFMutableArrayRef SOSRingCopyConcurringPeers(SOSRingRef ring, CFErrorRef* error) {
551 SOSRingAssertStable(ring);
552
553 CFMutableArrayRef concurringPeers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
554
555 if (!SOSRingAppendConcurringPeers(ring, concurringPeers, error))
556 CFReleaseNull(concurringPeers);
557
558 return concurringPeers;
559 }
560
561
562 bool SOSRingAppendConcurringPeers(SOSCircleRef circle, SOSRingRef ring, CFMutableArrayRef appendHere, CFErrorRef *error) {
563 SOSRingForEachActivePeer(circle, ring, ^(SOSPeerInfoRef peer) {
564 CFErrorRef localError = NULL;
565 if (SOSRingVerifyPeerSigned(ring, peer, &localError)) {
566 CFArrayAppendValue(appendHere, peer);
567 } else if (error != NULL) {
568 secerror("Error checking concurrence: %@", localError);
569 }
570 CFReleaseNull(localError);
571 });
572
573 return true;
574 }
575 #endif