]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSKVSKeys.c
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSKVSKeys.c
1 /*
2 * Copyright (c) 2013-2014 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/SOSKVSKeys.h>
25 #include <utilities/SecCFWrappers.h>
26 #include <Security/SecureObjectSync/SOSAccountPriv.h>
27 #include <CoreFoundation/CFDate.h>
28
29 void AppendCircleKeyName(CFMutableArrayRef array, CFStringRef name) {
30 CFStringRef circle_key = SOSCircleKeyCreateWithName(name, NULL);
31 CFArrayAppendValue(array, circle_key);
32 CFReleaseNull(circle_key);
33 }
34
35 //
36 //
37 // MARK: KVS Keys
38 // TODO: Handle '|' and "¬" in other strings.
39 //
40 const CFStringRef kSOSKVSKeyParametersKey = CFSTR(">KeyParameters");
41 const CFStringRef kSOSKVSInitialSyncKey = CFSTR("^InitialSync");
42 const CFStringRef kSOSKVSAccountChangedKey = CFSTR("^AccountChanged");
43 const CFStringRef kSOSKVSRequiredKey = CFSTR("^Required");
44 const CFStringRef kSOSKVSOfficialDSIDKey = CFSTR("^OfficialDSID");
45
46 const CFStringRef kSOSKVSDebugScope = CFSTR("^DebugScope");
47
48 const CFStringRef sPeerInfoPrefix = CFSTR("+");
49 const CFStringRef sRingPrefix = CFSTR("~");
50 const CFStringRef sDebugInfoPrefix = CFSTR("dbg-");
51
52 const CFStringRef sWarningPrefix = CFSTR("!");
53 const CFStringRef sAncientCirclePrefix = CFSTR("@");
54 const CFStringRef sCirclePrefix = CFSTR("o");
55 const CFStringRef sRetirementPrefix = CFSTR("-");
56 const CFStringRef sLastCirclePushedPrefix = CFSTR("p");
57 const CFStringRef sLastKeyParametersPushedPrefix = CFSTR("k");
58 const CFStringRef sCircleSeparator = CFSTR("|");
59 const CFStringRef sFromToSeparator = CFSTR(":");
60
61 static CFStringRef copyStringEndingIn(CFMutableStringRef in, CFStringRef token) {
62 if(token == NULL) return CFStringCreateCopy(NULL, in);
63 CFRange tokenAt = CFStringFind(in, token, 0);
64 if(tokenAt.location == kCFNotFound) return NULL;
65 CFStringRef retval = CFStringCreateWithSubstring(NULL, in, CFRangeMake(0, tokenAt.location));
66 CFStringDelete(in, CFRangeMake(0, tokenAt.location+1));
67 return retval;
68 }
69
70 SOSKVSKeyType SOSKVSKeyGetKeyTypeAndParse(CFStringRef key, CFStringRef *circle, CFStringRef *peerInfo, CFStringRef *ring, CFStringRef *backupName, CFStringRef *from, CFStringRef *to)
71 {
72 SOSKVSKeyType retval = kUnknownKey;
73
74 if(CFStringHasPrefix(key, sCirclePrefix)) retval = kCircleKey;
75 else if (CFStringHasPrefix(key, sRingPrefix)) retval = kRingKey;
76 else if(CFStringHasPrefix(key, sPeerInfoPrefix)) retval = kPeerInfoKey;
77 else if(CFStringHasPrefix(key, sRetirementPrefix)) retval = kRetirementKey;
78 else if(CFStringHasPrefix(key, kSOSKVSKeyParametersKey)) retval = kParametersKey;
79 else if(CFStringHasPrefix(key, kSOSKVSInitialSyncKey)) retval = kInitialSyncKey;
80 else if(CFStringHasPrefix(key, kSOSKVSAccountChangedKey)) retval = kAccountChangedKey;
81 else if(CFStringHasPrefix(key, sDebugInfoPrefix)) retval = kDebugInfoKey;
82 else if(CFStringHasPrefix(key, sLastCirclePushedPrefix)) retval = kLastCircleKey;
83 else if(CFStringHasPrefix(key, sLastKeyParametersPushedPrefix)) retval = kLastKeyParameterKey;
84 else retval = kMessageKey;
85
86 switch(retval) {
87 case kCircleKey:
88 if (circle) {
89 CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1);
90 *circle = CFStringCreateWithSubstring(NULL, key, fromRange);
91 }
92 break;
93 case kMessageKey: {
94 CFStringRef mCircle = NULL;
95 CFStringRef mFrom = NULL;
96 CFStringRef mTo = NULL;
97 CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key);
98
99 if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) &&
100 ((mFrom = copyStringEndingIn(keycopy, sFromToSeparator)) != NULL) &&
101 (CFStringGetLength(mFrom) > 0) ) {
102 mTo = copyStringEndingIn(keycopy, NULL);
103 if (circle && mCircle) *circle = CFStringCreateCopy(NULL, mCircle);
104 if (from && mFrom) *from = CFStringCreateCopy(NULL, mFrom);
105 if (to && mTo) *to = CFStringCreateCopy(NULL, mTo);
106 } else {
107 retval = kUnknownKey;
108 }
109 CFReleaseNull(mCircle);
110 CFReleaseNull(mFrom);
111 CFReleaseNull(mTo);
112 CFReleaseNull(keycopy);
113 }
114 break;
115 case kRetirementKey: {
116 CFStringRef mCircle = NULL;
117 CFStringRef mPeer = NULL;
118 CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key);
119 CFStringDelete(keycopy, CFRangeMake(0, 1));
120 if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) &&
121 ((mPeer = copyStringEndingIn(keycopy, NULL)) != NULL)) {
122 if (circle) *circle = CFStringCreateCopy(NULL, mCircle);
123 if (from) *from = CFStringCreateCopy(NULL, mPeer);
124 } else {
125 retval = kUnknownKey;
126 }
127 // TODO - Update our circle
128 CFReleaseNull(mCircle);
129 CFReleaseNull(mPeer);
130 CFReleaseNull(keycopy);
131 }
132 break;
133 case kRingKey:
134 if (ring) {
135 CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1);
136 *ring = CFStringCreateWithSubstring(NULL, key, fromRange);
137 }
138 break;
139 case kPeerInfoKey:
140 if (peerInfo) {
141 CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1);
142 *peerInfo = CFStringCreateWithSubstring(NULL, key, fromRange);
143 }
144 break;
145 case kDebugInfoKey:
146 /* piggybacking on peerinfo */
147 if (peerInfo) {
148 CFRange dbgRange = CFRangeMake(CFStringGetLength(sDebugInfoPrefix),
149 CFStringGetLength(key)-CFStringGetLength(sDebugInfoPrefix));
150 *peerInfo = CFStringCreateWithSubstring(NULL, key, dbgRange);
151 }
152 break;
153 case kAccountChangedKey:
154 case kParametersKey:
155 case kInitialSyncKey:
156 case kUnknownKey:
157 case kLastKeyParameterKey:
158 case kLastCircleKey:
159 break;
160 }
161
162 return retval;
163 }
164
165
166 SOSKVSKeyType SOSKVSKeyGetKeyType(CFStringRef key)
167 {
168 return SOSKVSKeyGetKeyTypeAndParse(key, NULL, NULL, NULL, NULL, NULL, NULL);
169 }
170
171 CFStringRef SOSCircleKeyCreateWithCircle(SOSCircleRef circle, CFErrorRef *error)
172 {
173 return SOSCircleKeyCreateWithName(SOSCircleGetName(circle), error);
174 }
175
176
177 CFStringRef SOSCircleKeyCreateWithName(CFStringRef circleName, CFErrorRef *error)
178 {
179 if(!circleName) return NULL;
180 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sCirclePrefix, circleName);
181 }
182
183 CFStringRef SOSPeerInfoKeyCreateWithName(CFStringRef peer_info_name, CFErrorRef *error)
184 {
185 if(!peer_info_name) return NULL;
186 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sPeerInfoPrefix, peer_info_name);
187 }
188
189 CFStringRef SOSRingKeyCreateWithName(CFStringRef ring_name, CFErrorRef *error)
190 {
191 if(!ring_name) return NULL;
192 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sRingPrefix, ring_name);
193 }
194
195 CFStringRef SOSCircleKeyCopyCircleName(CFStringRef key, CFErrorRef *error)
196 {
197 CFStringRef circleName = NULL;
198
199 if (kCircleKey != SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL, NULL, NULL, NULL)) {
200 SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key);
201
202 CFReleaseNull(circleName);
203 }
204
205 return circleName;
206 }
207
208 CFStringRef SOSMessageKeyCopyCircleName(CFStringRef key, CFErrorRef *error)
209 {
210 CFStringRef circleName = NULL;
211
212 if (SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL, NULL, NULL, NULL) != kMessageKey) {
213 SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key);
214
215 CFReleaseNull(circleName);
216 }
217 return circleName;
218 }
219
220 CFStringRef SOSMessageKeyCopyFromPeerName(CFStringRef messageKey, CFErrorRef *error)
221 {
222 CFStringRef fromPeer = NULL;
223
224 if (SOSKVSKeyGetKeyTypeAndParse(messageKey, NULL, NULL, NULL, NULL, &fromPeer, NULL) != kMessageKey) {
225 SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find from peer in key '%@'"), messageKey);
226
227 CFReleaseNull(fromPeer);
228 }
229 return fromPeer;
230 }
231
232 CFStringRef SOSMessageKeyCreateWithCircleNameAndPeerNames(CFStringRef circleName, CFStringRef from_peer_name, CFStringRef to_peer_name)
233 {
234 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"),
235 circleName, sCircleSeparator, from_peer_name, sFromToSeparator, to_peer_name);
236 }
237
238 CFStringRef SOSMessageKeyCreateWithCircleNameAndTransportType(CFStringRef circleName, CFStringRef transportType)
239 {
240 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"),
241 circleName, sCircleSeparator, transportType, sFromToSeparator, SOSTransportMessageTypeIDS);
242 }
243
244 CFStringRef SOSMessageKeyCreateWithCircleAndPeerNames(SOSCircleRef circle, CFStringRef from_peer_name, CFStringRef to_peer_name)
245 {
246 return SOSMessageKeyCreateWithCircleNameAndPeerNames(SOSCircleGetName(circle), from_peer_name, to_peer_name);
247 }
248
249 CFStringRef SOSMessageKeyCreateWithCircleAndPeerInfos(SOSCircleRef circle, SOSPeerInfoRef from_peer, SOSPeerInfoRef to_peer)
250 {
251 return SOSMessageKeyCreateWithCircleAndPeerNames(circle, SOSPeerInfoGetPeerID(from_peer), SOSPeerInfoGetPeerID(to_peer));
252 }
253
254 CFStringRef SOSMessageKeyCreateFromPeerToTransport(SOSTransportMessageKVSRef transport, CFStringRef peer_name) {
255 CFErrorRef error = NULL;
256 SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport);
257
258 CFStringRef circleName = SOSTransportMessageGetCircleName((SOSTransportMessageRef)transport);
259 CFStringRef my_id = SOSEngineGetMyID(engine);
260
261 CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, peer_name, my_id);
262 CFReleaseSafe(error);
263 return result;
264 }
265
266 CFStringRef SOSMessageKeyCreateFromTransportToPeer(SOSTransportMessageKVSRef transport, CFStringRef peer_name) {
267 CFErrorRef error = NULL;
268 SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport);
269
270 CFStringRef circleName = SOSTransportMessageGetCircleName((SOSTransportMessageRef)transport);
271 CFStringRef my_id = SOSEngineGetMyID(engine);
272
273 CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, my_id, peer_name);
274 CFReleaseSafe(error);
275 return result;
276 }
277
278 CFStringRef SOSRetirementKeyCreateWithCircleNameAndPeer(CFStringRef circle_name, CFStringRef retirement_peer_name)
279 {
280 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"),
281 sRetirementPrefix, circle_name, sCircleSeparator, retirement_peer_name);
282 }
283
284 CFStringRef SOSPeerInfoV2KeyCreateWithPeerName(CFStringRef peer_name)
285 {
286 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
287 sPeerInfoPrefix, peer_name);
288 }
289
290 CFStringRef SOSRingKeyCreateWithRingName(CFStringRef ring_name)
291 {
292 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
293 sRingPrefix, ring_name);
294 }
295
296 CFStringRef SOSRetirementKeyCreateWithCircleAndPeer(SOSCircleRef circle, CFStringRef retirement_peer_name)
297 {
298 return SOSRetirementKeyCreateWithCircleNameAndPeer(SOSCircleGetName(circle), retirement_peer_name);
299 }
300
301 //should be poak|ourPeerID
302 CFStringRef SOSLastCirclePushedKeyCreateWithCircleNameAndPeerID(CFStringRef circleName, CFStringRef peerID){
303
304 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"),
305 sLastCirclePushedPrefix, sCirclePrefix, circleName, sCircleSeparator, peerID);
306 }
307
308 CFStringRef SOSLastCirclePushedKeyCreateWithAccountGestalt(SOSAccountRef account){
309 CFStringRef gestaltInfo = SOSAccountCreateCompactDescription(account);
310 CFStringRef key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@"),
311 sLastCirclePushedPrefix, sCirclePrefix, gestaltInfo);
312 CFReleaseNull(gestaltInfo);
313 return key;
314 }
315
316 //should be >KeyParameters|ourPeerID
317 CFStringRef SOSLastKeyParametersPushedKeyCreateWithPeerID(CFStringRef peerID){
318
319 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"),
320 sLastKeyParametersPushedPrefix,kSOSKVSKeyParametersKey, sCircleSeparator, peerID);
321 }
322
323
324 //should be >KeyParameters|ourPeerID
325 CFStringRef SOSLastKeyParametersPushedKeyCreateWithAccountGestalt(SOSAccountRef account){
326
327 CFStringRef gestaltInfo = SOSAccountCreateCompactDescription(account);
328 CFStringRef key= CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"),
329 sLastKeyParametersPushedPrefix, kSOSKVSKeyParametersKey, sCircleSeparator, gestaltInfo);
330 CFReleaseNull(gestaltInfo);
331 return key;
332 }
333
334 CFStringRef SOSDebugInfoKeyCreateWithTypeName(CFStringRef type_name)
335 {
336 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
337 sDebugInfoPrefix, type_name);
338 }
339