]> git.saurik.com Git - apple/security.git/blob - Security/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.c
Security-57031.1.35.tar.gz
[apple/security.git] / Security / sec / SOSCircle / SecureObjectSync / SOSPeerCoder.c
1 #include <SecureObjectSync/SOSPeer.h>
2 #include <SecureObjectSync/SOSPeerCoder.h>
3 #include <SecureObjectSync/SOSTransportMessage.h>
4 #include <SecureObjectSync/SOSCoder.h>
5 #include <SecureObjectSync/SOSAccount.h>
6 #include <SecureObjectSync/SOSEngine.h>
7
8 #include <utilities/debugging.h>
9 #include <utilities/SecCFWrappers.h>
10
11 #include <AssertMacros.h>
12 #include "SOSInternal.h"
13
14 static CFStringRef kSOSPeerCoderKey = CFSTR("coder");
15
16 bool SOSPeerCoderInitializeForPeer(SOSTransportMessageRef transport, SOSFullPeerInfoRef myPeerInfo, SOSPeerInfoRef peerInfo, CFErrorRef *error){
17 CFErrorRef coderError = NULL;
18
19 CFStringRef peer_id = SOSPeerInfoGetPeerID(peerInfo);
20 SOSCoderRef coder = NULL;
21 CFDataRef coderData = NULL;
22 bool haveGoodCoder = false;
23 CFMutableDictionaryRef peerState = SOSEngineGetPeerState(SOSTransportMessageGetEngine(transport), peer_id);
24
25 if(peerState){
26 coderData = CFDictionaryGetValue(peerState, kSOSPeerCoderKey);
27 if(coderData){
28 coder = SOSCoderCreateFromData(coderData, &coderError);
29 if (!coder) {
30 secerror("Found data but couldn't make coder for %@: %@", peer_id, coderError);
31 }
32 haveGoodCoder = coder;
33 SOSCoderDispose(coder);
34 coder = NULL;
35 }
36 }
37
38 if (!haveGoodCoder) {
39 secnotice("peer", "New coder for id %@.", peer_id);
40 CFReleaseNull(coder);
41 coder = SOSCoderCreate(peerInfo, myPeerInfo, error);
42 if (coder) {
43 coderData = SOSCoderCopyDER(coder, error);
44 if(coderData){
45 if(!(haveGoodCoder = SOSEngineSetCoderData(SOSTransportMessageGetEngine(transport), peer_id, coderData, error))){
46 secerror("SOSPeerCoderInitializeForPeer, Could not save coder data");
47 }
48 }
49 CFReleaseNull(coderData);
50 SOSCoderDispose(coder);
51 } else {
52 secerror("Couldn't make coder for %@", peer_id);
53 }
54 }
55 CFReleaseNull(coderError);
56 return haveGoodCoder;
57 }
58
59 void SOSPeerCoderConsume(SOSEnginePeerMessageSentBlock *sent, bool ok){
60 if (*sent)
61 (*sent)(ok);
62 }
63
64 enum SOSCoderUnwrapStatus SOSPeerHandleCoderMessage(SOSPeerRef peer, CFStringRef peer_id, CFDataRef codedMessage, CFDataRef *decodedMessage, CFErrorRef *error){
65
66 enum SOSCoderUnwrapStatus result = SOSCoderUnwrapError;
67 CFMutableDataRef localDecodedMessage = NULL;
68
69 SOSCoderStatus coderStatus = kSOSCoderDataReturned;
70 CFDataRef coderData = SOSEngineGetCoderData(SOSPeerGetEngine(peer), SOSPeerGetID(peer));
71 require_quiet(coderData, fail);
72 SOSCoderRef coder = SOSCoderCreateFromData(coderData, error);
73 require(coder, fail);
74 CFErrorRef localError = NULL;
75 if (coder) {
76 coderStatus = SOSCoderUnwrap(coder, codedMessage, &localDecodedMessage, peer_id, error);
77
78 switch(coderStatus) {
79 case kSOSCoderDataReturned: {
80 logRawMessage(localDecodedMessage, false, 0);
81 result = SOSCoderUnwrapDecoded;
82 break;
83 }
84 case kSOSCoderNegotiating: // Sent message already in Unwrap.
85 result = SOSCoderUnwrapHandled;
86 secnotice("engine", "%@ engine negotiating", peer_id);
87 break;
88 case kSOSCoderNegotiationCompleted:
89 if(SOSEnginePeerDidConnect(SOSPeerGetEngine(peer), peer_id, error))
90 result = SOSCoderUnwrapHandled;
91 secnotice("engine", "%@ engine negotiation complete", peer_id);
92 break;
93 case kSOSCoderFailure: // Probably restart coder
94 secnotice("engine", "%@ engine failed handling message %@", peer_id, error ? *error : NULL);
95 SOSCoderReset(coder);
96 if(SOSCoderStart(coder, &localError) == kSOSCoderFailure){
97 secerror("Attempt to recover coder failed to restart: %@", localError);
98 }
99 break;
100 case kSOSCoderStaleEvent: // We received an event we have already processed in the past.
101 secnotice("engine", "%@ engine stale event ignored", peer_id);
102 break;
103 default:
104 assert(false);
105 break;
106 }
107 if(decodedMessage)
108 *decodedMessage = CFRetainSafe(localDecodedMessage);
109 CFReleaseNull(localDecodedMessage);
110
111 coderData = SOSCoderCopyDER(coder, error);
112 if(!SOSEngineSetCoderData(SOSPeerGetEngine(peer), peer_id, coderData, error)){
113 secerror("SOSTransportMessageSendMessageIfNeeded, Could not save peer state");
114 }
115 CFReleaseNull(coderData);
116 SOSCoderDispose(coder);
117 }
118
119 CFReleaseNull(localError);
120 fail:
121 return result;
122
123 }
124
125 bool SOSPeerCoderSendMessageIfNeeded(SOSPeerRef peer, CFDataRef *message_to_send, CFStringRef circle_id, CFStringRef peer_id, SOSEnginePeerMessageSentBlock *sent, CFErrorRef *error){
126 SOSCoderRef coder = SOSPeerGetCoder(peer);
127
128 bool ok = false;
129 require_quiet(coder, fail);
130
131 if (SOSCoderCanWrap(coder)) {
132 secnotice("transport", "%@ Coder can wrap, getting message from engine", peer_id);
133 CFMutableDataRef codedMessage = NULL;
134 CFDataRef message = SOSEngineCreateMessageToSyncToPeer(SOSPeerGetEngine(peer), peer_id, sent, error);
135 if (!message) {
136 secnotice("transport", "%@ SOSEngineCreateMessageToSyncToPeer failed: %@",peer_id, *error);
137 }
138 ok = message && (SOSCoderWrap(coder, message, &codedMessage, peer_id, error) == kSOSCoderDataReturned);
139 if (!ok) {
140 secnotice("transport", "%@ SOSCoderWrap failed: %@",peer_id, *error);
141 }
142
143 if (ok)
144 CFRetainAssign(*message_to_send, codedMessage);
145
146 CFReleaseNull(codedMessage);
147 CFReleaseNull(message);
148 } else {
149 *message_to_send = SOSCoderCopyPendingResponse(coder);
150 secnotice("transport", "%@ Negotiating, %@", peer_id, message_to_send ? CFSTR("Sending negotiation message.") : CFSTR("waiting for negotiation message."));
151 *sent = Block_copy(^(bool wasSent){
152 if (wasSent)
153 SOSCoderConsumeResponse(coder);
154 });
155 ok = true;
156 }
157
158 fail:
159 return ok;
160 }