]> git.saurik.com Git - apple/security.git/blobdiff - Security/sec/securityd/Regressions/SOSAccountTesting.h
Security-57031.1.35.tar.gz
[apple/security.git] / Security / sec / securityd / Regressions / SOSAccountTesting.h
diff --git a/Security/sec/securityd/Regressions/SOSAccountTesting.h b/Security/sec/securityd/Regressions/SOSAccountTesting.h
new file mode 100644 (file)
index 0000000..569066d
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 2013-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@
+ */
+
+
+#ifndef SEC_SOSAccountTesting_h
+#define SEC_SOSAccountTesting_h
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SecureObjectSync/SOSAccount.h>
+#include <SecureObjectSync/SOSAccountPriv.h>
+#include <SecureObjectSync/SOSTransport.h>
+#include "SOSTransportTestTransports.h"
+//
+// Account comparison
+//
+
+#define kAccountsAgreeTestMin 9
+#define kAccountsAgreeTestPerPeer 1
+#define accountsAgree(x) (kAccountsAgreeTestMin + kAccountsAgreeTestPerPeer * (x))
+
+
+static SOSAccountRef SOSAccountCreateBasicTest(CFAllocatorRef allocator,
+                                               CFStringRef accountName,
+                                               CFDictionaryRef gestalt,
+                                               SOSDataSourceFactoryRef factory) {
+    SOSAccountRef a = SOSAccountCreateBasic(allocator, gestalt, factory);
+    
+    return a;
+}
+
+static SOSAccountRef SOSAccountCreateTest(CFAllocatorRef allocator,
+                                          CFStringRef accountName,
+                                          CFDictionaryRef gestalt,
+                                          SOSDataSourceFactoryRef factory) {
+    SOSAccountRef a = SOSAccountCreateBasicTest(allocator, accountName, gestalt, factory);
+    
+    a->retired_peers = CFDictionaryCreateMutableForCFTypes(allocator);
+    SOSUnregisterTransportKeyParameter(a->key_transport);
+
+    CFReleaseNull(a->circle_transports);
+    CFReleaseNull(a->message_transports);
+    CFReleaseNull(a->key_transport);
+
+    SOSAccountEnsureFactoryCirclesTest(a, accountName);
+    
+    return a;
+}
+
+
+static void unretired_peers_is_subset(const char* label, CFArrayRef peers, CFArrayRef allowed_peers)
+{
+    CFArrayForEach(peers, ^(const void *value) {
+        SOSPeerInfoRef pi = (SOSPeerInfoRef) value;
+        CFErrorRef leftError = NULL;
+        CFErrorRef rightError = NULL;
+        
+        ok(SOSPeerInfoIsRetirementTicket(pi) || SOSPeerInfoIsCloudIdentity(pi) || CFArrayContainsValue(allowed_peers, CFRangeMake(0, CFArrayGetCount(allowed_peers)), pi), "Peer is allowed (%s) Peer: %@, Allowed %@", label, pi, allowed_peers);
+        
+        CFReleaseNull(leftError);
+        CFReleaseNull(rightError);
+    });
+}
+
+static void accounts_agree_internal(char *label, SOSAccountRef left, SOSAccountRef right, bool check_peers)
+{
+    CFErrorRef error = NULL;
+    {
+        CFArrayRef leftPeers = SOSAccountCopyActivePeers(left, &error);
+        ok(leftPeers, "Left peers (%@) - %s", error, label);
+        CFReleaseNull(error);
+
+        CFArrayRef rightPeers = SOSAccountCopyActivePeers(right, &error);
+        ok(rightPeers, "Right peers (%@) - %s", error, label);
+        CFReleaseNull(error);
+
+        ok(CFEqual(leftPeers, rightPeers), "Matching peers (%s) Left: %@, Right: %@", label, leftPeers, rightPeers);
+
+        if (check_peers) {
+            CFMutableArrayRef allowed_identities = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
+
+            CFArrayRef leftIdentities = SOSAccountCopyAccountIdentityPeerInfos(left, kCFAllocatorDefault, &error);
+            ok(leftIdentities, "Get identities (%@)", error);
+            CFReleaseNull(error);
+            
+            CFArrayAppendArray(allowed_identities, leftIdentities, CFRangeMake(0, CFArrayGetCount(leftIdentities)));
+            
+            CFReleaseNull(leftIdentities);
+            
+            CFArrayRef rightIdentities = SOSAccountCopyAccountIdentityPeerInfos(right, kCFAllocatorDefault, &error);
+            ok(rightIdentities, "Get identities (%@)", error);
+            CFReleaseNull(error);
+            
+            CFArrayAppendArray(allowed_identities, rightIdentities, CFRangeMake(0, CFArrayGetCount(rightIdentities)));
+            
+            CFReleaseNull(rightIdentities);
+
+            unretired_peers_is_subset(label, leftPeers, allowed_identities);
+        }
+
+        CFReleaseNull(leftPeers);
+        CFReleaseNull(rightPeers);
+    }
+    {
+        CFArrayRef leftConcurringPeers = SOSAccountCopyConcurringPeers(left, &error);
+        ok(leftConcurringPeers, "Left peers (%@) - %s", error, label);
+
+        CFArrayRef rightConcurringPeers = SOSAccountCopyConcurringPeers(right, &error);
+        ok(rightConcurringPeers, "Right peers (%@) - %s", error, label);
+
+        ok(CFEqual(leftConcurringPeers, rightConcurringPeers), "Matching concurring peers Left: %@, Right: %@", leftConcurringPeers, rightConcurringPeers);
+
+        CFReleaseNull(leftConcurringPeers);
+        CFReleaseNull(rightConcurringPeers);
+    }
+    {
+        CFArrayRef leftApplicants = SOSAccountCopyApplicants(left, &error);
+        ok(leftApplicants, "Left Applicants (%@) - %s", error, label);
+
+        CFArrayRef rightApplicants = SOSAccountCopyApplicants(right, &error);
+        ok(rightApplicants, "Left Applicants (%@) - %s", error, label);
+
+        ok(CFEqual(leftApplicants, rightApplicants), "Matching applicants (%s) Left: %@, Right: %@", label, leftApplicants, rightApplicants);
+
+        CFReleaseNull(leftApplicants);
+        CFReleaseNull(rightApplicants);
+    }
+}
+
+static inline void accounts_agree(char *label, SOSAccountRef left, SOSAccountRef right)
+{
+    accounts_agree_internal(label, left, right, true);
+}
+
+
+//
+// Change handling
+//
+
+static void CFDictionaryOverlayDictionary(CFMutableDictionaryRef target, CFDictionaryRef overlay) {
+    CFDictionaryForEach(overlay, ^(const void *key, const void *value) {
+        CFDictionarySetValue(target, key, value);
+    });
+}
+
+static void CFArrayAppendKeys(CFMutableArrayRef keys, CFDictionaryRef newKeysToAdd) {
+    CFDictionaryForEach(newKeysToAdd, ^(const void *key, const void *value) {
+        CFArrayAppendValue(keys, key);
+    });
+}
+
+static bool AddNewChanges(CFMutableDictionaryRef changesRecord, CFMutableDictionaryRef newKeysAndValues, SOSAccountRef sender)
+{
+    __block bool changes_added = false;
+    CFMutableDictionaryRef emptyDictionary = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
+    CFDictionaryAddValue(changesRecord, kCFNull, emptyDictionary);
+    CFReleaseNull(emptyDictionary);
+
+    CFDictionaryOverlayDictionary((CFMutableDictionaryRef) CFDictionaryGetValue(changesRecord, kCFNull), newKeysAndValues);
+
+    CFDictionaryForEach(changesRecord, ^(const void *key, const void *value) {
+        if (isArray(value) && (sender == NULL || !CFEqual(sender, key))) {
+            CFArrayAppendKeys((CFMutableArrayRef) value, newKeysAndValues);
+            if (CFDictionaryGetCount(newKeysAndValues))
+                changes_added = true;
+        }
+    });
+
+    CFDictionaryRemoveAllValues(newKeysAndValues);
+
+    return changes_added;
+}
+
+static bool FillAllChanges(CFMutableDictionaryRef changes) {
+    __block bool changed = false;
+    CFArrayForEach(key_transports, ^(const void *value) {
+        SOSTransportKeyParameterTestRef tpt = (SOSTransportKeyParameterTestRef) value;
+        changed |= AddNewChanges(changes, SOSTransportKeyParameterTestGetChanges(tpt), SOSTransportKeyParameterTestGetAccount(tpt));
+    });
+    CFArrayForEach(circle_transports, ^(const void *value) {
+        SOSTransportCircleTestRef tpt = (SOSTransportCircleTestRef) value;
+        changed |= AddNewChanges(changes, SOSTransportCircleTestGetChanges(tpt), SOSTransportCircleTestGetAccount(tpt));
+    });
+    CFArrayForEach(message_transports, ^(const void *value) {
+        SOSTransportMessageTestRef tpt = (SOSTransportMessageTestRef) value;
+        CFDictionaryRemoveValue(SOSTransportMessageTestGetChanges(tpt), kCFNull);
+        changed |=AddNewChanges(changes, SOSTransportMessageTestGetChanges(tpt), SOSTransportMessageTestGetAccount(tpt));
+    });
+
+    return changed;
+}
+
+static void FillChanges(CFMutableDictionaryRef changes, SOSAccountRef forAccount)
+{
+    CFArrayForEach(key_transports, ^(const void *value) {
+        SOSTransportKeyParameterTestRef tpt = (SOSTransportKeyParameterTestRef) value;
+        if(CFEqualSafe(forAccount, SOSTransportKeyParameterTestGetAccount(tpt))){
+            AddNewChanges(changes, SOSTransportKeyParameterTestGetChanges(tpt), SOSTransportKeyParameterTestGetAccount(tpt));
+        }
+    });
+    CFArrayForEach(circle_transports, ^(const void *value) {
+        SOSTransportCircleTestRef tpt = (SOSTransportCircleTestRef) value;
+        if(CFEqualSafe(forAccount, SOSTransportCircleTestGetAccount(tpt))){
+            AddNewChanges(changes, SOSTransportCircleTestGetChanges(tpt), SOSTransportCircleTestGetAccount(tpt));
+        }
+    });
+    CFArrayForEach(message_transports, ^(const void *value) {
+        SOSTransportMessageTestRef tpt = (SOSTransportMessageTestRef) value;
+        if(CFEqualSafe(forAccount, SOSTransportMessageTestGetAccount(tpt))){
+            CFDictionaryRemoveValue(SOSTransportMessageTestGetChanges(tpt), kCFNull);
+            AddNewChanges(changes, SOSTransportMessageTestGetChanges(tpt), SOSTransportMessageTestGetAccount(tpt));
+        }
+    });
+
+}
+
+static inline void FillChangesMulti(CFMutableDictionaryRef changes, SOSAccountRef account, ...)
+{
+    SOSAccountRef next_account = account;
+    va_list argp;
+    va_start(argp, account);
+    while(next_account != NULL) {
+        FillChanges(changes, next_account);
+        next_account = va_arg(argp, SOSAccountRef);
+    }
+}
+
+static inline CFMutableArrayRef CFDictionaryCopyKeys(CFDictionaryRef dictionary)
+{
+    CFMutableArrayRef result = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
+
+    CFArrayAppendKeys(result, dictionary);
+
+    return result;
+}
+
+#define kFeedChangesToTestCount 1
+static inline void FeedChangesTo(CFMutableDictionaryRef changes, SOSAccountRef account)
+{
+    CFDictionaryRef full_list = (CFDictionaryRef) CFDictionaryGetValue(changes, kCFNull);
+
+    if (!isDictionary(full_list))
+        return; // Nothing recorded to send!
+
+    CFMutableArrayRef account_pending_keys = (CFMutableArrayRef)CFDictionaryGetValue(changes, account);
+    if (!isArray(account_pending_keys)) {
+        CFReleaseNull(account_pending_keys);
+
+        account_pending_keys = CFDictionaryCopyKeys(full_list);
+        CFDictionaryAddValue(changes, account, account_pending_keys);
+        CFReleaseSafe(account_pending_keys); // The dictionary keeps it, we don't retain it here.
+    }
+
+    CFMutableArrayRef handled = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
+
+    secerror("Changes for %@: %@", SOSTransportKeyParameterTestGetName((SOSTransportKeyParameterTestRef) account->key_transport), account_pending_keys);
+
+    CFErrorRef error = NULL;
+    CFMutableDictionaryRef account_pending_messages = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
+    CFArrayForEach(account_pending_keys, ^(const void *value) {
+        CFDictionaryAddValue(account_pending_messages, value, CFDictionaryGetValue(full_list, value));
+    });
+    
+    ok(handled = SOSTransportDispatchMessages(account, account_pending_messages, &error), "SOSTransportHandleMessages failed (%@)", error);
+    
+    if (isArray(handled)) {
+        CFArrayForEach(handled, ^(const void *value) {
+            CFArrayRemoveAllValue(account_pending_keys, value);
+        });
+    }
+    
+    CFReleaseNull(handled);
+    CFReleaseNull(error);
+}
+
+#define kFeedChangesToMultieTestCountPer 1
+
+static inline void FeedChangesToMultiV(CFMutableDictionaryRef changes, va_list argp)
+{
+    SOSAccountRef account = NULL;
+    while((account = va_arg(argp, SOSAccountRef)) != NULL) {
+        FeedChangesTo(changes, account);
+    }
+}
+
+static inline void FeedChangesToMulti(CFMutableDictionaryRef changes, ...)
+{
+    va_list argp;
+    va_start(argp, changes);
+
+    FeedChangesToMultiV(changes, argp);
+
+    va_end(argp);
+}
+
+static inline void InjectChangeToMulti(CFMutableDictionaryRef changes,
+                                       CFStringRef changeKey, CFTypeRef changeValue, ...)
+{
+    CFMutableDictionaryRef changes_to_send = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault,
+                                                                                     changeKey, changeValue,
+                                                                                     NULL);
+    AddNewChanges(changes, changes_to_send, NULL);
+    CFReleaseNull(changes_to_send);
+
+    va_list argp;
+    va_start(argp, changeValue);
+    FeedChangesToMultiV(changes, argp);
+
+}
+
+
+static inline bool ProcessChangesOnceV(CFMutableDictionaryRef changes, va_list argp)
+{
+    bool result = FillAllChanges(changes);
+
+    FeedChangesToMultiV(changes, argp);
+
+    return result;
+}
+
+
+static inline bool ProcessChangesOnce(CFMutableDictionaryRef changes, ...)
+{
+    va_list argp;
+    va_start(argp, changes);
+
+    bool result = ProcessChangesOnceV(changes, argp);
+
+    va_end(argp);
+
+    return result;
+}
+
+static inline int ProcessChangesUntilNoChange(CFMutableDictionaryRef changes, ...)
+{
+    va_list argp;
+    va_start(argp, changes);
+
+    int result = 0;
+    bool new_data = false;
+    do {
+        va_list argp_copy;
+        va_copy(argp_copy, argp);
+
+        new_data = ProcessChangesOnceV(changes, argp_copy);
+
+        ++result;
+
+        va_end(argp_copy);
+    } while (new_data);
+    
+    va_end(argp);
+    
+    return result;
+    
+}
+
+//
+// MARK: Account creation
+//
+
+static SOSAccountRef CreateAccountForLocalChanges(CFStringRef name, CFStringRef data_source_name)
+{
+    SOSDataSourceFactoryRef factory = SOSTestDataSourceFactoryCreate();
+    SOSDataSourceRef ds = SOSTestDataSourceCreate();
+    SOSTestDataSourceFactoryAddDataSource(factory, data_source_name, ds);
+    SOSEngineRef engine = SOSEngineCreate(ds, NULL);
+    ds->engine = engine;
+    CFDictionaryRef gestalt = SOSCreatePeerGestaltFromName(name);
+
+    SOSAccountRef result = SOSAccountCreateTest(kCFAllocatorDefault, name, gestalt, factory);
+
+    CFReleaseNull(gestalt);
+
+    return result;
+}
+
+
+static inline int countPeers(SOSAccountRef account) {
+    CFErrorRef error = NULL;
+    CFArrayRef peers;
+    
+    peers = SOSAccountCopyPeers(account, &error);
+    int retval = (int) CFArrayGetCount(peers);
+    CFReleaseNull(error);
+    CFReleaseNull(peers);
+    return retval;
+}
+
+static inline int countActivePeers(SOSAccountRef account) {
+    CFErrorRef error = NULL;
+    CFArrayRef peers;
+    
+    peers = SOSAccountCopyActivePeers(account, &error);
+    int retval = (int) CFArrayGetCount(peers);
+    CFReleaseNull(error);
+    CFReleaseNull(peers);
+    return retval;
+}
+
+static inline int countActiveValidPeers(SOSAccountRef account) {
+    CFErrorRef error = NULL;
+    CFArrayRef peers;
+    
+    peers = SOSAccountCopyActiveValidPeers(account, &error);
+    int retval = (int) CFArrayGetCount(peers);
+    CFReleaseNull(error);
+    CFReleaseNull(peers);
+    return retval;
+}
+
+static inline int countApplicants(SOSAccountRef account) {
+    CFErrorRef error = NULL;
+    CFArrayRef applicants = SOSAccountCopyApplicants(account, &error);
+    int retval = 0;
+    
+    if(applicants) retval = (int)CFArrayGetCount(applicants);
+    CFReleaseNull(error);
+    CFReleaseNull(applicants);
+    return retval;
+}
+
+
+static inline void showActiveValidPeers(SOSAccountRef account) {
+    CFErrorRef error = NULL;
+    CFArrayRef peers;
+    
+    peers = SOSAccountCopyActiveValidPeers(account, &error);
+    CFArrayForEach(peers, ^(const void *value) {
+        SOSPeerInfoRef pi = (SOSPeerInfoRef) value;
+        ok(0, "Active Valid Peer %@", pi);
+    });
+    CFReleaseNull(peers);
+}
+
+#endif