]> git.saurik.com Git - apple/security.git/blobdiff - OSX/sec/SOSCircle/SecureObjectSync/SOSAccountGetSet.c
Security-57740.51.3.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / SecureObjectSync / SOSAccountGetSet.c
diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountGetSet.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountGetSet.c
new file mode 100644 (file)
index 0000000..397b505
--- /dev/null
@@ -0,0 +1,105 @@
+//
+//  SOSAccountGetSet.c
+//  Security
+//
+//
+
+#include "SOSAccountPriv.h"
+
+#include <utilities/SecCFWrappers.h>
+
+//
+// MARK: Generic Value manipulation
+//
+
+static inline bool SOSAccountEnsureExpansion(SOSAccountRef account, CFErrorRef *error) {
+    if (!account->expansion) {
+        account->expansion = CFDictionaryCreateMutableForCFTypes(NULL);
+    }
+
+    return SecAllocationError(account->expansion, error, CFSTR("Can't Alloc Account Expansion dictionary"));
+}
+
+bool SOSAccountClearValue(SOSAccountRef account, CFStringRef key, CFErrorRef *error) {
+    bool success = SOSAccountEnsureExpansion(account, error);
+    require_quiet(success, errOut);
+
+    CFDictionaryRemoveValue(account->expansion, key);
+errOut:
+    return success;
+}
+
+bool SOSAccountSetValue(SOSAccountRef account, CFStringRef key, CFTypeRef value, CFErrorRef *error) {
+    if (value == NULL) return SOSAccountClearValue(account, key, error);
+
+    bool success = SOSAccountEnsureExpansion(account, error);
+    require_quiet(success, errOut);
+
+    CFDictionarySetValue(account->expansion, key, value);
+errOut:
+    return success;
+}
+
+CFTypeRef SOSAccountGetValue(SOSAccountRef account, CFStringRef key, CFErrorRef *error) {
+    if (!account->expansion) {
+        return NULL;
+    }
+    return CFDictionaryGetValue(account->expansion, key);
+}
+
+
+//
+// MARK: Value as Set manipulation
+//
+bool SOSAccountValueSetContainsValue(SOSAccountRef account, CFStringRef key, CFTypeRef value);
+void SOSAccountValueUnionWith(SOSAccountRef account, CFStringRef key, CFSetRef valuesToUnion);
+void SOSAccountValueSubtractFrom(SOSAccountRef account, CFStringRef key, CFSetRef valuesToSubtract);
+
+bool SOSAccountValueSetContainsValue(SOSAccountRef account, CFStringRef key, CFTypeRef value) {
+    CFSetRef foundSet = asSet(SOSAccountGetValue(account, key, NULL), NULL);
+    return foundSet && CFSetContainsValue(foundSet, value);
+}
+
+void SOSAccountValueUnionWith(SOSAccountRef account, CFStringRef key, CFSetRef valuesToUnion) {
+    CFMutableSetRef unionedSet = CFSetCreateMutableCopy(kCFAllocatorDefault, 0, valuesToUnion);
+    CFSetRef foundSet = asSet(SOSAccountGetValue(account, key, NULL), NULL);
+    if (foundSet) {
+        CFSetUnion(unionedSet, foundSet);
+    }
+    SOSAccountSetValue(account, key, unionedSet, NULL);
+    CFReleaseNull(unionedSet);
+}
+
+void SOSAccountValueSubtractFrom(SOSAccountRef account, CFStringRef key, CFSetRef valuesToSubtract) {
+    CFSetRef foundSet = asSet(SOSAccountGetValue(account, key, NULL), NULL);
+    if (foundSet) {
+        CFMutableSetRef subtractedSet = CFSetCreateMutableCopy(kCFAllocatorDefault, 0, foundSet);
+        CFSetSubtract(subtractedSet, valuesToSubtract);
+        SOSAccountSetValue(account, key, subtractedSet, NULL);
+        CFReleaseNull(subtractedSet);
+    }
+}
+
+//
+// MARK: UUID
+CFStringRef SOSAccountCopyUUID(SOSAccountRef account) {
+    CFStringRef uuid = CFRetainSafe(asString(SOSAccountGetValue(account, kSOSAccountUUID, NULL), NULL));
+    if (uuid == NULL) {
+        CFUUIDRef newID = CFUUIDCreate(kCFAllocatorDefault);
+        uuid = CFUUIDCreateString(kCFAllocatorDefault, newID);
+
+        CFErrorRef setError = NULL;
+        if (!SOSAccountSetValue(account, kSOSAccountUUID, uuid, &setError)) {
+            secerror("Failed to set UUID: %@ (%@)", uuid, setError);
+        }
+        CFReleaseNull(setError);
+        CFReleaseNull(newID);
+    }
+    return uuid;
+}
+
+void SOSAccountEnsureUUID(SOSAccountRef account) {
+    CFStringRef uuid = SOSAccountCopyUUID(account);
+    CFReleaseNull(uuid);
+}
+