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