5 //  Created by Richard Murphy on 3/23/15. 
   9 #include "SOSAccountHSAJoin.h" 
  10 #include "SOSAccountPriv.h" 
  11 #include <Security/SecureObjectSync/SOSPeerInfo.h> 
  12 #include <Security/SecureObjectSync/SOSPeerInfoV2.h> 
  13 #include <Security/SecureObjectSync/SOSPeerInfoPriv.h> 
  14 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h> 
  15 #include <Security/SecureObjectSync/SOSTransportCircle.h> 
  16 #include <Security/SecureObjectSync/SOSTransportMessage.h> 
  17 #include <Security/SecureObjectSync/SOSTransportMessageIDS.h> 
  18 #include <Security/SecureObjectSync/SOSKVSKeys.h> 
  19 #include <Security/SecureObjectSync/SOSTransport.h> 
  20 #include <Security/SecureObjectSync/SOSTransportKeyParameter.h> 
  21 #include <Security/SecureObjectSync/SOSTransportKeyParameterKVS.h> 
  22 #include <Security/SecureObjectSync/SOSEngine.h> 
  23 #include <Security/SecureObjectSync/SOSPeerCoder.h> 
  24 #include <Security/SecureObjectSync/SOSInternal.h> 
  25 #include <sys/unistd.h> 
  27 const CFStringRef kSOSHsaPreApprovedPeerKeyInfo 
= CFSTR("HSAPreApprovedPeer"); 
  29 const CFStringRef kSOSHsaCrKeyUUID 
= CFSTR("HSAUUID"); 
  30 const CFStringRef kSOSHsaCrKeyDescription 
= CFSTR("HSADESC"); 
  32 CFMutableSetRef 
SOSAccountCopyPreApprovedHSA2Info(SOSAccountRef account
) { 
  33     CFMutableSetRef preApprovedPeers 
= (CFMutableSetRef
) SOSAccountGetValue(account
, kSOSHsaPreApprovedPeerKeyInfo
, NULL
); 
  34     if(preApprovedPeers
) { 
  35         preApprovedPeers 
= CFSetCreateMutableCopy(NULL
, 0, preApprovedPeers
); 
  37         preApprovedPeers 
= CFSetCreateMutableForCFTypes(NULL
); 
  39     return preApprovedPeers
; 
  42 static bool sosAccountSetPreApprovedInfo(SOSAccountRef account
, CFStringRef peerID
, CFErrorRef 
*error
) { 
  44     CFMutableSetRef preApprovedPeers 
= SOSAccountCopyPreApprovedHSA2Info(account
); 
  45     require_action_quiet(preApprovedPeers
, errOut
, SOSCreateError(kSOSErrorAllocationFailure
, CFSTR("Can't Alloc Pre-Approved Peers Set"), NULL
, error
)); 
  46     CFSetSetValue(preApprovedPeers
, peerID
); 
  47     require(SOSAccountSetValue(account
, kSOSHsaPreApprovedPeerKeyInfo
, preApprovedPeers
, error
), errOut
); 
  50     CFReleaseNull(preApprovedPeers
); 
  54 bool SOSAccountSetHSAPubKeyExpected(SOSAccountRef account
, CFDataRef pubKeyBytes
, CFErrorRef 
*error
) { 
  56     SecKeyRef publicKey 
= SecKeyCreateFromPublicBytes(NULL
, kSecECDSAAlgorithmID
, CFDataGetBytePtr(pubKeyBytes
), CFDataGetLength(pubKeyBytes
)); 
  57     CFStringRef peerID 
= SOSCopyIDOfKey(publicKey
, error
); 
  58     require(sosAccountSetPreApprovedInfo(account
, peerID
, error
), errOut
); 
  61     CFReleaseNull(publicKey
); 
  62     CFReleaseNull(peerID
); 
  66 bool SOSAccountVerifyAndAcceptHSAApplicants(SOSAccountRef account
, SOSCircleRef newCircle
, CFErrorRef 
*error
) { 
  67     SOSFullPeerInfoRef fpi 
= account
->my_identity
; 
  68     __block 
bool circleChanged 
= false; 
  69     CFMutableSetRef approvals 
= SOSAccountCopyPreApprovedHSA2Info(account
); 
  70     if(approvals 
&& CFSetGetCount(approvals
) > 0) { 
  71         SOSCircleForEachApplicant(newCircle
, ^(SOSPeerInfoRef peer
) { 
  72             CFStringRef peerID 
= SOSPeerInfoGetPeerID(peer
); 
  73             if(CFSetContainsValue(approvals
, peerID
)) { 
  74                 SOSPeerInfoRef copypi 
= SOSPeerInfoCreateCopy(NULL
, peer
, NULL
); 
  75                 circleChanged 
= SOSCircleAcceptRequest(newCircle
, SOSAccountGetPrivateCredential(account
, NULL
), fpi
, copypi
, error
); 
  76                 CFSetRemoveValue(approvals
, peerID
); 
  81         bool local 
= SOSAccountSetValue(account
, kSOSHsaPreApprovedPeerKeyInfo
, approvals
, error
); 
  82         if(!local
) secnotice("hsa2approval", "Couldn't clean pre-approved peer list"); 
  84     CFReleaseNull(approvals
); 
  88 bool SOSAccountClientPing(SOSAccountRef account
) { 
  89     if (account
->trusted_circle 
&& account
->my_identity
 
  90         && SOSFullPeerInfoPing(account
->my_identity
, NULL
)) { 
  91         SOSAccountModifyCircle(account
, NULL
, ^(SOSCircleRef circle_to_change
) { 
  92             secnotice("circleChange", "Calling SOSCircleUpdatePeerInfo for gestalt change"); 
  93             return SOSCircleUpdatePeerInfo(circle_to_change
, SOSFullPeerInfoGetPeerInfo(account
->my_identity
));