]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.c
a7aa186ff0b6a71738fbc85c0e1ece50b5e8915e
[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
107 bool SOSPeerCoderSendMessageIfNeeded(SOSEngineRef engine, SOSTransactionRef txn, SOSPeerRef peer, SOSCoderRef coder, CFDataRef *message_to_send, CFStringRef peer_id, SOSEnginePeerMessageSentBlock *sent, CFErrorRef *error) {
108 bool ok = false;
109 secnotice("transport", "coder state: %@", coder);
110 require_action_quiet(coder, xit, secerror("%@ getCoder: %@", peer_id, error ? *error : NULL));
111
112 if (SOSCoderCanWrap(coder)) {
113 secinfo("transport", "%@ Coder can wrap, getting message from engine", peer_id);
114 CFMutableDataRef codedMessage = NULL;
115 CFDataRef message = SOSEngineCreateMessage_locked(engine, txn, peer, error, sent);
116 if (!message) {
117 secnotice("transport", "%@ SOSEngineCreateMessageToSyncToPeer failed: %@", peer_id, *error);
118 } else if (CFDataGetLength(message) || SOSPeerMustSendMessage(peer)) {
119 // TODO: Remove SOSPeerMustSendMessage from peer and move into coder/transport instead
120 ok = message && (SOSCoderWrap(coder, message, &codedMessage, peer_id, error) == kSOSCoderDataReturned);
121 if (!ok) {
122 secnotice("transport", "%@ SOSCoderWrap failed: %@", peer_id, *error);
123 } else {
124 CFRetainAssign(*message_to_send, codedMessage);
125 engine->codersNeedSaving = true;
126 }
127 CFReleaseNull(codedMessage);
128 } else {
129 // Zero length message means we have no work to do.
130 ok = true;
131 }
132 CFReleaseNull(message);
133 } else {
134 *message_to_send = SOSCoderCopyPendingResponse(coder);
135 engine->codersNeedSaving = true;
136 secinfo("transport", "%@ negotiating, %@", peer_id, (message_to_send && *message_to_send) ? CFSTR("sending negotiation message.") : CFSTR("waiting for negotiation message."));
137 *sent = Block_copy(^(bool wasSent){
138 if (wasSent)
139 SOSCoderConsumeResponse(coder);
140 });
141 ok = true;
142 }
143
144 xit:
145 return ok;
146 }