]> git.saurik.com Git - apple/security.git/blame - OSX/sec/SOSCircle/SecureObjectSync/SOSKVSKeys.c
Security-57740.51.3.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSKVSKeys.c
CommitLineData
d8f41ccd
A
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
5c19dc3a 24#include <Security/SecureObjectSync/SOSKVSKeys.h>
d8f41ccd 25#include <utilities/SecCFWrappers.h>
5c19dc3a
A
26#include <Security/SecureObjectSync/SOSAccountPriv.h>
27#include <CoreFoundation/CFDate.h>
d8f41ccd
A
28
29void 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//
40const CFStringRef kSOSKVSKeyParametersKey = CFSTR(">KeyParameters");
41const CFStringRef kSOSKVSInitialSyncKey = CFSTR("^InitialSync");
42const CFStringRef kSOSKVSAccountChangedKey = CFSTR("^AccountChanged");
5c19dc3a
A
43const CFStringRef kSOSKVSRequiredKey = CFSTR("^Required");
44const CFStringRef kSOSKVSOfficialDSIDKey = CFSTR("^OfficialDSID");
45
46const CFStringRef kSOSKVSDebugScope = CFSTR("^DebugScope");
47
48const CFStringRef sPeerInfoPrefix = CFSTR("+");
49const CFStringRef sRingPrefix = CFSTR("~");
50const CFStringRef sDebugInfoPrefix = CFSTR("dbg-");
d8f41ccd
A
51
52const CFStringRef sWarningPrefix = CFSTR("!");
53const CFStringRef sAncientCirclePrefix = CFSTR("@");
54const CFStringRef sCirclePrefix = CFSTR("o");
55const CFStringRef sRetirementPrefix = CFSTR("-");
5c19dc3a
A
56const CFStringRef sLastCirclePushedPrefix = CFSTR("p");
57const CFStringRef sLastKeyParametersPushedPrefix = CFSTR("k");
d8f41ccd
A
58const CFStringRef sCircleSeparator = CFSTR("|");
59const CFStringRef sFromToSeparator = CFSTR(":");
60
61static 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
fa7225c8 70SOSKVSKeyType SOSKVSKeyGetKeyType(CFStringRef key) {
d8f41ccd
A
71 SOSKVSKeyType retval = kUnknownKey;
72
73 if(CFStringHasPrefix(key, sCirclePrefix)) retval = kCircleKey;
5c19dc3a
A
74 else if (CFStringHasPrefix(key, sRingPrefix)) retval = kRingKey;
75 else if(CFStringHasPrefix(key, sPeerInfoPrefix)) retval = kPeerInfoKey;
d8f41ccd
A
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;
5c19dc3a
A
80 else if(CFStringHasPrefix(key, sDebugInfoPrefix)) retval = kDebugInfoKey;
81 else if(CFStringHasPrefix(key, sLastCirclePushedPrefix)) retval = kLastCircleKey;
82 else if(CFStringHasPrefix(key, sLastKeyParametersPushedPrefix)) retval = kLastKeyParameterKey;
d8f41ccd 83 else retval = kMessageKey;
fa7225c8
A
84
85 return retval;
86}
87
88bool SOSKVSKeyParse(SOSKVSKeyType keyType, CFStringRef key, CFStringRef *circle, CFStringRef *peerInfo, CFStringRef *ring, CFStringRef *backupName, CFStringRef *from, CFStringRef *to) {
89 bool retval = true;
d8f41ccd 90
fa7225c8 91 switch(keyType) {
d8f41ccd
A
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 {
fa7225c8 112 retval = false;
d8f41ccd
A
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 {
fa7225c8 130 retval = false;
d8f41ccd 131 }
d8f41ccd
A
132 CFReleaseNull(mCircle);
133 CFReleaseNull(mPeer);
134 CFReleaseNull(keycopy);
135 }
136 break;
5c19dc3a
A
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;
d8f41ccd
A
157 case kAccountChangedKey:
158 case kParametersKey:
159 case kInitialSyncKey:
160 case kUnknownKey:
fa7225c8 161 break;
5c19dc3a 162 case kLastKeyParameterKey:
fa7225c8
A
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;
5c19dc3a 179 case kLastCircleKey:
fa7225c8
A
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
d8f41ccd
A
197 break;
198 }
d8f41ccd
A
199 return retval;
200}
201
fa7225c8 202SOSKVSKeyType SOSKVSKeyGetKeyTypeAndParse(CFStringRef key, CFStringRef *circle, CFStringRef *peerInfo, CFStringRef *ring, CFStringRef *backupName, CFStringRef *from, CFStringRef *to)
d8f41ccd 203{
fa7225c8
A
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;
d8f41ccd
A
209}
210
fa7225c8 211
d8f41ccd
A
212CFStringRef SOSCircleKeyCreateWithCircle(SOSCircleRef circle, CFErrorRef *error)
213{
214 return SOSCircleKeyCreateWithName(SOSCircleGetName(circle), error);
215}
216
217
218CFStringRef SOSCircleKeyCreateWithName(CFStringRef circleName, CFErrorRef *error)
219{
220 if(!circleName) return NULL;
221 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sCirclePrefix, circleName);
222}
223
5c19dc3a
A
224CFStringRef 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
230CFStringRef SOSRingKeyCreateWithName(CFStringRef ring_name, CFErrorRef *error)
231{
232 if(!ring_name) return NULL;
233 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sRingPrefix, ring_name);
234}
235
d8f41ccd
A
236CFStringRef SOSCircleKeyCopyCircleName(CFStringRef key, CFErrorRef *error)
237{
238 CFStringRef circleName = NULL;
239
5c19dc3a 240 if (kCircleKey != SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL, NULL, NULL, NULL)) {
d8f41ccd
A
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
249CFStringRef SOSMessageKeyCopyCircleName(CFStringRef key, CFErrorRef *error)
250{
251 CFStringRef circleName = NULL;
252
5c19dc3a 253 if (SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL, NULL, NULL, NULL) != kMessageKey) {
d8f41ccd
A
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
261CFStringRef SOSMessageKeyCopyFromPeerName(CFStringRef messageKey, CFErrorRef *error)
262{
263 CFStringRef fromPeer = NULL;
264
5c19dc3a 265 if (SOSKVSKeyGetKeyTypeAndParse(messageKey, NULL, NULL, NULL, NULL, &fromPeer, NULL) != kMessageKey) {
d8f41ccd
A
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
273CFStringRef 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
5c19dc3a
A
279CFStringRef SOSMessageKeyCreateWithCircleNameAndTransportType(CFStringRef circleName, CFStringRef transportType)
280{
281 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"),
fa7225c8 282 circleName, sCircleSeparator, transportType, sFromToSeparator, SOSTransportMessageTypeIDSV2);
5c19dc3a
A
283}
284
d8f41ccd
A
285CFStringRef 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
290CFStringRef SOSMessageKeyCreateWithCircleAndPeerInfos(SOSCircleRef circle, SOSPeerInfoRef from_peer, SOSPeerInfoRef to_peer)
291{
292 return SOSMessageKeyCreateWithCircleAndPeerNames(circle, SOSPeerInfoGetPeerID(from_peer), SOSPeerInfoGetPeerID(to_peer));
293}
294
fa7225c8 295CFStringRef SOSMessageKeyCreateFromPeerToTransport(SOSTransportMessageRef transport, CFStringRef peer_name) {
d8f41ccd
A
296 CFErrorRef error = NULL;
297 SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport);
298
5c19dc3a 299 CFStringRef circleName = SOSTransportMessageGetCircleName((SOSTransportMessageRef)transport);
d8f41ccd 300 CFStringRef my_id = SOSEngineGetMyID(engine);
fa7225c8
A
301 if(my_id == NULL)
302 {
303 secerror("cannot create message keys, SOSEngineGetMyID returned NULL");
304 return NULL;
305 }
d8f41ccd
A
306 CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, peer_name, my_id);
307 CFReleaseSafe(error);
308 return result;
309}
310
fa7225c8 311CFStringRef SOSMessageKeyCreateFromTransportToPeer(SOSTransportMessageRef transport, CFStringRef peer_name) {
d8f41ccd
A
312 CFErrorRef error = NULL;
313 SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport);
314
5c19dc3a 315 CFStringRef circleName = SOSTransportMessageGetCircleName((SOSTransportMessageRef)transport);
d8f41ccd
A
316 CFStringRef my_id = SOSEngineGetMyID(engine);
317
318 CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, my_id, peer_name);
319 CFReleaseSafe(error);
320 return result;
321}
322
323CFStringRef 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
5c19dc3a
A
329CFStringRef SOSPeerInfoV2KeyCreateWithPeerName(CFStringRef peer_name)
330{
331 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
332 sPeerInfoPrefix, peer_name);
333}
334
335CFStringRef SOSRingKeyCreateWithRingName(CFStringRef ring_name)
336{
337 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
338 sRingPrefix, ring_name);
339}
340
d8f41ccd
A
341CFStringRef SOSRetirementKeyCreateWithCircleAndPeer(SOSCircleRef circle, CFStringRef retirement_peer_name)
342{
343 return SOSRetirementKeyCreateWithCircleNameAndPeer(SOSCircleGetName(circle), retirement_peer_name);
344}
345
5c19dc3a
A
346//should be poak|ourPeerID
347CFStringRef SOSLastCirclePushedKeyCreateWithCircleNameAndPeerID(CFStringRef circleName, CFStringRef peerID){
348
349 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"),
350 sLastCirclePushedPrefix, sCirclePrefix, circleName, sCircleSeparator, peerID);
351}
352
353CFStringRef 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
362CFStringRef SOSLastKeyParametersPushedKeyCreateWithPeerID(CFStringRef peerID){
363
364 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"),
365 sLastKeyParametersPushedPrefix,kSOSKVSKeyParametersKey, sCircleSeparator, peerID);
366}
367
368
369//should be >KeyParameters|ourPeerID
370CFStringRef 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
379CFStringRef SOSDebugInfoKeyCreateWithTypeName(CFStringRef type_name)
380{
381 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"),
382 sDebugInfoPrefix, type_name);
383}
384