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