]> git.saurik.com Git - apple/security.git/blob - OSX/sec/SOSCircle/Tool/accountCirclesViewsPrint.m
0ca7efe4b678fd6df5002a7ed61a1bac80b04d9c
[apple/security.git] / OSX / sec / SOSCircle / Tool / accountCirclesViewsPrint.m
1 //
2 // accountCirclesViewsPrint.c
3 // Security
4 //
5 // Created by Richard Murphy on 12/8/16.
6 //
7 //
8
9 #include "accountCirclesViewsPrint.h"
10
11 //
12 // SOSSysdiagnose.c
13 // sec
14 //
15 // Created by Richard Murphy on 1/27/16.
16 //
17 //
18
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/utsname.h>
25 #include <sys/stat.h>
26 #include <time.h>
27 #include <notify.h>
28 #include <pwd.h>
29
30 #include <Security/SecItem.h>
31
32 #include <CoreFoundation/CFNumber.h>
33 #include <CoreFoundation/CFString.h>
34
35 #include <Security/SecureObjectSync/SOSCloudCircle.h>
36 #include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
37 #include <Security/SecureObjectSync/SOSPeerInfo.h>
38 #include <Security/SecureObjectSync/SOSPeerInfoPriv.h>
39 #include <Security/SecureObjectSync/SOSPeerInfoV2.h>
40 #include <Security/SecureObjectSync/SOSUserKeygen.h>
41 #include <Security/SecureObjectSync/SOSKVSKeys.h>
42 #include <securityd/SOSCloudCircleServer.h>
43 #include <Security/SecOTRSession.h>
44 #include <SOSCircle/CKBridge/SOSCloudKeychainClient.h>
45
46 #include <utilities/SecCFWrappers.h>
47 #include <utilities/debugging.h>
48
49 #include <SecurityTool/readline.h>
50
51 #include "keychain_log.h"
52 #include "secToolFileIO.h"
53 #include "secViewDisplay.h"
54
55
56 #include <Security/SecPasswordGenerate.h>
57
58 /* Copied from CFPriv.h */
59 // #include <CoreFoundation/CFPriv.h>
60
61 CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
62 CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey;
63 CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey;
64 CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey;
65
66 #define MAXKVSKEYTYPE kUnknownKey
67 #define DATE_LENGTH 18
68
69 #include <utilities/SecCFWrappers.h>
70
71
72 static const char *getSOSCCStatusDescription(SOSCCStatus ccstatus)
73 {
74 switch (ccstatus)
75 {
76 case kSOSCCInCircle: return "In Circle";
77 case kSOSCCNotInCircle: return "Not in Circle";
78 case kSOSCCRequestPending: return "Request pending";
79 case kSOSCCCircleAbsent: return "Circle absent";
80 case kSOSCCError: return "Circle error";
81
82 default:
83 return "<unknown ccstatus>";
84 break;
85 }
86 }
87
88 static const char *
89 getSOSCCLastDepartureReasonDescription(enum DepartureReason reason)
90 {
91 switch (reason) {
92 #define CASE_REASON(x) case kSOS##x: return #x
93 CASE_REASON(DepartureReasonError);
94 CASE_REASON(NeverLeftCircle);
95 CASE_REASON(WithdrewMembership);
96 CASE_REASON(MembershipRevoked);
97 CASE_REASON(LeftUntrustedCircle);
98 CASE_REASON(NeverAppliedToCircle);
99 CASE_REASON(DiscoveredRetirement); // we should all be so lucky
100 CASE_REASON(LostPrivateKey);
101 CASE_REASON(PasswordChanged);
102 #undef CASE_REASON
103 default:
104 return "Unknown";
105 }
106 }
107
108 static void printPeerInfos(char *label, CFArrayRef (^getArray)(CFErrorRef *error)) {
109 CFErrorRef error = NULL;
110 CFArrayRef ppi = getArray(&error);
111 SOSPeerInfoRef me = SOSCCCopyMyPeerInfo(NULL);
112 CFStringRef mypeerID = SOSPeerInfoGetPeerID(me);
113
114 if(ppi) {
115 printmsg(CFSTR("%s count: %ld\n"), label, (long)CFArrayGetCount(ppi));
116 CFArrayForEach(ppi, ^(const void *value) {
117 char buf[160];
118 SOSPeerInfoRef peer = (SOSPeerInfoRef)value;
119 CFIndex version = SOSPeerInfoGetVersion(peer);
120 CFStringRef peerName = SOSPeerInfoGetPeerName(peer);
121 CFStringRef devtype = SOSPeerInfoGetPeerDeviceType(peer);
122 CFStringRef peerID = SOSPeerInfoGetPeerID(peer);
123 CFStringRef transportType = CFSTR("KVS");
124 CFStringRef deviceID = CFSTR("");
125 CFDictionaryRef gestalt = SOSPeerInfoCopyPeerGestalt(peer);
126 CFStringRef osVersion = CFDictionaryGetValue(gestalt, CFSTR("OSVersion"));
127
128
129 if(version >= 2){
130 CFDictionaryRef v2Dictionary = peer->v2Dictionary;
131 transportType = CFDictionaryGetValue(v2Dictionary, sTransportType);
132 deviceID = CFDictionaryGetValue(v2Dictionary, sDeviceID);
133 }
134 char *pname = CFStringToCString(peerName);
135 char *dname = CFStringToCString(devtype);
136 char *tname = CFStringToCString(transportType);
137 char *iname = CFStringToCString(deviceID);
138 const char *me = CFEqualSafe(mypeerID, peerID) ? "me>" : " ";
139
140
141 snprintf(buf, 160, "%s %s: %-16s %-16s %-16s %-36s", me, label, pname, dname, tname, iname);
142
143 free(pname);
144 free(dname);
145 free(tname);
146 free(iname);
147
148 // %s in (Core)Foundation format strings treats the string as MacRoman, need to do this to guarantee UTF8 handling
149 CFStringRef bufstr = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
150 CFStringRef pid = SOSPeerInfoGetPeerID(peer);
151 CFIndex vers = SOSPeerInfoGetVersion(peer);
152 printmsg(CFSTR("%@ %@ V%d OS:%@\n"), bufstr, pid, vers, osVersion ?: CFSTR(""));
153 CFRelease(bufstr);
154
155 CFReleaseNull(gestalt);
156 });
157 } else {
158 printmsg(CFSTR("No %s, error: %@\n"), label, error);
159 }
160 CFReleaseNull(ppi);
161 CFReleaseNull(error);
162 CFReleaseNull(me);
163 }
164
165 void SOSCCDumpCircleInformation()
166 {
167 CFErrorRef error = NULL;
168 CFArrayRef generations = NULL;
169 bool is_accountKeyIsTrusted = false;
170 __block int count = 0;
171
172 SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error);
173 printmsg(CFSTR("ccstatus: %s (%d)\n"), getSOSCCStatusDescription(ccstatus), ccstatus);
174 if (error != NULL) {
175 printmsg(CFSTR("Error checking circle status: %@\n"), error);
176 }
177 CFReleaseNull(error);
178
179 enum DepartureReason departureReason = SOSCCGetLastDepartureReason(&error);
180 printmsg(CFSTR("LastDepartureReason: %s (%d)\n"), getSOSCCLastDepartureReasonDescription(departureReason), departureReason);
181 if (error != NULL) {
182 printmsg(CFSTR("Error checking last departure reason error: %@\n"), error);
183 }
184 CFReleaseNull(error);
185
186 is_accountKeyIsTrusted = SOSCCValidateUserPublic(&error);
187 if(is_accountKeyIsTrusted)
188 printmsg(CFSTR("Account user public is trusted\n"));
189 else
190 printmsg(CFSTR("Account user public is not trusted error:(%@)\n"), error);
191 CFReleaseNull(error);
192
193 generations = SOSCCCopyGenerationPeerInfo(&error);
194 if(generations) {
195 CFArrayForEach(generations, ^(const void *value) {
196 count++;
197 if(count%2 == 0)
198 printmsg(CFSTR("Circle name: %@, "),value);
199
200 if(count%2 != 0) {
201 CFStringRef genDesc = SOSGenerationCountCopyDescription(value);
202 printmsg(CFSTR("Generation Count: %@"), genDesc);
203 CFReleaseNull(genDesc);
204 }
205 printmsg(CFSTR("%s\n"), "");
206 });
207 } else {
208 printmsg(CFSTR("No generation count: %@\n"), error);
209 }
210 CFReleaseNull(generations);
211 CFReleaseNull(error);
212
213 printPeerInfos(" Peers", ^(CFErrorRef *error) { return SOSCCCopyValidPeerPeerInfo(error); });
214 printPeerInfos(" Invalid", ^(CFErrorRef *error) { return SOSCCCopyNotValidPeerPeerInfo(error); });
215 printPeerInfos(" Retired", ^(CFErrorRef *error) { return SOSCCCopyRetirementPeerInfo(error); });
216 printPeerInfos(" Concur", ^(CFErrorRef *error) { return SOSCCCopyConcurringPeerPeerInfo(error); });
217 printPeerInfos("Applicants", ^(CFErrorRef *error) { return SOSCCCopyApplicantPeerInfo(error); });
218
219 CFReleaseNull(error);
220 }
221
222 void
223 SOSCCDumpEngineInformation(void)
224 {
225 CFErrorRef error = NULL;
226
227 printmsg(CFSTR("Engine state:\n"));
228 if (!SOSCCForEachEngineStateAsString(&error, ^(CFStringRef oneStateString) {
229 printmsg(CFSTR("%@\n"), oneStateString);
230 })) {
231 printmsg(CFSTR("No engine state, got error: %@\n"), error);
232 }
233 }
234
235 // security sync -o
236 void
237 SOSCCDumpViewUnwarePeers(void)
238 {
239 printPeerInfos("view-unaware", ^(CFErrorRef *error) { return SOSCCCopyViewUnawarePeerInfo(error); });
240 }
241
242 /* KVS Dumping Support for iCloud Keychain */
243
244 static CFTypeRef getObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, dispatch_group_t dgroup)
245 {
246 __block CFTypeRef object = NULL;
247
248 const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC;
249 dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
250 dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
251
252 dispatch_group_enter(dgroup);
253
254 CloudKeychainReplyBlock replyBlock =
255 ^ (CFDictionaryRef returnedValues, CFErrorRef error)
256 {
257 secinfo("sync", "SOSCloudKeychainGetObjectsFromCloud returned: %@", returnedValues);
258 object = returnedValues;
259 if (object)
260 CFRetain(object);
261 if (error)
262 {
263 secerror("SOSCloudKeychainGetObjectsFromCloud returned error: %@", error);
264 }
265 dispatch_group_leave(dgroup);
266 secinfo("sync", "SOSCloudKeychainGetObjectsFromCloud block exit: %@", object);
267 dispatch_semaphore_signal(waitSemaphore);
268 };
269
270 if (!keysToGet)
271 SOSCloudKeychainGetAllObjectsFromCloud(processQueue, replyBlock);
272 else
273 SOSCloudKeychainGetObjectsFromCloud(keysToGet, processQueue, replyBlock);
274
275 dispatch_semaphore_wait(waitSemaphore, finishTime);
276 if (object && (CFGetTypeID(object) == CFNullGetTypeID())) // return a NULL instead of a CFNull
277 {
278 CFRelease(object);
279 object = NULL;
280 }
281 secerror("returned: %@", object);
282 return object;
283 }
284
285 static CFStringRef printFullDataString(CFDataRef data){
286 __block CFStringRef fullData = NULL;
287
288 BufferPerformWithHexString(CFDataGetBytePtr(data), CFDataGetLength(data), ^(CFStringRef dataHex) {
289 fullData = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@"), dataHex);
290 });
291
292 return fullData;
293 }
294
295 static void displayLastKeyParameters(CFTypeRef key, CFTypeRef value)
296 {
297 CFDataRef valueAsData = asData(value, NULL);
298 if(valueAsData){
299 CFDataRef dateData = CFDataCreateCopyFromRange(kCFAllocatorDefault, valueAsData, CFRangeMake(0, DATE_LENGTH));
300 CFDataRef keyParameterData = CFDataCreateCopyFromPositions(kCFAllocatorDefault, valueAsData, DATE_LENGTH, CFDataGetLength(valueAsData));
301 CFStringRef dateString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, dateData, kCFStringEncodingUTF8);
302 CFStringRef keyParameterDescription = UserParametersDescription(keyParameterData);
303 if(keyParameterDescription)
304 printmsg(CFSTR("%@: %@: %@\n"), key, dateString, keyParameterDescription);
305 else
306 printmsg(CFSTR("%@: %@\n"), key, printFullDataString(value));
307 CFReleaseNull(dateString);
308 CFReleaseNull(keyParameterData);
309 CFReleaseNull(dateData);
310 CFReleaseNull(keyParameterDescription);
311 }
312 else{
313 printmsg(CFSTR("%@: %@\n"), key, value);
314 }
315 }
316
317 static void displayKeyParameters(CFTypeRef key, CFTypeRef value)
318 {
319 if(isData(value)){
320 CFStringRef keyParameterDescription = UserParametersDescription((CFDataRef)value);
321
322 if(keyParameterDescription)
323 printmsg(CFSTR("%@: %@\n"), key, keyParameterDescription);
324 else
325 printmsg(CFSTR("%@: %@\n"), key, value);
326
327 CFReleaseNull(keyParameterDescription);
328 }
329 else{
330 printmsg(CFSTR("%@: %@\n"), key, value);
331 }
332 }
333
334 static void displayLastCircle(CFTypeRef key, CFTypeRef value)
335 {
336 CFDataRef valueAsData = asData(value, NULL);
337 if(valueAsData){
338 CFErrorRef localError = NULL;
339
340 CFDataRef dateData = CFDataCreateCopyFromRange(kCFAllocatorDefault, valueAsData, CFRangeMake(0, DATE_LENGTH));
341 CFDataRef circleData = CFDataCreateCopyFromPositions(kCFAllocatorDefault, valueAsData, DATE_LENGTH, CFDataGetLength(valueAsData));
342 CFStringRef dateString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, dateData, kCFStringEncodingUTF8);
343 SOSCircleRef circle = SOSCircleCreateFromData(NULL, (CFDataRef) circleData, &localError);
344
345 if(circle){
346 CFIndex size = 5;
347 CFNumberRef idLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &size);
348 CFDictionaryRef format = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, CFSTR("SyncD"), CFSTR("SyncD"), CFSTR("idLength"), idLength, NULL);
349 printmsgWithFormatOptions(format, CFSTR("%@: %@: %@\n"), key, dateString, circle);
350 CFReleaseNull(idLength);
351 CFReleaseNull(format);
352
353 }
354 else
355 printmsg(CFSTR("%@: %@\n"), key, printFullDataString(circleData));
356
357 CFReleaseNull(dateString);
358 CFReleaseNull(circleData);
359 CFReleaseSafe(circle);
360 CFReleaseNull(dateData);
361 CFReleaseNull(localError);
362 }
363 else{
364 printmsg(CFSTR("%@: %@\n"), key, value);
365 }
366 }
367
368 static void displayCircle(CFTypeRef key, CFTypeRef value)
369 {
370 CFDataRef circleData = (CFDataRef)value;
371
372 CFErrorRef localError = NULL;
373 if (isData(circleData))
374 {
375 CFIndex size = 5;
376 CFNumberRef idLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &size);
377 CFDictionaryRef format = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, CFSTR("SyncD"), CFSTR("SyncD"), CFSTR("idLength"), idLength, NULL);
378 SOSCircleRef circle = SOSCircleCreateFromData(NULL, circleData, &localError);
379 printmsgWithFormatOptions(format, CFSTR("%@: %@\n"), key, circle);
380 CFReleaseSafe(circle);
381 CFReleaseNull(idLength);
382 CFReleaseNull(format);
383
384 }
385 else
386 printmsg(CFSTR("%@: %@\n"), key, value);
387 }
388
389 static void displayMessage(CFTypeRef key, CFTypeRef value)
390 {
391 CFDataRef message = (CFDataRef)value;
392 if(isData(message)){
393 const char* messageType = SecOTRPacketTypeString(message);
394 printmsg(CFSTR("%@: %s: %ld\n"), key, messageType, CFDataGetLength(message));
395 }
396 else
397 printmsg(CFSTR("%@: %@\n"), key, value);
398 }
399
400 static void printEverything(CFTypeRef objects)
401 {
402 CFDictionaryForEach(objects, ^(const void *key, const void *value) {
403 if (isData(value))
404 {
405 printmsg(CFSTR("%@: %@\n\n"), key, printFullDataString(value));
406 }
407 else
408 printmsg(CFSTR("%@: %@\n"), key, value);
409 });
410
411 }
412
413 static void decodeForKeyType(CFTypeRef key, CFTypeRef value, SOSKVSKeyType type){
414 switch (type) {
415 case kCircleKey:
416 displayCircle(key, value);
417 break;
418 case kRetirementKey:
419 case kMessageKey:
420 displayMessage(key, value);
421 break;
422 case kParametersKey:
423 displayKeyParameters(key, value);
424 break;
425 case kLastKeyParameterKey:
426 displayLastKeyParameters(key, value);
427 break;
428 case kLastCircleKey:
429 displayLastCircle(key, value);
430 break;
431 case kInitialSyncKey:
432 case kAccountChangedKey:
433 case kDebugInfoKey:
434 case kRingKey:
435 default:
436 printmsg(CFSTR("%@: %@\n"), key, value);
437 break;
438 }
439 }
440
441 static void decodeAllTheValues(CFTypeRef objects){
442 SOSKVSKeyType keyType = 0;
443 __block bool didPrint = false;
444
445 for (keyType = 0; keyType <= MAXKVSKEYTYPE; keyType++){
446 CFDictionaryForEach(objects, ^(const void *key, const void *value) {
447 if(SOSKVSKeyGetKeyType(key) == keyType){
448 decodeForKeyType(key, value, keyType);
449 didPrint = true;
450 }
451 });
452 if(didPrint)
453 printmsg(CFSTR("%@\n"), CFSTR(""));
454 didPrint = false;
455 }
456 }
457
458 bool SOSCCDumpCircleKVSInformation(char *itemName) {
459 CFArrayRef keysToGet = NULL;
460 if (itemName)
461 {
462 CFStringRef itemStr = CFStringCreateWithCString(kCFAllocatorDefault, itemName, kCFStringEncodingUTF8);
463 fprintf(outFile, "Retrieving %s from KVS\n", itemName);
464 keysToGet = CFArrayCreateForCFTypes(kCFAllocatorDefault, itemStr, NULL);
465 CFReleaseSafe(itemStr);
466 }
467 dispatch_queue_t generalq = dispatch_queue_create("general", DISPATCH_QUEUE_SERIAL);
468 dispatch_group_t work_group = dispatch_group_create();
469 CFTypeRef objects = getObjectsFromCloud(keysToGet, generalq, work_group);
470 CFReleaseSafe(keysToGet);
471 if (objects)
472 {
473 fprintf(outFile, "All keys and values straight from KVS\n");
474 printEverything(objects);
475 fprintf(outFile, "\nAll values in decoded form...\n");
476 decodeAllTheValues(objects);
477 }
478 fprintf(outFile, "\n");
479 return true;
480 }