]> git.saurik.com Git - apple/security.git/blobdiff - OSX/sec/SOSCircle/CKBridge/SOSCloudKeychainLogging.c
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / sec / SOSCircle / CKBridge / SOSCloudKeychainLogging.c
diff --git a/OSX/sec/SOSCircle/CKBridge/SOSCloudKeychainLogging.c b/OSX/sec/SOSCircle/CKBridge/SOSCloudKeychainLogging.c
new file mode 100644 (file)
index 0000000..066e05e
--- /dev/null
@@ -0,0 +1,222 @@
+//
+//  SOSCloudKeychainLogging.c
+//  sec
+//
+//  Created by Richard Murphy on 6/21/16.
+//
+//
+
+#include <AssertMacros.h>
+#include <CoreFoundation/CoreFoundation.h>
+//#include <syslog.h>
+//#include <os/activity.h>
+#include <utilities/debugging.h>
+#include <utilities/SecCFWrappers.h>
+#include <utilities/SecXPCError.h>
+#include "SOSCloudKeychainConstants.h"
+#include "SOSCloudKeychainClient.h"
+#include "SOSKVSKeys.h"
+#include "SOSUserKeygen.h"
+#include "SecOTRSession.h"
+#include "SOSCloudKeychainLogging.h"
+
+
+#define DATE_LENGTH 18
+
+#define KVSLOGSTATE "kvsLogState"
+
+static CFStringRef SOSCloudKVSCreateDateFromValue(CFDataRef valueAsData) {
+    CFStringRef dateString = NULL;
+    CFDataRef dateData = CFDataCreateCopyFromRange(kCFAllocatorDefault, valueAsData, CFRangeMake(0, DATE_LENGTH));
+    require_quiet(dateData, retOut);
+    dateString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, dateData, kCFStringEncodingUTF8);
+    CFReleaseNull(dateData);
+retOut:
+    return dateString;
+}
+
+static CFDataRef SOSCloudKVSCreateDataFromValueAfterDate(CFDataRef valueAsData) {
+    return CFDataCreateCopyFromPositions(kCFAllocatorDefault, valueAsData, DATE_LENGTH, CFDataGetLength(valueAsData));
+}
+
+static void SOSCloudKVSLogCircle(CFTypeRef key, CFStringRef dateString, CFTypeRef value) {
+    if(!isData(value)) return;
+    SOSCircleRef circle = SOSCircleCreateFromData(NULL, value, NULL);
+    require_quiet(circle, retOut);
+    secnotice(KVSLOGSTATE, "%@ %@:", key, dateString);
+    SOSCircleLogState(KVSLOGSTATE, circle, NULL, NULL);
+    CFReleaseSafe(circle);
+retOut:
+    return;
+}
+
+static void SOSCloudKVSLogLastCircle(CFTypeRef key, CFTypeRef value) {
+    if(!isData(value)) return;
+    CFStringRef circle = NULL;
+    CFStringRef from = NULL;
+    CFStringRef peerID = CFSTR("        ");
+    bool parsed = SOSKVSKeyParse(kLastCircleKey, key, &circle, NULL, NULL, NULL, &from, NULL);
+    if(parsed) {
+        peerID = from;
+    }
+    CFStringRef speerID = CFStringCreateTruncatedCopy(peerID, 8);
+    CFStringRef dateString = SOSCloudKVSCreateDateFromValue(value);
+    CFDataRef circleData = SOSCloudKVSCreateDataFromValueAfterDate(value);
+    CFStringRef keyPrefix = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ from %@: "), circle, speerID);
+    SOSCloudKVSLogCircle(keyPrefix, dateString, circleData);
+    CFReleaseNull(keyPrefix);
+    CFReleaseNull(speerID);
+    CFReleaseNull(from);
+    CFReleaseNull(dateString);
+    CFReleaseNull(circleData);
+}
+
+static void SOSCloudKVSLogKeyParameters(CFTypeRef key, CFStringRef dateString, CFTypeRef value) {
+    if(!isData(value)) return;
+    CFStringRef keyParameterDescription = UserParametersDescription(value);
+    if(!keyParameterDescription) keyParameterDescription = CFDataCopyHexString(value);
+    secnotice(KVSLOGSTATE, "%@: %@: %@", key, dateString, keyParameterDescription);
+    CFReleaseNull(keyParameterDescription);
+}
+
+static void SOSCloudKVSLogLastKeyParameters(CFTypeRef key, CFTypeRef value) {
+    if(!isData(value)) return;
+    CFStringRef from = NULL;
+    CFStringRef peerID = CFSTR("        ");
+    bool parsed = SOSKVSKeyParse(kLastKeyParameterKey, key, NULL, NULL, NULL, NULL, &from, NULL);
+    if(parsed) {
+        peerID = from;
+    }
+    CFStringRef speerID = CFStringCreateTruncatedCopy(peerID, 8);
+    CFDataRef keyParameterData = SOSCloudKVSCreateDataFromValueAfterDate(value);
+    CFStringRef dateString = SOSCloudKVSCreateDateFromValue(value);
+    CFStringRef keyPrefix = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("k%@ from %@: "), kSOSKVSKeyParametersKey, speerID);
+
+    SOSCloudKVSLogKeyParameters(keyPrefix, dateString, keyParameterData);
+    CFReleaseNull(keyPrefix);
+    CFReleaseNull(speerID);
+    CFReleaseNull(dateString);
+    CFReleaseNull(from);
+    CFReleaseNull(keyParameterData);
+}
+
+static void SOSCloudKVSLogMessage(CFTypeRef key, CFTypeRef value) {
+    CFStringRef circle = NULL;
+    CFStringRef from = NULL;
+    CFStringRef to = NULL;
+    bool parsed = SOSKVSKeyParse(kMessageKey, key, &circle, NULL, NULL, NULL, &from, &to);
+    if(parsed) {
+        CFStringRef sfrom = CFStringCreateTruncatedCopy(from, 8);
+        CFStringRef sto = CFStringCreateTruncatedCopy(to, 8);
+        if(isData(value)){
+            const char* messageType = SecOTRPacketTypeString(value);
+            secnotice(KVSLOGSTATE, "message packet from: %@ to: %@ : %s: %ld", sfrom, sto, messageType, CFDataGetLength(value));
+        } else {
+            secnotice(KVSLOGSTATE, "message packet from: %@ to: %@: %@", sfrom, sto, value);
+        }
+        CFReleaseNull(sfrom);
+        CFReleaseNull(sto);
+    } else {
+        secnotice(KVSLOGSTATE, "%@: %@", key, value);
+    }
+    CFReleaseNull(circle);
+    CFReleaseNull(from);
+    CFReleaseNull(to);
+}
+
+static void SOSCloudKVSLogRetirement(CFTypeRef key, CFTypeRef value) {
+    CFStringRef circle = NULL;
+    CFStringRef from = NULL;
+    bool parsed = SOSKVSKeyParse(kRetirementKey, key, &circle, NULL, NULL, NULL, &from, NULL);
+    if(parsed) {
+        CFStringRef sfrom = CFStringCreateTruncatedCopy(from, 8);
+        secnotice(KVSLOGSTATE, "Retired Peer: %@, from Circle: %@", sfrom, circle);
+        CFReleaseNull(sfrom);
+    } else {
+        secnotice(KVSLOGSTATE, "Retired Peer format unknown - %@", key);
+    }
+    CFReleaseNull(circle);
+    CFReleaseNull(from);
+}
+
+static void SOSCloudKVSLogKeyType(CFTypeRef key, CFTypeRef value, SOSKVSKeyType type){
+    switch (type) {
+        case kCircleKey:
+            SOSCloudKVSLogCircle(key, CFSTR("     Current     "), value);
+            break;
+        case kRetirementKey:
+            SOSCloudKVSLogRetirement(key, value);
+            break;
+        case kMessageKey:
+            SOSCloudKVSLogMessage(key, value);
+            break;
+        case kParametersKey:
+            SOSCloudKVSLogKeyParameters(key, CFSTR("     Current     "), value);
+            break;
+        case kLastKeyParameterKey:
+            SOSCloudKVSLogLastKeyParameters(key, value);
+            break;
+        case kLastCircleKey:
+            SOSCloudKVSLogLastCircle(key, value);
+            break;
+        case kInitialSyncKey:
+        case kAccountChangedKey:
+        case kDebugInfoKey:
+        case kRingKey:
+        case kPeerInfoKey:
+        default:
+            break;
+    }
+}
+
+void SOSCloudKVSLogState(void) {
+    static int ordering[] = {
+        kParametersKey,
+        kLastKeyParameterKey,
+        kCircleKey,
+        kLastCircleKey,
+        kRetirementKey,
+        kMessageKey,
+        kInitialSyncKey,
+        kAccountChangedKey,
+        kDebugInfoKey,
+        kRingKey,
+        kPeerInfoKey,
+        kUnknownKey,
+    };
+    dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
+    dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, 10ull * NSEC_PER_SEC);
+    static volatile bool inUse = false; // Don't let log attempts stack
+
+    if(!inUse) {
+        inUse = true;
+        dispatch_retain(waitSemaphore);
+        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+                CFDictionaryRef kvsDictionary = SOSCloudCopyKVSState();
+                if(kvsDictionary){
+                    secnotice(KVSLOGSTATE, "Start");
+                    // if we have anything to log - do it here.
+                    for (size_t i = 0; i < (sizeof(ordering) / sizeof(SOSKVSKeyType)); i++){
+                        CFDictionaryForEach(kvsDictionary, ^(const void *key, const void *value) {
+                            if(SOSKVSKeyGetKeyType(key) == ordering[i]){
+                                SOSCloudKVSLogKeyType(key, value, ordering[i]);
+                            }
+                        });
+                    }
+                    secnotice(KVSLOGSTATE, "Finish");
+                    CFReleaseNull(kvsDictionary);
+                } else{
+                    secnotice(KVSLOGSTATE, "dictionary from KVS is NULL");
+                }
+
+            inUse=false;
+            dispatch_semaphore_signal(waitSemaphore);
+            dispatch_release(waitSemaphore);
+        });
+    }
+
+    dispatch_semaphore_wait(waitSemaphore, finishTime);
+    dispatch_release(waitSemaphore);
+    
+}
+