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