1 #include <Security/SecureObjectSync/SOSTransport.h> 
   2 #include <Security/SecureObjectSync/SOSTransportMessage.h> 
   3 #include <Security/SecureObjectSync/SOSTransportMessageIDS.h> 
   4 #include <Security/SecureObjectSync/SOSKVSKeys.h> 
   5 #include <Security/SecureObjectSync/SOSPeerCoder.h> 
   6 #include <Security/SecureObjectSync/SOSEngine.h> 
   7 #include <utilities/SecCFWrappers.h> 
   8 #include <SOSInternal.h> 
   9 #include <Security/SecureObjectSync/SOSAccountPriv.h> 
  10 #include <SOSCloudKeychainClient.h> 
  11 #include <securityd/SecItemServer.h> // TODO: Remove this layer violation. 
  13 CFGiblisWithHashFor(SOSTransportMessage
); 
  15 SOSTransportMessageRef 
SOSTransportMessageCreateForSubclass(size_t size
, 
  16                                                                    SOSAccountRef account
, CFStringRef circleName
, 
  19     SOSTransportMessageRef tpt 
= CFTypeAllocateWithSpace(SOSTransportMessage
, size
, kCFAllocatorDefault
); 
  21     SOSEngineRef engine 
= SOSDataSourceFactoryGetEngineForDataSourceName(account
->factory
, circleName
, error
); 
  23     tpt
->engine 
= CFRetainSafe(engine
); 
  24     tpt
->account 
= CFRetainSafe(account
); 
  25     tpt
->circleName 
= CFRetainSafe(circleName
); 
  30 static CFStringRef 
SOSTransportMessageCopyFormatDescription(CFTypeRef aObj
, CFDictionaryRef formatOptions
){ 
  31     SOSTransportMessageRef t 
= (SOSTransportMessageRef
) aObj
; 
  33     return t
->copyDescription 
? t
->copyDescription(t
) 
  34                               : CFStringCreateWithFormat(NULL
, NULL
, CFSTR("<SOSTransportMessage@%p\n>"), t
); 
  37 static void SOSTransportMessageDestroy(CFTypeRef aObj
){ 
  38     SOSTransportMessageRef transport 
= (SOSTransportMessageRef
) aObj
; 
  40     if (transport
->destroy
) 
  41         transport
->destroy(transport
); 
  43     CFReleaseSafe(transport
->account
); 
  46 CFStringRef 
SOSTransportMessageGetCircleName(SOSTransportMessageRef transport
){ 
  47     return transport
->circleName
; 
  50 CFIndex 
SOSTransportMessageGetTransportType(SOSTransportMessageRef transport
, CFErrorRef 
*error
){ 
  51     return transport
->getTransportType 
? transport
->getTransportType(transport
, error
) : kUnknown
; 
  55 SOSAccountRef 
SOSTransportMessageGetAccount(SOSTransportMessageRef transport
){ 
  56     return transport
->account
; 
  59 static CFHashCode 
SOSTransportMessageHash(CFTypeRef obj
){ 
  60     return (intptr_t) obj
; 
  63 static Boolean 
SOSTransportMessageCompare(CFTypeRef lhs
, CFTypeRef rhs
){ 
  64     return SOSTransportMessageHash(lhs
) == SOSTransportMessageHash(rhs
); 
  67 bool SOSTransportMessageSendMessages(SOSTransportMessageRef transport
, CFDictionaryRef circle_messages
, CFErrorRef 
*error
) { 
  68     return transport
->sendMessages(transport
, circle_messages
, error
); 
  71 bool SOSTransportMessageFlushChanges(SOSTransportMessageRef transport
, CFErrorRef 
*error
){ 
  72     return transport
->flushChanges(transport
, error
); 
  75 bool SOSTransportMessageSyncWithPeers(SOSTransportMessageRef transport
, CFDictionaryRef circleToPeerIDs
, CFErrorRef 
*error
){ 
  76     return transport
->syncWithPeers(transport
, circleToPeerIDs
, error
); 
  79 bool SOSTransportMessageCleanupAfterPeerMessages(SOSTransportMessageRef transport
, CFDictionaryRef circleToPeerIDs
, CFErrorRef
* error
){ 
  80     return transport
->cleanupAfterPeerMessages(transport
, circleToPeerIDs
, error
); 
  84 CFDictionaryRef 
SOSTransportMessageHandleMessages(SOSTransportMessageRef transport
, CFMutableDictionaryRef circle_peer_messages_table
, CFErrorRef 
*error
){ 
  85     return transport
->handleMessages(transport
, circle_peer_messages_table
, error
); 
  88 SOSEngineRef 
SOSTransportMessageGetEngine(SOSTransportMessageRef transport
) { 
  89     return transport
->engine
; 
  92 bool SOSTransportMessageHandlePeerMessage(SOSTransportMessageRef transport
, CFStringRef peerID
, CFDataRef codedMessage
, CFErrorRef 
*error
) { 
  93     __block 
bool result 
= true; 
  94     __block 
bool somethingChanged 
= false; 
  95     SOSEngineRef engine 
= SOSTransportMessageGetEngine(transport
); 
  96     result 
&= SOSEngineWithPeerID(engine
, peerID
, error
, ^(SOSPeerRef peer
, SOSDataSourceRef dataSource
, SOSTransactionRef txn
, bool *shouldSave
) { 
  97         CFDataRef decodedMessage 
= NULL
; 
  98         enum SOSCoderUnwrapStatus uwstatus 
= SOSPeerHandleCoderMessage(peer
, peerID
, codedMessage
, &decodedMessage
, shouldSave
, error
); 
  99         if (uwstatus 
== SOSCoderUnwrapDecoded
) { 
 100             SOSMessageRef message 
=  NULL
; 
 101             if (decodedMessage 
&& CFDataGetLength(decodedMessage
)) { 
 102                 // Only hand non empty messages to the engine, empty messages are an artifact 
 104                 message 
= SOSMessageCreateWithData(kCFAllocatorDefault
, decodedMessage
, error
); 
 107                 bool engineHandleMessageDoesNotGetToRollbackTransactions 
= true; 
 108                 result 
= SOSEngineHandleMessage_locked(engine
, peerID
, message
, txn
, &engineHandleMessageDoesNotGetToRollbackTransactions
, &somethingChanged
, error
); 
 109                 CFReleaseSafe(message
); 
 112             result 
= uwstatus 
!= SOSCoderUnwrapError
; 
 114         CFReleaseNull(decodedMessage
); 
 116     // TODO: Wish this wasn't here but alas.  See the comment for SOSEngineHandleMessage_locked() on why this is needed. 
 117     if (somethingChanged
) 
 118         SecKeychainChanged(false); 
 123 bool SOSTransportMessageSendMessageIfNeeded(SOSTransportMessageRef transport
, CFStringRef circle_id
, CFStringRef peer_id
, CFErrorRef 
*error
) { 
 124     __block 
bool ok 
= true; 
 125     SOSEngineRef engine 
= SOSTransportMessageGetEngine(transport
); 
 127     ok 
&= SOSEngineForPeerID(engine
, peer_id
, error
, ^(SOSPeerRef peer
) { 
 128         // Now under engine lock do stuff 
 129         CFDataRef message_to_send 
= NULL
; 
 130         SOSEnginePeerMessageSentBlock sent 
= NULL
; 
 131         ok 
= SOSPeerCoderSendMessageIfNeeded(engine
, peer
, &message_to_send
, circle_id
, peer_id
, &sent
, error
); 
 132         if (message_to_send
) { 
 133             CFDictionaryRef peer_dict 
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
, 
 134                                                                      peer_id
, message_to_send
, 
 136             CFDictionaryRef circle_peers 
= CFDictionaryCreateForCFTypes(kCFAllocatorDefault
, 
 137                                                                         circle_id
, peer_dict
, 
 139             ok 
= ok 
&& SOSTransportMessageSendMessages(transport
, circle_peers
, error
); 
 141             SOSPeerCoderConsume(&sent
, ok
); 
 143             CFReleaseSafe(peer_dict
); 
 144             CFReleaseSafe(circle_peers
); 
 148         CFReleaseSafe(message_to_send
);