]> git.saurik.com Git - apple/security.git/blob - Security/utilities/src/cloud_keychain_diagnose.c
Security-57031.30.12.tar.gz
[apple/security.git] / Security / utilities / src / cloud_keychain_diagnose.c
1 /*
2 * clang cloud_keychain_diagnose.c -laks -framework CoreFoundation -framework IOKit -framework Security -o /tmp/cloud_keychain_diagnose
3 */
4
5 #include <CoreFoundation/CoreFoundation.h>
6 #include <CoreFoundation/CFPriv.h>
7
8 #if !TARGET_IPHONE_SIMULATOR
9
10 /* Header Declarations */
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <asl.h>
15 #include <asl_msg.h>
16
17 #if TARGET_OS_EMBEDDED
18 #include <asl_core.h>
19 #endif
20
21 #include <string.h>
22 #include <errno.h>
23 #include <libaks.h>
24
25 #include "SOSCloudCircle.h"
26 #include "SOSPeerInfo.h"
27
28
29 /* Constant Declarations */
30 #define SUCCESS 0
31 #define FAILURE -1
32
33 #define MAX_PATH_LEN 1024
34 #define SUFFIX_LENGTH 4
35 #define BUFFER_SIZE 1024
36 #define MAX_DATA_RATE 32
37
38 /* External CloudKeychain Bridge Types */
39 typedef void (^CloudKeychainReplyBlock)(CFDictionaryRef returnedValues, CFErrorRef error);
40 extern void SOSCloudKeychainGetAllObjectsFromCloud(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock);
41
42 /* External AppleKeyStore Types */
43 enum {
44 my_keybag_state_bio_unlock = 1 << 3
45 };
46
47
48 /* Dictionary Dump State */
49 struct dict_dump_state
50 {
51 FILE *log_file;
52 CFDictionaryRef dict;
53 unsigned int indent_level;
54 };
55
56 /* Static Function Declarations */
57 static
58 void
59 usage();
60
61 static
62 int
63 gather_diagnostics();
64
65 static
66 int
67 enable_cloud_keychain_diagnostics(
68 const unsigned int enable_flag);
69
70 static
71 int
72 build_log_path(
73 char *log_path);
74
75 static
76 int
77 dump_system_information(
78 FILE *log_file);
79
80 static
81 int
82 dump_circle_state(
83 FILE *log_file);
84
85 static
86 int
87 dump_keychain_sync_kvs(
88 FILE *log_file);
89
90 static
91 void
92 dump_dict(
93 FILE *log_file,
94 CFDictionaryRef dict,
95 const unsigned int indent_level);
96
97 static
98 void
99 dump_dict_applier(
100 const void *key,
101 const void *value,
102 void *context);
103
104 static
105 int
106 dump_asl_sender(
107 FILE *log_file,
108 const char *asl_sender);
109
110 static
111 void
112 dump_cferror(
113 FILE *log_file,
114 const char *description,
115 CFErrorRef error);
116
117 /* Function Definitions */
118 int
119 main(
120 int argc,
121 char **argv)
122 {
123 int result = EXIT_FAILURE;
124
125 /* Parse the arguments. */
126 if (argc > 2) {
127
128 usage();
129 }
130
131 /* Should we just gather logs and status? */
132 if (argc == 1) {
133
134 if (gather_diagnostics()) {
135
136 fprintf(stderr, "Could not gather diagnostics\n");
137 goto BAIL;
138 }
139 } else {
140
141 /* Should we enable or disable logging? */
142 if (strncmp(argv[1], "enable", 6) == 0) {
143
144 /* Enable. */
145 if (enable_cloud_keychain_diagnostics(1)) {
146
147 fprintf(stderr, "Could not enable additional cloud keychain diagnostics\n");
148 goto BAIL;
149 }
150 } else if (strncmp(argv[1], "disable", 7) == 0) {
151
152 /* Enable. */
153 if (enable_cloud_keychain_diagnostics(1)) {
154
155 fprintf(stderr, "Could not disable additional cloud keychain diagnostics\n");
156 goto BAIL;
157 }
158 } else {
159
160 /* Get a job, hippy. */
161 usage();
162 }
163 }
164
165 /* Set the exit status to success. */
166 result = EXIT_FAILURE;
167
168 BAIL:
169
170 return result;
171 }
172
173 /* Static Function Definitions */
174 static
175 void
176 usage()
177 {
178 fprintf(stderr, "usage: cloud_keychain_diagnose [enable|disable]\n");
179 exit(EXIT_FAILURE);
180 }
181
182 static
183 int
184 gather_diagnostics()
185 {
186 int result = FAILURE;
187 char log_path[MAX_PATH_LEN] = "";
188 int log_fd = -1;
189 FILE *log_file = NULL;
190
191 /*
192 * Create the diagnostics file.
193 *
194 * Dump the system information.
195 * on OS X, defaults read if the shim is active
196 * Dump the circle state.
197 * Dump the raw KVS data.
198 * Dump known ASL logs
199 *
200 * Remaining work to do from rdar://12479351
201 * grab the syslog
202 * query for all items with sync=1
203 * enable KVS logging
204 * enable push notification logging
205 */
206
207 /* Build the log path. */
208 if (build_log_path(log_path)) {
209
210 fprintf(stderr, "Could not build the log path\n");
211 goto BAIL;
212 }
213
214 /* Create it with a randomized suffix. */
215 log_fd = mkstemps(log_path, SUFFIX_LENGTH);
216 if (log_fd == -1) {
217
218 fprintf(stderr, "Could not create the log file: %s\n", strerror(errno));
219 goto BAIL;
220 }
221
222 /* Create a file object from the descriptor. */
223 log_file = fdopen(log_fd, "w");
224 if (log_file == NULL) {
225
226 fprintf(stderr, "Could not recreate the log file: %s\n", strerror(errno));
227 goto BAIL;
228 }
229
230 log_fd = -1;
231
232 printf("Writing cloud keychain diagnostics to %s\n", log_path);
233
234 /* Dump the system information. */
235 if (dump_system_information(log_file)) {
236
237 fprintf(stderr, "Could not dump the system information\n");
238 goto BAIL;
239 }
240
241 /* Dump the SOS circle state. */
242 if (dump_circle_state(log_file)) {
243
244 fprintf(stderr, "Could not dump the SOS circle state\n");
245 goto BAIL;
246 }
247
248 /* Dump the raw keychain syncing KVS. */
249 if (dump_keychain_sync_kvs(log_file)) {
250
251 fprintf(stderr, "Could not the raw keychain syncing KVS\n");
252 goto BAIL;
253 }
254
255 /*
256 * Dump the various and sundry ASL logs.
257 */
258
259 if (dump_asl_sender(log_file, "com.apple.kb-service")) {
260
261 fprintf(stderr, "Could not dump the ASL log for com.apple.kb-service\n");
262 goto BAIL;
263 }
264
265 if (dump_asl_sender(log_file, "com.apple.securityd")) {
266
267 fprintf(stderr, "Could not dump the ASL log for com.apple.securityd\n");
268 goto BAIL;
269 }
270
271 if (dump_asl_sender(log_file, "com.apple.secd")) {
272
273 fprintf(stderr, "Could not dump the ASL log for com.apple.secd\n");
274 goto BAIL;
275 }
276
277 if (dump_asl_sender(log_file, "CloudKeychainProxy")) {
278
279 fprintf(stderr, "Could not dump the ASL log for CloudKeychainProxy\n");
280 goto BAIL;
281 }
282
283 if (dump_asl_sender(log_file, "securityd")) {
284
285 fprintf(stderr, "Could not dump the ASL log for securityd\n");
286 goto BAIL;
287 }
288
289 if (dump_asl_sender(log_file, "secd")) {
290
291 fprintf(stderr, "Could not dump the ASL log for secd\n");
292 goto BAIL;
293 }
294
295 /* Set the result to success. */
296 result = SUCCESS;
297
298 BAIL:
299
300 /* Close the diagnostics file? */
301 if (log_file != NULL) {
302
303 fclose(log_file);
304 log_file = NULL;
305 }
306
307 /* Close the diagnostics file descriptor? */
308 if (log_fd != -1) {
309
310 close(log_fd);
311 log_fd = -1;
312 (void) log_fd;
313 }
314
315 return result;
316 }
317
318 static
319 int
320 enable_cloud_keychain_diagnostics(
321 const unsigned int enable_flag)
322 {
323 int result = FAILURE;
324
325 /* Set the result to success. */
326 result = SUCCESS;
327
328 return result;
329 }
330
331 static
332 int
333 build_log_path(
334 char *log_path)
335 {
336 int result = FAILURE;
337 time_t now;
338 struct tm *time_cube;
339 CFDictionaryRef system_version_dict = NULL;
340 CFStringRef product_name = NULL;
341
342 /* Get the current time. */
343 now = time(NULL);
344
345 /* Convert the time into something usable. */
346 time_cube = localtime(&now);
347 if (time_cube == NULL) {
348
349 fprintf(stderr, "I don't know what time it is.\n");
350 goto BAIL;
351 }
352
353 /* Copy the system version dictionary. */
354 system_version_dict = _CFCopySystemVersionDictionary();
355 if (system_version_dict == NULL) {
356
357 fprintf(stderr, "Could not copy the system version dictionary\n");
358 goto BAIL;
359 }
360
361 /* Extract the product name. */
362 product_name = CFDictionaryGetValue(system_version_dict, _kCFSystemVersionProductNameKey);
363 if (product_name == NULL) {
364
365 fprintf(stderr, "Could not extract the product name from the system version dictionary\n");
366 goto BAIL;
367 }
368
369 /* Is this a Mac? */
370 if (CFEqual(product_name, CFSTR("Mac OS X"))) {
371
372 /* Prepare the file template to go into /tmp. */
373 snprintf(
374 log_path,
375 MAX_PATH_LEN,
376 "/tmp/cloud_keychain_diagnostics.%d_%d_%d.%d%d%d.XXXX.txt",
377 1900 + time_cube->tm_year,
378 time_cube->tm_mon,
379 time_cube->tm_mday,
380 time_cube->tm_hour,
381 time_cube->tm_min,
382 time_cube->tm_sec);
383 } else {
384
385 /* Prepare the file template to go into CrashReporter. */
386 snprintf(
387 log_path,
388 MAX_PATH_LEN,
389 "/Library/Logs/CrashReporter/cloud_keychain_diagnostics.%d_%d_%d.%d%d%d.XXXX.txt",
390 1900 + time_cube->tm_year,
391 time_cube->tm_mon,
392 time_cube->tm_mday,
393 time_cube->tm_hour,
394 time_cube->tm_min,
395 time_cube->tm_sec);
396 }
397
398 /* Set the result to success. */
399 result = SUCCESS;
400
401 BAIL:
402
403 /* Release the system version dictionary? */
404 if (system_version_dict != NULL) {
405
406 CFRelease(system_version_dict);
407 system_version_dict = NULL;
408 }
409
410 return result;
411 }
412
413 static
414 int
415 dump_system_information(
416 FILE *log_file)
417 {
418 int result = FAILURE;
419 CFDictionaryRef dict = NULL;
420 char buffer[BUFFER_SIZE];
421 CFStringRef product_name;
422 CFStringRef product_version;
423 CFStringRef product_build_version;
424 time_t now;
425 CFTypeRef shim_flag = NULL;
426 int keybag_handle = bad_keybag_handle;
427 kern_return_t kr = 0;
428 keybag_state_t keybag_state = 0;
429
430 /*
431 * Dump the system information.
432 * ProductName
433 * ProductVersion
434 * ProductBuildVersion
435 * Host name
436 */
437
438 /* Dump a header. */
439 fprintf(log_file, "Host Information:\n");
440 fprintf(log_file, "=================\n");
441
442 /* Copy the system version dictionary. */
443 dict = _CFCopySystemVersionDictionary();
444 if (dict == NULL) {
445
446 fprintf(stderr, "Could not copy the system version dictionary\n");
447 goto BAIL;
448 }
449
450 /* Extract the product name. */
451 product_name = CFDictionaryGetValue(dict, _kCFSystemVersionProductNameKey);
452 if (product_name == NULL) {
453
454 fprintf(stderr, "Could not extract the product name from the system version dictionary\n");
455 goto BAIL;
456 }
457
458 /* Convert the product name to a C string. */
459 if (!CFStringGetCString(product_name, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
460
461 fprintf(stderr, "Could not convert the product name to a C string\n");
462 goto BAIL;
463 }
464
465 /* Dump the product name. */
466 fprintf(log_file, "Product Name: %s\n", buffer);
467
468 /* Extract the product version. */
469 product_version = CFDictionaryGetValue(dict, _kCFSystemVersionProductVersionKey);
470 if (product_version == NULL) {
471
472 fprintf(stderr, "Could not extract the product version from the system version dictionary\n");
473 goto BAIL;
474 }
475
476 /* Convert the product version to a C string. */
477 if (!CFStringGetCString(product_version, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
478
479 fprintf(stderr, "Could not convert the product version to a C string\n");
480 goto BAIL;
481 }
482
483 /* Dump the product version */
484 fprintf(log_file, "Product Version: %s\n", buffer);
485
486 /* Extract the product build version. */
487 product_build_version = CFDictionaryGetValue(dict, _kCFSystemVersionBuildVersionKey);
488 if (product_build_version == NULL) {
489
490 fprintf(stderr, "Could not extract the product build version from the system version dictionary\n");
491 goto BAIL;
492 }
493
494 /* Convert the product build version to a C string. */
495 if (!CFStringGetCString(product_build_version, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
496
497 fprintf(stderr, "Could not convert the product build version to a C string\n");
498 goto BAIL;
499 }
500
501 /* Dump the product build version. */
502 fprintf(log_file, "Product Build Version: %s\n", buffer);
503
504 /* Lookup the host name. */
505 if (gethostname(buffer, BUFFER_SIZE) == -1) {
506
507 fprintf(stderr, "Could not lookup the host name\n");
508 goto BAIL;
509 }
510
511 /* Dump the host name. */
512 fprintf(log_file, "Host Name: %s\n", buffer);
513
514 /* Lookup the current time. */
515 if (gethostname(buffer, BUFFER_SIZE) == -1) {
516
517 fprintf(stderr, "Could not lookup the host name\n");
518 goto BAIL;
519 }
520
521 /* Get the current time. */
522 now = time(NULL);
523
524 /* Dump the current time. */
525 fprintf(log_file, "Time: %s", ctime(&now));
526
527 /* Is this a Mac? */
528 if (CFEqual(product_name, CFSTR("Mac OS X"))) {
529
530 /* Set the keybag handle. */
531 keybag_handle = session_keybag_handle;
532
533 /* Lookup the state of the shim. */
534 shim_flag = (CFNumberRef)CFPreferencesCopyValue(CFSTR("SecItemSynchronizable"), CFSTR("com.apple.security"), kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
535 if (shim_flag && CFGetTypeID(shim_flag) == CFBooleanGetTypeID()) {
536
537 /* Is the shim enabled? */
538 if (CFBooleanGetValue((CFBooleanRef)shim_flag)) {
539
540 fprintf(log_file, "The SecItem shim is enabled\n");
541 } else {
542
543 fprintf(log_file, "The SecItem shim is disabled\n");
544 }
545 } else {
546
547 fprintf(log_file, "The SecItem shim is disabled\n");
548 }
549 } else {
550
551 /* Set the keybag handle. */
552 keybag_handle = device_keybag_handle;
553 }
554
555 /* Get the keybag state. */
556 kr = aks_get_lock_state(keybag_handle, &keybag_state);
557 if (kr) {
558
559 fprintf(stderr, "Could not call aks_get_lock_state\n");
560 } else {
561
562 switch (keybag_state) {
563
564 case keybag_state_unlocked: {
565
566 fprintf(log_file, "Keybag State: Unlocked\n");
567 }break;
568
569 case keybag_state_locked: {
570
571 fprintf(log_file, "Keybag State: Locked\n");
572 }break;
573
574 case keybag_state_no_pin: {
575
576 fprintf(log_file, "Keybag State: No Passcode\n");
577 }break;
578
579 case keybag_state_been_unlocked: {
580
581 fprintf(log_file, "Keybag State: Been Unlocked\n");
582 }break;
583
584 case my_keybag_state_bio_unlock: {
585
586 fprintf(log_file, "Keybag State: Bio Unlock\n");
587 }break;
588
589 default: {
590
591 fprintf(log_file, "Keybag State: UNKNOWN\n");
592 }break;
593 }
594 }
595
596 /* Dump a footer. */
597 fprintf(log_file, "=================\n\n");
598
599 /* Set the result to success. */
600 result = SUCCESS;
601
602 BAIL:
603
604 /* Release the shim flag? */
605 if (shim_flag) {
606
607 CFRelease(shim_flag);
608 shim_flag = NULL;
609 }
610
611 /* Release the system version dictionary? */
612 if (dict != NULL) {
613
614 CFRelease(dict);
615 dict = NULL;
616 }
617
618 return result;
619 }
620
621 static
622 int
623 dump_circle_state(
624 FILE *log_file)
625 {
626 int result = FAILURE;
627 CFErrorRef error = NULL;
628 SOSCCStatus circle_status;
629 CFArrayRef peer_list = NULL;
630 CFIndex num_peers;
631 CFIndex i;
632 SOSPeerInfoRef peer_info;
633 CFDictionaryRef peer_gestalt = NULL;
634 CFStringRef peer_name;
635 CFStringRef peer_device_type;
636 CFStringRef peerID;
637 char buffer[BUFFER_SIZE] = {};
638
639 /*
640 * Dump the SOS circle state.
641 */
642
643 /* Dump a header. */
644 fprintf(log_file, "SOS Circle State:\n");
645 fprintf(log_file, "=================\n");
646
647 /* Are we in a circle? */
648 circle_status = SOSCCThisDeviceIsInCircle(&error);
649 if (error != NULL) {
650
651 /* Dump and consume the error. */
652 dump_cferror(log_file, "Could not call SOSCCThisDeviceIsInCircle", error);
653 } else {
654 char *circle_state_string = NULL;
655
656 switch (circle_status) {
657
658 case kSOSCCInCircle: {
659 circle_state_string = "kSOSCCInCircle";
660 }break;
661
662 case kSOSCCNotInCircle: {
663 circle_state_string = "kSOSCCNotInCircle";
664 }break;
665
666 case kSOSCCRequestPending: {
667 circle_state_string = "kSOSCCRequestPending";
668 }break;
669
670 case kSOSCCCircleAbsent: {
671 circle_state_string = "kSOSCCCircleAbsent";
672 }break;
673
674 case kSOSCCError: {
675 circle_state_string = "kSOSCCError";
676 }break;
677
678 default: {
679 sprintf(buffer, "Unknown circle status (%d)?", circle_status);
680 circle_state_string = buffer;
681 }
682 }
683
684 fprintf(log_file, "Circle Status: %s\n", circle_state_string);
685 }
686
687 /* Can we authenticate? */
688 if (!SOSCCCanAuthenticate(&error)) {
689
690 if (error) {
691
692 /* Dump and consume the error. */
693 dump_cferror(log_file, "Could not call SOSCCCanAuthenticate", error);
694 } else {
695
696 fprintf(log_file, "Can Authenticate: NO\n");
697 }
698 } else {
699
700 fprintf(log_file, "Can Authenticate: YES\n");
701 }
702
703 /* Copy the peers. */
704 peer_list = SOSCCCopyPeerPeerInfo(&error);
705 if (!peer_list) {
706
707 /* Dump the error. */
708 dump_cferror(log_file, "Could not call SOSCCCopyPeerPeerInfo", error);
709 } else {
710
711 /* Get the number of peers. */
712 num_peers = CFArrayGetCount(peer_list);
713
714 fprintf(log_file, "Number of syncing peers: %ld\n", num_peers);
715
716 if (num_peers > 0) {
717
718 fprintf(log_file, "\n");
719 }
720
721 /* Enumerate the peers. */
722 for (i = 0; i < num_peers; i++) {
723
724 peer_info = (SOSPeerInfoRef) CFArrayGetValueAtIndex(peer_list, i);
725 if (peer_info == NULL) {
726
727 fprintf(stderr, "Could not extract peer %ld of %ld\n", i, num_peers);
728 goto BAIL;
729 }
730
731 /*
732 peer_gestalt = SOSPeerInfoCopyPeerGestalt(peer_info);
733 if (peer_gestalt == NULL) {
734
735 fprintf(stderr, "Could not copy peer gestalt %ld of %ld\n", i, num_peers);
736 goto BAIL;
737 }
738 */
739
740 /* Get the peer name. */
741 peer_name = SOSPeerInfoGetPeerName(peer_info);
742 if (peer_name == NULL) {
743
744 fprintf(stderr, "Could not extract peer name %ld of %ld\n", i, num_peers);
745 goto BAIL;
746 }
747
748 /* Convert the peer name to a C string. */
749 if (!CFStringGetCString(peer_name, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
750
751 fprintf(stderr, "Could not convert the peer name to a C string\n");
752 goto BAIL;
753 }
754
755 /* Dump the peer name. */
756 fprintf(log_file, " Peer Name: %s\n", buffer);
757
758 /* Get the peer device type. */
759 peer_device_type = SOSPeerInfoGetPeerDeviceType(peer_info);
760 if (peer_device_type == NULL) {
761
762 fprintf(stderr, "Could not extract peer device type %ld of %ld\n", i, num_peers);
763 goto BAIL;
764 }
765
766 /* Convert the peer device type to a C string. */
767 if (!CFStringGetCString(peer_device_type, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
768
769 fprintf(stderr, "Could not convert the peer device type to a C string\n");
770 goto BAIL;
771 }
772
773 /* Dump the peer name. */
774 fprintf(log_file, " Peer Device Type: %s\n", buffer);
775
776 /* Get the peer ID. */
777 peerID = SOSPeerInfoGetPeerID(peer_info);
778 if (peerID == NULL) {
779
780 fprintf(stderr, "Could not extract peer ID %ld of %ld\n", i, num_peers);
781 goto BAIL;
782 }
783
784 /* Dump the peer name. */
785 fprintf(log_file, " Peer ID: %s\n", buffer);
786
787 /* Convert the peer ID to a C string. */
788 if (!CFStringGetCString(peerID, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
789
790 fprintf(stderr, "Could not convert the peer ID to a C string\n");
791 goto BAIL;
792 }
793
794 /* Make it pretty. */
795 fprintf(log_file, "\n");
796 }
797
798 /* Release the peer list. */
799 CFRelease(peer_list);
800 peer_list = NULL;
801 }
802
803 /* Copy the applicant peers. */
804 peer_list = SOSCCCopyApplicantPeerInfo(&error);
805 if (!peer_list) {
806
807 /* Dump the error. */
808 dump_cferror(log_file, "Could not call SOSCCCopyApplicantPeerInfo", error);
809 } else {
810
811 /* Get the number of peers. */
812 num_peers = CFArrayGetCount(peer_list);
813
814 fprintf(log_file, "Number of applicant peers: %ld\n", num_peers);
815
816 if (num_peers > 0) {
817
818 fprintf(log_file, "\n");
819 }
820
821 /* Enumerate the peers. */
822 for (i = 0; i < num_peers; i++) {
823
824 peer_info = (SOSPeerInfoRef) CFArrayGetValueAtIndex(peer_list, i);
825 if (peer_info == NULL) {
826
827 fprintf(stderr, "Could not extract peer %ld of %ld\n", i, num_peers);
828 goto BAIL;
829 }
830
831 /*
832 peer_gestalt = SOSPeerInfoCopyPeerGestalt(peer_info);
833 if (peer_gestalt == NULL) {
834
835 fprintf(stderr, "Could not copy peer gestalt %ld of %ld\n", i, num_peers);
836 goto BAIL;
837 }
838 */
839
840 /* Get the peer name. */
841 peer_name = SOSPeerInfoGetPeerName(peer_info);
842 if (peer_name == NULL) {
843
844 fprintf(stderr, "Could not extract peer name %ld of %ld\n", i, num_peers);
845 goto BAIL;
846 }
847
848 /* Convert the peer name to a C string. */
849 if (!CFStringGetCString(peer_name, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
850
851 fprintf(stderr, "Could not convert the peer name to a C string\n");
852 goto BAIL;
853 }
854
855 /* Dump the peer name. */
856 fprintf(log_file, " Applicant Name: %s\n", buffer);
857
858 /* Get the peer device type. */
859 peer_device_type = SOSPeerInfoGetPeerDeviceType(peer_info);
860 if (peer_device_type == NULL) {
861
862 fprintf(stderr, "Could not extract peer device type %ld of %ld\n", i, num_peers);
863 goto BAIL;
864 }
865
866 /* Convert the peer device type to a C string. */
867 if (!CFStringGetCString(peer_device_type, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
868
869 fprintf(stderr, "Could not convert the peer device type to a C string\n");
870 goto BAIL;
871 }
872
873 /* Dump the peer name. */
874 fprintf(log_file, " Applicant Device Type: %s\n", buffer);
875
876 /* Get the peer ID. */
877 peerID = SOSPeerInfoGetPeerID(peer_info);
878 if (peerID == NULL) {
879
880 fprintf(stderr, "Could not extract peer ID %ld of %ld\n", i, num_peers);
881 goto BAIL;
882 }
883
884 /* Dump the peer name. */
885 fprintf(log_file, " Applicant ID: %s\n", buffer);
886
887 /* Convert the peer ID to a C string. */
888 if (!CFStringGetCString(peerID, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
889
890 fprintf(stderr, "Could not convert the peer ID to a C string\n");
891 goto BAIL;
892 }
893
894 /* Make it pretty. */
895 if (i < num_peers - 1) {
896
897 fprintf(log_file, "\n");
898 }
899 }
900
901 /* Release the peer list. */
902 CFRelease(peer_list);
903 peer_list = NULL;
904 }
905
906 /* Dump a footer. */
907 fprintf(log_file, "=================\n\n");
908
909 /* Set the result to success. */
910 result = SUCCESS;
911
912 BAIL:
913
914 /* Release the peer gestalt? */
915 if (peer_gestalt != NULL) {
916
917 CFRelease(peer_gestalt);
918 peer_gestalt = NULL;
919 }
920
921 /* Release the peer list? */
922 if (peer_list != NULL) {
923
924 CFRelease(peer_list);
925 peer_list = NULL;
926 }
927
928 /* Release the error string? */
929 if (error != NULL) {
930
931 CFRelease(error);
932 error = NULL;
933 }
934
935 return result;
936 }
937
938 static
939 int
940 dump_keychain_sync_kvs(
941 FILE *log_file)
942 {
943 int result = FAILURE;
944 dispatch_group_t cloud_group;
945 dispatch_queue_t cloud_queue;
946 dispatch_semaphore_t waitSemaphore;
947 dispatch_time_t finishTime;
948 __block CFDictionaryRef kvs_dict = NULL;
949
950 /*
951 * Dump the keychain syncing KVS.
952 */
953
954 /* Dump a header. */
955 fprintf(log_file, "Keychain Syncing KVS:\n");
956 fprintf(log_file, "=================\n");
957
958 /* Create the serial dispatch queue to talk to CloudKeychainProxy. */
959 cloud_queue = dispatch_queue_create("cloud_queue", DISPATCH_QUEUE_SERIAL);
960
961 /* Create a semaphore. */
962 waitSemaphore = dispatch_semaphore_create(0);
963
964 /* Create the finish time. */
965 finishTime = dispatch_time(DISPATCH_TIME_NOW, 30ull * NSEC_PER_SEC);
966
967 /* Create the dispatch group. */
968 cloud_group = dispatch_group_create();
969
970 /* Enter the dispatch group. */
971 dispatch_group_enter(cloud_group);
972
973 /* Establish the CloudKeychainProxy reply hander. */
974 CloudKeychainReplyBlock replyBlock = ^(CFDictionaryRef returnedValues, CFErrorRef error)
975 {
976 /* Did we get back some values? */
977 if (returnedValues) {
978
979 kvs_dict = (returnedValues);
980 CFRetain(kvs_dict);
981 }
982
983 /* Leave the cloud group. */
984 dispatch_group_leave(cloud_group);
985
986 /* Signal the other queue we're done. */
987 dispatch_semaphore_signal(waitSemaphore);
988 };
989
990 /* Ask CloudKeychainProxy for all of the raw KVS data. */
991 SOSCloudKeychainGetAllObjectsFromCloud(cloud_queue, replyBlock);
992
993 /* Wait for CloudKeychainProxy to respond, up to 30 seconds. */
994 dispatch_semaphore_wait(waitSemaphore, finishTime);
995
996 /* Release the semaphore. */
997 dispatch_release(waitSemaphore);
998
999 /* Did we get any raw KVS data from CloudKeychainProxy? */
1000 if (kvs_dict) {
1001
1002 dump_dict(log_file, kvs_dict, 0);
1003 }
1004
1005 /* Dump a footer. */
1006 fprintf(log_file, "=================\n\n");
1007
1008 /* Set the result to success. */
1009 result = SUCCESS;
1010
1011 /* Release the KVS dictionary? */
1012 if (kvs_dict != NULL) {
1013
1014 CFRelease(kvs_dict);
1015 kvs_dict = NULL;
1016 }
1017
1018 return result;
1019 }
1020
1021 static
1022 void
1023 dump_dict(
1024 FILE *log_file,
1025 CFDictionaryRef dict,
1026 const unsigned int indent_level)
1027 {
1028 struct dict_dump_state dump_state;
1029
1030 /* Setup the context. */
1031 dump_state.log_file = log_file;
1032 dump_state.dict = dict;
1033 dump_state.indent_level = indent_level;
1034
1035 /* Apply the dumper to each element in the dictionary. */
1036 CFDictionaryApplyFunction(dict, dump_dict_applier, (void *)&dump_state);
1037 }
1038
1039 static
1040 void
1041 dump_dict_applier(
1042 const void *key,
1043 const void *value,
1044 void *context)
1045 {
1046 CFTypeRef key_object;
1047 CFTypeRef value_object;
1048 struct dict_dump_state *dump_state;
1049 unsigned int i;
1050 char buffer[BUFFER_SIZE];
1051 CFIndex length;
1052 const UInt8* bytes;
1053
1054 /* Assign the CF types. */
1055 key_object = (CFTypeRef) key;
1056 value_object = (CFTypeRef) value;
1057
1058 /* Get the context. */
1059 dump_state = (struct dict_dump_state *)context;
1060
1061 /* Indent appropriately. */
1062 for (i = 0; i < dump_state->indent_level; i++) {
1063
1064 fprintf(dump_state->log_file, " ");
1065 }
1066
1067 /* Determine the key type. */
1068 if (CFGetTypeID(key_object) == CFStringGetTypeID()) {
1069
1070 /* Convert the key to a C string. */
1071 if (!CFStringGetCString((CFStringRef) key_object, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
1072
1073 fprintf(stderr, "Could not convert the key to a C string\n");
1074 fprintf(dump_state->log_file, "[Failed Key Type]: ");
1075 } else {
1076
1077 fprintf(dump_state->log_file, "%s: ", buffer);
1078 }
1079 }
1080
1081 /* Determine the value type. */
1082 if (CFGetTypeID(value_object) == CFStringGetTypeID()) {
1083
1084 /* Convert the value to a C string. */
1085 if (!CFStringGetCString((CFStringRef) value_object, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
1086
1087 fprintf(stderr, "Could not convert the value to a C string\n");
1088 fprintf(dump_state->log_file, "[Failed Value Type]: ");
1089 } else {
1090
1091 fprintf(dump_state->log_file, "%s\n", buffer);
1092 }
1093 } else if (CFGetTypeID(value_object) == CFDataGetTypeID()) {
1094
1095 length = CFDataGetLength((CFDataRef)value_object);
1096 bytes = CFDataGetBytePtr((CFDataRef) value_object);
1097
1098 fprintf(dump_state->log_file, "0x");
1099
1100 for (i = 0; i < (unsigned int)length && i < MAX_DATA_RATE; i++) {
1101
1102 fprintf(dump_state->log_file, "%02x", (unsigned char)bytes[i]);
1103 }
1104
1105 fprintf(dump_state->log_file, " (%ld bytes)\n", length);
1106
1107
1108 } else if (CFGetTypeID(value_object) == CFDictionaryGetTypeID()) {
1109
1110 /* Recurse */
1111 fprintf(dump_state->log_file, "\n");
1112 dump_dict(dump_state->log_file, (CFDictionaryRef) value_object, dump_state->indent_level + 1);
1113 } else {
1114
1115 fprintf(dump_state->log_file, "[Unknown Value Type]\n");
1116 }
1117 }
1118
1119 static
1120 int
1121 dump_asl_sender(
1122 FILE *log_file,
1123 const char *asl_sender)
1124 {
1125 int result = FAILURE;
1126 aslmsg log_query = NULL;
1127 aslresponse log_response = NULL;
1128 aslmsg log_message;
1129 char *message_string;
1130 uint32_t message_length;
1131
1132 /*
1133 * Dump the ASL logs for the given sender.
1134 */
1135
1136 /* Dump a header. */
1137 fprintf(log_file, "ASL: %s\n", asl_sender);
1138 fprintf(log_file, "=================\n");
1139
1140 /* Create the ASL query. */
1141 log_query = asl_new(ASL_TYPE_QUERY);
1142 if (log_query == NULL) {
1143
1144 fprintf(stderr, "Could not create ASL query\n");
1145 goto BAIL;
1146 }
1147
1148 /* Setup the ASL query. */
1149 asl_set_query(log_query, ASL_KEY_SENDER, asl_sender, ASL_QUERY_OP_EQUAL);
1150
1151 /* Perform the ASL search. */
1152 log_response = asl_search(NULL, log_query);
1153 if (log_response == NULL) {
1154
1155 fprintf(log_file, "Could not perform ASL search for %s\n", asl_sender);
1156 } else {
1157
1158 /* Enumerate the ASL messages in the response. */
1159 while ((log_message = asl_next(log_response)) != NULL) {
1160
1161 /* Format the message entry. */
1162 message_string = asl_format_message((asl_msg_t *)log_message, ASL_MSG_FMT_STD, ASL_TIME_FMT_LCL, ASL_ENCODE_SAFE, &message_length);
1163 if (message_string == NULL) {
1164
1165 fprintf(stderr, "Could not create ASL message string\n");
1166 goto BAIL;
1167 }
1168
1169 fprintf(log_file, "%s", message_string);
1170
1171 /* Release the message string. */
1172 free(message_string);
1173 message_string = NULL;
1174 }
1175 }
1176
1177 /* Dump a footer. */
1178 fprintf(log_file, "=================\n\n");
1179
1180 /* Set the result to success. */
1181 result = SUCCESS;
1182
1183 BAIL:
1184
1185 /* Release the ASL response? */
1186 if (log_response != NULL) {
1187
1188 asl_free(log_response);
1189 log_response = NULL;
1190 }
1191
1192 /* Release the ASL query? */
1193 if (log_query != NULL) {
1194
1195 asl_free(log_query);
1196 log_query = NULL;
1197 }
1198
1199 return result;
1200 }
1201
1202 static
1203 void
1204 dump_cferror(
1205 FILE *log_file,
1206 const char *description,
1207 CFErrorRef error)
1208 {
1209 CFStringRef error_string = NULL;
1210 char buffer[BUFFER_SIZE];
1211
1212 error_string = CFErrorCopyDescription(error);
1213 if (error_string == NULL) {
1214
1215 fprintf(stderr, "Could not copy error description?\n");
1216 goto BAIL;
1217 }
1218
1219 (void) CFStringGetCString(error_string, buffer, BUFFER_SIZE, kCFStringEncodingUTF8);
1220
1221 fprintf(stderr, "%s: %s\n", description, buffer);
1222 fprintf(log_file, "%s: %s\n", description, buffer);
1223
1224 BAIL:
1225
1226 /* Release the error string? */
1227 if (error_string != NULL) {
1228
1229 CFRelease(error_string);
1230 error_string = NULL;
1231 }
1232 }
1233
1234 #else // TARGET_IPHONE_SIMULATOR
1235
1236 int
1237 main(
1238 int argc,
1239 char **argv)
1240 {
1241 #pragma unused (argc, argv)
1242 return 0;
1243 }
1244
1245 #endif