]> git.saurik.com Git - apple/security.git/blame - OSX/sec/SOSCircle/SecureObjectSync/SOSTransportMessage.c
Security-57740.20.22.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSTransportMessage.c
CommitLineData
5c19dc3a
A
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.
12
13CFGiblisWithHashFor(SOSTransportMessage);
14
15SOSTransportMessageRef SOSTransportMessageCreateForSubclass(size_t size,
16 SOSAccountRef account, CFStringRef circleName,
17 CFErrorRef *error)
18{
19 SOSTransportMessageRef tpt = CFTypeAllocateWithSpace(SOSTransportMessage, size, kCFAllocatorDefault);
20
21 SOSEngineRef engine = SOSDataSourceFactoryGetEngineForDataSourceName(account->factory, circleName, error);
22
23 tpt->engine = CFRetainSafe(engine);
24 tpt->account = CFRetainSafe(account);
25 tpt->circleName = CFRetainSafe(circleName);
26 return tpt;
27}
28
29
30static CFStringRef SOSTransportMessageCopyFormatDescription(CFTypeRef aObj, CFDictionaryRef formatOptions){
31 SOSTransportMessageRef t = (SOSTransportMessageRef) aObj;
32
33 return t->copyDescription ? t->copyDescription(t)
34 : CFStringCreateWithFormat(NULL, NULL, CFSTR("<SOSTransportMessage@%p\n>"), t);
35}
36
37static void SOSTransportMessageDestroy(CFTypeRef aObj){
38 SOSTransportMessageRef transport = (SOSTransportMessageRef) aObj;
39
40 if (transport->destroy)
41 transport->destroy(transport);
42
43 CFReleaseSafe(transport->account);
44}
45
46CFStringRef SOSTransportMessageGetCircleName(SOSTransportMessageRef transport){
47 return transport->circleName;
48}
49
50CFIndex SOSTransportMessageGetTransportType(SOSTransportMessageRef transport, CFErrorRef *error){
51 return transport->getTransportType ? transport->getTransportType(transport, error) : kUnknown;
52}
53
54
55SOSAccountRef SOSTransportMessageGetAccount(SOSTransportMessageRef transport){
56 return transport->account;
57}
58
59static CFHashCode SOSTransportMessageHash(CFTypeRef obj){
60 return (intptr_t) obj;
61}
62
63static Boolean SOSTransportMessageCompare(CFTypeRef lhs, CFTypeRef rhs){
64 return SOSTransportMessageHash(lhs) == SOSTransportMessageHash(rhs);
65}
66
67bool SOSTransportMessageSendMessages(SOSTransportMessageRef transport, CFDictionaryRef circle_messages, CFErrorRef *error) {
68 return transport->sendMessages(transport, circle_messages, error);
69}
70
71bool SOSTransportMessageFlushChanges(SOSTransportMessageRef transport, CFErrorRef *error){
72 return transport->flushChanges(transport, error);
73}
74
75bool SOSTransportMessageSyncWithPeers(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef *error){
76 return transport->syncWithPeers(transport, circleToPeerIDs, error);
77}
78
79bool SOSTransportMessageCleanupAfterPeerMessages(SOSTransportMessageRef transport, CFDictionaryRef circleToPeerIDs, CFErrorRef* error){
80 return transport->cleanupAfterPeerMessages(transport, circleToPeerIDs, error);
81}
82
83CF_RETURNS_RETAINED
84CFDictionaryRef SOSTransportMessageHandleMessages(SOSTransportMessageRef transport, CFMutableDictionaryRef circle_peer_messages_table, CFErrorRef *error){
85 return transport->handleMessages(transport, circle_peer_messages_table, error);
86}
87
88SOSEngineRef SOSTransportMessageGetEngine(SOSTransportMessageRef transport) {
89 return transport->engine;
90}
91
92bool SOSTransportMessageHandlePeerMessage(SOSTransportMessageRef transport, CFStringRef peerID, CFDataRef codedMessage, CFErrorRef *error) {
93 __block bool result = true;
94 __block bool somethingChanged = false;
95 SOSEngineRef engine = SOSTransportMessageGetEngine(transport);
fa7225c8 96 result &= SOSEngineWithPeerID(engine, peerID, error, ^(SOSPeerRef peer, SOSCoderRef coder, SOSDataSourceRef dataSource, SOSTransactionRef txn, bool *shouldSave) {
5c19dc3a 97 CFDataRef decodedMessage = NULL;
fa7225c8 98 enum SOSCoderUnwrapStatus uwstatus = SOSPeerHandleCoderMessage(peer, coder, peerID, codedMessage, &decodedMessage, shouldSave, error);
5c19dc3a
A
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
103 // of coder startup.
104 message = SOSMessageCreateWithData(kCFAllocatorDefault, decodedMessage, error);
105 }
106 if (message) {
107 bool engineHandleMessageDoesNotGetToRollbackTransactions = true;
108 result = SOSEngineHandleMessage_locked(engine, peerID, message, txn, &engineHandleMessageDoesNotGetToRollbackTransactions, &somethingChanged, error);
109 CFReleaseSafe(message);
110 }
111 } else {
112 result = uwstatus != SOSCoderUnwrapError;
113 }
114 CFReleaseNull(decodedMessage);
115 });
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);
119
120 return result;
121}
122
123bool SOSTransportMessageSendMessageIfNeeded(SOSTransportMessageRef transport, CFStringRef circle_id, CFStringRef peer_id, CFErrorRef *error) {
124 __block bool ok = true;
125 SOSEngineRef engine = SOSTransportMessageGetEngine(transport);
126
fa7225c8 127 ok &= SOSEngineForPeerID(engine, peer_id, error, ^(SOSTransactionRef txn, SOSPeerRef peer, SOSCoderRef coder) {
5c19dc3a
A
128 // Now under engine lock do stuff
129 CFDataRef message_to_send = NULL;
130 SOSEnginePeerMessageSentBlock sent = NULL;
fa7225c8 131 ok = SOSPeerCoderSendMessageIfNeeded(engine, txn, peer, coder, &message_to_send, circle_id, peer_id, &sent, error);
5c19dc3a
A
132 if (message_to_send) {
133 CFDictionaryRef peer_dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
134 peer_id, message_to_send,
135 NULL);
136 CFDictionaryRef circle_peers = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
137 circle_id, peer_dict,
138 NULL);
139 ok = ok && SOSTransportMessageSendMessages(transport, circle_peers, error);
140
141 SOSPeerCoderConsume(&sent, ok);
142
143 CFReleaseSafe(peer_dict);
144 CFReleaseSafe(circle_peers);
145 }
146
147 Block_release(sent);
148 CFReleaseSafe(message_to_send);
149 });
150 return ok;
151}