SOSDataSource.h
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 25 /*! 26 @header SOSDataSource.h 27 The functions provided in SOSDataSource.h provide the protocol to a 28 secure object syncing data source. This is something than can produce 29 manifests and manifest digests and query objects by digest and merge 30 objects into the data source. 31 */ 32 33 #ifndef _SEC_SOSDATASOURCE_H_ 34 #define _SEC_SOSDATASOURCE_H_ 35 36 #include "keychain/SecureObjectSync/SOSManifest.h" 37 #include <Security/SecureObjectSync/SOSCloudCircle.h> 38 #include "utilities/array_size.h" 39 #include "utilities/SecCFRelease.h" 40 #include "utilities/SecCFError.h" 41 42 __BEGIN_DECLS 43 44 /* SOSDataSource protocol (non opaque). */ 45 typedef struct SOSDataSourceFactory *SOSDataSourceFactoryRef; 46 typedef struct SOSDataSource *SOSDataSourceRef; 47 typedef struct __OpaqueSOSEngine *SOSEngineRef; 48 typedef struct __OpaqueSOSObject *SOSObjectRef; 49 typedef struct __OpaqueSOSTransaction *SOSTransactionRef; 50 51 // 52 // MARK: - SOSDataSourceFactory protocol 53 // 54 struct SOSDataSourceFactory { 55 CFStringRef (*copy_name)(SOSDataSourceFactoryRef factory); 56 SOSDataSourceRef (*create_datasource)(SOSDataSourceFactoryRef factory, CFStringRef dataSourceName, CFErrorRef *error); 57 void (*release)(SOSDataSourceFactoryRef factory); 58 }; 59 60 static inline CFStringRef SOSDataSourceFactoryCopyName(SOSDataSourceFactoryRef dsf) { 61 return dsf->copy_name(dsf); 62 } 63 64 static inline SOSDataSourceRef SOSDataSourceFactoryCreateDataSource(SOSDataSourceFactoryRef dsf, CFStringRef dataSourceName, CFErrorRef *error) { 65 (void)SecRequirementError(dsf != NULL, error, CFSTR("No datasource")); 66 return dsf ? dsf->create_datasource(dsf, dataSourceName, error) : NULL; 67 } 68 69 static inline void SOSDataSourceFactoryRelease(SOSDataSourceFactoryRef dsf) { 70 dsf->release(dsf); 71 } 72 73 // 74 // MARK: - SOSDataSource protocol 75 // 76 77 /* Implement this if you want to create a new type of sync client. 78 Currently we support keychains, but the engine should scale to 79 entire filesystems. */ 80 enum SOSMergeResult { 81 kSOSMergeFailure = 0, // CFErrorRef returned, no error returned in any other case 82 kSOSMergeLocalObject, // We choose the current object in the dataSource the manifest is still valid. 83 kSOSMergePeersObject, // We chose the peers object over our own, manifest is now dirty. 84 kSOSMergeCreatedObject, // *createdObject is returned and should be released 85 }; 86 typedef CFIndex SOSMergeResult; 87 88 // 89 // MARK: SOSDataSourceTransactionType 90 // 91 enum SOSDataSourceTransactionType { 92 kSOSDataSourceNoneTransactionType = 0, 93 kSOSDataSourceImmediateTransactionType, 94 kSOSDataSourceExclusiveTransactionType, 95 kSOSDataSourceNormalTransactionType, 96 kSOSDataSourceExclusiveRemoteTransactionType, 97 }; 98 typedef CFOptionFlags SOSDataSourceTransactionType; 99 100 enum SOSDataSourceTransactionPhase { 101 kSOSDataSourceTransactionDidRollback = 0, // A transaction just got rolled back 102 kSOSDataSourceTransactionWillCommit, // A transaction is about to commit. 103 kSOSDataSourceTransactionDidCommit, // A transaction successfully committed. 104 }; 105 typedef CFOptionFlags SOSDataSourceTransactionPhase; 106 107 // These must match the values in SecDbTransactionSource 108 enum SOSDataSourceTransactionSource { 109 kSOSDataSourceSOSTransaction = 0, // A remotely initated transaction. 110 kSOSDataSourceCKKSTransaction = 3, // A transaction initiated by CKKS. 111 kSOSDataSourceAPITransaction = 1, // A user initated transaction. 112 }; 113 typedef CFOptionFlags SOSDataSourceTransactionSource; 114 115 typedef void (^SOSDataSourceNotifyBlock)(SOSDataSourceRef ds, SOSTransactionRef txn, SOSDataSourceTransactionPhase phase, SOSDataSourceTransactionSource source, CFArrayRef changes); 116 117 // 118 // MARK: - SOSDataSource struct 119 // 120 121 struct SOSDataSource { 122 // SOSEngine - every datasource has an engine that is notified of changes 123 // to the datasource. 124 SOSEngineRef engine; 125 126 // General SOSDataSource methods 127 CFStringRef (*dsGetName)(SOSDataSourceRef ds); 128 void (*dsAddNotifyPhaseBlock)(SOSDataSourceRef ds, SOSDataSourceNotifyBlock notifyBlock); 129 SOSManifestRef (*dsCopyManifestWithViewNameSet)(SOSDataSourceRef ds, CFSetRef viewNameSet, CFErrorRef *error); 130 bool (*dsForEachObject)(SOSDataSourceRef ds, SOSTransactionRef txn, SOSManifestRef manifest, CFErrorRef *error, void (^handleObject)(CFDataRef key, SOSObjectRef object, bool *stop)); 131 CFDataRef (*dsCopyStateWithKey)(SOSDataSourceRef ds, CFStringRef key, CFStringRef pdmn, SOSTransactionRef txn, CFErrorRef *error); 132 CFDataRef (*dsCopyItemDataWithKeys)(SOSDataSourceRef ds, CFDictionaryRef keys, CFErrorRef *error); 133 bool (*dsDeleteStateWithKey)(SOSDataSourceRef ds, CFStringRef key, CFStringRef pdmn, SOSTransactionRef txn, CFErrorRef *error); 134 135 bool (*dsWith)(SOSDataSourceRef ds, CFErrorRef *error, SOSDataSourceTransactionSource source, bool onCommitQueue, void(^transaction)(SOSTransactionRef txn, bool *commit)); 136 bool (*dsRelease)(SOSDataSourceRef ds, CFErrorRef *error); // Destructor 137 bool (*dsReadWith)(SOSDataSourceRef ds, CFErrorRef *error, SOSDataSourceTransactionSource source, void(^perform)(SOSTransactionRef txn)); 138 139 // SOSTransaction methods, writes to a dataSource require a transaction. 140 SOSMergeResult (*dsMergeObject)(SOSTransactionRef txn, SOSObjectRef object, SOSObjectRef *createdObject, CFErrorRef *error); 141 bool (*dsSetStateWithKey)(SOSDataSourceRef ds, SOSTransactionRef txn, CFStringRef pdmn, CFStringRef key, CFDataRef state, CFErrorRef *error); 142 bool (*dsRestoreObject)(SOSTransactionRef txn, uint64_t handle, CFDictionaryRef item, CFErrorRef *error); 143 144 // SOSObject methods 145 CFDataRef (*objectCopyDigest)(SOSObjectRef object, CFErrorRef *error); 146 CFDateRef (*objectCopyModDate)(SOSObjectRef object, CFErrorRef *error); 147 SOSObjectRef (*objectCreateWithPropertyList)(CFDictionaryRef plist, CFErrorRef *error); 148 CFDictionaryRef (*objectCopyPropertyList)(SOSObjectRef object, CFErrorRef *error); 149 CFDictionaryRef (*objectCopyBackup)(SOSObjectRef object, uint64_t handle, CFErrorRef *error); 150 }; 151 152 // 153 // MARK: - SOSDataSource protocol implementation 154 // 155 static inline SOSEngineRef SOSDataSourceGetSharedEngine(SOSDataSourceRef ds, CFErrorRef *error) { 156 return ds->engine; 157 } 158 159 static inline CFStringRef SOSDataSourceGetName(SOSDataSourceRef ds) { 160 return ds->dsGetName(ds); 161 } 162 163 static inline void SOSDataSourceAddNotifyPhaseBlock(SOSDataSourceRef ds, SOSDataSourceNotifyBlock notifyBlock) { 164 ds->dsAddNotifyPhaseBlock(ds, notifyBlock); 165 } 166 167 static inline SOSManifestRef SOSDataSourceCopyManifestWithViewNameSet(SOSDataSourceRef ds, CFSetRef viewNameSet, CFErrorRef *error) { 168 return ds->dsCopyManifestWithViewNameSet(ds, viewNameSet, error); 169 } 170 171 static inline bool SOSDataSourceForEachObject(SOSDataSourceRef ds, SOSTransactionRef txn, SOSManifestRef manifest, CFErrorRef *error, void (^handleObject)(CFDataRef digest, SOSObjectRef object, bool *stop)) { 172 return ds->dsForEachObject(ds, txn, manifest, error, handleObject); 173 } 174 175 static inline bool SOSDataSourceWith(SOSDataSourceRef ds, CFErrorRef *error, 176 void(^transaction)(SOSTransactionRef txn, bool *commit)) { 177 return ds->dsWith(ds, error, kSOSDataSourceSOSTransaction, false, transaction); 178 } 179 180 static inline bool SOSDataSourceWithCommitQueue(SOSDataSourceRef ds, CFErrorRef *error, 181 void(^transaction)(SOSTransactionRef txn, bool *commit)) { 182 return ds->dsWith(ds, error, kSOSDataSourceSOSTransaction, true, transaction); 183 } 184 185 static inline bool SOSDataSourceWithAPI(SOSDataSourceRef ds, bool isAPI, CFErrorRef *error, 186 void(^transaction)(SOSTransactionRef txn, bool *commit)) { 187 return ds->dsWith(ds, error, isAPI ? kSOSDataSourceAPITransaction : kSOSDataSourceSOSTransaction, false, transaction); 188 } 189 190 static inline bool SOSDataSourceReadWithCommitQueue(SOSDataSourceRef ds, CFErrorRef *error, 191 void(^perform)(SOSTransactionRef txn)) { 192 return ds->dsReadWith(ds, error, kSOSDataSourceSOSTransaction, perform); 193 } 194 195 196 static inline CFDataRef SOSDataSourceCopyStateWithKey(SOSDataSourceRef ds, CFStringRef key, CFStringRef pdmn, SOSTransactionRef txn, CFErrorRef *error) 197 { 198 return ds->dsCopyStateWithKey(ds, key, pdmn, txn, error); 199 } 200 201 static inline CFDataRef SOSDataSourceCopyItemDataWithKeys(SOSDataSourceRef ds, CFDictionaryRef keys, CFErrorRef *error) { 202 return ds->dsCopyItemDataWithKeys(ds, keys, error); 203 } 204 205 static inline bool SOSDataSourceDeleteStateWithKey(SOSDataSourceRef ds, CFStringRef key, CFStringRef pdmn, SOSTransactionRef txn, CFErrorRef *error) 206 { 207 return ds->dsDeleteStateWithKey(ds, key, pdmn, txn, error); 208 } 209 210 static inline bool SOSDataSourceRelease(SOSDataSourceRef ds, CFErrorRef *error) { 211 return !ds || ds->dsRelease(ds, error); 212 } 213 214 // 215 // MARK: - SOSTransaction 216 // 217 218 static inline SOSMergeResult SOSDataSourceMergeObject(SOSDataSourceRef ds, SOSTransactionRef txn, SOSObjectRef peersObject, SOSObjectRef *mergedObject, CFErrorRef *error) { 219 return ds->dsMergeObject(txn, peersObject, mergedObject, error); 220 } 221 222 static inline bool SOSDataSourceSetStateWithKey(SOSDataSourceRef ds, SOSTransactionRef txn, CFStringRef key, CFStringRef pdmn, CFDataRef state, CFErrorRef *error) 223 { 224 return ds->dsSetStateWithKey(ds, txn, key, pdmn, state, error); 225 } 226 227 228 // 229 // MARK: - SOSObject methods 230 // 231 static inline CFDataRef SOSObjectCopyDigest(SOSDataSourceRef ds, SOSObjectRef object, CFErrorRef *error) { 232 return ds->objectCopyDigest(object, error); 233 } 234 235 static inline CFDateRef SOSObjectCopyModificationDate(SOSDataSourceRef ds, SOSObjectRef object, CFErrorRef *error) { 236 return ds->objectCopyModDate(object, error); 237 } 238 239 static inline SOSObjectRef SOSObjectCreateWithPropertyList(SOSDataSourceRef ds, CFDictionaryRef plist, CFErrorRef *error) { 240 return ds->objectCreateWithPropertyList(plist, error); 241 } 242 243 static inline CFDictionaryRef SOSObjectCopyPropertyList(SOSDataSourceRef ds, SOSObjectRef object, CFErrorRef *error) { 244 return ds->objectCopyPropertyList(object, error); 245 } 246 247 static inline CFDictionaryRef SOSObjectCopyBackup(SOSDataSourceRef ds, SOSObjectRef object, uint64_t handle, CFErrorRef *error) { 248 return ds->objectCopyBackup(object, handle, error); 249 } 250 251 static inline bool SOSObjectRestoreObject(SOSDataSourceRef ds, SOSTransactionRef txn, uint64_t handle, CFDictionaryRef item, CFErrorRef *error) { 252 return ds->dsRestoreObject(txn, handle, item, error); 253 } 254 255 256 // 257 // MARK: SOSDataSourceFactory helpers 258 // 259 260 static inline SOSEngineRef SOSDataSourceFactoryGetEngineForDataSourceName(SOSDataSourceFactoryRef factory, CFStringRef dataSourceName, CFErrorRef *error) 261 { 262 SOSDataSourceRef ds = SOSDataSourceFactoryCreateDataSource(factory, dataSourceName, error); 263 SOSEngineRef engine = ds ? SOSDataSourceGetSharedEngine(ds, error) : (SOSEngineRef) NULL; 264 SOSDataSourceRelease(ds, NULL); // TODO: Log this error?! 265 266 return engine; 267 } 268 269 __END_DECLS 270 271 #endif /* !_SEC_SOSDATASOURCE_H_ */