2 // SOSCloudKeychainLogging.c
5 // Created by Richard Murphy on 6/21/16.
9 #include <AssertMacros.h>
10 #include <CoreFoundation/CoreFoundation.h>
12 //#include <os/activity.h>
13 #include <utilities/debugging.h>
14 #include <utilities/SecCFWrappers.h>
15 #include <utilities/SecXPCError.h>
16 #include "SOSCloudKeychainConstants.h"
17 #include "SOSCloudKeychainClient.h"
18 #include "SOSKVSKeys.h"
19 #include "SOSUserKeygen.h"
20 #include "SecOTRSession.h"
21 #include "SOSCloudKeychainLogging.h"
24 #define DATE_LENGTH 18
26 #define KVSLOGSTATE "kvsLogState"
28 static CFStringRef
SOSCloudKVSCreateDateFromValue(CFDataRef valueAsData
) {
29 CFStringRef dateString
= NULL
;
30 CFDataRef dateData
= CFDataCreateCopyFromRange(kCFAllocatorDefault
, valueAsData
, CFRangeMake(0, DATE_LENGTH
));
31 require_quiet(dateData
, retOut
);
32 dateString
= CFStringCreateFromExternalRepresentation(kCFAllocatorDefault
, dateData
, kCFStringEncodingUTF8
);
33 CFReleaseNull(dateData
);
38 static CFDataRef
SOSCloudKVSCreateDataFromValueAfterDate(CFDataRef valueAsData
) {
39 return CFDataCreateCopyFromPositions(kCFAllocatorDefault
, valueAsData
, DATE_LENGTH
, CFDataGetLength(valueAsData
));
42 static void SOSCloudKVSLogCircle(CFTypeRef key
, CFStringRef dateString
, CFTypeRef value
) {
43 if(!isData(value
)) return;
44 SOSCircleRef circle
= SOSCircleCreateFromData(NULL
, value
, NULL
);
45 require_quiet(circle
, retOut
);
46 secnotice(KVSLOGSTATE
, "%@ %@:", key
, dateString
);
47 SOSCircleLogState(KVSLOGSTATE
, circle
, NULL
, NULL
);
48 CFReleaseSafe(circle
);
53 static void SOSCloudKVSLogLastCircle(CFTypeRef key
, CFTypeRef value
) {
54 if(!isData(value
)) return;
55 CFStringRef circle
= NULL
;
56 CFStringRef from
= NULL
;
57 CFStringRef peerID
= CFSTR(" ");
58 bool parsed
= SOSKVSKeyParse(kLastCircleKey
, key
, &circle
, NULL
, NULL
, NULL
, &from
, NULL
);
62 CFStringRef speerID
= CFStringCreateTruncatedCopy(peerID
, 8);
63 CFStringRef dateString
= SOSCloudKVSCreateDateFromValue(value
);
64 CFDataRef circleData
= SOSCloudKVSCreateDataFromValueAfterDate(value
);
65 CFStringRef keyPrefix
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("%@ from %@: "), circle
, speerID
);
66 SOSCloudKVSLogCircle(keyPrefix
, dateString
, circleData
);
67 CFReleaseNull(keyPrefix
);
68 CFReleaseNull(speerID
);
70 CFReleaseNull(dateString
);
71 CFReleaseNull(circleData
);
74 static void SOSCloudKVSLogKeyParameters(CFTypeRef key
, CFStringRef dateString
, CFTypeRef value
) {
75 if(!isData(value
)) return;
76 CFStringRef keyParameterDescription
= UserParametersDescription(value
);
77 if(!keyParameterDescription
) keyParameterDescription
= CFDataCopyHexString(value
);
78 secnotice(KVSLOGSTATE
, "%@: %@: %@", key
, dateString
, keyParameterDescription
);
79 CFReleaseNull(keyParameterDescription
);
82 static void SOSCloudKVSLogLastKeyParameters(CFTypeRef key
, CFTypeRef value
) {
83 if(!isData(value
)) return;
84 CFStringRef from
= NULL
;
85 CFStringRef peerID
= CFSTR(" ");
86 bool parsed
= SOSKVSKeyParse(kLastKeyParameterKey
, key
, NULL
, NULL
, NULL
, NULL
, &from
, NULL
);
90 CFStringRef speerID
= CFStringCreateTruncatedCopy(peerID
, 8);
91 CFDataRef keyParameterData
= SOSCloudKVSCreateDataFromValueAfterDate(value
);
92 CFStringRef dateString
= SOSCloudKVSCreateDateFromValue(value
);
93 CFStringRef keyPrefix
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("k%@ from %@: "), kSOSKVSKeyParametersKey
, speerID
);
95 SOSCloudKVSLogKeyParameters(keyPrefix
, dateString
, keyParameterData
);
96 CFReleaseNull(keyPrefix
);
97 CFReleaseNull(speerID
);
98 CFReleaseNull(dateString
);
100 CFReleaseNull(keyParameterData
);
103 static void SOSCloudKVSLogMessage(CFTypeRef key
, CFTypeRef value
) {
104 CFStringRef circle
= NULL
;
105 CFStringRef from
= NULL
;
106 CFStringRef to
= NULL
;
107 bool parsed
= SOSKVSKeyParse(kMessageKey
, key
, &circle
, NULL
, NULL
, NULL
, &from
, &to
);
109 CFStringRef sfrom
= CFStringCreateTruncatedCopy(from
, 8);
110 CFStringRef sto
= CFStringCreateTruncatedCopy(to
, 8);
112 const char* messageType
= SecOTRPacketTypeString(value
);
113 secnotice(KVSLOGSTATE
, "message packet from: %@ to: %@ : %s: %ld", sfrom
, sto
, messageType
, CFDataGetLength(value
));
115 secnotice(KVSLOGSTATE
, "message packet from: %@ to: %@: %@", sfrom
, sto
, value
);
117 CFReleaseNull(sfrom
);
120 secnotice(KVSLOGSTATE
, "%@: %@", key
, value
);
122 CFReleaseNull(circle
);
127 static void SOSCloudKVSLogRetirement(CFTypeRef key
, CFTypeRef value
) {
128 CFStringRef circle
= NULL
;
129 CFStringRef from
= NULL
;
130 bool parsed
= SOSKVSKeyParse(kRetirementKey
, key
, &circle
, NULL
, NULL
, NULL
, &from
, NULL
);
132 CFStringRef sfrom
= CFStringCreateTruncatedCopy(from
, 8);
133 secnotice(KVSLOGSTATE
, "Retired Peer: %@, from Circle: %@", sfrom
, circle
);
134 CFReleaseNull(sfrom
);
136 secnotice(KVSLOGSTATE
, "Retired Peer format unknown - %@", key
);
138 CFReleaseNull(circle
);
142 static void SOSCloudKVSLogKeyType(CFTypeRef key
, CFTypeRef value
, SOSKVSKeyType type
){
145 SOSCloudKVSLogCircle(key
, CFSTR(" Current "), value
);
148 SOSCloudKVSLogRetirement(key
, value
);
151 SOSCloudKVSLogMessage(key
, value
);
154 SOSCloudKVSLogKeyParameters(key
, CFSTR(" Current "), value
);
156 case kLastKeyParameterKey
:
157 SOSCloudKVSLogLastKeyParameters(key
, value
);
160 SOSCloudKVSLogLastCircle(key
, value
);
162 case kInitialSyncKey
:
163 case kAccountChangedKey
:
172 void SOSCloudKVSLogState(void) {
173 static int ordering
[] = {
175 kLastKeyParameterKey
,
187 dispatch_semaphore_t waitSemaphore
= dispatch_semaphore_create(0);
188 dispatch_time_t finishTime
= dispatch_time(DISPATCH_TIME_NOW
, 10ull * NSEC_PER_SEC
);
189 static volatile bool inUse
= false; // Don't let log attempts stack
193 dispatch_retain(waitSemaphore
);
194 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
195 CFDictionaryRef kvsDictionary
= SOSCloudCopyKVSState();
197 secnotice(KVSLOGSTATE
, "Start");
198 // if we have anything to log - do it here.
199 for (size_t i
= 0; i
< (sizeof(ordering
) / sizeof(SOSKVSKeyType
)); i
++){
200 CFDictionaryForEach(kvsDictionary
, ^(const void *key
, const void *value
) {
201 if(SOSKVSKeyGetKeyType(key
) == ordering
[i
]){
202 SOSCloudKVSLogKeyType(key
, value
, ordering
[i
]);
206 secnotice(KVSLOGSTATE
, "Finish");
207 CFReleaseNull(kvsDictionary
);
209 secnotice(KVSLOGSTATE
, "dictionary from KVS is NULL");
213 dispatch_semaphore_signal(waitSemaphore
);
214 dispatch_release(waitSemaphore
);
218 dispatch_semaphore_wait(waitSemaphore
, finishTime
);
219 dispatch_release(waitSemaphore
);