]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.c
Security-57337.40.85.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSPeerCoder.c
1 #include <Security/SecureObjectSync/SOSPeer.h>
2 #include <Security/SecureObjectSync/SOSPeerCoder.h>
3 #include <Security/SecureObjectSync/SOSTransportMessage.h>
4 #include <Security/SecureObjectSync/SOSCoder.h>
5 #include <Security/SecureObjectSync/SOSAccount.h>
6 #include <Security/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 // TODO: This could possibly move to SOSEngine?
15 bool SOSPeerCoderInitializeForPeer(SOSEngineRef engine, SOSFullPeerInfoRef myPeerInfo, SOSPeerInfoRef peerInfo, CFErrorRef *error) {
16 __block bool ok = true;
17 ok &= SOSEngineForPeerID(engine, SOSPeerInfoGetPeerID(peerInfo), error, ^(SOSPeerRef peer) {
18 ok = SOSPeerEnsureCoder(peer, myPeerInfo, peerInfo, error);
19 });
20 return ok;
21 }
22
23 void SOSPeerCoderConsume(SOSEnginePeerMessageSentBlock *sent, bool ok) {
24 if (*sent)
25 (*sent)(ok);
26 }
27
28 enum SOSCoderUnwrapStatus SOSPeerHandleCoderMessage(SOSPeerRef peer, CFStringRef peer_id, CFDataRef codedMessage, CFDataRef *decodedMessage, bool *forceSave, CFErrorRef *error) {
29
30 enum SOSCoderUnwrapStatus result = SOSCoderUnwrapError;
31 CFMutableDataRef localDecodedMessage = NULL;
32
33 SOSCoderStatus coderStatus = kSOSCoderDataReturned;
34 SOSCoderRef coder = SOSPeerGetCoder(peer, error);
35 require_action_quiet(coder, xit, secerror("%@ getCoder: %@", peer_id, error ? *error : NULL));
36 CFErrorRef localError = NULL;
37 if (coder) {
38 coderStatus = SOSCoderUnwrap(coder, codedMessage, &localDecodedMessage, peer_id, error);
39
40 switch(coderStatus) {
41 case kSOSCoderDataReturned: {
42 logRawMessage(localDecodedMessage, false, 0);
43 result = SOSCoderUnwrapDecoded;
44 break;
45 }
46 case kSOSCoderNegotiating: // Sent message already in Unwrap.
47 result = SOSCoderUnwrapHandled;
48 secnotice("engine", "%@ engine negotiating", peer_id);
49 break;
50 case kSOSCoderNegotiationCompleted:
51 SOSPeerDidConnect(peer);
52 result = SOSCoderUnwrapHandled;
53 *forceSave = true;
54 secnotice("engine", "%@ engine negotiation complete", peer_id);
55 break;
56 case kSOSCoderFailure: // Probably restart coder
57 secnotice("engine", "%@ engine failed handling message %@", peer_id, error ? *error : NULL);
58 SOSCoderReset(coder);
59 if(SOSCoderStart(coder, &localError) == kSOSCoderFailure){
60 secerror("Attempt to recover coder failed to restart: %@", localError);
61 }
62 break;
63 case kSOSCoderStaleEvent: // We received an event we have already processed in the past.
64 secinfo("engine", "%@ engine stale event ignored", peer_id);
65 result = SOSCoderUnwrapHandled;
66 break;
67 case kSOSCoderTooNew: // We received an event from the future!
68 secnotice("engine", "%@ engine received a message too soon, time to restart", peer_id);
69 SOSCoderReset(coder);
70 if(SOSCoderStart(coder, &localError) == kSOSCoderFailure){
71 secerror("Attempt to recover coder failed to restart: %@", localError);
72 }
73 break;
74 default:
75 assert(false);
76 break;
77 }
78 if(decodedMessage)
79 *decodedMessage = CFRetainSafe(localDecodedMessage);
80 CFReleaseNull(localDecodedMessage);
81 }
82
83 CFReleaseNull(localError);
84 xit:
85 return result;
86 }
87
88 bool SOSPeerCoderSendMessageIfNeeded(SOSEngineRef engine, SOSPeerRef peer, CFDataRef *message_to_send, CFStringRef circle_id, CFStringRef peer_id, SOSEnginePeerMessageSentBlock *sent, CFErrorRef *error) {
89 SOSCoderRef coder = SOSPeerGetCoder(peer, error);
90 bool ok = false;
91 require_action_quiet(coder, xit, secerror("%@ getCoder: %@", peer_id, error ? *error : NULL));
92
93 if (SOSCoderCanWrap(coder)) {
94 secinfo("transport", "%@ Coder can wrap, getting message from engine", peer_id);
95 CFMutableDataRef codedMessage = NULL;
96 CFDataRef message = SOSEngineCreateMessage_locked(engine, peer, error, sent);
97 if (!message) {
98 secnotice("transport", "%@ SOSEngineCreateMessageToSyncToPeer failed: %@", peer_id, *error);
99 } else if (CFDataGetLength(message) || SOSPeerMustSendMessage(peer)) {
100 // TODO: Remove SOSPeerMustSendMessage from peer and move into coder/transport instead
101 ok = message && (SOSCoderWrap(coder, message, &codedMessage, peer_id, error) == kSOSCoderDataReturned);
102 if (!ok) {
103 secnotice("transport", "%@ SOSCoderWrap failed: %@", peer_id, *error);
104 } else {
105 CFRetainAssign(*message_to_send, codedMessage);
106 }
107 CFReleaseNull(codedMessage);
108 } else {
109 // Zero length message means we have no work to do.
110 ok = true;
111 }
112 CFReleaseNull(message);
113 } else {
114 *message_to_send = SOSCoderCopyPendingResponse(coder);
115 secinfo("transport", "%@ negotiating, %@", peer_id, message_to_send ? CFSTR("sending negotiation message.") : CFSTR("waiting for negotiation message."));
116 *sent = Block_copy(^(bool wasSent){
117 if (wasSent)
118 SOSCoderConsumeResponse(coder);
119 });
120 ok = true;
121 }
122
123 xit:
124 return ok;
125 }