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 */ 39typedef void (^CloudKeychainReplyBlock)(CFDictionaryRef returnedValues, CFErrorRef error); 40extern void SOSCloudKeychainGetAllObjectsFromCloud(dispatch_queue_t processQueue, CloudKeychainReplyBlock replyBlock); 41 42/* External AppleKeyStore Types */ 43enum { 44 my_keybag_state_bio_unlock = 1 << 3 45}; 46 47 48/* Dictionary Dump State */ 49struct dict_dump_state 50{ 51 FILE *log_file; 52 CFDictionaryRef dict; 53 unsigned int indent_level; 54}; 55 56/* Static Function Declarations */ 57static 58void 59usage(); 60 61static 62int 63gather_diagnostics(); 64 65static 66int 67enable_cloud_keychain_diagnostics( 68 const unsigned int enable_flag); 69 70static 71int 72build_log_path( 73 char *log_path); 74 75static 76int 77dump_system_information( 78 FILE *log_file); 79 80static 81int 82dump_circle_state( 83 FILE *log_file); 84 85static 86int 87dump_keychain_sync_kvs( 88 FILE *log_file); 89 90static 91void 92dump_dict( 93 FILE *log_file, 94 CFDictionaryRef dict, 95 const unsigned int indent_level); 96 97static 98void 99dump_dict_applier( 100 const void *key, 101 const void *value, 102 void *context); 103 104static 105int 106dump_asl_sender( 107 FILE *log_file, 108 const char *asl_sender); 109 110static 111void 112dump_cferror( 113 FILE *log_file, 114 const char *description, 115 CFErrorRef error); 116 117/* Function Definitions */ 118int 119main( 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 168BAIL: 169 170 return result; 171} 172 173/* Static Function Definitions */ 174static 175void 176usage() 177{ 178 fprintf(stderr, "usage: cloud_keychain_diagnose [enable|disable]\n"); 179 exit(EXIT_FAILURE); 180} 181 182static 183int 184gather_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 298BAIL: 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 318static 319int 320enable_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 331static 332int 333build_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 401BAIL: 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 413static 414int 415dump_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 602BAIL: 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 621static 622int 623dump_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 912BAIL: 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 938static 939int 940dump_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 1021static 1022void 1023dump_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 1039static 1040void 1041dump_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 1119static 1120int 1121dump_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 1183BAIL: 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 1202static 1203void 1204dump_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 1224BAIL: 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 1236int 1237main( 1238 int argc, 1239 char **argv) 1240{ 1241#pragma unused (argc, argv) 1242 return 0; 1243} 1244 1245#endif 1246