/ keychain / SecureObjectSync / SOSAccountPeers.m
SOSAccountPeers.m
  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  #include "SOSAccountPriv.h"
 25  #include "SOSAccount.h"
 26  #include "keychain/SecureObjectSync/SOSPeerInfoCollections.h"
 27  #include "keychain/SecureObjectSync/SOSTransportMessage.h"
 28  #include "keychain/SecureObjectSync/SOSPeerInfoV2.h"
 29  #import "keychain/SecureObjectSync/SOSAccountTrust.h"
 30  #include "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h"
 31  
 32  bool SOSAccountIsMyPeerActive(SOSAccount* account, CFErrorRef* error) {
 33      SOSFullPeerInfoRef identity = NULL;
 34      SOSCircleRef circle = NULL;
 35  
 36      SOSAccountTrustClassic *trust = account.trust;
 37      identity = trust.fullPeerInfo;
 38      circle = trust.trustedCircle;
 39  
 40      SOSPeerInfoRef me = SOSFullPeerInfoGetPeerInfo(identity);
 41      return me ? SOSCircleHasActivePeer(circle, me, error) : false;
 42  }
 43  
 44  //
 45  // MARK: Peer Querying
 46  //
 47  
 48  
 49  static void sosArrayAppendPeerCopy(CFMutableArrayRef appendPeersTo, SOSPeerInfoRef peer) {
 50      SOSPeerInfoRef peerInfo = SOSPeerInfoCreateCopy(kCFAllocatorDefault, peer, NULL);
 51      CFArrayAppendValue(appendPeersTo, peerInfo);
 52      CFRelease(peerInfo);
 53  }
 54  
 55  static CFArrayRef SOSAccountCopySortedPeerArray(SOSAccount* account,
 56                                                  CFErrorRef *error,
 57                                                  void (^action)(SOSCircleRef circle, CFMutableArrayRef appendPeersTo)) {
 58      if (!SOSAccountHasPublicKey(account, error))
 59          return NULL;
 60      
 61      CFMutableArrayRef peers = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
 62      SOSCircleRef circle = NULL;
 63  
 64      SOSAccountTrustClassic *trust = account.trust;
 65      circle = trust.trustedCircle;
 66      action(circle, peers);
 67  
 68      CFArrayOfSOSPeerInfosSortByID(peers);
 69  
 70      return peers;
 71  }
 72  
 73  
 74  CFArrayRef SOSAccountCopyNotValidPeers(SOSAccount* account, CFErrorRef *error) {
 75      return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
 76          SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) {
 77              if(!SOSPeerInfoApplicationVerify(peer, account.accountKey, NULL)) {
 78                  sosArrayAppendPeerCopy(appendPeersTo, peer);
 79              }
 80          });
 81      });
 82  }
 83  
 84  
 85  CFArrayRef SOSAccountCopyValidPeers(SOSAccount* account, CFErrorRef *error) {
 86      return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
 87          SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) {
 88              if(SOSPeerInfoApplicationVerify(peer, account.accountKey, NULL)) {
 89                  sosArrayAppendPeerCopy(appendPeersTo, peer);
 90              }
 91          });
 92      });
 93  }
 94  
 95  
 96  
 97  CFArrayRef SOSAccountCopyPeersToListenTo(SOSAccount* account, CFErrorRef *error) {
 98      SOSFullPeerInfoRef identity = NULL;
 99  
100      SOSAccountTrustClassic *trust = account.trust;
101      identity = trust.fullPeerInfo;
102      SOSPeerInfoRef myPeerInfo = SOSFullPeerInfoGetPeerInfo(identity);
103      CFStringRef myID = myPeerInfo ? SOSPeerInfoGetPeerID(myPeerInfo) : NULL;
104      return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
105          SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) {
106              if(!CFEqualSafe(myID, SOSPeerInfoGetPeerID(peer)) &&
107                 SOSPeerInfoApplicationVerify(peer, account.accountKey, NULL) &&
108                 !SOSPeerInfoIsRetirementTicket(peer)) {
109                  CFArrayAppendValue(appendPeersTo, peer);
110              }
111          });
112      });
113  }
114  
115  CFArrayRef SOSAccountCopyRetired(SOSAccount* account, CFErrorRef *error) {
116      return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
117          SOSCircleForEachRetiredPeer(circle, ^(SOSPeerInfoRef peer) {
118              sosArrayAppendPeerCopy(appendPeersTo, peer);
119          });
120      });
121  }
122  
123  CFArrayRef SOSAccountCopyViewUnaware(SOSAccount* account, CFErrorRef *error) {
124      return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
125          SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) {
126              if (!SOSPeerInfoVersionHasV2Data(peer) ) {
127                  sosArrayAppendPeerCopy(appendPeersTo, peer);
128              }        });
129      });
130  }
131  
132  CFArrayRef SOSAccountCopyApplicants(SOSAccount* account, CFErrorRef *error) {
133      return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
134          SOSCircleForEachApplicant(circle, ^(SOSPeerInfoRef peer) {
135              sosArrayAppendPeerCopy(appendPeersTo, peer);
136          });
137      });
138  }
139  
140  CFArrayRef SOSAccountCopyPeers(SOSAccount* account, CFErrorRef *error) {
141      return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
142          SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) {
143              sosArrayAppendPeerCopy(appendPeersTo, peer);
144          });
145      });
146  }
147  
148  CFArrayRef SOSAccountCopyActivePeers(SOSAccount* account, CFErrorRef *error) {
149      return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
150          SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) {
151              sosArrayAppendPeerCopy(appendPeersTo, peer);
152          });
153      });
154  }
155  
156  CFArrayRef CF_RETURNS_RETAINED SOSAccountCopyActiveValidPeers(SOSAccount* account, CFErrorRef *error) {
157      return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
158          SOSCircleForEachActiveValidPeer(circle, account.accountKey, ^(SOSPeerInfoRef peer) {
159              sosArrayAppendPeerCopy(appendPeersTo, peer);
160          });
161      });
162  }
163  
164  CFArrayRef SOSAccountCopyConcurringPeers(SOSAccount* account, CFErrorRef *error)
165  {
166      return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) {
167          SOSCircleAppendConcurringPeers(circle, appendPeersTo, NULL);
168      });
169  }
170  
171  SOSPeerInfoRef SOSAccountCopyPeerWithID(SOSAccount* account, CFStringRef peerid, CFErrorRef *error) {
172      SOSCircleRef circle = NULL;
173  
174      SOSAccountTrustClassic *trust = account.trust;
175      circle = trust.trustedCircle;
176      if(!circle) return NULL;
177      return SOSCircleCopyPeerWithID(circle, peerid, error);
178  }
179  
180  CFBooleanRef SOSAccountPeersHaveViewsEnabled(SOSAccount* account, CFArrayRef viewNames, CFErrorRef *error) {
181      CFBooleanRef result = NULL;
182      CFMutableSetRef viewsRemaining = NULL;
183      CFSetRef viewsToLookFor = NULL;
184  
185      if(![account isInCircle:error]) {
186          CFReleaseNull(viewsToLookFor);
187          CFReleaseNull(viewsRemaining);
188          return result;
189      }
190  
191      viewsToLookFor = CFSetCreateCopyOfArrayForCFTypes(viewNames);
192      viewsRemaining = CFSetCreateMutableCopy(kCFAllocatorDefault, 0, viewsToLookFor);
193      CFReleaseNull(viewsToLookFor);
194  
195      SOSAccountForEachCirclePeerExceptMe(account, ^(SOSPeerInfoRef peer) {
196          if (SOSPeerInfoApplicationVerify(peer, account.accountKey, NULL)) {
197              CFSetRef peerViews = SOSPeerInfoCopyEnabledViews(peer);
198              CFSetSubtract(viewsRemaining, peerViews);
199              CFReleaseNull(peerViews);
200          }
201      });
202  
203      result = CFSetIsEmpty(viewsRemaining) ? kCFBooleanTrue : kCFBooleanFalse;
204  
205      CFReleaseNull(viewsToLookFor);
206      CFReleaseNull(viewsRemaining);
207  
208      return result;
209  }
210  
211  bool SOSAccountRemoveV0Clients(SOSAccount *account, CFErrorRef *error) {
212      CFErrorRef localError = NULL;
213      
214      CFArrayRef v0Peers = SOSAccountCopyViewUnaware(account, &localError);
215      if (error && localError) {
216          CFTransferRetained(*error, localError);
217      }
218      
219      if (v0Peers == NULL || CFArrayGetCount(v0Peers) == 0) {
220          CFReleaseNull(localError);
221          CFReleaseNull(v0Peers);
222          return true;
223      }
224      
225      bool result = SOSAccountRemovePeersFromCircle(account, v0Peers, &localError);
226      if (error && localError) {
227          CFTransferRetained(*error, localError);
228      }
229      
230      CFReleaseNull(localError);
231      CFReleaseNull(v0Peers);
232  
233      return result;
234  }