]> git.saurik.com Git - apple/security.git/blob - OSX/sec/ProjectHeaders/Security/SecureObjectSync/SOSPeerCoder.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / sec / ProjectHeaders / Security / 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 break;
66 case kSOSCoderTooNew: //We received an event from the future!
67 secnotice("engine", "%@ engine received a message too soon, time to restart", peer_id);
68 SOSCoderReset(coder);
69 if(SOSCoderStart(coder, &localError) == kSOSCoderFailure){
70 secerror("Attempt to recover coder failed to restart: %@", localError);
71 }
72 break;
73 default:
74 assert(false);
75 break;
76 }
77 if(decodedMessage)
78 *decodedMessage = CFRetainSafe(localDecodedMessage);
79 CFReleaseNull(localDecodedMessage);
80 }
81
82 CFReleaseNull(localError);
83 xit:
84 return result;
85 }
86
87 bool SOSPeerCoderSendMessageIfNeeded(SOSEngineRef engine, SOSPeerRef peer, CFDataRef *message_to_send, CFStringRef circle_id, CFStringRef peer_id, SOSEnginePeerMessageSentBlock *sent, CFErrorRef *error) {
88 SOSCoderRef coder = SOSPeerGetCoder(peer, error);
89 bool ok = false;
90 require_action_quiet(coder, xit, secerror("%@ getCoder: %@", peer_id, error ? *error : NULL));
91
92 if (SOSCoderCanWrap(coder)) {
93 secinfo("transport", "%@ Coder can wrap, getting message from engine", peer_id);
94 CFMutableDataRef codedMessage = NULL;
95 CFDataRef message = SOSEngineCreateMessage_locked(engine, peer, error, sent);
96 if (!message) {
97 secnotice("transport", "%@ SOSEngineCreateMessageToSyncToPeer failed: %@", peer_id, *error);
98 } else if (CFDataGetLength(message) || SOSPeerMustSendMessage(peer)) {
99 // TODO: Remove SOSPeerMustSendMessage from peer and move into coder/transport instead
100 ok = message && (SOSCoderWrap(coder, message, &codedMessage, peer_id, error) == kSOSCoderDataReturned);
101 if (!ok) {
102 secnotice("transport", "%@ SOSCoderWrap failed: %@", peer_id, *error);
103 } else {
104 CFRetainAssign(*message_to_send, codedMessage);
105 }
106 CFReleaseNull(codedMessage);
107 } else {
108 // Zero length message means we have no work to do.
109 ok = true;
110 }
111 CFReleaseNull(message);
112 } else {
113 *message_to_send = SOSCoderCopyPendingResponse(coder);
114 secinfo("transport", "%@ negotiating, %@", peer_id, message_to_send ? CFSTR("sending negotiation message.") : CFSTR("waiting for negotiation message."));
115 *sent = Block_copy(^(bool wasSent){
116 if (wasSent)
117 SOSCoderConsumeResponse(coder);
118 });
119 ok = true;
120 }
121
122 xit:
123 return ok;
124 }