diff options
Diffstat (limited to 'src/lockdown.c')
| -rw-r--r-- | src/lockdown.c | 164 |
1 files changed, 108 insertions, 56 deletions
diff --git a/src/lockdown.c b/src/lockdown.c index ea161bc..a85f8ae 100644 --- a/src/lockdown.c +++ b/src/lockdown.c | |||
| @@ -656,10 +656,10 @@ lockdownd_error_t lockdownd_client_new_with_handshake(iphone_device_t device, lo | |||
| 656 | } | 656 | } |
| 657 | 657 | ||
| 658 | if (LOCKDOWN_E_SUCCESS == ret && !userpref_has_device_public_key(client_loc->uuid)) | 658 | if (LOCKDOWN_E_SUCCESS == ret && !userpref_has_device_public_key(client_loc->uuid)) |
| 659 | ret = lockdownd_pair(client_loc, host_id); | 659 | ret = lockdownd_pair(client_loc, NULL); |
| 660 | 660 | ||
| 661 | /* in any case, we need to validate pairing to receive trusted host status */ | 661 | /* in any case, we need to validate pairing to receive trusted host status */ |
| 662 | ret = lockdownd_validate_pair(client_loc, host_id); | 662 | ret = lockdownd_validate_pair(client_loc, NULL); |
| 663 | 663 | ||
| 664 | if (LOCKDOWN_E_SUCCESS == ret) { | 664 | if (LOCKDOWN_E_SUCCESS == ret) { |
| 665 | ret = lockdownd_start_session(client_loc, host_id, NULL, NULL); | 665 | ret = lockdownd_start_session(client_loc, host_id, NULL, NULL); |
| @@ -682,57 +682,109 @@ lockdownd_error_t lockdownd_client_new_with_handshake(iphone_device_t device, lo | |||
| 682 | return ret; | 682 | return ret; |
| 683 | } | 683 | } |
| 684 | 684 | ||
| 685 | static plist_t lockdownd_pair_record_to_plist(lockdownd_pair_record_t pair_record) | ||
| 686 | { | ||
| 687 | if (!pair_record) | ||
| 688 | return NULL; | ||
| 689 | |||
| 690 | char *host_id_loc = pair_record->host_id; | ||
| 691 | |||
| 692 | /* setup request plist */ | ||
| 693 | plist_t dict = plist_new_dict(); | ||
| 694 | plist_dict_insert_item(dict, "DeviceCertificate", plist_new_data(pair_record->device_certificate, strlen(pair_record->device_certificate))); | ||
| 695 | plist_dict_insert_item(dict, "HostCertificate", plist_new_data(pair_record->host_certificate, strlen(pair_record->host_certificate))); | ||
| 696 | if (!pair_record->host_id) | ||
| 697 | userpref_get_host_id(&host_id_loc); | ||
| 698 | plist_dict_insert_item(dict, "HostID", plist_new_string(host_id_loc)); | ||
| 699 | plist_dict_insert_item(dict, "RootCertificate", plist_new_data(pair_record->root_certificate, strlen(pair_record->root_certificate))); | ||
| 700 | |||
| 701 | if (!pair_record->host_id) | ||
| 702 | free(host_id_loc); | ||
| 703 | |||
| 704 | return dict; | ||
| 705 | } | ||
| 706 | |||
| 707 | static lockdownd_error_t generate_pair_record_plist(gnutls_datum_t public_key, char *host_id, plist_t *pair_record_plist) | ||
| 708 | { | ||
| 709 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | ||
| 710 | |||
| 711 | gnutls_datum_t device_cert = { NULL, 0 }; | ||
| 712 | gnutls_datum_t host_cert = { NULL, 0 }; | ||
| 713 | gnutls_datum_t root_cert = { NULL, 0 }; | ||
| 714 | |||
| 715 | ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert); | ||
| 716 | if (ret != LOCKDOWN_E_SUCCESS) { | ||
| 717 | return ret; | ||
| 718 | } | ||
| 719 | |||
| 720 | char *host_id_loc = host_id; | ||
| 721 | |||
| 722 | if (!host_id) | ||
| 723 | userpref_get_host_id(&host_id_loc); | ||
| 724 | |||
| 725 | /* setup request plist */ | ||
| 726 | *pair_record_plist = plist_new_dict(); | ||
| 727 | plist_dict_insert_item(*pair_record_plist, "DeviceCertificate", plist_new_data((const char*)device_cert.data, device_cert.size)); | ||
| 728 | plist_dict_insert_item(*pair_record_plist, "HostCertificate", plist_new_data((const char*)host_cert.data, host_cert.size)); | ||
| 729 | plist_dict_insert_item(*pair_record_plist, "HostID", plist_new_string(host_id_loc)); | ||
| 730 | plist_dict_insert_item(*pair_record_plist, "RootCertificate", plist_new_data((const char*)root_cert.data, root_cert.size)); | ||
| 731 | |||
| 732 | if (!host_id) | ||
| 733 | free(host_id_loc); | ||
| 734 | |||
| 735 | return ret; | ||
| 736 | } | ||
| 737 | |||
| 685 | /** Function used internally by lockdownd_pair() and lockdownd_validate_pair() | 738 | /** Function used internally by lockdownd_pair() and lockdownd_validate_pair() |
| 686 | * | 739 | * |
| 687 | * @param client The lockdown client to pair with. | 740 | * @param client The lockdown client to pair with. |
| 688 | * @param host_id The HostID to use for pairing. If NULL is passed, then | 741 | * @param pair_record The pair record to use for pairing. If NULL is passed, then |
| 689 | * the HostID of the current machine is used. A new HostID will be | 742 | * the pair records from the current machine are used. New records will be |
| 690 | * generated automatically when pairing is done for the first time. | 743 | * generated automatically when pairing is done for the first time. |
| 691 | * @param verb This is either "Pair" or "ValidatePair". | 744 | * @param verb This is either "Pair", "ValidatePair" or "Unpair". |
| 692 | * | 745 | * |
| 693 | * @return an error code (LOCKDOWN_E_SUCCESS on success) | 746 | * @return an error code (LOCKDOWN_E_SUCCESS on success) |
| 694 | */ | 747 | */ |
| 695 | static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, char *host_id, const char *verb) | 748 | static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record, const char *verb) |
| 696 | { | 749 | { |
| 697 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | 750 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 698 | plist_t dict = NULL; | 751 | plist_t dict = NULL; |
| 699 | plist_t dict_record = NULL; | 752 | plist_t dict_record = NULL; |
| 700 | |||
| 701 | gnutls_datum_t device_cert = { NULL, 0 }; | ||
| 702 | gnutls_datum_t host_cert = { NULL, 0 }; | ||
| 703 | gnutls_datum_t root_cert = { NULL, 0 }; | ||
| 704 | gnutls_datum_t public_key = { NULL, 0 }; | 753 | gnutls_datum_t public_key = { NULL, 0 }; |
| 754 | int pairing_mode = 0; /* 0 = libiphone, 1 = external */ | ||
| 705 | 755 | ||
| 706 | char *host_id_loc = host_id; | 756 | if (pair_record && pair_record->host_id) { |
| 707 | 757 | /* valid pair_record passed? */ | |
| 708 | ret = lockdownd_get_device_public_key(client, &public_key); | 758 | if (!pair_record->device_certificate || !pair_record->host_certificate || !pair_record->root_certificate) { |
| 709 | if (ret != LOCKDOWN_E_SUCCESS) { | 759 | return LOCKDOWN_E_PLIST_ERROR; |
| 710 | debug_info("device refused to send public key."); | 760 | } |
| 711 | return ret; | ||
| 712 | } | ||
| 713 | debug_info("device public key follows:\n%s", public_key.data); | ||
| 714 | 761 | ||
| 715 | ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert); | 762 | /* use passed pair_record */ |
| 716 | if (ret != LOCKDOWN_E_SUCCESS) { | 763 | dict_record = lockdownd_pair_record_to_plist(pair_record); |
| 717 | free(public_key.data); | ||
| 718 | return ret; | ||
| 719 | } | ||
| 720 | 764 | ||
| 721 | if (!host_id) { | 765 | pairing_mode = 1; |
| 722 | userpref_get_host_id(&host_id_loc); | 766 | } else { |
| 767 | ret = lockdownd_get_device_public_key(client, &public_key); | ||
| 768 | if (ret != LOCKDOWN_E_SUCCESS) { | ||
| 769 | if (public_key.data) | ||
| 770 | free(public_key.data); | ||
| 771 | debug_info("device refused to send public key."); | ||
| 772 | return ret; | ||
| 773 | } | ||
| 774 | debug_info("device public key follows:\n%s", public_key.data); | ||
| 775 | /* get libiphone pair_record */ | ||
| 776 | ret = generate_pair_record_plist(public_key, NULL, &dict_record); | ||
| 777 | if (ret != LOCKDOWN_E_SUCCESS) { | ||
| 778 | if (dict_record) | ||
| 779 | plist_free(dict_record); | ||
| 780 | return ret; | ||
| 781 | } | ||
| 723 | } | 782 | } |
| 724 | 783 | ||
| 725 | /* Setup Pair request plist */ | 784 | /* Setup Pair request plist */ |
| 726 | dict = plist_new_dict(); | 785 | dict = plist_new_dict(); |
| 727 | dict_record = plist_new_dict(); | ||
| 728 | plist_dict_add_label(dict, client->label); | 786 | plist_dict_add_label(dict, client->label); |
| 729 | plist_dict_insert_item(dict,"PairRecord", dict_record); | 787 | plist_dict_insert_item(dict,"PairRecord", dict_record); |
| 730 | |||
| 731 | plist_dict_insert_item(dict_record, "DeviceCertificate", plist_new_data((const char*)device_cert.data, device_cert.size)); | ||
| 732 | plist_dict_insert_item(dict_record, "HostCertificate", plist_new_data((const char*)host_cert.data, host_cert.size)); | ||
| 733 | plist_dict_insert_item(dict_record, "HostID", plist_new_string(host_id_loc)); | ||
| 734 | plist_dict_insert_item(dict_record, "RootCertificate", plist_new_data((const char*)root_cert.data, root_cert.size)); | ||
| 735 | |||
| 736 | plist_dict_insert_item(dict, "Request", plist_new_string(verb)); | 788 | plist_dict_insert_item(dict, "Request", plist_new_string(verb)); |
| 737 | 789 | ||
| 738 | /* send to iPhone */ | 790 | /* send to iPhone */ |
| @@ -740,10 +792,6 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, char *host | |||
| 740 | plist_free(dict); | 792 | plist_free(dict); |
| 741 | dict = NULL; | 793 | dict = NULL; |
| 742 | 794 | ||
| 743 | if (!host_id) { | ||
| 744 | free(host_id_loc); | ||
| 745 | } | ||
| 746 | |||
| 747 | if (ret != LOCKDOWN_E_SUCCESS) | 795 | if (ret != LOCKDOWN_E_SUCCESS) |
| 748 | return ret; | 796 | return ret; |
| 749 | 797 | ||
| @@ -760,12 +808,14 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, char *host | |||
| 760 | /* if pairing succeeded */ | 808 | /* if pairing succeeded */ |
| 761 | if (ret == LOCKDOWN_E_SUCCESS) { | 809 | if (ret == LOCKDOWN_E_SUCCESS) { |
| 762 | debug_info("%s success", verb); | 810 | debug_info("%s success", verb); |
| 763 | if (!strcmp("Unpair", verb)) { | 811 | if (!pairing_mode) { |
| 764 | /* remove public key from config */ | 812 | if (!strcmp("Unpair", verb)) { |
| 765 | userpref_remove_device_public_key(client->uuid); | 813 | /* remove public key from config */ |
| 766 | } else { | 814 | userpref_remove_device_public_key(client->uuid); |
| 767 | /* store public key in config */ | 815 | } else { |
| 768 | userpref_set_device_public_key(client->uuid, public_key); | 816 | /* store public key in config */ |
| 817 | userpref_set_device_public_key(client->uuid, public_key); | ||
| 818 | } | ||
| 769 | } | 819 | } |
| 770 | } else { | 820 | } else { |
| 771 | debug_info("%s failure", verb); | 821 | debug_info("%s failure", verb); |
| @@ -786,7 +836,8 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, char *host | |||
| 786 | } | 836 | } |
| 787 | plist_free(dict); | 837 | plist_free(dict); |
| 788 | dict = NULL; | 838 | dict = NULL; |
| 789 | free(public_key.data); | 839 | if (public_key.data) |
| 840 | free(public_key.data); | ||
| 790 | return ret; | 841 | return ret; |
| 791 | } | 842 | } |
| 792 | 843 | ||
| @@ -795,15 +846,15 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, char *host | |||
| 795 | * It's part of the lockdownd handshake. | 846 | * It's part of the lockdownd handshake. |
| 796 | * | 847 | * |
| 797 | * @param client The lockdown client to pair with. | 848 | * @param client The lockdown client to pair with. |
| 798 | * @param host_id The HostID to use for pairing. If NULL is passed, then | 849 | * @param pair_record The pair record to use for pairing. If NULL is passed, then |
| 799 | * the HostID of the current machine is used. A new HostID will be | 850 | * the pair records from the current machine are used. New records will be |
| 800 | * generated automatically when pairing is done for the first time. | 851 | * generated automatically when pairing is done for the first time. |
| 801 | * | 852 | * |
| 802 | * @return an error code (LOCKDOWN_E_SUCCESS on success) | 853 | * @return an error code (LOCKDOWN_E_SUCCESS on success) |
| 803 | */ | 854 | */ |
| 804 | lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *host_id) | 855 | lockdownd_error_t lockdownd_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) |
| 805 | { | 856 | { |
| 806 | return lockdownd_do_pair(client, host_id, "Pair"); | 857 | return lockdownd_do_pair(client, pair_record, "Pair"); |
| 807 | } | 858 | } |
| 808 | 859 | ||
| 809 | /** | 860 | /** |
| @@ -812,15 +863,16 @@ lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *host_id) | |||
| 812 | * It's part of the lockdownd handshake. | 863 | * It's part of the lockdownd handshake. |
| 813 | * | 864 | * |
| 814 | * @param client The lockdown client to pair with. | 865 | * @param client The lockdown client to pair with. |
| 815 | * @param host_id The HostID to use for pairing. If NULL is passed, then | 866 | * @param pair_record The pair record to validate pairing with. If NULL is |
| 816 | * the HostID of the current machine is used. A new HostID will be | 867 | * passed, then the pair records from the current machine are used. |
| 817 | * generated automatically when pairing is done for the first time. | 868 | * New records will be generated automatically when pairing is done |
| 869 | * for the first time. | ||
| 818 | * | 870 | * |
| 819 | * @return an error code (LOCKDOWN_E_SUCCESS on success) | 871 | * @return an error code (LOCKDOWN_E_SUCCESS on success) |
| 820 | */ | 872 | */ |
| 821 | lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, char *host_id) | 873 | lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) |
| 822 | { | 874 | { |
| 823 | return lockdownd_do_pair(client, host_id, "ValidatePair"); | 875 | return lockdownd_do_pair(client, pair_record, "ValidatePair"); |
| 824 | } | 876 | } |
| 825 | 877 | ||
| 826 | /** | 878 | /** |
| @@ -828,14 +880,14 @@ lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, char *host_ | |||
| 828 | * from the device and host. | 880 | * from the device and host. |
| 829 | * | 881 | * |
| 830 | * @param client The lockdown client to pair with. | 882 | * @param client The lockdown client to pair with. |
| 831 | * @param host_id The HostID to use for unpairing. If NULL is passed, then | 883 | * @param pair_record The pair record to use for unpair. If NULL is passed, then |
| 832 | * the HostID of the current machine is used. | 884 | * the pair records from the current machine are used. |
| 833 | * | 885 | * |
| 834 | * @return an error code (LOCKDOWN_E_SUCCESS on success) | 886 | * @return an error code (LOCKDOWN_E_SUCCESS on success) |
| 835 | */ | 887 | */ |
| 836 | lockdownd_error_t lockdownd_unpair(lockdownd_client_t client, char *host_id) | 888 | lockdownd_error_t lockdownd_unpair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) |
| 837 | { | 889 | { |
| 838 | return lockdownd_do_pair(client, host_id, "Unpair"); | 890 | return lockdownd_do_pair(client, pair_record, "Unpair"); |
| 839 | } | 891 | } |
| 840 | 892 | ||
| 841 | /** | 893 | /** |
