]> git.saurik.com Git - apple/security.git/blob - OSX/utilities/src/cloud_keychain_diagnose.c
Security-57337.50.23.tar.gz
[apple/security.git] / OSX / 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, "IDSKeychainSyncingProxy")) {
284
285 fprintf(stderr, "Could not dump the ASL log for IDSKeychainSyncingProxy\n");
286 goto BAIL;
287
288 }
289
290 if (dump_asl_sender(log_file, "securityd")) {
291
292 fprintf(stderr, "Could not dump the ASL log for securityd\n");
293 goto BAIL;
294 }
295
296 if (dump_asl_sender(log_file, "secd")) {
297
298 fprintf(stderr, "Could not dump the ASL log for secd\n");
299 goto BAIL;
300 }
301
302 /* Set the result to success. */
303 result = SUCCESS;
304
305 BAIL:
306
307 /* Close the diagnostics file? */
308 if (log_file != NULL) {
309
310 fclose(log_file);
311 log_file = NULL;
312 }
313
314 /* Close the diagnostics file descriptor? */
315 if (log_fd != -1) {
316
317 close(log_fd);
318 log_fd = -1;
319 (void) log_fd;
320 }
321
322 return result;
323 }
324
325 static
326 int
327 enable_cloud_keychain_diagnostics(
328 const unsigned int enable_flag)
329 {
330 int result = FAILURE;
331
332 /* Set the result to success. */
333 result = SUCCESS;
334
335 return result;
336 }
337
338 static
339 int
340 build_log_path(
341 char *log_path)
342 {
343 int result = FAILURE;
344 time_t now;
345 struct tm *time_cube;
346 CFDictionaryRef system_version_dict = NULL;
347 CFStringRef product_name = NULL;
348
349 /* Get the current time. */
350 now = time(NULL);
351
352 /* Convert the time into something usable. */
353 time_cube = localtime(&now);
354 if (time_cube == NULL) {
355
356 fprintf(stderr, "I don't know what time it is.\n");
357 goto BAIL;
358 }
359
360 /* Copy the system version dictionary. */
361 system_version_dict = _CFCopySystemVersionDictionary();
362 if (system_version_dict == NULL) {
363
364 fprintf(stderr, "Could not copy the system version dictionary\n");
365 goto BAIL;
366 }
367
368 /* Extract the product name. */
369 product_name = CFDictionaryGetValue(system_version_dict, _kCFSystemVersionProductNameKey);
370 if (product_name == NULL) {
371
372 fprintf(stderr, "Could not extract the product name from the system version dictionary\n");
373 goto BAIL;
374 }
375
376 /* Is this a Mac? */
377 if (CFEqual(product_name, CFSTR("Mac OS X"))) {
378
379 /* Prepare the file template to go into /tmp. */
380 snprintf(
381 log_path,
382 MAX_PATH_LEN,
383 "/tmp/cloud_keychain_diagnostics.%d_%d_%d.%d%d%d.XXXX.txt",
384 1900 + time_cube->tm_year,
385 time_cube->tm_mon,
386 time_cube->tm_mday,
387 time_cube->tm_hour,
388 time_cube->tm_min,
389 time_cube->tm_sec);
390 } else {
391
392 /* Prepare the file template to go into CrashReporter. */
393 snprintf(
394 log_path,
395 MAX_PATH_LEN,
396 "/Library/Logs/CrashReporter/cloud_keychain_diagnostics.%d_%d_%d.%d%d%d.XXXX.txt",
397 1900 + time_cube->tm_year,
398 time_cube->tm_mon,
399 time_cube->tm_mday,
400 time_cube->tm_hour,
401 time_cube->tm_min,
402 time_cube->tm_sec);
403 }
404
405 /* Set the result to success. */
406 result = SUCCESS;
407
408 BAIL:
409
410 /* Release the system version dictionary? */
411 if (system_version_dict != NULL) {
412
413 CFRelease(system_version_dict);
414 system_version_dict = NULL;
415 }
416
417 return result;
418 }
419
420 static
421 int
422 dump_system_information(
423 FILE *log_file)
424 {
425 int result = FAILURE;
426 CFDictionaryRef dict = NULL;
427 char buffer[BUFFER_SIZE];
428 CFStringRef product_name;
429 CFStringRef product_version;
430 CFStringRef product_build_version;
431 time_t now;
432 CFTypeRef shim_flag = NULL;
433 int keybag_handle = bad_keybag_handle;
434 kern_return_t kr = 0;
435 keybag_state_t keybag_state = 0;
436
437 /*
438 * Dump the system information.
439 * ProductName
440 * ProductVersion
441 * ProductBuildVersion
442 * Host name
443 */
444
445 /* Dump a header. */
446 fprintf(log_file, "Host Information:\n");
447 fprintf(log_file, "=================\n");
448
449 /* Copy the system version dictionary. */
450 dict = _CFCopySystemVersionDictionary();
451 if (dict == NULL) {
452
453 fprintf(stderr, "Could not copy the system version dictionary\n");
454 goto BAIL;
455 }
456
457 /* Extract the product name. */
458 product_name = CFDictionaryGetValue(dict, _kCFSystemVersionProductNameKey);
459 if (product_name == NULL) {
460
461 fprintf(stderr, "Could not extract the product name from the system version dictionary\n");
462 goto BAIL;
463 }
464
465 /* Convert the product name to a C string. */
466 if (!CFStringGetCString(product_name, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
467
468 fprintf(stderr, "Could not convert the product name to a C string\n");
469 goto BAIL;
470 }
471
472 /* Dump the product name. */
473 fprintf(log_file, "Product Name: %s\n", buffer);
474
475 /* Extract the product version. */
476 product_version = CFDictionaryGetValue(dict, _kCFSystemVersionProductVersionKey);
477 if (product_version == NULL) {
478
479 fprintf(stderr, "Could not extract the product version from the system version dictionary\n");
480 goto BAIL;
481 }
482
483 /* Convert the product version to a C string. */
484 if (!CFStringGetCString(product_version, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
485
486 fprintf(stderr, "Could not convert the product version to a C string\n");
487 goto BAIL;
488 }
489
490 /* Dump the product version */
491 fprintf(log_file, "Product Version: %s\n", buffer);
492
493 /* Extract the product build version. */
494 product_build_version = CFDictionaryGetValue(dict, _kCFSystemVersionBuildVersionKey);
495 if (product_build_version == NULL) {
496
497 fprintf(stderr, "Could not extract the product build version from the system version dictionary\n");
498 goto BAIL;
499 }
500
501 /* Convert the product build version to a C string. */
502 if (!CFStringGetCString(product_build_version, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
503
504 fprintf(stderr, "Could not convert the product build version to a C string\n");
505 goto BAIL;
506 }
507
508 /* Dump the product build version. */
509 fprintf(log_file, "Product Build Version: %s\n", buffer);
510
511 /* Lookup the host name. */
512 if (gethostname(buffer, BUFFER_SIZE) == -1) {
513
514 fprintf(stderr, "Could not lookup the host name\n");
515 goto BAIL;
516 }
517
518 /* Dump the host name. */
519 fprintf(log_file, "Host Name: %s\n", buffer);
520
521 /* Lookup the current time. */
522 if (gethostname(buffer, BUFFER_SIZE) == -1) {
523
524 fprintf(stderr, "Could not lookup the host name\n");
525 goto BAIL;
526 }
527
528 /* Get the current time. */
529 now = time(NULL);
530
531 /* Dump the current time. */
532 fprintf(log_file, "Time: %s", ctime(&now));
533
534 /* Is this a Mac? */
535 if (CFEqual(product_name, CFSTR("Mac OS X"))) {
536
537 /* Set the keybag handle. */
538 keybag_handle = session_keybag_handle;
539
540 /* Lookup the state of the shim. */
541 shim_flag = (CFNumberRef)CFPreferencesCopyValue(CFSTR("SecItemSynchronizable"), CFSTR("com.apple.security"), kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
542 if (shim_flag && CFGetTypeID(shim_flag) == CFBooleanGetTypeID()) {
543
544 /* Is the shim enabled? */
545 if (CFBooleanGetValue((CFBooleanRef)shim_flag)) {
546
547 fprintf(log_file, "The SecItem shim is enabled\n");
548 } else {
549
550 fprintf(log_file, "The SecItem shim is disabled\n");
551 }
552 } else {
553
554 fprintf(log_file, "The SecItem shim is disabled\n");
555 }
556 } else {
557
558 /* Set the keybag handle. */
559 keybag_handle = device_keybag_handle;
560 }
561
562 /* Get the keybag state. */
563 kr = aks_get_lock_state(keybag_handle, &keybag_state);
564 if (kr) {
565
566 fprintf(stderr, "Could not call aks_get_lock_state\n");
567 } else {
568
569 switch (keybag_state) {
570
571 case keybag_state_unlocked: {
572
573 fprintf(log_file, "Keybag State: Unlocked\n");
574 }break;
575
576 case keybag_state_locked: {
577
578 fprintf(log_file, "Keybag State: Locked\n");
579 }break;
580
581 case keybag_state_no_pin: {
582
583 fprintf(log_file, "Keybag State: No Passcode\n");
584 }break;
585
586 case keybag_state_been_unlocked: {
587
588 fprintf(log_file, "Keybag State: Been Unlocked\n");
589 }break;
590
591 case my_keybag_state_bio_unlock: {
592
593 fprintf(log_file, "Keybag State: Bio Unlock\n");
594 }break;
595
596 default: {
597
598 fprintf(log_file, "Keybag State: UNKNOWN\n");
599 }break;
600 }
601 }
602
603 /* Dump a footer. */
604 fprintf(log_file, "=================\n\n");
605
606 /* Set the result to success. */
607 result = SUCCESS;
608
609 BAIL:
610
611 /* Release the shim flag? */
612 if (shim_flag) {
613
614 CFRelease(shim_flag);
615 shim_flag = NULL;
616 }
617
618 /* Release the system version dictionary? */
619 if (dict != NULL) {
620
621 CFRelease(dict);
622 dict = NULL;
623 }
624
625 return result;
626 }
627
628 static
629 int
630 dump_circle_state(
631 FILE *log_file)
632 {
633 int result = FAILURE;
634 CFErrorRef error = NULL;
635 SOSCCStatus circle_status;
636 CFArrayRef peer_list = NULL;
637 CFIndex num_peers;
638 CFIndex i;
639 SOSPeerInfoRef peer_info;
640 CFDictionaryRef peer_gestalt = NULL;
641 CFStringRef peer_name;
642 CFStringRef peer_device_type;
643 CFStringRef peerID;
644 char buffer[BUFFER_SIZE] = {};
645
646 /*
647 * Dump the SOS circle state.
648 */
649
650 /* Dump a header. */
651 fprintf(log_file, "SOS Circle State:\n");
652 fprintf(log_file, "=================\n");
653
654 /* Are we in a circle? */
655 circle_status = SOSCCThisDeviceIsInCircle(&error);
656 if (error != NULL) {
657
658 /* Dump and consume the error. */
659 dump_cferror(log_file, "Could not call SOSCCThisDeviceIsInCircle", error);
660 } else {
661 char *circle_state_string = NULL;
662
663 switch (circle_status) {
664
665 case kSOSCCInCircle: {
666 circle_state_string = "kSOSCCInCircle";
667 }break;
668
669 case kSOSCCNotInCircle: {
670 circle_state_string = "kSOSCCNotInCircle";
671 }break;
672
673 case kSOSCCRequestPending: {
674 circle_state_string = "kSOSCCRequestPending";
675 }break;
676
677 case kSOSCCCircleAbsent: {
678 circle_state_string = "kSOSCCCircleAbsent";
679 }break;
680
681 case kSOSCCError: {
682 circle_state_string = "kSOSCCError";
683 }break;
684
685 default: {
686 sprintf(buffer, "Unknown circle status (%d)?", circle_status);
687 circle_state_string = buffer;
688 }
689 }
690
691 fprintf(log_file, "Circle Status: %s\n", circle_state_string);
692 }
693
694 /* Can we authenticate? */
695 if (!SOSCCCanAuthenticate(&error)) {
696
697 if (error) {
698
699 /* Dump and consume the error. */
700 dump_cferror(log_file, "Could not call SOSCCCanAuthenticate", error);
701 } else {
702
703 fprintf(log_file, "Can Authenticate: NO\n");
704 }
705 } else {
706
707 fprintf(log_file, "Can Authenticate: YES\n");
708 }
709
710 /* Copy the peers. */
711 peer_list = SOSCCCopyPeerPeerInfo(&error);
712 if (!peer_list) {
713
714 /* Dump the error. */
715 dump_cferror(log_file, "Could not call SOSCCCopyPeerPeerInfo", error);
716 } else {
717
718 /* Get the number of peers. */
719 num_peers = CFArrayGetCount(peer_list);
720
721 fprintf(log_file, "Number of syncing peers: %ld\n", num_peers);
722
723 if (num_peers > 0) {
724
725 fprintf(log_file, "\n");
726 }
727
728 /* Enumerate the peers. */
729 for (i = 0; i < num_peers; i++) {
730
731 peer_info = (SOSPeerInfoRef) CFArrayGetValueAtIndex(peer_list, i);
732 if (peer_info == NULL) {
733
734 fprintf(stderr, "Could not extract peer %ld of %ld\n", i, num_peers);
735 goto BAIL;
736 }
737
738 /*
739 peer_gestalt = SOSPeerInfoCopyPeerGestalt(peer_info);
740 if (peer_gestalt == NULL) {
741
742 fprintf(stderr, "Could not copy peer gestalt %ld of %ld\n", i, num_peers);
743 goto BAIL;
744 }
745 */
746
747 /* Get the peer name. */
748 peer_name = SOSPeerInfoGetPeerName(peer_info);
749 if (peer_name == NULL) {
750
751 fprintf(stderr, "Could not extract peer name %ld of %ld\n", i, num_peers);
752 goto BAIL;
753 }
754
755 /* Convert the peer name to a C string. */
756 if (!CFStringGetCString(peer_name, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
757
758 fprintf(stderr, "Could not convert the peer name to a C string\n");
759 goto BAIL;
760 }
761
762 /* Dump the peer name. */
763 fprintf(log_file, " Peer Name: %s\n", buffer);
764
765 /* Get the peer device type. */
766 peer_device_type = SOSPeerInfoGetPeerDeviceType(peer_info);
767 if (peer_device_type == NULL) {
768
769 fprintf(stderr, "Could not extract peer device type %ld of %ld\n", i, num_peers);
770 goto BAIL;
771 }
772
773 /* Convert the peer device type to a C string. */
774 if (!CFStringGetCString(peer_device_type, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
775
776 fprintf(stderr, "Could not convert the peer device type to a C string\n");
777 goto BAIL;
778 }
779
780 /* Dump the peer name. */
781 fprintf(log_file, " Peer Device Type: %s\n", buffer);
782
783 /* Get the peer ID. */
784 peerID = SOSPeerInfoGetPeerID(peer_info);
785 if (peerID == NULL) {
786
787 fprintf(stderr, "Could not extract peer ID %ld of %ld\n", i, num_peers);
788 goto BAIL;
789 }
790
791 /* Dump the peer name. */
792 fprintf(log_file, " Peer ID: %s\n", buffer);
793
794 /* Convert the peer ID to a C string. */
795 if (!CFStringGetCString(peerID, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
796
797 fprintf(stderr, "Could not convert the peer ID to a C string\n");
798 goto BAIL;
799 }
800
801 /* Make it pretty. */
802 fprintf(log_file, "\n");
803 }
804
805 /* Release the peer list. */
806 CFRelease(peer_list);
807 peer_list = NULL;
808 }
809
810 /* Copy the applicant peers. */
811 peer_list = SOSCCCopyApplicantPeerInfo(&error);
812 if (!peer_list) {
813
814 /* Dump the error. */
815 dump_cferror(log_file, "Could not call SOSCCCopyApplicantPeerInfo", error);
816 } else {
817
818 /* Get the number of peers. */
819 num_peers = CFArrayGetCount(peer_list);
820
821 fprintf(log_file, "Number of applicant peers: %ld\n", num_peers);
822
823 if (num_peers > 0) {
824
825 fprintf(log_file, "\n");
826 }
827
828 /* Enumerate the peers. */
829 for (i = 0; i < num_peers; i++) {
830
831 peer_info = (SOSPeerInfoRef) CFArrayGetValueAtIndex(peer_list, i);
832 if (peer_info == NULL) {
833
834 fprintf(stderr, "Could not extract peer %ld of %ld\n", i, num_peers);
835 goto BAIL;
836 }
837
838 /*
839 peer_gestalt = SOSPeerInfoCopyPeerGestalt(peer_info);
840 if (peer_gestalt == NULL) {
841
842 fprintf(stderr, "Could not copy peer gestalt %ld of %ld\n", i, num_peers);
843 goto BAIL;
844 }
845 */
846
847 /* Get the peer name. */
848 peer_name = SOSPeerInfoGetPeerName(peer_info);
849 if (peer_name == NULL) {
850
851 fprintf(stderr, "Could not extract peer name %ld of %ld\n", i, num_peers);
852 goto BAIL;
853 }
854
855 /* Convert the peer name to a C string. */
856 if (!CFStringGetCString(peer_name, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
857
858 fprintf(stderr, "Could not convert the peer name to a C string\n");
859 goto BAIL;
860 }
861
862 /* Dump the peer name. */
863 fprintf(log_file, " Applicant Name: %s\n", buffer);
864
865 /* Get the peer device type. */
866 peer_device_type = SOSPeerInfoGetPeerDeviceType(peer_info);
867 if (peer_device_type == NULL) {
868
869 fprintf(stderr, "Could not extract peer device type %ld of %ld\n", i, num_peers);
870 goto BAIL;
871 }
872
873 /* Convert the peer device type to a C string. */
874 if (!CFStringGetCString(peer_device_type, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
875
876 fprintf(stderr, "Could not convert the peer device type to a C string\n");
877 goto BAIL;
878 }
879
880 /* Dump the peer name. */
881 fprintf(log_file, " Applicant Device Type: %s\n", buffer);
882
883 /* Get the peer ID. */
884 peerID = SOSPeerInfoGetPeerID(peer_info);
885 if (peerID == NULL) {
886
887 fprintf(stderr, "Could not extract peer ID %ld of %ld\n", i, num_peers);
888 goto BAIL;
889 }
890
891 /* Dump the peer name. */
892 fprintf(log_file, " Applicant ID: %s\n", buffer);
893
894 /* Convert the peer ID to a C string. */
895 if (!CFStringGetCString(peerID, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
896
897 fprintf(stderr, "Could not convert the peer ID to a C string\n");
898 goto BAIL;
899 }
900
901 /* Make it pretty. */
902 if (i < num_peers - 1) {
903
904 fprintf(log_file, "\n");
905 }
906 }
907
908 /* Release the peer list. */
909 CFRelease(peer_list);
910 peer_list = NULL;
911 }
912
913 /* Dump a footer. */
914 fprintf(log_file, "=================\n\n");
915
916 /* Set the result to success. */
917 result = SUCCESS;
918
919 BAIL:
920
921 /* Release the peer gestalt? */
922 if (peer_gestalt != NULL) {
923
924 CFRelease(peer_gestalt);
925 peer_gestalt = NULL;
926 }
927
928 /* Release the peer list? */
929 if (peer_list != NULL) {
930
931 CFRelease(peer_list);
932 peer_list = NULL;
933 }
934
935 /* Release the error string? */
936 if (error != NULL) {
937
938 CFRelease(error);
939 error = NULL;
940 }
941
942 return result;
943 }
944
945 static
946 int
947 dump_keychain_sync_kvs(
948 FILE *log_file)
949 {
950 int result = FAILURE;
951 dispatch_group_t cloud_group;
952 dispatch_queue_t cloud_queue;
953 dispatch_semaphore_t waitSemaphore;
954 dispatch_time_t finishTime;
955 __block CFDictionaryRef kvs_dict = NULL;
956
957 /*
958 * Dump the keychain syncing KVS.
959 */
960
961 /* Dump a header. */
962 fprintf(log_file, "Keychain Syncing KVS:\n");
963 fprintf(log_file, "=================\n");
964
965 /* Create the serial dispatch queue to talk to CloudKeychainProxy. */
966 cloud_queue = dispatch_queue_create("cloud_queue", DISPATCH_QUEUE_SERIAL);
967
968 /* Create a semaphore. */
969 waitSemaphore = dispatch_semaphore_create(0);
970
971 /* Create the finish time. */
972 finishTime = dispatch_time(DISPATCH_TIME_NOW, 30ull * NSEC_PER_SEC);
973
974 /* Create the dispatch group. */
975 cloud_group = dispatch_group_create();
976
977 /* Enter the dispatch group. */
978 dispatch_group_enter(cloud_group);
979
980 /* Establish the CloudKeychainProxy reply hander. */
981 CloudKeychainReplyBlock replyBlock = ^(CFDictionaryRef returnedValues, CFErrorRef error)
982 {
983 /* Did we get back some values? */
984 if (returnedValues) {
985
986 kvs_dict = (returnedValues);
987 CFRetain(kvs_dict);
988 }
989
990 /* Leave the cloud group. */
991 dispatch_group_leave(cloud_group);
992
993 /* Signal the other queue we're done. */
994 dispatch_semaphore_signal(waitSemaphore);
995 };
996
997 /* Ask CloudKeychainProxy for all of the raw KVS data. */
998 SOSCloudKeychainGetAllObjectsFromCloud(cloud_queue, replyBlock);
999
1000 /* Wait for CloudKeychainProxy to respond, up to 30 seconds. */
1001 dispatch_semaphore_wait(waitSemaphore, finishTime);
1002
1003 /* Release the semaphore. */
1004 dispatch_release(waitSemaphore);
1005
1006 /* Did we get any raw KVS data from CloudKeychainProxy? */
1007 if (kvs_dict) {
1008
1009 dump_dict(log_file, kvs_dict, 0);
1010 }
1011
1012 /* Dump a footer. */
1013 fprintf(log_file, "=================\n\n");
1014
1015 /* Set the result to success. */
1016 result = SUCCESS;
1017
1018 /* Release the KVS dictionary? */
1019 if (kvs_dict != NULL) {
1020
1021 CFRelease(kvs_dict);
1022 kvs_dict = NULL;
1023 }
1024
1025 return result;
1026 }
1027
1028 static
1029 void
1030 dump_dict(
1031 FILE *log_file,
1032 CFDictionaryRef dict,
1033 const unsigned int indent_level)
1034 {
1035 struct dict_dump_state dump_state;
1036
1037 /* Setup the context. */
1038 dump_state.log_file = log_file;
1039 dump_state.dict = dict;
1040 dump_state.indent_level = indent_level;
1041
1042 /* Apply the dumper to each element in the dictionary. */
1043 CFDictionaryApplyFunction(dict, dump_dict_applier, (void *)&dump_state);
1044 }
1045
1046 static
1047 void
1048 dump_dict_applier(
1049 const void *key,
1050 const void *value,
1051 void *context)
1052 {
1053 CFTypeRef key_object;
1054 CFTypeRef value_object;
1055 struct dict_dump_state *dump_state;
1056 unsigned int i;
1057 char buffer[BUFFER_SIZE];
1058 CFIndex length;
1059 const UInt8* bytes;
1060
1061 /* Assign the CF types. */
1062 key_object = (CFTypeRef) key;
1063 value_object = (CFTypeRef) value;
1064
1065 /* Get the context. */
1066 dump_state = (struct dict_dump_state *)context;
1067
1068 /* Indent appropriately. */
1069 for (i = 0; i < dump_state->indent_level; i++) {
1070
1071 fprintf(dump_state->log_file, " ");
1072 }
1073
1074 /* Determine the key type. */
1075 if (CFGetTypeID(key_object) == CFStringGetTypeID()) {
1076
1077 /* Convert the key to a C string. */
1078 if (!CFStringGetCString((CFStringRef) key_object, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
1079
1080 fprintf(stderr, "Could not convert the key to a C string\n");
1081 fprintf(dump_state->log_file, "[Failed Key Type]: ");
1082 } else {
1083
1084 fprintf(dump_state->log_file, "%s: ", buffer);
1085 }
1086 }
1087
1088 /* Determine the value type. */
1089 if (CFGetTypeID(value_object) == CFStringGetTypeID()) {
1090
1091 /* Convert the value to a C string. */
1092 if (!CFStringGetCString((CFStringRef) value_object, buffer, BUFFER_SIZE, kCFStringEncodingUTF8)) {
1093
1094 fprintf(stderr, "Could not convert the value to a C string\n");
1095 fprintf(dump_state->log_file, "[Failed Value Type]: ");
1096 } else {
1097
1098 fprintf(dump_state->log_file, "%s\n", buffer);
1099 }
1100 } else if (CFGetTypeID(value_object) == CFDataGetTypeID()) {
1101
1102 length = CFDataGetLength((CFDataRef)value_object);
1103 bytes = CFDataGetBytePtr((CFDataRef) value_object);
1104
1105 fprintf(dump_state->log_file, "0x");
1106
1107 for (i = 0; i < (unsigned int)length && i < MAX_DATA_RATE; i++) {
1108
1109 fprintf(dump_state->log_file, "%02x", (unsigned char)bytes[i]);
1110 }
1111
1112 fprintf(dump_state->log_file, " (%ld bytes)\n", length);
1113
1114
1115 } else if (CFGetTypeID(value_object) == CFDictionaryGetTypeID()) {
1116
1117 /* Recurse */
1118 fprintf(dump_state->log_file, "\n");
1119 dump_dict(dump_state->log_file, (CFDictionaryRef) value_object, dump_state->indent_level + 1);
1120 } else {
1121
1122 fprintf(dump_state->log_file, "[Unknown Value Type]\n");
1123 }
1124 }
1125
1126 static
1127 int
1128 dump_asl_sender(
1129 FILE *log_file,
1130 const char *asl_sender)
1131 {
1132 int result = FAILURE;
1133 aslmsg log_query = NULL;
1134 aslresponse log_response = NULL;
1135 aslmsg log_message;
1136 char *message_string;
1137 uint32_t message_length;
1138
1139 /*
1140 * Dump the ASL logs for the given sender.
1141 */
1142
1143 /* Dump a header. */
1144 fprintf(log_file, "ASL: %s\n", asl_sender);
1145 fprintf(log_file, "=================\n");
1146
1147 /* Create the ASL query. */
1148 log_query = asl_new(ASL_TYPE_QUERY);
1149 if (log_query == NULL) {
1150
1151 fprintf(stderr, "Could not create ASL query\n");
1152 goto BAIL;
1153 }
1154
1155 /* Setup the ASL query. */
1156 asl_set_query(log_query, ASL_KEY_SENDER, asl_sender, ASL_QUERY_OP_EQUAL);
1157
1158 /* Perform the ASL search. */
1159 log_response = asl_search(NULL, log_query);
1160 if (log_response == NULL) {
1161
1162 fprintf(log_file, "Could not perform ASL search for %s\n", asl_sender);
1163 } else {
1164
1165 /* Enumerate the ASL messages in the response. */
1166 while ((log_message = asl_next(log_response)) != NULL) {
1167
1168 /* Format the message entry. */
1169 message_string = asl_format_message((asl_msg_t *)log_message, ASL_MSG_FMT_STD, ASL_TIME_FMT_LCL, ASL_ENCODE_SAFE, &message_length);
1170 if (message_string == NULL) {
1171
1172 fprintf(stderr, "Could not create ASL message string\n");
1173 goto BAIL;
1174 }
1175
1176 fprintf(log_file, "%s", message_string);
1177
1178 /* Release the message string. */
1179 free(message_string);
1180 message_string = NULL;
1181 }
1182 }
1183
1184 /* Dump a footer. */
1185 fprintf(log_file, "=================\n\n");
1186
1187 /* Set the result to success. */
1188 result = SUCCESS;
1189
1190 BAIL:
1191
1192 /* Release the ASL response? */
1193 if (log_response != NULL) {
1194
1195 asl_free(log_response);
1196 log_response = NULL;
1197 }
1198
1199 /* Release the ASL query? */
1200 if (log_query != NULL) {
1201
1202 asl_free(log_query);
1203 log_query = NULL;
1204 }
1205
1206 return result;
1207 }
1208
1209 static
1210 void
1211 dump_cferror(
1212 FILE *log_file,
1213 const char *description,
1214 CFErrorRef error)
1215 {
1216 CFStringRef error_string = NULL;
1217 char buffer[BUFFER_SIZE];
1218
1219 error_string = CFErrorCopyDescription(error);
1220 if (error_string == NULL) {
1221
1222 fprintf(stderr, "Could not copy error description?\n");
1223 goto BAIL;
1224 }
1225
1226 (void) CFStringGetCString(error_string, buffer, BUFFER_SIZE, kCFStringEncodingUTF8);
1227
1228 fprintf(stderr, "%s: %s\n", description, buffer);
1229 fprintf(log_file, "%s: %s\n", description, buffer);
1230
1231 BAIL:
1232
1233 /* Release the error string? */
1234 if (error_string != NULL) {
1235
1236 CFRelease(error_string);
1237 error_string = NULL;
1238 }
1239 }
1240
1241 #else // TARGET_IPHONE_SIMULATOR
1242
1243 int
1244 main(
1245 int argc,
1246 char **argv)
1247 {
1248 #pragma unused (argc, argv)
1249 return 0;
1250 }
1251
1252 #endif