/ keychain / SecureObjectSync / SOSDataSource.h
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_ */