]>
Commit | Line | Data |
---|---|---|
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 | |
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"); | |
5c19dc3a A |
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-"); | |
d8f41ccd A |
51 | |
52 | const CFStringRef sWarningPrefix = CFSTR("!"); | |
53 | const CFStringRef sAncientCirclePrefix = CFSTR("@"); | |
54 | const CFStringRef sCirclePrefix = CFSTR("o"); | |
55 | const CFStringRef sRetirementPrefix = CFSTR("-"); | |
5c19dc3a A |
56 | const CFStringRef sLastCirclePushedPrefix = CFSTR("p"); |
57 | const CFStringRef sLastKeyParametersPushedPrefix = CFSTR("k"); | |
d8f41ccd A |
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 | ||
5c19dc3a | 70 | SOSKVSKeyType SOSKVSKeyGetKeyTypeAndParse(CFStringRef key, CFStringRef *circle, CFStringRef *peerInfo, CFStringRef *ring, CFStringRef *backupName, CFStringRef *from, CFStringRef *to) |
d8f41ccd A |
71 | { |
72 | SOSKVSKeyType retval = kUnknownKey; | |
73 | ||
74 | if(CFStringHasPrefix(key, sCirclePrefix)) retval = kCircleKey; | |
5c19dc3a A |
75 | else if (CFStringHasPrefix(key, sRingPrefix)) retval = kRingKey; |
76 | else if(CFStringHasPrefix(key, sPeerInfoPrefix)) retval = kPeerInfoKey; | |
d8f41ccd A |
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; | |
5c19dc3a A |
81 | else if(CFStringHasPrefix(key, sDebugInfoPrefix)) retval = kDebugInfoKey; |
82 | else if(CFStringHasPrefix(key, sLastCirclePushedPrefix)) retval = kLastCircleKey; | |
83 | else if(CFStringHasPrefix(key, sLastKeyParametersPushedPrefix)) retval = kLastKeyParameterKey; | |
d8f41ccd A |
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; | |
5c19dc3a A |
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; | |
d8f41ccd A |
153 | case kAccountChangedKey: |
154 | case kParametersKey: | |
155 | case kInitialSyncKey: | |
156 | case kUnknownKey: | |
5c19dc3a A |
157 | case kLastKeyParameterKey: |
158 | case kLastCircleKey: | |
d8f41ccd A |
159 | break; |
160 | } | |
161 | ||
162 | return retval; | |
163 | } | |
164 | ||
165 | ||
166 | SOSKVSKeyType SOSKVSKeyGetKeyType(CFStringRef key) | |
167 | { | |
5c19dc3a | 168 | return SOSKVSKeyGetKeyTypeAndParse(key, NULL, NULL, NULL, NULL, NULL, NULL); |
d8f41ccd A |
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 | ||
5c19dc3a A |
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 | ||
d8f41ccd A |
195 | CFStringRef SOSCircleKeyCopyCircleName(CFStringRef key, CFErrorRef *error) |
196 | { | |
197 | CFStringRef circleName = NULL; | |
198 | ||
5c19dc3a | 199 | if (kCircleKey != SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL, NULL, NULL, NULL)) { |
d8f41ccd A |
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 | ||
5c19dc3a | 212 | if (SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL, NULL, NULL, NULL) != kMessageKey) { |
d8f41ccd A |
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 | ||
5c19dc3a | 224 | if (SOSKVSKeyGetKeyTypeAndParse(messageKey, NULL, NULL, NULL, NULL, &fromPeer, NULL) != kMessageKey) { |
d8f41ccd A |
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 | ||
5c19dc3a A |
238 | CFStringRef SOSMessageKeyCreateWithCircleNameAndTransportType(CFStringRef circleName, CFStringRef transportType) |
239 | { | |
240 | return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"), | |
241 | circleName, sCircleSeparator, transportType, sFromToSeparator, SOSTransportMessageTypeIDS); | |
242 | } | |
243 | ||
d8f41ccd A |
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 | ||
5c19dc3a | 258 | CFStringRef circleName = SOSTransportMessageGetCircleName((SOSTransportMessageRef)transport); |
d8f41ccd A |
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 | ||
5c19dc3a | 270 | CFStringRef circleName = SOSTransportMessageGetCircleName((SOSTransportMessageRef)transport); |
d8f41ccd A |
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 | ||
5c19dc3a A |
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 | ||
d8f41ccd A |
296 | CFStringRef SOSRetirementKeyCreateWithCircleAndPeer(SOSCircleRef circle, CFStringRef retirement_peer_name) |
297 | { | |
298 | return SOSRetirementKeyCreateWithCircleNameAndPeer(SOSCircleGetName(circle), retirement_peer_name); | |
299 | } | |
300 | ||
5c19dc3a A |
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 |