]>
Commit | Line | Data |
---|---|---|
fa7225c8 A |
1 | /* |
2 | * Copyright (c) 2012-2016 Apple Inc. All Rights Reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
b54c578e A |
24 | #include "keychain/SecureObjectSync/SOSPeer.h" |
25 | #include "keychain/SecureObjectSync/SOSPeerCoder.h" | |
26 | #include "keychain/SecureObjectSync/SOSTransportMessage.h" | |
27 | #include "keychain/SecureObjectSync/SOSAccount.h" | |
28 | #include "keychain/SecureObjectSync/SOSCoder.h" | |
29 | #include "keychain/SecureObjectSync/SOSEngine.h" | |
30 | #include "keychain/SecureObjectSync/SOSDataSource.h" | |
31 | #import "keychain/SecureObjectSync/SOSAccountTransaction.h" | |
32 | #include "keychain/SecureObjectSync/SOSKVSKeys.h" | |
33 | #include "keychain/SecureObjectSync/SOSPeerOTRTimer.h" | |
866f8763 | 34 | |
b54c578e | 35 | #include "keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.h" |
5c19dc3a A |
36 | |
37 | #include <utilities/debugging.h> | |
38 | #include <utilities/SecCFWrappers.h> | |
39 | ||
40 | #include <AssertMacros.h> | |
b54c578e | 41 | #include "keychain/SecureObjectSync/SOSInternal.h" |
5c19dc3a | 42 | |
fa7225c8 | 43 | enum SOSCoderUnwrapStatus SOSPeerHandleCoderMessage(SOSPeerRef peer, SOSCoderRef coder, CFStringRef peer_id, CFDataRef codedMessage, CFDataRef *decodedMessage, bool *forceSave, CFErrorRef *error) { |
5c19dc3a A |
44 | |
45 | enum SOSCoderUnwrapStatus result = SOSCoderUnwrapError; | |
46 | CFMutableDataRef localDecodedMessage = NULL; | |
47 | ||
48 | SOSCoderStatus coderStatus = kSOSCoderDataReturned; | |
5c19dc3a A |
49 | require_action_quiet(coder, xit, secerror("%@ getCoder: %@", peer_id, error ? *error : NULL)); |
50 | CFErrorRef localError = NULL; | |
51 | if (coder) { | |
52 | coderStatus = SOSCoderUnwrap(coder, codedMessage, &localDecodedMessage, peer_id, error); | |
866f8763 A |
53 | dispatch_source_t timer = SOSPeerGetOTRTimer(peer); |
54 | if(timer){ | |
55 | secnotice("otrtimer","removing timer for peer: %@", peer); | |
56 | SOSPeerRemoveOTRTimerEntry(peer); | |
57 | dispatch_cancel(timer); | |
58 | } | |
5c19dc3a A |
59 | switch(coderStatus) { |
60 | case kSOSCoderDataReturned: { | |
866f8763 | 61 | //logRawMessage(localDecodedMessage, false, 0); |
5c19dc3a A |
62 | result = SOSCoderUnwrapDecoded; |
63 | break; | |
64 | } | |
65 | case kSOSCoderNegotiating: // Sent message already in Unwrap. | |
66 | result = SOSCoderUnwrapHandled; | |
67 | secnotice("engine", "%@ engine negotiating", peer_id); | |
68 | break; | |
69 | case kSOSCoderNegotiationCompleted: | |
70 | SOSPeerDidConnect(peer); | |
71 | result = SOSCoderUnwrapHandled; | |
72 | *forceSave = true; | |
73 | secnotice("engine", "%@ engine negotiation complete", peer_id); | |
74 | break; | |
75 | case kSOSCoderFailure: // Probably restart coder | |
76 | secnotice("engine", "%@ engine failed handling message %@", peer_id, error ? *error : NULL); | |
77 | SOSCoderReset(coder); | |
78 | if(SOSCoderStart(coder, &localError) == kSOSCoderFailure){ | |
79 | secerror("Attempt to recover coder failed to restart: %@", localError); | |
80 | } | |
81 | break; | |
82 | case kSOSCoderStaleEvent: // We received an event we have already processed in the past. | |
83 | secinfo("engine", "%@ engine stale event ignored", peer_id); | |
e3d460c9 | 84 | result = SOSCoderUnwrapHandled; |
5c19dc3a | 85 | break; |
fa7225c8 A |
86 | case kSOSCoderForceMessage: |
87 | SOSPeerSetMustSendMessage(peer, true); | |
88 | result = SOSCoderUnwrapHandled; | |
89 | break; | |
e3d460c9 | 90 | case kSOSCoderTooNew: // We received an event from the future! |
5c19dc3a A |
91 | secnotice("engine", "%@ engine received a message too soon, time to restart", peer_id); |
92 | SOSCoderReset(coder); | |
93 | if(SOSCoderStart(coder, &localError) == kSOSCoderFailure){ | |
94 | secerror("Attempt to recover coder failed to restart: %@", localError); | |
95 | } | |
96 | break; | |
97 | default: | |
b54c578e | 98 | secnotice("engine", "%@ engine unknown coder state: %d", peer_id, (int)coderStatus); |
5c19dc3a A |
99 | assert(false); |
100 | break; | |
101 | } | |
102 | if(decodedMessage) | |
103 | *decodedMessage = CFRetainSafe(localDecodedMessage); | |
104 | CFReleaseNull(localDecodedMessage); | |
105 | } | |
106 | ||
107 | CFReleaseNull(localError); | |
108 | xit: | |
109 | return result; | |
110 | } | |
ecaf5866 | 111 | bool SOSPeerCoderSendMessageIfNeeded(SOSAccount* account, SOSEngineRef engine, SOSTransactionRef txn, SOSPeerRef peer, SOSCoderRef coder, CFDataRef *message_to_send, CFStringRef peer_id, CFMutableArrayRef *attributeList, SOSEnginePeerMessageSentCallback **sentCallback, CFErrorRef *error) { |
5c19dc3a | 112 | bool ok = false; |
b54c578e A |
113 | |
114 | if(!coder) { | |
115 | account.engine_peer_state_needs_repair = true; | |
116 | } | |
117 | require_action_quiet(coder, xit, secnotice("transport", "%@ getCoder: %@", peer_id, error ? *error : NULL)); | |
b04fe171 | 118 | secnotice("transport", "coder state: %@", coder); |
5c19dc3a A |
119 | |
120 | if (SOSCoderCanWrap(coder)) { | |
121 | secinfo("transport", "%@ Coder can wrap, getting message from engine", peer_id); | |
122 | CFMutableDataRef codedMessage = NULL; | |
ecaf5866 | 123 | CFDataRef message = SOSEngineCreateMessage_locked(engine, txn, peer, attributeList, error, sentCallback); |
5c19dc3a | 124 | if (!message) { |
866f8763 | 125 | secnotice("transport", "%@ SOSEngineCreateMessage_locked failed: %@", peer_id, *error); |
5c19dc3a A |
126 | } else if (CFDataGetLength(message) || SOSPeerMustSendMessage(peer)) { |
127 | // TODO: Remove SOSPeerMustSendMessage from peer and move into coder/transport instead | |
128 | ok = message && (SOSCoderWrap(coder, message, &codedMessage, peer_id, error) == kSOSCoderDataReturned); | |
129 | if (!ok) { | |
130 | secnotice("transport", "%@ SOSCoderWrap failed: %@", peer_id, *error); | |
131 | } else { | |
132 | CFRetainAssign(*message_to_send, codedMessage); | |
866f8763 | 133 | SOSEngineSetCodersNeedSaving(engine, true); |
5c19dc3a A |
134 | } |
135 | CFReleaseNull(codedMessage); | |
136 | } else { | |
137 | // Zero length message means we have no work to do. | |
138 | ok = true; | |
139 | } | |
140 | CFReleaseNull(message); | |
866f8763 | 141 | |
5c19dc3a A |
142 | } else { |
143 | *message_to_send = SOSCoderCopyPendingResponse(coder); | |
866f8763 | 144 | SOSEngineSetCodersNeedSaving(engine, true); |
6b200bc3 | 145 | secinfo("transport", "%@ negotiating, %@", peer_id, (message_to_send && *message_to_send) ? CFSTR("sending negotiation message.") : CFSTR("waiting for negotiation message.")); |
ecaf5866 A |
146 | |
147 | SOSEnginePeerMessageSentCallback* pmsc = malloc(sizeof(SOSEnginePeerMessageSentCallback)); | |
148 | memset(pmsc, 0, sizeof(SOSEnginePeerMessageSentCallback)); | |
149 | ||
150 | pmsc->coder = CFRetainSafe(coder); | |
151 | SOSEngineMessageCallbackSetCallback(pmsc, ^(bool wasSent){ | |
152 | if (wasSent) { | |
153 | SOSCoderConsumeResponse(pmsc->coder); | |
154 | } | |
155 | }); | |
156 | ||
157 | *sentCallback = pmsc; | |
5c19dc3a A |
158 | ok = true; |
159 | } | |
866f8763 | 160 | /*if coder state is in awaiting for message, then set a timer and restart if failure*/ |
b54c578e A |
161 | BOOL initialSync = !SOSAccountHasCompletedInitialSync(account); |
162 | if(*message_to_send != NULL && initialSync && !SOSPeerOTRTimerHaveReachedMaxRetryAllowance(account, (__bridge NSString*)peer_id)){ | |
866f8763 A |
163 | if(SOSCoderIsCoderInAwaitingState(coder) && !SOSPeerTimerForPeerExist(peer) && SOSPeerOTRTimerHaveAnRTTAvailable(account, (__bridge NSString*)peer_id)){ |
164 | secnotice("otrtimer", "coder is in awaiting state"); | |
165 | SOSPeerOTRTimerSetupAwaitingTimer(account, peer, engine, coder); | |
166 | } | |
167 | else if(!SOSCoderIsCoderInAwaitingState(coder)){ | |
168 | secnotice("otrtimer", "coder not in awaiting state: %@", coder); | |
169 | } | |
170 | else if (SOSPeerTimerForPeerExist(peer)){ | |
171 | secnotice("otrtimer", "timer for coder already set: %@", coder); | |
172 | } | |
173 | } | |
5c19dc3a A |
174 | xit: |
175 | return ok; | |
176 | } |