+++ /dev/null
-/*
- * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-
-#include "SOSTestDataSource.h"
-
-#include <corecrypto/ccder.h>
-#include <Security/SecureObjectSync/SOSDataSource.h>
-#include <Security/SecureObjectSync/SOSDigestVector.h>
-#include <Security/SecureObjectSync/SOSViews.h>
-
-#include <utilities/array_size.h>
-#include <utilities/der_plist.h>
-#include <utilities/SecCFError.h>
-#include <utilities/SecCFWrappers.h>
-#include <Security/SecItem.h>
-#include <Security/SecItemPriv.h>
-#include <AssertMacros.h>
-
-CFStringRef sSOSDataSourceErrorDomain = CFSTR("com.apple.datasource");
-
-typedef struct SOSTestDataSource *SOSTestDataSourceRef;
-
-struct SOSTestDataSource {
- struct SOSDataSource ds;
- unsigned gm_count;
- unsigned cm_count;
- unsigned co_count;
- CFMutableDictionaryRef d2database;
- CFMutableDictionaryRef p2database;
- CFMutableDictionaryRef statedb;
- uint8_t manifest_digest[SOSDigestSize];
- bool clean;
-
- CFMutableArrayRef changes;
- SOSDataSourceNotifyBlock notifyBlock;
-};
-
-typedef struct SOSTestDataSourceFactory *SOSTestDataSourceFactoryRef;
-
-struct SOSTestDataSourceFactory {
- struct SOSDataSourceFactory dsf;
- CFMutableDictionaryRef data_sources;
-};
-
-
-/* DataSource protocol. */
-static SOSManifestRef dsCopyManifestWithViewNameSet(SOSDataSourceRef data_source, CFSetRef viewNameSet, CFErrorRef *error) {
- if (!CFSetContainsValue(viewNameSet, kSOSViewKeychainV0))
- return SOSManifestCreateWithData(NULL, error);
-
- struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source;
- ds->cm_count++;
- __block struct SOSDigestVector dv = SOSDigestVectorInit;
- CFDictionaryForEach(ds->d2database, ^(const void *key, const void *value) {
- SOSDigestVectorAppend(&dv, CFDataGetBytePtr((CFDataRef)key));
- });
- SOSDigestVectorSort(&dv);
- SOSManifestRef manifest = SOSManifestCreateWithDigestVector(&dv, error);
- SOSDigestVectorFree(&dv);
- ccdigest(ccsha1_di(), SOSManifestGetSize(manifest), SOSManifestGetBytePtr(manifest), ds->manifest_digest);
- ds->clean = true;
-
- return manifest;
-}
-
-static bool foreach_object(SOSDataSourceRef data_source, SOSTransactionRef txn, SOSManifestRef manifest, CFErrorRef *error, void (^handle_object)(CFDataRef key, SOSObjectRef object, bool *stop)) {
- struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source;
- ds->co_count++;
- __block bool result = true;
- SOSManifestForEach(manifest, ^(CFDataRef key, bool *stop) {
- handle_object(key, (SOSObjectRef)CFDictionaryGetValue(ds->d2database, key), stop);
- });
- return result;
-}
-
-static bool dispose(SOSDataSourceRef data_source, CFErrorRef *error) {
- struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source;
- CFReleaseSafe(ds->d2database);
- CFReleaseSafe(ds->p2database);
- CFReleaseSafe(ds->statedb);
- CFReleaseSafe(ds->changes);
- free(ds);
- return true;
-}
-
-static SOSObjectRef createWithPropertyList(CFDictionaryRef plist, CFErrorRef *error) {
- return (SOSObjectRef)CFDictionaryCreateCopy(kCFAllocatorDefault, plist);
-}
-
-static CFDataRef SOSObjectCopyDER(SOSObjectRef object, CFErrorRef *error) {
- CFDictionaryRef dict = (CFDictionaryRef)object;
- size_t size = der_sizeof_plist(dict, error);
- CFMutableDataRef data = CFDataCreateMutable(0, size);
- if (data) {
- CFDataSetLength(data, size);
- uint8_t *der = (uint8_t *)CFDataGetMutableBytePtr(data);
- uint8_t *der_end = der + size;
- der_end = der_encode_plist(dict, error, der, der_end);
- assert(der_end == der);
- (void)der_end;
- } else if (error && *error == NULL) {
- *error = CFErrorCreate(0, sSOSDataSourceErrorDomain, kSOSDataSourceObjectMallocFailed, NULL);
- }
- return data;
-}
-
-static CFDataRef ccdigest_copy_data(const struct ccdigest_info *di, size_t len,
- const void *data, CFErrorRef *error) {
- CFMutableDataRef digest = CFDataCreateMutable(0, di->output_size);
- if (digest) {
- CFDataSetLength(digest, di->output_size);
- ccdigest(di, len, data, CFDataGetMutableBytePtr(digest));
- } else if (error && *error == NULL) {
- *error = CFErrorCreate(0, sSOSDataSourceErrorDomain, kSOSDataSourceObjectMallocFailed, NULL);
- }
- return digest;
-}
-
-static CFDataRef copyDigest(SOSObjectRef object, CFErrorRef *error) {
- CFMutableDictionaryRef ocopy = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, (CFDictionaryRef)object);
- CFDictionaryRemoveValue(ocopy, kSecClass);
- CFDataRef der = SOSObjectCopyDER((SOSObjectRef)ocopy, error);
- CFRelease(ocopy);
- CFDataRef digest = NULL;
- if (der) {
- digest = ccdigest_copy_data(ccsha1_di(), CFDataGetLength(der), CFDataGetBytePtr(der), error);
- CFRelease(der);
- }
- return digest;
-}
-
-static CFDateRef copyModDate(SOSObjectRef object, CFErrorRef *error) {
- return CFRetainSafe(asDate(CFDictionaryGetValue((CFDictionaryRef) object, kSecAttrModificationDate), NULL));
-}
-
-static CFDataRef copyPrimaryKey(SOSObjectRef object, CFErrorRef *error) {
- CFMutableDictionaryRef ocopy = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
- CFTypeRef pkNames[] = {
- CFSTR("acct"),
- CFSTR("agrp"),
- CFSTR("svce"),
- CFSTR("sync"),
- CFSTR("sdmn"),
- CFSTR("srvr"),
- CFSTR("ptcl"),
- CFSTR("atyp"),
- CFSTR("port"),
- CFSTR("path"),
- CFSTR("ctyp"),
- CFSTR("issr"),
- CFSTR("slnr"),
- CFSTR("kcls"),
- CFSTR("klbl"),
- CFSTR("atag"),
- CFSTR("crtr"),
- CFSTR("type"),
- CFSTR("bsiz"),
- CFSTR("esiz"),
- CFSTR("sdat"),
- CFSTR("edat"),
- };
- CFSetRef pkAttrs = CFSetCreate(kCFAllocatorDefault, pkNames, array_size(pkNames), &kCFTypeSetCallBacks);
- CFDictionaryForEach((CFDictionaryRef)object, ^(const void *key, const void *value) {
- if (CFSetContainsValue(pkAttrs, key))
- CFDictionaryAddValue(ocopy, key, value);
- });
- CFRelease(pkAttrs);
- CFDataRef der = SOSObjectCopyDER((SOSObjectRef)ocopy, error);
- CFRelease(ocopy);
- CFDataRef digest = NULL;
- if (der) {
- digest = ccdigest_copy_data(ccsha1_di(), CFDataGetLength(der), CFDataGetBytePtr(der), error);
- CFRelease(der);
- }
- return digest;
-}
-
-static CFDictionaryRef copyPropertyList(SOSObjectRef object, CFErrorRef *error) {
- return (CFDictionaryRef) CFRetain(object);
-}
-
-// Return the newest object
-static SOSObjectRef copyMergedObject(SOSObjectRef object1, SOSObjectRef object2, CFErrorRef *error) {
- CFDictionaryRef dict1 = (CFDictionaryRef)object1;
- CFDictionaryRef dict2 = (CFDictionaryRef)object2;
- SOSObjectRef result = NULL;
- CFDateRef m1, m2;
- m1 = CFDictionaryGetValue(dict1, kSecAttrModificationDate);
- m2 = CFDictionaryGetValue(dict2, kSecAttrModificationDate);
- switch (CFDateCompare(m1, m2, NULL)) {
- case kCFCompareGreaterThan:
- result = (SOSObjectRef)dict1;
- break;
- case kCFCompareLessThan:
- result = (SOSObjectRef)dict2;
- break;
- case kCFCompareEqualTo:
- {
- // Return the item with the smallest digest.
- CFDataRef digest1 = copyDigest(object1, error);
- CFDataRef digest2 = copyDigest(object2, error);
- if (digest1 && digest2) switch (CFDataCompare(digest1, digest2)) {
- case kCFCompareGreaterThan:
- case kCFCompareEqualTo:
- result = (SOSObjectRef)dict2;
- break;
- case kCFCompareLessThan:
- result = (SOSObjectRef)dict1;
- break;
- }
- CFReleaseSafe(digest2);
- CFReleaseSafe(digest1);
- break;
- }
- }
- CFRetainSafe(result);
- return result;
-}
-
-static SOSMergeResult mergeObject(SOSTransactionRef txn, SOSObjectRef object, SOSObjectRef *mergedObject, CFErrorRef *error) {
- SOSTestDataSourceRef ds = (SOSTestDataSourceRef)txn;
- SOSMergeResult mr = kSOSMergeFailure;
- CFDataRef pk = copyPrimaryKey(object, error);
- if (!pk) return mr;
- SOSObjectRef myObject = (SOSObjectRef)CFDictionaryGetValue(ds->p2database, pk);
- if (myObject) {
- SOSObjectRef merged = copyMergedObject(object, myObject, error);
- if (mergedObject) *mergedObject = CFRetainSafe(merged);
- if (CFEqualSafe(merged, myObject)) {
- mr = kSOSMergeLocalObject;
- } else if (CFEqualSafe(merged, object)) {
- mr = kSOSMergePeersObject;
- } else {
- mr = kSOSMergeCreatedObject;
- }
- if (mr != kSOSMergeLocalObject) {
- CFDataRef myKey = copyDigest(myObject, error);
- CFDictionaryRemoveValue(ds->d2database, myKey);
- CFReleaseSafe(myKey);
- CFDataRef key = copyDigest(merged, error);
- CFDictionarySetValue(ds->d2database, key, merged);
- const void *values[2] = { myObject, merged };
- CFTypeRef entry = CFArrayCreate(kCFAllocatorDefault, values, 2, &kCFTypeArrayCallBacks);
- if (entry) {
- CFArrayAppendValue(ds->changes, entry);
- CFRelease(entry);
- }
- CFReleaseSafe(key);
- CFDictionarySetValue(ds->p2database, pk, merged);
- }
- CFReleaseSafe(merged);
- } else {
- SOSTestDataSourceAddObject((SOSDataSourceRef)ds, object, error);
- mr = kSOSMergePeersObject;
- }
- CFReleaseSafe(pk);
- return mr;
-}
-
-static CFStringRef dsGetName(SOSDataSourceRef ds) {
- return CFSTR("The sky is made of butterflies");
-}
-
-static void dsAddNotifyPhaseBlock(SOSDataSourceRef ds, SOSDataSourceNotifyBlock notifyBlock) {
- SOSTestDataSourceRef tds = (SOSTestDataSourceRef)ds;
- assert(tds->notifyBlock == NULL);
- tds->notifyBlock = Block_copy(notifyBlock);
-}
-
-static CFDataRef dsCopyStateWithKey(SOSDataSourceRef ds, CFStringRef key, CFStringRef pdmn, SOSTransactionRef txn, CFErrorRef *error) {
- SOSTestDataSourceRef tds = (SOSTestDataSourceRef)ds;
- CFStringRef dbkey = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@-%@"), pdmn, key);
- CFDataRef state = CFDictionaryGetValue(tds->statedb, dbkey);
- CFReleaseSafe(dbkey);
- return CFRetainSafe(state);
-}
-
-static CFDataRef dsCopyItemDataWithKeys(SOSDataSourceRef data_source, CFDictionaryRef keys, CFErrorRef *error) {
- SecError(errSecUnimplemented, error, CFSTR("dsCopyItemDataWithKeys on test data source not implemented"));
- return NULL;
-}
-
-static bool dsWith(SOSDataSourceRef ds, CFErrorRef *error, SOSDataSourceTransactionSource source, bool onCommitQueue, void(^transaction)(SOSTransactionRef txn, bool *commit)) {
- SOSTestDataSourceRef tds = (SOSTestDataSourceRef)ds;
- bool commit = true;
- transaction((SOSTransactionRef)ds, &commit);
- if (commit && ((SOSTestDataSourceRef)ds)->notifyBlock && (CFArrayGetCount(tds->changes))) {
- ((SOSTestDataSourceRef)ds)->notifyBlock(ds, (SOSTransactionRef)ds, kSOSDataSourceTransactionWillCommit, source, tds->changes);
- CFArrayRemoveAllValues(tds->changes);
- }
- return true;
-}
-
-static bool dsReadWith(SOSDataSourceRef ds, CFErrorRef *error, SOSDataSourceTransactionSource source, void(^perform)(SOSTransactionRef txn)) {
- SOSTestDataSourceRef tds = (SOSTestDataSourceRef)ds;
- perform((SOSTransactionRef)tds);
- return true;
-}
-
-static bool dsSetStateWithKey(SOSDataSourceRef ds, SOSTransactionRef txn, CFStringRef key, CFStringRef pdmn, CFDataRef state, CFErrorRef *error) {
- SOSTestDataSourceRef tds = (SOSTestDataSourceRef)ds;
- CFStringRef dbkey = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@-%@"), pdmn, key);
- CFDictionarySetValue(tds->statedb, dbkey, state);
- CFReleaseSafe(dbkey);
- return true;
-}
-
-static bool dsRestoreObject(SOSTransactionRef txn, uint64_t handle, CFDictionaryRef item, CFErrorRef *error) {
- // TODO: Just call merge, probably doesn't belong in protocol at all
- assert(false);
- return true;
-}
-
-static CFDictionaryRef objectCopyBackup(SOSObjectRef object, uint64_t handle, CFErrorRef *error) {
- // OMG We failed without an error.
- assert(false);
- return NULL;
-}
-
-SOSDataSourceRef SOSTestDataSourceCreate(void) {
- SOSTestDataSourceRef ds = calloc(1, sizeof(struct SOSTestDataSource));
-
- ds->ds.engine = NULL;
- ds->ds.dsGetName = dsGetName;
- ds->ds.dsAddNotifyPhaseBlock = dsAddNotifyPhaseBlock;
- ds->ds.dsCopyManifestWithViewNameSet = dsCopyManifestWithViewNameSet;
- ds->ds.dsForEachObject = foreach_object;
- ds->ds.dsCopyStateWithKey = dsCopyStateWithKey;
- ds->ds.dsCopyItemDataWithKeys = dsCopyItemDataWithKeys;
-
- ds->ds.dsWith = dsWith;
- ds->ds.dsRelease = dispose;
- ds->ds.dsReadWith = dsReadWith;
-
- ds->ds.dsMergeObject = mergeObject;
- ds->ds.dsSetStateWithKey = dsSetStateWithKey;
- ds->ds.dsRestoreObject = dsRestoreObject;
-
- ds->ds.objectCopyDigest = copyDigest;
- ds->ds.objectCopyModDate = copyModDate;
- ds->ds.objectCreateWithPropertyList = createWithPropertyList;
- ds->ds.objectCopyPropertyList = copyPropertyList;
- ds->ds.objectCopyBackup = objectCopyBackup;
-
- ds->d2database = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- ds->p2database = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- ds->statedb = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- ds->clean = false;
- ds->changes = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
-
- return (SOSDataSourceRef)ds;
-}
-
-static CFStringRef SOSTestDataSourceFactoryCopyName(SOSDataSourceFactoryRef factory)
-{
- SOSTestDataSourceFactoryRef dsf = (SOSTestDataSourceFactoryRef) factory;
-
- __block CFStringRef result = NULL;
- CFDictionaryForEach(dsf->data_sources, ^(const void*key, const void*value) { if (isString(key)) result = key; });
-
- return CFRetainSafe(result);
-}
-
-static SOSDataSourceRef SOSTestDataSourceFactoryCreateDataSource(SOSDataSourceFactoryRef factory, CFStringRef dataSourceName, CFErrorRef *error)
-{
- SOSTestDataSourceFactoryRef dsf = (SOSTestDataSourceFactoryRef) factory;
-
- return (SOSDataSourceRef) CFDictionaryGetValue(dsf->data_sources, dataSourceName);
-}
-
-static void SOSTestDataSourceFactoryDispose(SOSDataSourceFactoryRef factory)
-{
- SOSTestDataSourceFactoryRef dsf = (SOSTestDataSourceFactoryRef) factory;
-
- CFReleaseNull(dsf->data_sources);
- free(dsf);
-}
-
-SOSDataSourceFactoryRef SOSTestDataSourceFactoryCreate() {
- SOSTestDataSourceFactoryRef dsf = calloc(1, sizeof(struct SOSTestDataSourceFactory));
-
- dsf->dsf.copy_name = SOSTestDataSourceFactoryCopyName;
- dsf->dsf.create_datasource = SOSTestDataSourceFactoryCreateDataSource;
- dsf->dsf.release = SOSTestDataSourceFactoryDispose;
- dsf->data_sources = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL);
-
- return &(dsf->dsf);
-}
-
-static bool do_nothing(SOSDataSourceRef ds, CFErrorRef *error) {
- return true;
-}
-
-void SOSTestDataSourceFactorySetDataSource(SOSDataSourceFactoryRef factory, CFStringRef name, SOSDataSourceRef ds)
-{
- SOSTestDataSourceFactoryRef dsf = (SOSTestDataSourceFactoryRef) factory;
-
- // TODO This hack sucks. It leaks now.
- ds->dsRelease = do_nothing;
-
- CFDictionaryRemoveAllValues(dsf->data_sources);
- CFDictionarySetValue(dsf->data_sources, name, ds);
-
-}
-
-SOSMergeResult SOSTestDataSourceAddObject(SOSDataSourceRef data_source, SOSObjectRef object, CFErrorRef *error) {
- struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source;
- bool result = false;
- CFDataRef key = copyDigest(object, error);
- CFDataRef pk = copyPrimaryKey(object, error);
- if (key && pk) {
- SOSObjectRef myObject = (SOSObjectRef)CFDictionaryGetValue(ds->p2database, pk);
- SOSObjectRef merged = NULL;
- if (myObject) {
- merged = copyMergedObject(object, myObject, error);
- } else {
- merged = object;
- CFRetain(merged);
- }
- if (merged) {
- result = true;
- if (!CFEqualSafe(merged, myObject)) {
- if (myObject) {
- CFDataRef myKey = copyDigest(myObject, error);
- CFDictionaryRemoveValue(ds->d2database, myKey);
- CFReleaseSafe(myKey);
- const void *values[2] = { myObject, merged };
- CFTypeRef entry = CFArrayCreate(kCFAllocatorDefault, values, 2, &kCFTypeArrayCallBacks);
- if (entry) {
- CFArrayAppendValue(ds->changes, entry);
- CFRelease(entry);
- }
- } else {
- CFArrayAppendValue(ds->changes, merged);
- }
- CFDictionarySetValue(ds->d2database, key, merged);
- CFDictionarySetValue(ds->p2database, pk, merged);
- ds->clean = false;
- }
- CFRelease(merged);
- }
- }
- CFReleaseSafe(pk);
- CFReleaseSafe(key);
- return result;
-}
-
-bool SOSTestDataSourceDeleteObject(SOSDataSourceRef data_source, CFDataRef key, CFErrorRef *error) {
- //struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source;
- return false;
-}
-
-CFMutableDictionaryRef SOSTestDataSourceGetDatabase(SOSDataSourceRef data_source) {
- struct SOSTestDataSource *ds = (struct SOSTestDataSource *)data_source;
- return ds->d2database;
-}
-
-// This works for any datasource, not just the test one, but it's only used in testcases, so it's here for now.
-SOSObjectRef SOSDataSourceCreateGenericItemWithData(SOSDataSourceRef ds, CFStringRef account, CFStringRef service, bool is_tomb, CFDataRef data) {
- int32_t value = 0;
- CFNumberRef zero = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value);
- value = 1;
- CFNumberRef one = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value);
- CFAbsoluteTime timestamp = 3700000 + (is_tomb ? 1 : 0);
- CFDateRef now = CFDateCreate(kCFAllocatorDefault, timestamp);
-
- CFDataRef defaultData = NULL;
- if (!is_tomb && !data) {
- defaultData = CFDataCreate(NULL, (UInt8*)"some data", 9);
- data = defaultData;
- }
- CFDictionaryRef dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
- kSecClass, kSecClassGenericPassword,
- kSecAttrSynchronizable, one,
- kSecAttrTombstone, is_tomb ? one : zero,
- kSecAttrAccount, account,
- kSecAttrService, service,
- kSecAttrCreationDate, now,
- kSecAttrModificationDate, now,
- kSecAttrAccessGroup, CFSTR("test"),
- kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked,
- !is_tomb && data ? kSecValueData : NULL,data,
- NULL);
- CFRelease(one);
- CFRelease(zero);
- CFReleaseSafe(now);
- CFReleaseNull(defaultData);
- CFErrorRef localError = NULL;
- SOSObjectRef object = ds->objectCreateWithPropertyList(dict, &localError);
- if (!object) {
- secerror("createWithPropertyList: %@ failed: %@", dict, localError);
- CFRelease(localError);
- }
- CFRelease(dict);
- return object;
-}
-
-SOSObjectRef SOSDataSourceCreateGenericItem(SOSDataSourceRef ds, CFStringRef account, CFStringRef service) {
- return SOSDataSourceCreateGenericItemWithData(ds, account, service, false, NULL);
-}
-
-SOSObjectRef SOSDataSourceCreateV0EngineStateWithData(SOSDataSourceRef ds, CFDataRef engineStateData) {
- /*
- MANGO-iPhone:~ mobile$ security item class=genp,acct=engine-state
- acct : engine-state
- agrp : com.apple.security.sos
- cdat : 2016-04-18 20:40:33 +0000
- mdat : 2016-04-18 20:40:33 +0000
- musr : //
- pdmn : dk
- svce : SOSDataSource-ak
- sync : 0
- tomb : 0
- */
- CFAbsoluteTime timestamp = 3700000;
- CFDateRef now = CFDateCreate(kCFAllocatorDefault, timestamp);
- CFDictionaryRef item = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
- kSecClass, kSecClassGenericPassword,
- kSecAttrSynchronizable, kCFBooleanFalse,
- kSecAttrTombstone, kCFBooleanFalse,
- kSecAttrAccount, CFSTR("engine-state"),
- kSecAttrService, CFSTR("SOSDataSource-ak"),
- kSecAttrCreationDate, now,
- kSecAttrModificationDate, now,
- kSecAttrAccessGroup, CFSTR("com.apple.security.sos"),
- kSecAttrAccessible, kSecAttrAccessibleAlwaysPrivate,
- engineStateData ? kSecValueData : NULL, engineStateData,
- NULL);
- CFReleaseSafe(now);
- CFErrorRef localError = NULL;
- SOSObjectRef object = ds->objectCreateWithPropertyList(item, &localError);
- if (!object) {
- secerror("createWithPropertyList: %@ failed: %@", item, localError);
- CFRelease(localError);
- }
- CFRelease(item);
- return object;
-}
-
-SOSObjectRef SOSDataSourceCopyObject(SOSDataSourceRef ds, SOSObjectRef match, CFErrorRef *error)
-{
- __block SOSObjectRef result = NULL;
-
- CFDataRef digest = SOSObjectCopyDigest(ds, match, error);
- SOSManifestRef manifest = NULL;
-
- require(digest, exit);
- manifest = SOSManifestCreateWithData(digest, error);
-
- SOSDataSourceForEachObject(ds, NULL, manifest, error, ^void (CFDataRef key, SOSObjectRef object, bool *stop) {
- if (object == NULL) {
- if (error && !*error) {
- SecCFCreateErrorWithFormat(kSOSDataSourceObjectNotFoundError, sSOSDataSourceErrorDomain, NULL, error, 0, CFSTR("key %@ not in database"), key);
- }
- } else if (result == NULL) {
- result = CFRetainSafe(object);
- }
- });
-
-exit:
- CFReleaseNull(manifest);
- CFReleaseNull(digest);
- return result;
-}