diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/idevice.c | 2 | ||||
| -rw-r--r-- | src/lockdown.c | 257 | ||||
| -rw-r--r-- | src/lockdown.h | 4 |
3 files changed, 214 insertions, 49 deletions
diff --git a/src/idevice.c b/src/idevice.c index c605da3..4a6f544 100644 --- a/src/idevice.c +++ b/src/idevice.c | |||
| @@ -668,7 +668,7 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection) | |||
| 668 | key_data_t root_cert = { NULL, 0 }; | 668 | key_data_t root_cert = { NULL, 0 }; |
| 669 | key_data_t root_privkey = { NULL, 0 }; | 669 | key_data_t root_privkey = { NULL, 0 }; |
| 670 | 670 | ||
| 671 | userpref_error_t uerr = userpref_get_keys_and_certs(&root_privkey, &root_cert, NULL, NULL); | 671 | userpref_error_t uerr = userpref_device_record_get_keys_and_certs(connection->udid, &root_privkey, &root_cert, NULL, NULL); |
| 672 | if (uerr != USERPREF_E_SUCCESS) { | 672 | if (uerr != USERPREF_E_SUCCESS) { |
| 673 | debug_info("Error %d when loading keys and certificates! %d", uerr); | 673 | debug_info("Error %d when loading keys and certificates! %d", uerr); |
| 674 | } | 674 | } |
diff --git a/src/lockdown.c b/src/lockdown.c index b07366b..7c516c1 100644 --- a/src/lockdown.c +++ b/src/lockdown.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #define __USE_GNU 1 | 30 | #define __USE_GNU 1 |
| 31 | #include <stdio.h> | 31 | #include <stdio.h> |
| 32 | #include <ctype.h> | 32 | #include <ctype.h> |
| 33 | #include <unistd.h> | ||
| 33 | #ifdef HAVE_OPENSSL | 34 | #ifdef HAVE_OPENSSL |
| 34 | #include <openssl/pem.h> | 35 | #include <openssl/pem.h> |
| 35 | #include <openssl/x509.h> | 36 | #include <openssl/x509.h> |
| @@ -47,6 +48,11 @@ | |||
| 47 | #include "common/userpref.h" | 48 | #include "common/userpref.h" |
| 48 | #include "asprintf.h" | 49 | #include "asprintf.h" |
| 49 | 50 | ||
| 51 | #ifdef WIN32 | ||
| 52 | #include <windows.h> | ||
| 53 | #define sleep(x) Sleep(x*1000) | ||
| 54 | #endif | ||
| 55 | |||
| 50 | #define RESULT_SUCCESS 0 | 56 | #define RESULT_SUCCESS 0 |
| 51 | #define RESULT_FAILURE 1 | 57 | #define RESULT_FAILURE 1 |
| 52 | 58 | ||
| @@ -209,28 +215,18 @@ lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client, const char * | |||
| 209 | return ret; | 215 | return ret; |
| 210 | } | 216 | } |
| 211 | 217 | ||
| 212 | /** | 218 | static lockdownd_error_t lockdownd_client_free_simple(lockdownd_client_t client) |
| 213 | * Closes the lockdownd client session if one is running and frees up the | ||
| 214 | * lockdownd_client struct. | ||
| 215 | * | ||
| 216 | * @param client The lockdown client | ||
| 217 | * | ||
| 218 | * @return LOCKDOWN_E_SUCCESS on success, NP_E_INVALID_ARG when client is NULL | ||
| 219 | */ | ||
| 220 | lockdownd_error_t lockdownd_client_free(lockdownd_client_t client) | ||
| 221 | { | 219 | { |
| 222 | if (!client) | 220 | if (!client) |
| 223 | return LOCKDOWN_E_INVALID_ARG; | 221 | return LOCKDOWN_E_INVALID_ARG; |
| 222 | |||
| 224 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | 223 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 225 | 224 | ||
| 226 | if (client->session_id) { | 225 | if (client->session_id) { |
| 227 | lockdownd_stop_session(client, client->session_id); | ||
| 228 | free(client->session_id); | 226 | free(client->session_id); |
| 229 | } | 227 | } |
| 230 | 228 | ||
| 231 | if (client->parent) { | 229 | if (client->parent) { |
| 232 | lockdownd_goodbye(client); | ||
| 233 | |||
| 234 | if (property_list_service_client_free(client->parent) == PROPERTY_LIST_SERVICE_E_SUCCESS) { | 230 | if (property_list_service_client_free(client->parent) == PROPERTY_LIST_SERVICE_E_SUCCESS) { |
| 235 | ret = LOCKDOWN_E_SUCCESS; | 231 | ret = LOCKDOWN_E_SUCCESS; |
| 236 | } | 232 | } |
| @@ -244,6 +240,36 @@ lockdownd_error_t lockdownd_client_free(lockdownd_client_t client) | |||
| 244 | } | 240 | } |
| 245 | 241 | ||
| 246 | free(client); | 242 | free(client); |
| 243 | |||
| 244 | return ret; | ||
| 245 | } | ||
| 246 | |||
| 247 | /** | ||
| 248 | * Closes the lockdownd client session if one is running and frees up the | ||
| 249 | * lockdownd_client struct. | ||
| 250 | * | ||
| 251 | * @param client The lockdown client | ||
| 252 | * | ||
| 253 | * @return LOCKDOWN_E_SUCCESS on success, NP_E_INVALID_ARG when client is NULL | ||
| 254 | */ | ||
| 255 | lockdownd_error_t lockdownd_client_free(lockdownd_client_t client) | ||
| 256 | { | ||
| 257 | if (!client) | ||
| 258 | return LOCKDOWN_E_INVALID_ARG; | ||
| 259 | |||
| 260 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | ||
| 261 | |||
| 262 | |||
| 263 | if (client->session_id) { | ||
| 264 | lockdownd_stop_session(client, client->session_id); | ||
| 265 | } | ||
| 266 | |||
| 267 | if (client->parent) { | ||
| 268 | lockdownd_goodbye(client); | ||
| 269 | } | ||
| 270 | |||
| 271 | ret = lockdownd_client_free_simple(client); | ||
| 272 | |||
| 247 | return ret; | 273 | return ret; |
| 248 | } | 274 | } |
| 249 | 275 | ||
| @@ -674,6 +700,33 @@ lockdownd_error_t lockdownd_client_new(idevice_t device, lockdownd_client_t *cli | |||
| 674 | return LOCKDOWN_E_SUCCESS; | 700 | return LOCKDOWN_E_SUCCESS; |
| 675 | } | 701 | } |
| 676 | 702 | ||
| 703 | static lockdownd_error_t lockdownd_client_reconnect(idevice_t device, lockdownd_client_t *client, const char *label) | ||
| 704 | { | ||
| 705 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; | ||
| 706 | int attempts = 3; | ||
| 707 | char *udid = NULL; | ||
| 708 | |||
| 709 | /* free resources of lockownd_client */ | ||
| 710 | ret = lockdownd_client_free_simple(*client); | ||
| 711 | *client = NULL; | ||
| 712 | |||
| 713 | /* try to reconnect */ | ||
| 714 | do { | ||
| 715 | debug_info("reconnecting to udid %s, %d remaining attempts", udid, attempts); | ||
| 716 | ret = lockdownd_client_new(device, client, label); | ||
| 717 | if (ret == LOCKDOWN_E_SUCCESS) { | ||
| 718 | debug_info("reconnected to lockdownd with err %d", ret); | ||
| 719 | break; | ||
| 720 | } | ||
| 721 | sleep(1); | ||
| 722 | } while(attempts--); | ||
| 723 | |||
| 724 | free(udid); | ||
| 725 | udid = NULL; | ||
| 726 | |||
| 727 | return ret; | ||
| 728 | } | ||
| 729 | |||
| 677 | /** | 730 | /** |
| 678 | * Creates a new lockdownd client for the device and starts initial handshake. | 731 | * Creates a new lockdownd client for the device and starts initial handshake. |
| 679 | * The handshake consists out of query_type, validate_pair, pair and | 732 | * The handshake consists out of query_type, validate_pair, pair and |
| @@ -698,8 +751,10 @@ lockdownd_error_t lockdownd_client_new_with_handshake(idevice_t device, lockdown | |||
| 698 | 751 | ||
| 699 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; | 752 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; |
| 700 | lockdownd_client_t client_loc = NULL; | 753 | lockdownd_client_t client_loc = NULL; |
| 754 | char *system_buid = NULL; | ||
| 701 | char *host_id = NULL; | 755 | char *host_id = NULL; |
| 702 | char *type = NULL; | 756 | char *type = NULL; |
| 757 | int product_version_major = 0; | ||
| 703 | 758 | ||
| 704 | ret = lockdownd_client_new(device, &client_loc, label); | 759 | ret = lockdownd_client_new(device, &client_loc, label); |
| 705 | if (LOCKDOWN_E_SUCCESS != ret) { | 760 | if (LOCKDOWN_E_SUCCESS != ret) { |
| @@ -719,22 +774,55 @@ lockdownd_error_t lockdownd_client_new_with_handshake(idevice_t device, lockdown | |||
| 719 | free(type); | 774 | free(type); |
| 720 | } | 775 | } |
| 721 | 776 | ||
| 722 | userpref_get_host_id(&host_id); | 777 | /* get product version */ |
| 778 | plist_t product_version_node = NULL; | ||
| 779 | char* product_version = NULL; | ||
| 780 | lockdownd_get_value(client_loc, NULL, "ProductVersion", &product_version_node); | ||
| 781 | if (product_version_node && plist_get_node_type(product_version_node) == PLIST_STRING) { | ||
| 782 | plist_get_string_val(product_version_node, &product_version); | ||
| 783 | product_version_major = strtol(product_version, NULL, 10); | ||
| 784 | } | ||
| 785 | |||
| 786 | if (product_version_major >= 7) { | ||
| 787 | userpref_get_system_buid(&system_buid); | ||
| 788 | |||
| 789 | /* set our BUID for the trust dialog so the next pairing can succeed */ | ||
| 790 | lockdownd_set_value(client_loc, NULL, "UntrustedHostBUID", plist_new_string(system_buid)); | ||
| 791 | free(system_buid); | ||
| 792 | system_buid = NULL; | ||
| 793 | } | ||
| 794 | |||
| 795 | userpref_device_record_get_host_id(client_loc->udid, &host_id); | ||
| 723 | if (LOCKDOWN_E_SUCCESS == ret && !host_id) { | 796 | if (LOCKDOWN_E_SUCCESS == ret && !host_id) { |
| 724 | ret = LOCKDOWN_E_INVALID_CONF; | 797 | ret = LOCKDOWN_E_INVALID_CONF; |
| 725 | } | 798 | } |
| 726 | 799 | ||
| 727 | if (LOCKDOWN_E_SUCCESS == ret && !userpref_has_device_public_key(client_loc->udid)) | 800 | if (LOCKDOWN_E_SUCCESS == ret && !userpref_has_device_record(client_loc->udid)) { |
| 801 | /* attempt pairing */ | ||
| 728 | ret = lockdownd_pair(client_loc, NULL); | 802 | ret = lockdownd_pair(client_loc, NULL); |
| 729 | 803 | ||
| 804 | if (ret == LOCKDOWN_E_SUCCESS && product_version_major >= 7) { | ||
| 805 | /* the trust dialog was dissmissed, thus the device will reconnect after pairing */ | ||
| 806 | lockdownd_client_reconnect(device, &client_loc, label); | ||
| 807 | } | ||
| 808 | } | ||
| 809 | |||
| 730 | /* in any case, we need to validate pairing to receive trusted host status */ | 810 | /* in any case, we need to validate pairing to receive trusted host status */ |
| 731 | ret = lockdownd_validate_pair(client_loc, NULL); | 811 | ret = lockdownd_validate_pair(client_loc, NULL); |
| 732 | 812 | ||
| 733 | /* if not paired yet, let's do it now */ | 813 | /* if not paired yet, let's do it now */ |
| 734 | if (LOCKDOWN_E_INVALID_HOST_ID == ret) { | 814 | if (LOCKDOWN_E_INVALID_HOST_ID == ret) { |
| 735 | ret = lockdownd_pair(client_loc, NULL); | 815 | ret = lockdownd_pair(client_loc, NULL); |
| 816 | |||
| 817 | if (ret == LOCKDOWN_E_SUCCESS && product_version_major >= 7) { | ||
| 818 | /* the trust dialog was dissmissed, thus the device will reconnect after pairing */ | ||
| 819 | lockdownd_client_reconnect(device, &client_loc, label); | ||
| 820 | } | ||
| 821 | |||
| 736 | if (LOCKDOWN_E_SUCCESS == ret) { | 822 | if (LOCKDOWN_E_SUCCESS == ret) { |
| 737 | ret = lockdownd_validate_pair(client_loc, NULL); | 823 | ret = lockdownd_validate_pair(client_loc, NULL); |
| 824 | } else if (LOCKDOWN_E_PAIRING_DIALOG_PENDING == ret) { | ||
| 825 | debug_info("Device shows the pairing dialog."); | ||
| 738 | } | 826 | } |
| 739 | } | 827 | } |
| 740 | 828 | ||
| @@ -772,19 +860,13 @@ static plist_t lockdownd_pair_record_to_plist(lockdownd_pair_record_t pair_recor | |||
| 772 | if (!pair_record) | 860 | if (!pair_record) |
| 773 | return NULL; | 861 | return NULL; |
| 774 | 862 | ||
| 775 | char *host_id_loc = pair_record->host_id; | ||
| 776 | |||
| 777 | /* setup request plist */ | 863 | /* setup request plist */ |
| 778 | plist_t dict = plist_new_dict(); | 864 | plist_t dict = plist_new_dict(); |
| 779 | plist_dict_insert_item(dict, "DeviceCertificate", plist_new_data(pair_record->device_certificate, strlen(pair_record->device_certificate))); | 865 | plist_dict_insert_item(dict, "DeviceCertificate", plist_new_data(pair_record->device_certificate, strlen(pair_record->device_certificate))); |
| 780 | plist_dict_insert_item(dict, "HostCertificate", plist_new_data(pair_record->host_certificate, strlen(pair_record->host_certificate))); | 866 | plist_dict_insert_item(dict, "HostCertificate", plist_new_data(pair_record->host_certificate, strlen(pair_record->host_certificate))); |
| 781 | if (!pair_record->host_id) | 867 | plist_dict_insert_item(dict, "HostID", plist_new_string(pair_record->host_id)); |
| 782 | userpref_get_host_id(&host_id_loc); | ||
| 783 | plist_dict_insert_item(dict, "HostID", plist_new_string(host_id_loc)); | ||
| 784 | plist_dict_insert_item(dict, "RootCertificate", plist_new_data(pair_record->root_certificate, strlen(pair_record->root_certificate))); | 868 | plist_dict_insert_item(dict, "RootCertificate", plist_new_data(pair_record->root_certificate, strlen(pair_record->root_certificate))); |
| 785 | 869 | plist_dict_insert_item(dict, "SystemBUID", plist_new_string(pair_record->system_buid)); | |
| 786 | if (!pair_record->host_id) | ||
| 787 | free(host_id_loc); | ||
| 788 | 870 | ||
| 789 | return dict; | 871 | return dict; |
| 790 | } | 872 | } |
| @@ -800,7 +882,7 @@ static plist_t lockdownd_pair_record_to_plist(lockdownd_pair_record_t pair_recor | |||
| 800 | * | 882 | * |
| 801 | * @return LOCKDOWN_E_SUCCESS on success | 883 | * @return LOCKDOWN_E_SUCCESS on success |
| 802 | */ | 884 | */ |
| 803 | static lockdownd_error_t generate_pair_record_plist(key_data_t public_key, char *host_id, plist_t *pair_record_plist) | 885 | static lockdownd_error_t generate_pair_record_plist(const char *udid, char* system_buid, char *host_id, key_data_t public_key, plist_t *pair_record_plist) |
| 804 | { | 886 | { |
| 805 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | 887 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 806 | 888 | ||
| @@ -808,25 +890,18 @@ static lockdownd_error_t generate_pair_record_plist(key_data_t public_key, char | |||
| 808 | key_data_t host_cert = { NULL, 0 }; | 890 | key_data_t host_cert = { NULL, 0 }; |
| 809 | key_data_t root_cert = { NULL, 0 }; | 891 | key_data_t root_cert = { NULL, 0 }; |
| 810 | 892 | ||
| 811 | ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert); | 893 | ret = lockdownd_gen_pair_cert_for_udid(udid, public_key, &device_cert, &host_cert, &root_cert); |
| 812 | if (ret != LOCKDOWN_E_SUCCESS) { | 894 | if (ret != LOCKDOWN_E_SUCCESS) { |
| 813 | return ret; | 895 | return ret; |
| 814 | } | 896 | } |
| 815 | 897 | ||
| 816 | char *host_id_loc = host_id; | ||
| 817 | |||
| 818 | if (!host_id) | ||
| 819 | userpref_get_host_id(&host_id_loc); | ||
| 820 | |||
| 821 | /* setup request plist */ | 898 | /* setup request plist */ |
| 822 | *pair_record_plist = plist_new_dict(); | 899 | *pair_record_plist = plist_new_dict(); |
| 823 | plist_dict_insert_item(*pair_record_plist, "DeviceCertificate", plist_new_data((const char*)device_cert.data, device_cert.size)); | 900 | plist_dict_insert_item(*pair_record_plist, "DeviceCertificate", plist_new_data((const char*)device_cert.data, device_cert.size)); |
| 824 | plist_dict_insert_item(*pair_record_plist, "HostCertificate", plist_new_data((const char*)host_cert.data, host_cert.size)); | 901 | plist_dict_insert_item(*pair_record_plist, "HostCertificate", plist_new_data((const char*)host_cert.data, host_cert.size)); |
| 825 | plist_dict_insert_item(*pair_record_plist, "HostID", plist_new_string(host_id_loc)); | 902 | plist_dict_insert_item(*pair_record_plist, "HostID", plist_new_string(host_id)); |
| 826 | plist_dict_insert_item(*pair_record_plist, "RootCertificate", plist_new_data((const char*)root_cert.data, root_cert.size)); | 903 | plist_dict_insert_item(*pair_record_plist, "RootCertificate", plist_new_data((const char*)root_cert.data, root_cert.size)); |
| 827 | 904 | plist_dict_insert_item(*pair_record_plist, "SystemBUID", plist_new_string(system_buid)); | |
| 828 | if (!host_id) | ||
| 829 | free(host_id_loc); | ||
| 830 | 905 | ||
| 831 | if (device_cert.data) | 906 | if (device_cert.data) |
| 832 | free(device_cert.data); | 907 | free(device_cert.data); |
| @@ -863,8 +938,10 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ | |||
| 863 | plist_t dict_record = NULL; | 938 | plist_t dict_record = NULL; |
| 864 | key_data_t public_key = { NULL, 0 }; | 939 | key_data_t public_key = { NULL, 0 }; |
| 865 | int pairing_mode = 0; /* 0 = libimobiledevice, 1 = external */ | 940 | int pairing_mode = 0; /* 0 = libimobiledevice, 1 = external */ |
| 941 | char* host_id = NULL; | ||
| 942 | char* system_buid = NULL; | ||
| 866 | 943 | ||
| 867 | if (pair_record && pair_record->host_id) { | 944 | if (pair_record && pair_record->system_buid && pair_record->host_id) { |
| 868 | /* valid pair_record passed? */ | 945 | /* valid pair_record passed? */ |
| 869 | if (!pair_record->device_certificate || !pair_record->host_certificate || !pair_record->root_certificate) { | 946 | if (!pair_record->device_certificate || !pair_record->host_certificate || !pair_record->root_certificate) { |
| 870 | return LOCKDOWN_E_PLIST_ERROR; | 947 | return LOCKDOWN_E_PLIST_ERROR; |
| @@ -883,34 +960,73 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ | |||
| 883 | return ret; | 960 | return ret; |
| 884 | } | 961 | } |
| 885 | debug_info("device public key follows:\n%.*s", public_key.size, public_key.data); | 962 | debug_info("device public key follows:\n%.*s", public_key.size, public_key.data); |
| 963 | |||
| 886 | /* get libimobiledevice pair_record */ | 964 | /* get libimobiledevice pair_record */ |
| 887 | ret = generate_pair_record_plist(public_key, NULL, &dict_record); | 965 | userpref_get_system_buid(&system_buid); |
| 966 | userpref_device_record_get_host_id(client->udid, &host_id); | ||
| 967 | userpref_device_record_set_value(client->udid, USERPREF_SYSTEM_BUID_KEY, plist_new_string(system_buid)); | ||
| 968 | |||
| 969 | ret = generate_pair_record_plist(client->udid, system_buid, host_id, public_key, &dict_record); | ||
| 970 | |||
| 971 | if (host_id) | ||
| 972 | free(host_id); | ||
| 973 | if (system_buid) | ||
| 974 | free(system_buid); | ||
| 975 | |||
| 888 | if (ret != LOCKDOWN_E_SUCCESS) { | 976 | if (ret != LOCKDOWN_E_SUCCESS) { |
| 977 | if (public_key.data) | ||
| 978 | free(public_key.data); | ||
| 889 | if (dict_record) | 979 | if (dict_record) |
| 890 | plist_free(dict_record); | 980 | plist_free(dict_record); |
| 891 | return ret; | 981 | return ret; |
| 892 | } | 982 | } |
| 893 | } | 983 | } |
| 894 | 984 | ||
| 895 | /* Setup Pair request plist */ | 985 | if (!strcmp("Pair", verb)) { |
| 986 | /* get wifi mac */ | ||
| 987 | plist_t wifi_mac_node = NULL; | ||
| 988 | lockdownd_get_value(client, NULL, "WiFiAddress", &wifi_mac_node); | ||
| 989 | |||
| 990 | /* save wifi mac address in config */ | ||
| 991 | if (wifi_mac_node) { | ||
| 992 | userpref_device_record_set_value(client->udid, USERPREF_WIFI_MAC_ADDRESS_KEY, plist_copy(wifi_mac_node)); | ||
| 993 | plist_free(wifi_mac_node); | ||
| 994 | wifi_mac_node = NULL; | ||
| 995 | } | ||
| 996 | } | ||
| 997 | |||
| 998 | /* setup pair request plist */ | ||
| 896 | dict = plist_new_dict(); | 999 | dict = plist_new_dict(); |
| 897 | plist_dict_add_label(dict, client->label); | 1000 | plist_dict_add_label(dict, client->label); |
| 898 | plist_dict_insert_item(dict,"PairRecord", dict_record); | 1001 | plist_dict_insert_item(dict, "PairRecord", plist_copy(dict_record)); |
| 899 | plist_dict_insert_item(dict, "Request", plist_new_string(verb)); | 1002 | plist_dict_insert_item(dict, "Request", plist_new_string(verb)); |
| 1003 | plist_dict_insert_item(dict, "ProtocolVersion", plist_new_string(LOCKDOWN_PROTOCOL_VERSION)); | ||
| 1004 | |||
| 1005 | plist_t options = plist_new_dict(); | ||
| 1006 | plist_dict_insert_item(options, "ExtendedPairingErrors", plist_new_bool(1)); | ||
| 1007 | plist_dict_insert_item(dict, "PairingOptions", options); | ||
| 900 | 1008 | ||
| 901 | /* send to device */ | 1009 | /* send to device */ |
| 902 | ret = lockdownd_send(client, dict); | 1010 | ret = lockdownd_send(client, dict); |
| 903 | plist_free(dict); | 1011 | plist_free(dict); |
| 904 | dict = NULL; | 1012 | dict = NULL; |
| 905 | 1013 | ||
| 906 | if (ret != LOCKDOWN_E_SUCCESS) | 1014 | if (ret != LOCKDOWN_E_SUCCESS) { |
| 1015 | if (public_key.data) | ||
| 1016 | free(public_key.data); | ||
| 1017 | plist_free(dict_record); | ||
| 907 | return ret; | 1018 | return ret; |
| 1019 | } | ||
| 908 | 1020 | ||
| 909 | /* Now get device's answer */ | 1021 | /* Now get device's answer */ |
| 910 | ret = lockdownd_receive(client, &dict); | 1022 | ret = lockdownd_receive(client, &dict); |
| 911 | 1023 | ||
| 912 | if (ret != LOCKDOWN_E_SUCCESS) | 1024 | if (ret != LOCKDOWN_E_SUCCESS) { |
| 1025 | if (public_key.data) | ||
| 1026 | free(public_key.data); | ||
| 1027 | plist_free(dict_record); | ||
| 913 | return ret; | 1028 | return ret; |
| 1029 | } | ||
| 914 | 1030 | ||
| 915 | if (strcmp(verb, "Unpair") == 0) { | 1031 | if (strcmp(verb, "Unpair") == 0) { |
| 916 | /* workaround for Unpair giving back ValidatePair, | 1032 | /* workaround for Unpair giving back ValidatePair, |
| @@ -928,13 +1044,25 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ | |||
| 928 | if (ret == LOCKDOWN_E_SUCCESS) { | 1044 | if (ret == LOCKDOWN_E_SUCCESS) { |
| 929 | debug_info("%s success", verb); | 1045 | debug_info("%s success", verb); |
| 930 | if (!pairing_mode) { | 1046 | if (!pairing_mode) { |
| 1047 | debug_info("internal pairing mode"); | ||
| 931 | if (!strcmp("Unpair", verb)) { | 1048 | if (!strcmp("Unpair", verb)) { |
| 932 | /* remove public key from config */ | 1049 | /* remove public key from config */ |
| 933 | userpref_remove_device_public_key(client->udid); | 1050 | userpref_remove_device_record(client->udid); |
| 934 | } else { | 1051 | } else { |
| 935 | /* store public key in config */ | 1052 | if (!strcmp("Pair", verb)) { |
| 936 | userpref_set_device_public_key(client->udid, public_key); | 1053 | debug_info("getting EscrowBag from response"); |
| 1054 | |||
| 1055 | /* add returned escrow bag if available */ | ||
| 1056 | plist_t escrow_bag = plist_dict_get_item(dict, "EscrowBag"); | ||
| 1057 | if (escrow_bag && plist_get_node_type(escrow_bag) == PLIST_DATA) { | ||
| 1058 | userpref_device_record_set_value(client->udid, USERPREF_ESCROW_BAG_KEY, plist_copy(escrow_bag)); | ||
| 1059 | plist_free(escrow_bag); | ||
| 1060 | escrow_bag = NULL; | ||
| 1061 | } | ||
| 1062 | } | ||
| 937 | } | 1063 | } |
| 1064 | } else { | ||
| 1065 | debug_info("external pairing mode"); | ||
| 938 | } | 1066 | } |
| 939 | } else { | 1067 | } else { |
| 940 | debug_info("%s failure", verb); | 1068 | debug_info("%s failure", verb); |
| @@ -950,6 +1078,10 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ | |||
| 950 | ret = LOCKDOWN_E_PASSWORD_PROTECTED; | 1078 | ret = LOCKDOWN_E_PASSWORD_PROTECTED; |
| 951 | } else if (!strcmp(value, "InvalidHostID")) { | 1079 | } else if (!strcmp(value, "InvalidHostID")) { |
| 952 | ret = LOCKDOWN_E_INVALID_HOST_ID; | 1080 | ret = LOCKDOWN_E_INVALID_HOST_ID; |
| 1081 | } else if (!strcmp(value, "UserDeniedPairing")) { | ||
| 1082 | ret = LOCKDOWN_E_USER_DENIED_PAIRING; | ||
| 1083 | } else if (!strcmp(value, "PairingDialogResponsePending")) { | ||
| 1084 | ret = LOCKDOWN_E_PAIRING_DIALOG_PENDING; | ||
| 953 | } | 1085 | } |
| 954 | free(value); | 1086 | free(value); |
| 955 | } | 1087 | } |
| @@ -958,10 +1090,18 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ | |||
| 958 | error_node = NULL; | 1090 | error_node = NULL; |
| 959 | } | 1091 | } |
| 960 | } | 1092 | } |
| 1093 | |||
| 1094 | if (dict_record) { | ||
| 1095 | plist_free(dict_record); | ||
| 1096 | dict_record = NULL; | ||
| 1097 | } | ||
| 1098 | |||
| 961 | plist_free(dict); | 1099 | plist_free(dict); |
| 962 | dict = NULL; | 1100 | dict = NULL; |
| 1101 | |||
| 963 | if (public_key.data) | 1102 | if (public_key.data) |
| 964 | free(public_key.data); | 1103 | free(public_key.data); |
| 1104 | |||
| 965 | return ret; | 1105 | return ret; |
| 966 | } | 1106 | } |
| 967 | 1107 | ||
| @@ -1115,11 +1255,12 @@ lockdownd_error_t lockdownd_goodbye(lockdownd_client_t client) | |||
| 1115 | * system failed, LOCKDOWN_E_SSL_ERROR if the certificates could not be | 1255 | * system failed, LOCKDOWN_E_SSL_ERROR if the certificates could not be |
| 1116 | * generated | 1256 | * generated |
| 1117 | */ | 1257 | */ |
| 1118 | lockdownd_error_t lockdownd_gen_pair_cert(key_data_t public_key, key_data_t * odevice_cert, | 1258 | lockdownd_error_t lockdownd_gen_pair_cert_for_udid(const char *udid, key_data_t public_key, key_data_t * odevice_cert, |
| 1119 | key_data_t * ohost_cert, key_data_t * oroot_cert) | 1259 | key_data_t * ohost_cert, key_data_t * oroot_cert) |
| 1120 | { | 1260 | { |
| 1121 | if (!public_key.data || !odevice_cert || !ohost_cert || !oroot_cert) | 1261 | if (!public_key.data || !odevice_cert || !ohost_cert || !oroot_cert) |
| 1122 | return LOCKDOWN_E_INVALID_ARG; | 1262 | return LOCKDOWN_E_INVALID_ARG; |
| 1263 | |||
| 1123 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | 1264 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 1124 | userpref_error_t uret = USERPREF_E_UNKNOWN_ERROR; | 1265 | userpref_error_t uret = USERPREF_E_UNKNOWN_ERROR; |
| 1125 | 1266 | ||
| @@ -1148,7 +1289,7 @@ lockdownd_error_t lockdownd_gen_pair_cert(key_data_t public_key, key_data_t * od | |||
| 1148 | host_privkey.data = NULL; | 1289 | host_privkey.data = NULL; |
| 1149 | host_privkey.size = 0; | 1290 | host_privkey.size = 0; |
| 1150 | 1291 | ||
| 1151 | uret = userpref_get_keys_and_certs(&root_privkey, &root_cert, &host_privkey, &host_cert); | 1292 | uret = userpref_device_record_get_keys_and_certs(udid, &root_privkey, &root_cert, &host_privkey, &host_cert); |
| 1152 | if (USERPREF_E_SUCCESS == uret) { | 1293 | if (USERPREF_E_SUCCESS == uret) { |
| 1153 | /* generate device certificate */ | 1294 | /* generate device certificate */ |
| 1154 | ASN1_INTEGER* sn = ASN1_INTEGER_new(); | 1295 | ASN1_INTEGER* sn = ASN1_INTEGER_new(); |
| @@ -1209,7 +1350,7 @@ lockdownd_error_t lockdownd_gen_pair_cert(key_data_t public_key, key_data_t * od | |||
| 1209 | key_data_t pem_root_cert = { NULL, 0 }; | 1350 | key_data_t pem_root_cert = { NULL, 0 }; |
| 1210 | key_data_t pem_host_cert = { NULL, 0 }; | 1351 | key_data_t pem_host_cert = { NULL, 0 }; |
| 1211 | 1352 | ||
| 1212 | uret = userpref_get_certs_as_pem(&pem_root_cert, &pem_host_cert); | 1353 | uret = userpref_device_record_get_certs_as_pem(udid, &pem_root_cert, &pem_host_cert); |
| 1213 | if (USERPREF_E_SUCCESS == uret) { | 1354 | if (USERPREF_E_SUCCESS == uret) { |
| 1214 | /* copy buffer for output */ | 1355 | /* copy buffer for output */ |
| 1215 | membp = BIO_new(BIO_s_mem()); | 1356 | membp = BIO_new(BIO_s_mem()); |
| @@ -1395,6 +1536,10 @@ lockdownd_error_t lockdownd_gen_pair_cert(key_data_t public_key, key_data_t * od | |||
| 1395 | 1536 | ||
| 1396 | gnutls_free(der_pub_key.data); | 1537 | gnutls_free(der_pub_key.data); |
| 1397 | #endif | 1538 | #endif |
| 1539 | /* save device cert in config */ | ||
| 1540 | if (odevice_cert->size) { | ||
| 1541 | userpref_device_record_set_value(udid, USERPREF_DEVICE_CERTIFICATE_KEY, plist_new_data((char*)odevice_cert->data, (uint64_t)odevice_cert->size)); | ||
| 1542 | } | ||
| 1398 | 1543 | ||
| 1399 | return ret; | 1544 | return ret; |
| 1400 | } | 1545 | } |
| @@ -1429,9 +1574,24 @@ lockdownd_error_t lockdownd_start_session(lockdownd_client_t client, const char | |||
| 1429 | /* setup request plist */ | 1574 | /* setup request plist */ |
| 1430 | dict = plist_new_dict(); | 1575 | dict = plist_new_dict(); |
| 1431 | plist_dict_add_label(dict, client->label); | 1576 | plist_dict_add_label(dict, client->label); |
| 1432 | plist_dict_insert_item(dict,"HostID", plist_new_string(host_id)); | ||
| 1433 | plist_dict_insert_item(dict,"Request", plist_new_string("StartSession")); | 1577 | plist_dict_insert_item(dict,"Request", plist_new_string("StartSession")); |
| 1434 | 1578 | ||
| 1579 | /* add host id */ | ||
| 1580 | if (host_id) { | ||
| 1581 | plist_dict_insert_item(dict, "HostID", plist_new_string(host_id)); | ||
| 1582 | } | ||
| 1583 | |||
| 1584 | /* add system buid */ | ||
| 1585 | char *system_buid = NULL; | ||
| 1586 | userpref_get_system_buid(&system_buid); | ||
| 1587 | if (system_buid) { | ||
| 1588 | plist_dict_insert_item(dict, "SystemBUID", plist_new_string(system_buid)); | ||
| 1589 | if (system_buid) { | ||
| 1590 | free(system_buid); | ||
| 1591 | system_buid = NULL; | ||
| 1592 | } | ||
| 1593 | } | ||
| 1594 | |||
| 1435 | ret = lockdownd_send(client, dict); | 1595 | ret = lockdownd_send(client, dict); |
| 1436 | plist_free(dict); | 1596 | plist_free(dict); |
| 1437 | dict = NULL; | 1597 | dict = NULL; |
| @@ -1471,6 +1631,7 @@ lockdownd_error_t lockdownd_start_session(lockdownd_client_t client, const char | |||
| 1471 | if (session_node && (plist_get_node_type(session_node) == PLIST_STRING)) { | 1631 | if (session_node && (plist_get_node_type(session_node) == PLIST_STRING)) { |
| 1472 | plist_get_string_val(session_node, &client->session_id); | 1632 | plist_get_string_val(session_node, &client->session_id); |
| 1473 | } | 1633 | } |
| 1634 | |||
| 1474 | if (client->session_id) { | 1635 | if (client->session_id) { |
| 1475 | debug_info("SessionID: %s", client->session_id); | 1636 | debug_info("SessionID: %s", client->session_id); |
| 1476 | if (session_id != NULL) | 1637 | if (session_id != NULL) |
| @@ -1478,7 +1639,9 @@ lockdownd_error_t lockdownd_start_session(lockdownd_client_t client, const char | |||
| 1478 | } else { | 1639 | } else { |
| 1479 | debug_info("Failed to get SessionID!"); | 1640 | debug_info("Failed to get SessionID!"); |
| 1480 | } | 1641 | } |
| 1642 | |||
| 1481 | debug_info("Enable SSL Session: %s", (use_ssl?"true":"false")); | 1643 | debug_info("Enable SSL Session: %s", (use_ssl?"true":"false")); |
| 1644 | |||
| 1482 | if (use_ssl) { | 1645 | if (use_ssl) { |
| 1483 | ret = property_list_service_enable_ssl(client->parent); | 1646 | ret = property_list_service_enable_ssl(client->parent); |
| 1484 | if (ret == PROPERTY_LIST_SERVICE_E_SUCCESS) { | 1647 | if (ret == PROPERTY_LIST_SERVICE_E_SUCCESS) { |
| @@ -1523,7 +1686,7 @@ lockdownd_error_t lockdownd_start_service(lockdownd_client_t client, const char | |||
| 1523 | } | 1686 | } |
| 1524 | 1687 | ||
| 1525 | char *host_id = NULL; | 1688 | char *host_id = NULL; |
| 1526 | userpref_get_host_id(&host_id); | 1689 | userpref_device_record_get_host_id(client->udid, &host_id); |
| 1527 | if (!host_id) | 1690 | if (!host_id) |
| 1528 | return LOCKDOWN_E_INVALID_CONF; | 1691 | return LOCKDOWN_E_INVALID_CONF; |
| 1529 | if (!client->session_id) | 1692 | if (!client->session_id) |
diff --git a/src/lockdown.h b/src/lockdown.h index 30ebc15..9c2be44 100644 --- a/src/lockdown.h +++ b/src/lockdown.h | |||
| @@ -27,6 +27,8 @@ | |||
| 27 | #include "libimobiledevice/lockdown.h" | 27 | #include "libimobiledevice/lockdown.h" |
| 28 | #include "property_list_service.h" | 28 | #include "property_list_service.h" |
| 29 | 29 | ||
| 30 | #define LOCKDOWN_PROTOCOL_VERSION "2" | ||
| 31 | |||
| 30 | struct lockdownd_client_private { | 32 | struct lockdownd_client_private { |
| 31 | property_list_service_client_t parent; | 33 | property_list_service_client_t parent; |
| 32 | int ssl_enabled; | 34 | int ssl_enabled; |
| @@ -36,6 +38,6 @@ struct lockdownd_client_private { | |||
| 36 | }; | 38 | }; |
| 37 | 39 | ||
| 38 | lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, key_data_t * public_key); | 40 | lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, key_data_t * public_key); |
| 39 | lockdownd_error_t lockdownd_gen_pair_cert(key_data_t public_key, key_data_t * device_cert, key_data_t * host_cert, key_data_t * root_cert); | 41 | lockdownd_error_t lockdownd_gen_pair_cert_for_udid(const char *udid, key_data_t public_key, key_data_t * device_cert, key_data_t * host_cert, key_data_t * root_cert); |
| 40 | 42 | ||
| 41 | #endif | 43 | #endif |
