]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/SecureObjectSync/SOSKVSKeys.c
Security-57740.1.18.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 SOSKVSKeyGetKeyType(CFStringRef key) {
71 SOSKVSKeyType retval = kUnknownKey;
72
73 if(CFStringHasPrefix(key, sCirclePrefix)) retval = kCircleKey;
74 else if (CFStringHasPrefix(key, sRingPrefix)) retval = kRingKey;
75 else if(CFStringHasPrefix(key, sPeerInfoPrefix)) retval = kPeerInfoKey;
76 else if(CFStringHasPrefix(key, sRetirementPrefix)) retval = kRetirementKey;
77 else if(CFStringHasPrefix(key, kSOSKVSKeyParametersKey)) retval = kParametersKey;
78 else if(CFStringHasPrefix(key, kSOSKVSInitialSyncKey)) retval = kInitialSyncKey;
79 else if(CFStringHasPrefix(key, kSOSKVSAccountChangedKey)) retval = kAccountChangedKey;
80 else if(CFStringHasPrefix(key, sDebugInfoPrefix)) retval = kDebugInfoKey;
81 else if(CFStringHasPrefix(key, sLastCirclePushedPrefix)) retval = kLastCircleKey;
82 else if(CFStringHasPrefix(key, sLastKeyParametersPushedPrefix)) retval = kLastKeyParameterKey;
83 else retval = kMessageKey;
84
85 return retval;
86 }
87
88 bool SOSKVSKeyParse(SOSKVSKeyType keyType, CFStringRef key, CFStringRef *circle, CFStringRef *peerInfo, CFStringRef *ring, CFStringRef *backupName, CFStringRef *from, CFStringRef *to) {
89 bool retval = true;
90
91 switch(keyType) {
92 case kCircleKey:
93 if (circle) {
94 CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1);
95 *circle = CFStringCreateWithSubstring(NULL, key, fromRange);
96 }
97 break;
98 case kMessageKey: {
99 CFStringRef mCircle = NULL;
100 CFStringRef mFrom = NULL;
101 CFStringRef mTo = NULL;
102 CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key);
103
104 if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) &&
105 ((mFrom = copyStringEndingIn(keycopy, sFromToSeparator)) != NULL) &&
106 (CFStringGetLength(mFrom) > 0) ) {
107 mTo = copyStringEndingIn(keycopy, NULL);
108 if (circle && mCircle) *circle = CFStringCreateCopy(NULL, mCircle);
109 if (from && mFrom) *from = CFStringCreateCopy(NULL, mFrom);
110 if (to && mTo) *to = CFStringCreateCopy(NULL, mTo);
111 } else {
112 retval = false;
113 }
114 CFReleaseNull(mCircle);
115 CFReleaseNull(mFrom);
116 CFReleaseNull(mTo);
117 CFReleaseNull(keycopy);
118 }
119 break;
120 case kRetirementKey: {
121 CFStringRef mCircle = NULL;
122 CFStringRef mPeer = NULL;
123 CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key);
124 CFStringDelete(keycopy, CFRangeMake(0, 1));
125 if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) &&
126 ((mPeer = copyStringEndingIn(keycopy, NULL)) != NULL)) {
127 if (circle) *circle = CFStringCreateCopy(NULL, mCircle);
128 if (from) *from = CFStringCreateCopy(NULL, mPeer);
129 } else {
130 retval = false;
131 }
132 CFReleaseNull(mCircle);
133 CFReleaseNull(mPeer);
134 CFReleaseNull(keycopy);
135 }
136 break;
137 case kRingKey:
138 if (ring) {
139 CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1);
140 *ring = CFStringCreateWithSubstring(NULL, key, fromRange);
141 }
142 break;
143 case kPeerInfoKey:
144 if (peerInfo) {
145 CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1);
146 *peerInfo = CFStringCreateWithSubstring(NULL, key, fromRange);
147 }
148 break;
149 case kDebugInfoKey:
150 /* piggybacking on peerinfo */
151 if (peerInfo) {
152 CFRange dbgRange = CFRangeMake(CFStringGetLength(sDebugInfoPrefix),
153 CFStringGetLength(key)-CFStringGetLength(sDebugInfoPrefix));
154 *peerInfo = CFStringCreateWithSubstring(NULL, key, dbgRange);
155 }
156 break;
157 case kAccountChangedKey:
158 case kParametersKey:
159 case kInitialSyncKey:
160 case kUnknownKey:
161 break;
162 case kLastKeyParameterKey:
163 if(from) {
164 CFStringRef mPrefix = NULL;
165 CFStringRef mFrom = NULL;
166 CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key);
167
168 if( ((mPrefix = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) &&
169 ((mFrom = copyStringEndingIn(keycopy, NULL)) != NULL)) {
170 if (from && mFrom) *from = CFStringCreateCopy(NULL, mFrom);
171 } else {
172 retval = false;
173 }
174 CFReleaseNull(mPrefix);
175 CFReleaseNull(mFrom);
176 CFReleaseNull(keycopy);
177 }
178 break;
179 case kLastCircleKey:
180 if (circle && from) {
181 CFStringRef mCircle = NULL;
182 CFStringRef mFrom = NULL;
183 CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key);
184
185 if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) &&
186 ((mFrom = copyStringEndingIn(keycopy, NULL)) != NULL)) {
187 if (circle && mCircle) *circle = CFStringCreateCopy(NULL, mCircle);
188 if (from && mFrom) *from = CFStringCreateCopy(NULL, mFrom);
189 } else {
190 retval = false;
191 }
192 CFReleaseNull(mCircle);
193 CFReleaseNull(mFrom);
194 CFReleaseNull(keycopy);
195 }
196
197 break;
198 }
199 return retval;
200 }
201
202 SOSKVSKeyType SOSKVSKeyGetKeyTypeAndParse(CFStringRef key, CFStringRef *circle, CFStringRef *peerInfo, CFStringRef *ring, CFStringRef *backupName, CFStringRef *from, CFStringRef *to)
203 {
204 SOSKVSKeyType retval = SOSKVSKeyGetKeyType(key);
205 bool parsed = SOSKVSKeyParse(retval, key, circle, peerInfo, ring, backupName, from, to);
206 if(!parsed) retval = kUnknownKey;
207
208 return retval;
209 }
210
211
212 CFStringRef SOSCircleKeyCreateWithCircle(SOSCircleRef circle, CFErrorRef *error)
213 {
214 return SOSCircleKeyCreateWithName(SOSCircleGetName(circle), error);
215 }
216
217
218 CFStringRef SOSCircleKeyCreateWithName(CFStringRef circleName, CFErrorRef *error)
219 {
220 if(!circleName) return NULL;
221 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sCirclePrefix, circleName);
222 }
223
224 CFStringRef SOSPeerInfoKeyCreateWithName(CFStringRef peer_info_name, CFErrorRef *error)
225 {
226 if(!peer_info_name) return NULL;
227 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sPeerInfoPrefix, peer_info_name);
228 }
229
230 CFStringRef SOSRingKeyCreateWithName(CFStringRef ring_name, CFErrorRef *error)
231 {
232 if(!ring_name) return NULL;
233 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sRingPrefix, ring_name);
234 }
235
236 CFStringRef SOSCircleKeyCopyCircleName(CFStringRef key, CFErrorRef *error)
237 {
238 CFStringRef circleName = NULL;
239
240 if (kCircleKey != SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL, NULL, NULL, NULL)) {
241 SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key);
242
243 CFReleaseNull(circleName);
244 }
245
246 return circleName;
247 }
248
249 CFStringRef SOSMessageKeyCopyCircleName(CFStringRef key, CFErrorRef *error)
250 {
251 CFStringRef circleName = NULL;
252
253 if (SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL, NULL, NULL, NULL) != kMessageKey) {
254 SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key);
255
256 CFReleaseNull(circleName);
257 }
258 return circleName;
259 }
260
261 CFStringRef SOSMessageKeyCopyFromPeerName(CFStringRef messageKey, CFErrorRef *error)
262 {
263 CFStringRef fromPeer = NULL;
264
265 if (SOSKVSKeyGetKeyTypeAndParse(messageKey, NULL, NULL, NULL, NULL, &fromPeer, NULL) != kMessageKey) {
266 SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find from peer in key '%@'"), messageKey);
267
268 CFReleaseNull(fromPeer);
269 }
270 return fromPeer;
271 }
272
273 CFStringRef SOSMessageKeyCreateWithCircleNameAndPeerNames(CFStringRef circleName, CFStringRef from_peer_name, CFStringRef to_peer_name)
274 {
275 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"),
276 circleName, sCircleSeparator, from_peer_name, sFromToSeparator, to_peer_name);
277 }
278
279 CFStringRef SOSMessageKeyCreateWithCircleNameAndTransportType(CFStringRef circleName, CFStringRef transportType)
280 {
281 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"),
282 circleName, sCircleSeparator, transportType, sFromToSeparator, SOSTransportMessageTypeIDSV2);
283 }
284
285 CFStringRef SOSMessageKeyCreateWithCircleAndPeerNames(SOSCircleRef circle, CFStringRef from_peer_name, CFStringRef to_peer_name)
286 {
287 return SOSMessageKeyCreateWithCircleNameAndPeerNames(SOSCircleGetName(circle), from_peer_name, to_peer_name);
288 }
289
290 CFStringRef SOSMessageKeyCreateWithCircleAndPeerInfos(SOSCircleRef circle, SOSPeerInfoRef from_peer, SOSPeerInfoRef to_peer)
291 {
292 return SOSMessageKeyCreateWithCircleAndPeerNames(circle, SOSPeerInfoGetPeerID(from_peer), SOSPeerInfoGetPeerID(to_peer));
293 }
294
295 CFStringRef SOSMessageKeyCreateFromPeerToTransport(SOSTransportMessageRef transport, CFStringRef peer_name) {
296 CFErrorRef error = NULL;
297 SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport);
298
299 CFStringRef circleName = SOSTransportMessageGetCircleName((SOSTransportMessageRef)transport);
300 CFStringRef my_id = SOSEngineGetMyID(engine);
301 if(my_id == NULL)
302 {
303 secerror("cannot create message keys, SOSEngineGetMyID returned NULL");
304 return NULL;
305 }
306 CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, peer_name, my_id);
307 CFReleaseSafe(error);
308 return result;
309 }
310
311 CFStringRef SOSMessageKeyCreateFromTransportToPeer(SOSTransportMessageRef transport, CFStringRef peer_name) {
312 CFErrorRef error = NULL;
313 SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport);
314
315 CFStringRef circleName = SOSTransportMessageGetCircleName((SOSTransportMessageRef)transport);
316 CFStringRef my_id = SOSEngineGetMyID(engine);
317
318 CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, my_id, peer_name);
319 CFReleaseSafe(error);
320 return result;
321 }
322
323 CFStringRef SOSRetirementKeyCreateWithCircleNameAndPeer(CFStringRef circle_name, CFStringRef retirement_peer_name)
324 {
325 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"),
326 sRetirementPrefix, circle_name, sCircleSeparator, retirement_peer_name);
327 }
328
329 CFStringRef SOSPeerInfoV2KeyCreateWithPeerName(CFStringRef peer_name)
330 {
331 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
332 sPeerInfoPrefix, peer_name);
333 }
334
335 CFStringRef SOSRingKeyCreateWithRingName(CFStringRef ring_name)
336 {
337 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
338 sRingPrefix, ring_name);
339 }
340
341 CFStringRef SOSRetirementKeyCreateWithCircleAndPeer(SOSCircleRef circle, CFStringRef retirement_peer_name)
342 {
343 return SOSRetirementKeyCreateWithCircleNameAndPeer(SOSCircleGetName(circle), retirement_peer_name);
344 }
345
346 //should be poak|ourPeerID
347 CFStringRef SOSLastCirclePushedKeyCreateWithCircleNameAndPeerID(CFStringRef circleName, CFStringRef peerID){
348
349 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"),
350 sLastCirclePushedPrefix, sCirclePrefix, circleName, sCircleSeparator, peerID);
351 }
352
353 CFStringRef SOSLastCirclePushedKeyCreateWithAccountGestalt(SOSAccountRef account){
354 CFStringRef gestaltInfo = SOSAccountCreateCompactDescription(account);
355 CFStringRef key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@"),
356 sLastCirclePushedPrefix, sCirclePrefix, gestaltInfo);
357 CFReleaseNull(gestaltInfo);
358 return key;
359 }
360
361 //should be >KeyParameters|ourPeerID
362 CFStringRef SOSLastKeyParametersPushedKeyCreateWithPeerID(CFStringRef peerID){
363
364 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"),
365 sLastKeyParametersPushedPrefix,kSOSKVSKeyParametersKey, sCircleSeparator, peerID);
366 }
367
368
369 //should be >KeyParameters|ourPeerID
370 CFStringRef SOSLastKeyParametersPushedKeyCreateWithAccountGestalt(SOSAccountRef account){
371
372 CFStringRef gestaltInfo = SOSAccountCreateCompactDescription(account);
373 CFStringRef key= CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"),
374 sLastKeyParametersPushedPrefix, kSOSKVSKeyParametersKey, sCircleSeparator, gestaltInfo);
375 CFReleaseNull(gestaltInfo);
376 return key;
377 }
378
379 CFStringRef SOSDebugInfoKeyCreateWithTypeName(CFStringRef type_name)
380 {
381 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
382 sDebugInfoPrefix, type_name);
383 }
384