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 <SecureObjectSync/SOSKVSKeys.h> 25#include <utilities/SecCFWrappers.h> 26#include <SecureObjectSync/SOSAccountPriv.h> 27 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"); 43 44const CFStringRef sWarningPrefix = CFSTR("!"); 45const CFStringRef sAncientCirclePrefix = CFSTR("@"); 46const CFStringRef sCirclePrefix = CFSTR("o"); 47const CFStringRef sRetirementPrefix = CFSTR("-"); 48const CFStringRef sCircleSeparator = CFSTR("|"); 49const CFStringRef sFromToSeparator = CFSTR(":"); 50 51static CFStringRef copyStringEndingIn(CFMutableStringRef in, CFStringRef token) { 52 if(token == NULL) return CFStringCreateCopy(NULL, in); 53 CFRange tokenAt = CFStringFind(in, token, 0); 54 if(tokenAt.location == kCFNotFound) return NULL; 55 CFStringRef retval = CFStringCreateWithSubstring(NULL, in, CFRangeMake(0, tokenAt.location)); 56 CFStringDelete(in, CFRangeMake(0, tokenAt.location+1)); 57 return retval; 58} 59 60SOSKVSKeyType SOSKVSKeyGetKeyTypeAndParse(CFStringRef key, CFStringRef *circle, CFStringRef *from, CFStringRef *to) 61{ 62 SOSKVSKeyType retval = kUnknownKey; 63 64 if(CFStringHasPrefix(key, sCirclePrefix)) retval = kCircleKey; 65 else if(CFStringHasPrefix(key, sRetirementPrefix)) retval = kRetirementKey; 66 else if(CFStringHasPrefix(key, kSOSKVSKeyParametersKey)) retval = kParametersKey; 67 else if(CFStringHasPrefix(key, kSOSKVSInitialSyncKey)) retval = kInitialSyncKey; 68 else if(CFStringHasPrefix(key, kSOSKVSAccountChangedKey)) retval = kAccountChangedKey; 69 else retval = kMessageKey; 70 71 switch(retval) { 72 case kCircleKey: 73 if (circle) { 74 CFRange fromRange = CFRangeMake(1, CFStringGetLength(key)-1); 75 *circle = CFStringCreateWithSubstring(NULL, key, fromRange); 76 } 77 break; 78 case kMessageKey: { 79 CFStringRef mCircle = NULL; 80 CFStringRef mFrom = NULL; 81 CFStringRef mTo = NULL; 82 CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key); 83 84 if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) && 85 ((mFrom = copyStringEndingIn(keycopy, sFromToSeparator)) != NULL) && 86 (CFStringGetLength(mFrom) > 0) ) { 87 mTo = copyStringEndingIn(keycopy, NULL); 88 if (circle && mCircle) *circle = CFStringCreateCopy(NULL, mCircle); 89 if (from && mFrom) *from = CFStringCreateCopy(NULL, mFrom); 90 if (to && mTo) *to = CFStringCreateCopy(NULL, mTo); 91 } else { 92 retval = kUnknownKey; 93 } 94 CFReleaseNull(mCircle); 95 CFReleaseNull(mFrom); 96 CFReleaseNull(mTo); 97 CFReleaseNull(keycopy); 98 } 99 break; 100 case kRetirementKey: { 101 CFStringRef mCircle = NULL; 102 CFStringRef mPeer = NULL; 103 CFMutableStringRef keycopy = CFStringCreateMutableCopy(NULL, 128, key); 104 CFStringDelete(keycopy, CFRangeMake(0, 1)); 105 if( ((mCircle = copyStringEndingIn(keycopy, sCircleSeparator)) != NULL) && 106 ((mPeer = copyStringEndingIn(keycopy, NULL)) != NULL)) { 107 if (circle) *circle = CFStringCreateCopy(NULL, mCircle); 108 if (from) *from = CFStringCreateCopy(NULL, mPeer); 109 } else { 110 retval = kUnknownKey; 111 } 112 // TODO - Update our circle 113 CFReleaseNull(mCircle); 114 CFReleaseNull(mPeer); 115 CFReleaseNull(keycopy); 116 } 117 break; 118 case kAccountChangedKey: 119 case kParametersKey: 120 case kInitialSyncKey: 121 case kUnknownKey: 122 break; 123 } 124 125 return retval; 126} 127 128 129SOSKVSKeyType SOSKVSKeyGetKeyType(CFStringRef key) 130{ 131 return SOSKVSKeyGetKeyTypeAndParse(key, NULL, NULL, NULL); 132} 133 134CFStringRef SOSCircleKeyCreateWithCircle(SOSCircleRef circle, CFErrorRef *error) 135{ 136 return SOSCircleKeyCreateWithName(SOSCircleGetName(circle), error); 137} 138 139 140CFStringRef SOSCircleKeyCreateWithName(CFStringRef circleName, CFErrorRef *error) 141{ 142 if(!circleName) return NULL; 143 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), sCirclePrefix, circleName); 144} 145 146CFStringRef SOSCircleKeyCopyCircleName(CFStringRef key, CFErrorRef *error) 147{ 148 CFStringRef circleName = NULL; 149 150 if (kCircleKey != SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL)) { 151 SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key); 152 153 CFReleaseNull(circleName); 154 } 155 156 return circleName; 157} 158 159CFStringRef SOSMessageKeyCopyCircleName(CFStringRef key, CFErrorRef *error) 160{ 161 CFStringRef circleName = NULL; 162 163 if (SOSKVSKeyGetKeyTypeAndParse(key, &circleName, NULL, NULL) != kMessageKey) { 164 SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find circle name in key '%@'"), key); 165 166 CFReleaseNull(circleName); 167 } 168 return circleName; 169} 170 171CFStringRef SOSMessageKeyCopyFromPeerName(CFStringRef messageKey, CFErrorRef *error) 172{ 173 CFStringRef fromPeer = NULL; 174 175 if (SOSKVSKeyGetKeyTypeAndParse(messageKey, NULL, &fromPeer, NULL) != kMessageKey) { 176 SOSCreateErrorWithFormat(kSOSErrorNoCircleName, NULL, error, NULL, CFSTR("Couldn't find from peer in key '%@'"), messageKey); 177 178 CFReleaseNull(fromPeer); 179 } 180 return fromPeer; 181} 182 183CFStringRef SOSMessageKeyCreateWithCircleNameAndPeerNames(CFStringRef circleName, CFStringRef from_peer_name, CFStringRef to_peer_name) 184{ 185 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@%@"), 186 circleName, sCircleSeparator, from_peer_name, sFromToSeparator, to_peer_name); 187} 188 189CFStringRef SOSMessageKeyCreateWithCircleAndPeerNames(SOSCircleRef circle, CFStringRef from_peer_name, CFStringRef to_peer_name) 190{ 191 return SOSMessageKeyCreateWithCircleNameAndPeerNames(SOSCircleGetName(circle), from_peer_name, to_peer_name); 192} 193 194CFStringRef SOSMessageKeyCreateWithCircleAndPeerInfos(SOSCircleRef circle, SOSPeerInfoRef from_peer, SOSPeerInfoRef to_peer) 195{ 196 return SOSMessageKeyCreateWithCircleAndPeerNames(circle, SOSPeerInfoGetPeerID(from_peer), SOSPeerInfoGetPeerID(to_peer)); 197} 198 199CFStringRef SOSMessageKeyCreateFromPeerToTransport(SOSTransportMessageKVSRef transport, CFStringRef peer_name) { 200 CFErrorRef error = NULL; 201 SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport); 202 203 CFStringRef circleName = SOSTransportMessageKVSGetCircleName(transport); 204 CFStringRef my_id = SOSEngineGetMyID(engine); 205 206 CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, peer_name, my_id); 207 CFReleaseSafe(error); 208 return result; 209} 210 211CFStringRef SOSMessageKeyCreateFromTransportToPeer(SOSTransportMessageKVSRef transport, CFStringRef peer_name) { 212 CFErrorRef error = NULL; 213 SOSEngineRef engine = SOSTransportMessageGetEngine((SOSTransportMessageRef)transport); 214 215 CFStringRef circleName = SOSTransportMessageKVSGetCircleName(transport); 216 CFStringRef my_id = SOSEngineGetMyID(engine); 217 218 CFStringRef result = SOSMessageKeyCreateWithCircleNameAndPeerNames(circleName, my_id, peer_name); 219 CFReleaseSafe(error); 220 return result; 221} 222 223CFStringRef SOSRetirementKeyCreateWithCircleNameAndPeer(CFStringRef circle_name, CFStringRef retirement_peer_name) 224{ 225 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@%@%@"), 226 sRetirementPrefix, circle_name, sCircleSeparator, retirement_peer_name); 227} 228 229CFStringRef SOSRetirementKeyCreateWithCircleAndPeer(SOSCircleRef circle, CFStringRef retirement_peer_name) 230{ 231 return SOSRetirementKeyCreateWithCircleNameAndPeer(SOSCircleGetName(circle), retirement_peer_name); 232} 233 234