2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <Security/SecureObjectSync/SOSKVSKeys.h>
25 #include <utilities/SecCFWrappers.h>
26 #include <Security/SecureObjectSync/SOSAccountPriv.h>
27 #include <CoreFoundation/CFDate.h>
29 void AppendCircleKeyName(CFMutableArrayRef array
, CFStringRef name
) {
30 CFStringRef circle_key
= SOSCircleKeyCreateWithName(name
, NULL
);
31 CFArrayAppendValue(array
, circle_key
);
32 CFReleaseNull(circle_key
);
38 // TODO: Handle '|' and "¬" in other strings.
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");
46 const CFStringRef kSOSKVSDebugScope
= CFSTR("^DebugScope");
48 const CFStringRef sPeerInfoPrefix
= CFSTR("+");
49 const CFStringRef sRingPrefix
= CFSTR("~");
50 const CFStringRef sDebugInfoPrefix
= CFSTR("dbg-");
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(":");
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));
70 SOSKVSKeyType
SOSKVSKeyGetKeyTypeAndParse(CFStringRef key
, CFStringRef
*circle
, CFStringRef
*peerInfo
, CFStringRef
*ring
, CFStringRef
*backupName
, CFStringRef
*from
, CFStringRef
*to
)
72 SOSKVSKeyType retval
= kUnknownKey
;
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
;
89 CFRange fromRange
= CFRangeMake(1, CFStringGetLength(key
)-1);
90 *circle
= CFStringCreateWithSubstring(NULL
, key
, fromRange
);
94 CFStringRef mCircle
= NULL
;
95 CFStringRef mFrom
= NULL
;
96 CFStringRef mTo
= NULL
;
97 CFMutableStringRef keycopy
= CFStringCreateMutableCopy(NULL
, 128, key
);
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
);
107 retval
= kUnknownKey
;
109 CFReleaseNull(mCircle
);
110 CFReleaseNull(mFrom
);
112 CFReleaseNull(keycopy
);
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
);
125 retval
= kUnknownKey
;
127 // TODO - Update our circle
128 CFReleaseNull(mCircle
);
129 CFReleaseNull(mPeer
);
130 CFReleaseNull(keycopy
);
135 CFRange fromRange
= CFRangeMake(1, CFStringGetLength(key
)-1);
136 *ring
= CFStringCreateWithSubstring(NULL
, key
, fromRange
);
141 CFRange fromRange
= CFRangeMake(1, CFStringGetLength(key
)-1);
142 *peerInfo
= CFStringCreateWithSubstring(NULL
, key
, fromRange
);
146 /* piggybacking on peerinfo */
148 CFRange dbgRange
= CFRangeMake(CFStringGetLength(sDebugInfoPrefix
),
149 CFStringGetLength(key
)-CFStringGetLength(sDebugInfoPrefix
));
150 *peerInfo
= CFStringCreateWithSubstring(NULL
, key
, dbgRange
);
153 case kAccountChangedKey
:
155 case kInitialSyncKey
:
157 case kLastKeyParameterKey
:
166 SOSKVSKeyType
SOSKVSKeyGetKeyType(CFStringRef key
)
168 return SOSKVSKeyGetKeyTypeAndParse(key
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
171 CFStringRef
SOSCircleKeyCreateWithCircle(SOSCircleRef circle
, CFErrorRef
*error
)
173 return SOSCircleKeyCreateWithName(SOSCircleGetName(circle
), error
);
177 CFStringRef
SOSCircleKeyCreateWithName(CFStringRef circleName
, CFErrorRef
*error
)
179 if(!circleName
) return NULL
;
180 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@"), sCirclePrefix
, circleName
);
183 CFStringRef
SOSPeerInfoKeyCreateWithName(CFStringRef peer_info_name
, CFErrorRef
*error
)
185 if(!peer_info_name
) return NULL
;
186 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@"), sPeerInfoPrefix
, peer_info_name
);
189 CFStringRef
SOSRingKeyCreateWithName(CFStringRef ring_name
, CFErrorRef
*error
)
191 if(!ring_name
) return NULL
;
192 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@"), sRingPrefix
, ring_name
);
195 CFStringRef
SOSCircleKeyCopyCircleName(CFStringRef key
, CFErrorRef
*error
)
197 CFStringRef circleName
= NULL
;
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
);
202 CFReleaseNull(circleName
);
208 CFStringRef
SOSMessageKeyCopyCircleName(CFStringRef key
, CFErrorRef
*error
)
210 CFStringRef circleName
= NULL
;
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
);
215 CFReleaseNull(circleName
);
220 CFStringRef
SOSMessageKeyCopyFromPeerName(CFStringRef messageKey
, CFErrorRef
*error
)
222 CFStringRef fromPeer
= NULL
;
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
);
227 CFReleaseNull(fromPeer
);
232 CFStringRef
SOSMessageKeyCreateWithCircleNameAndPeerNames(CFStringRef circleName
, CFStringRef from_peer_name
, CFStringRef to_peer_name
)
234 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@%@%@%@"),
235 circleName
, sCircleSeparator
, from_peer_name
, sFromToSeparator
, to_peer_name
);
238 CFStringRef
SOSMessageKeyCreateWithCircleNameAndTransportType(CFStringRef circleName
, CFStringRef transportType
)
240 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@%@%@%@"),
241 circleName
, sCircleSeparator
, transportType
, sFromToSeparator
, SOSTransportMessageTypeIDS
);
244 CFStringRef
SOSMessageKeyCreateWithCircleAndPeerNames(SOSCircleRef circle
, CFStringRef from_peer_name
, CFStringRef to_peer_name
)
246 return SOSMessageKeyCreateWithCircleNameAndPeerNames(SOSCircleGetName(circle
), from_peer_name
, to_peer_name
);
249 CFStringRef
SOSMessageKeyCreateWithCircleAndPeerInfos(SOSCircleRef circle
, SOSPeerInfoRef from_peer
, SOSPeerInfoRef to_peer
)
251 return SOSMessageKeyCreateWithCircleAndPeerNames(circle
, SOSPeerInfoGetPeerID(from_peer
), SOSPeerInfoGetPeerID(to_peer
));
254 CFStringRef
SOSMessageKeyCreateFromPeerToTransport(SOSTransportMessageKVSRef transport
, CFStringRef peer_name
) {
255 CFErrorRef error
= NULL
;
256 SOSEngineRef engine
= SOSTransportMessageGetEngine((SOSTransportMessageRef
)transport
);
258 CFStringRef circleName
= SOSTransportMessageGetCircleName((SOSTransportMessageRef
)transport
);
259 CFStringRef my_id
= SOSEngineGetMyID(engine
);
261 CFStringRef result
= SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName
, peer_name
, my_id
);
262 CFReleaseSafe(error
);
266 CFStringRef
SOSMessageKeyCreateFromTransportToPeer(SOSTransportMessageKVSRef transport
, CFStringRef peer_name
) {
267 CFErrorRef error
= NULL
;
268 SOSEngineRef engine
= SOSTransportMessageGetEngine((SOSTransportMessageRef
)transport
);
270 CFStringRef circleName
= SOSTransportMessageGetCircleName((SOSTransportMessageRef
)transport
);
271 CFStringRef my_id
= SOSEngineGetMyID(engine
);
273 CFStringRef result
= SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName
, my_id
, peer_name
);
274 CFReleaseSafe(error
);
278 CFStringRef
SOSRetirementKeyCreateWithCircleNameAndPeer(CFStringRef circle_name
, CFStringRef retirement_peer_name
)
280 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@%@%@"),
281 sRetirementPrefix
, circle_name
, sCircleSeparator
, retirement_peer_name
);
284 CFStringRef
SOSPeerInfoV2KeyCreateWithPeerName(CFStringRef peer_name
)
286 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@"),
287 sPeerInfoPrefix
, peer_name
);
290 CFStringRef
SOSRingKeyCreateWithRingName(CFStringRef ring_name
)
292 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@"),
293 sRingPrefix
, ring_name
);
296 CFStringRef
SOSRetirementKeyCreateWithCircleAndPeer(SOSCircleRef circle
, CFStringRef retirement_peer_name
)
298 return SOSRetirementKeyCreateWithCircleNameAndPeer(SOSCircleGetName(circle
), retirement_peer_name
);
301 //should be poak|ourPeerID
302 CFStringRef
SOSLastCirclePushedKeyCreateWithCircleNameAndPeerID(CFStringRef circleName
, CFStringRef peerID
){
304 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@%@%@%@"),
305 sLastCirclePushedPrefix
, sCirclePrefix
, circleName
, sCircleSeparator
, peerID
);
308 CFStringRef
SOSLastCirclePushedKeyCreateWithAccountGestalt(SOSAccountRef account
){
309 CFStringRef gestaltInfo
= SOSAccountCreateCompactDescription(account
);
310 CFStringRef key
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@%@"),
311 sLastCirclePushedPrefix
, sCirclePrefix
, gestaltInfo
);
312 CFReleaseNull(gestaltInfo
);
316 //should be >KeyParameters|ourPeerID
317 CFStringRef
SOSLastKeyParametersPushedKeyCreateWithPeerID(CFStringRef peerID
){
319 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@%@%@"),
320 sLastKeyParametersPushedPrefix
,kSOSKVSKeyParametersKey
, sCircleSeparator
, peerID
);
324 //should be >KeyParameters|ourPeerID
325 CFStringRef
SOSLastKeyParametersPushedKeyCreateWithAccountGestalt(SOSAccountRef account
){
327 CFStringRef gestaltInfo
= SOSAccountCreateCompactDescription(account
);
328 CFStringRef key
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@%@%@"),
329 sLastKeyParametersPushedPrefix
, kSOSKVSKeyParametersKey
, sCircleSeparator
, gestaltInfo
);
330 CFReleaseNull(gestaltInfo
);
334 CFStringRef
SOSDebugInfoKeyCreateWithTypeName(CFStringRef type_name
)
336 return CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@"),
337 sDebugInfoPrefix
, type_name
);