diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/idevice.c | 31 | ||||
| -rw-r--r-- | src/lockdown.c | 530 | ||||
| -rw-r--r-- | src/lockdown.h | 5 |
3 files changed, 130 insertions, 436 deletions
diff --git a/src/idevice.c b/src/idevice.c index d01aa8f..c656517 100644 --- a/src/idevice.c +++ b/src/idevice.c | |||
| @@ -511,7 +511,7 @@ static ssize_t internal_ssl_read(gnutls_transport_ptr_t transport, char *buffer, | |||
| 511 | 511 | ||
| 512 | debug_info("pre-read client wants %zi bytes", length); | 512 | debug_info("pre-read client wants %zi bytes", length); |
| 513 | 513 | ||
| 514 | recv_buffer = (char *) malloc(sizeof(char) * this_len); | 514 | recv_buffer = (char *)malloc(sizeof(char) * this_len); |
| 515 | 515 | ||
| 516 | /* repeat until we have the full data or an error occurs */ | 516 | /* repeat until we have the full data or an error occurs */ |
| 517 | do { | 517 | do { |
| @@ -637,12 +637,12 @@ static const char *errorstring(int e) | |||
| 637 | /** | 637 | /** |
| 638 | * Internally used gnutls callback function that gets called during handshake. | 638 | * Internally used gnutls callback function that gets called during handshake. |
| 639 | */ | 639 | */ |
| 640 | static int internal_cert_callback (gnutls_session_t session, const gnutls_datum_t * req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t * sign_algos, int sign_algos_length, gnutls_retr_st * st) | 640 | static int internal_cert_callback(gnutls_session_t session, const gnutls_datum_t * req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t * sign_algos, int sign_algos_length, gnutls_retr_st * st) |
| 641 | { | 641 | { |
| 642 | int res = -1; | 642 | int res = -1; |
| 643 | gnutls_certificate_type_t type = gnutls_certificate_type_get (session); | 643 | gnutls_certificate_type_t type = gnutls_certificate_type_get(session); |
| 644 | if (type == GNUTLS_CRT_X509) { | 644 | if (type == GNUTLS_CRT_X509) { |
| 645 | ssl_data_t ssl_data = (ssl_data_t)gnutls_session_get_ptr (session); | 645 | ssl_data_t ssl_data = (ssl_data_t)gnutls_session_get_ptr(session); |
| 646 | if (ssl_data && ssl_data->host_privkey && ssl_data->host_cert) { | 646 | if (ssl_data && ssl_data->host_privkey && ssl_data->host_cert) { |
| 647 | debug_info("Passing certificate"); | 647 | debug_info("Passing certificate"); |
| 648 | st->type = type; | 648 | st->type = type; |
| @@ -673,15 +673,20 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection) | |||
| 673 | 673 | ||
| 674 | idevice_error_t ret = IDEVICE_E_SSL_ERROR; | 674 | idevice_error_t ret = IDEVICE_E_SSL_ERROR; |
| 675 | uint32_t return_me = 0; | 675 | uint32_t return_me = 0; |
| 676 | plist_t pair_record = NULL; | ||
| 677 | |||
| 678 | userpref_read_pair_record(connection->udid, &pair_record); | ||
| 679 | if (!pair_record) { | ||
| 680 | debug_info("ERROR: Failed enabling SSL. Unable to read pair record for udid %s.", connection->udid); | ||
| 681 | return ret; | ||
| 682 | } | ||
| 676 | 683 | ||
| 677 | #ifdef HAVE_OPENSSL | 684 | #ifdef HAVE_OPENSSL |
| 678 | key_data_t root_cert = { NULL, 0 }; | 685 | key_data_t root_cert = { NULL, 0 }; |
| 679 | key_data_t root_privkey = { NULL, 0 }; | 686 | key_data_t root_privkey = { NULL, 0 }; |
| 680 | 687 | ||
| 681 | userpref_error_t uerr = userpref_device_record_get_keys_and_certs(connection->udid, &root_privkey, &root_cert, NULL, NULL); | 688 | pair_record_import_key_with_name(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert); |
| 682 | if (uerr != USERPREF_E_SUCCESS) { | 689 | pair_record_import_key_with_name(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_privkey); |
| 683 | debug_info("Error %d when loading keys and certificates! %d", uerr); | ||
| 684 | } | ||
| 685 | 690 | ||
| 686 | /* Set up OpenSSL */ | 691 | /* Set up OpenSSL */ |
| 687 | if (openssl_init_done == 0) { | 692 | if (openssl_init_done == 0) { |
| @@ -756,7 +761,7 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection) | |||
| 756 | errno = 0; | 761 | errno = 0; |
| 757 | gnutls_global_init(); | 762 | gnutls_global_init(); |
| 758 | gnutls_certificate_allocate_credentials(&ssl_data_loc->certificate); | 763 | gnutls_certificate_allocate_credentials(&ssl_data_loc->certificate); |
| 759 | gnutls_certificate_client_set_retrieve_function (ssl_data_loc->certificate, internal_cert_callback); | 764 | gnutls_certificate_client_set_retrieve_function(ssl_data_loc->certificate, internal_cert_callback); |
| 760 | gnutls_init(&ssl_data_loc->session, GNUTLS_CLIENT); | 765 | gnutls_init(&ssl_data_loc->session, GNUTLS_CLIENT); |
| 761 | gnutls_priority_set_direct(ssl_data_loc->session, "NONE:+VERS-SSL3.0:+ANON-DH:+RSA:+AES-128-CBC:+AES-256-CBC:+SHA1:+MD5:+COMP-NULL", NULL); | 766 | gnutls_priority_set_direct(ssl_data_loc->session, "NONE:+VERS-SSL3.0:+ANON-DH:+RSA:+AES-128-CBC:+AES-256-CBC:+SHA1:+MD5:+COMP-NULL", NULL); |
| 762 | gnutls_credentials_set(ssl_data_loc->session, GNUTLS_CRD_CERTIFICATE, ssl_data_loc->certificate); | 767 | gnutls_credentials_set(ssl_data_loc->session, GNUTLS_CRD_CERTIFICATE, ssl_data_loc->certificate); |
| @@ -767,10 +772,10 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection) | |||
| 767 | gnutls_x509_privkey_init(&ssl_data_loc->root_privkey); | 772 | gnutls_x509_privkey_init(&ssl_data_loc->root_privkey); |
| 768 | gnutls_x509_privkey_init(&ssl_data_loc->host_privkey); | 773 | gnutls_x509_privkey_init(&ssl_data_loc->host_privkey); |
| 769 | 774 | ||
| 770 | userpref_error_t uerr = userpref_device_record_get_keys_and_certs(connection->udid, ssl_data_loc->root_privkey, ssl_data_loc->root_cert, ssl_data_loc->host_privkey, ssl_data_loc->host_cert); | 775 | pair_record_import_key_with_name(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, ssl_data_loc->root_cert); |
| 771 | if (uerr != USERPREF_E_SUCCESS) { | 776 | pair_record_import_key_with_name(pair_record, USERPREF_HOST_CERTIFICATE_KEY, ssl_data_loc->host_cert); |
| 772 | debug_info("Error %d when loading keys and certificates! %d", uerr); | 777 | pair_record_import_key_with_name(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, ssl_data_loc->root_privkey); |
| 773 | } | 778 | pair_record_import_key_with_name(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, ssl_data_loc->host_privkey); |
| 774 | 779 | ||
| 775 | debug_info("GnuTLS step 1..."); | 780 | debug_info("GnuTLS step 1..."); |
| 776 | gnutls_transport_set_ptr(ssl_data_loc->session, (gnutls_transport_ptr_t)connection); | 781 | gnutls_transport_set_ptr(ssl_data_loc->session, (gnutls_transport_ptr_t)connection); |
diff --git a/src/lockdown.c b/src/lockdown.c index e21db30..6ea747f 100644 --- a/src/lockdown.c +++ b/src/lockdown.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | #include "idevice.h" | 47 | #include "idevice.h" |
| 48 | #include "common/debug.h" | 48 | #include "common/debug.h" |
| 49 | #include "common/userpref.h" | 49 | #include "common/userpref.h" |
| 50 | #include "common/utils.h" | ||
| 50 | #include "asprintf.h" | 51 | #include "asprintf.h" |
| 51 | 52 | ||
| 52 | #ifdef WIN32 | 53 | #ifdef WIN32 |
| @@ -57,17 +58,6 @@ | |||
| 57 | #define RESULT_SUCCESS 0 | 58 | #define RESULT_SUCCESS 0 |
| 58 | #define RESULT_FAILURE 1 | 59 | #define RESULT_FAILURE 1 |
| 59 | 60 | ||
| 60 | #ifndef HAVE_OPENSSL | ||
| 61 | const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { | ||
| 62 | {"PKCS1", 536872976, 0}, | ||
| 63 | {0, 1073741836, 0}, | ||
| 64 | {"RSAPublicKey", 536870917, 0}, | ||
| 65 | {"modulus", 1073741827, 0}, | ||
| 66 | {"publicExponent", 3, 0}, | ||
| 67 | {0, 0, 0} | ||
| 68 | }; | ||
| 69 | #endif | ||
| 70 | |||
| 71 | /** | 61 | /** |
| 72 | * Internally used function for checking the result from lockdown's answer | 62 | * Internally used function for checking the result from lockdown's answer |
| 73 | * plist to a previously sent request. | 63 | * plist to a previously sent request. |
| @@ -618,7 +608,7 @@ lockdownd_error_t lockdownd_get_device_udid(lockdownd_client_t client, char **ud | |||
| 618 | * | 608 | * |
| 619 | * @return LOCKDOWN_E_SUCCESS on success | 609 | * @return LOCKDOWN_E_SUCCESS on success |
| 620 | */ | 610 | */ |
| 621 | lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, key_data_t * public_key) | 611 | static lockdownd_error_t lockdownd_get_device_public_key_as_key_data(lockdownd_client_t client, key_data_t *public_key) |
| 622 | { | 612 | { |
| 623 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | 613 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 624 | plist_t value = NULL; | 614 | plist_t value = NULL; |
| @@ -758,16 +748,27 @@ lockdownd_error_t lockdownd_client_new_with_handshake(idevice_t device, lockdown | |||
| 758 | if (type) | 748 | if (type) |
| 759 | free(type); | 749 | free(type); |
| 760 | 750 | ||
| 761 | userpref_device_record_get_host_id(client_loc->udid, &host_id); | 751 | debug_info("reading pair record"); |
| 752 | |||
| 753 | plist_t pair_record = NULL; | ||
| 754 | userpref_read_pair_record(client_loc->udid, &pair_record); | ||
| 755 | |||
| 756 | debug_info("reading HostID"); | ||
| 757 | |||
| 758 | pair_record_get_host_id(pair_record, &host_id); | ||
| 762 | if (LOCKDOWN_E_SUCCESS == ret && !host_id) { | 759 | if (LOCKDOWN_E_SUCCESS == ret && !host_id) { |
| 763 | ret = LOCKDOWN_E_INVALID_CONF; | 760 | ret = LOCKDOWN_E_INVALID_CONF; |
| 764 | } | 761 | } |
| 765 | 762 | ||
| 766 | if (LOCKDOWN_E_SUCCESS == ret && !userpref_has_device_record(client_loc->udid)) { | 763 | debug_info("HostID: %s", host_id); |
| 764 | |||
| 765 | if (LOCKDOWN_E_SUCCESS == ret && !pair_record) { | ||
| 767 | /* attempt pairing */ | 766 | /* attempt pairing */ |
| 768 | ret = lockdownd_pair(client_loc, NULL); | 767 | ret = lockdownd_pair(client_loc, NULL); |
| 769 | } | 768 | } |
| 770 | 769 | ||
| 770 | plist_free(pair_record); | ||
| 771 | |||
| 771 | /* in any case, we need to validate pairing to receive trusted host status */ | 772 | /* in any case, we need to validate pairing to receive trusted host status */ |
| 772 | ret = lockdownd_validate_pair(client_loc, NULL); | 773 | ret = lockdownd_validate_pair(client_loc, NULL); |
| 773 | 774 | ||
| @@ -836,67 +837,69 @@ static plist_t lockdownd_pair_record_to_plist(lockdownd_pair_record_t pair_recor | |||
| 836 | * | 837 | * |
| 837 | * @return LOCKDOWN_E_SUCCESS on success | 838 | * @return LOCKDOWN_E_SUCCESS on success |
| 838 | */ | 839 | */ |
| 839 | static lockdownd_error_t generate_pair_record_plist(lockdownd_client_t client, plist_t *pair_record_plist) | 840 | static lockdownd_error_t pair_record_generate(lockdownd_client_t client, plist_t *pair_record) |
| 840 | { | 841 | { |
| 841 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | 842 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 842 | 843 | ||
| 844 | key_data_t public_key = { NULL, 0 }; | ||
| 843 | char* host_id = NULL; | 845 | char* host_id = NULL; |
| 844 | char* system_buid = NULL; | 846 | char* system_buid = NULL; |
| 845 | 847 | ||
| 846 | key_data_t public_key = { NULL, 0 }; | ||
| 847 | key_data_t device_cert = { NULL, 0 }; | ||
| 848 | key_data_t host_cert = { NULL, 0 }; | ||
| 849 | key_data_t root_cert = { NULL, 0 }; | ||
| 850 | |||
| 851 | /* load certificates if a pairing exists */ | ||
| 852 | userpref_error_t uret = userpref_device_record_get_certs_as_pem(client->udid, &root_cert, &host_cert, &device_cert); | ||
| 853 | if ((uret == USERPREF_E_SUCCESS) && (root_cert.size > 0) && (host_cert.size > 0) && (device_cert.size > 0)) { | ||
| 854 | ret = LOCKDOWN_E_SUCCESS; | ||
| 855 | } | ||
| 856 | |||
| 857 | /* get systembuid and host id */ | ||
| 858 | userpref_get_system_buid(&system_buid); | ||
| 859 | userpref_device_record_get_host_id(client->udid, &host_id); | ||
| 860 | |||
| 861 | /* generate new certificates if needed */ | 848 | /* generate new certificates if needed */ |
| 849 | ret = lockdownd_get_device_public_key_as_key_data(client, &public_key); | ||
| 862 | if (ret != LOCKDOWN_E_SUCCESS) { | 850 | if (ret != LOCKDOWN_E_SUCCESS) { |
| 863 | ret = lockdownd_get_device_public_key(client, &public_key); | 851 | debug_info("device refused to send public key."); |
| 864 | if (ret != LOCKDOWN_E_SUCCESS) { | 852 | goto leave; |
| 865 | debug_info("device refused to send public key."); | 853 | } |
| 866 | goto leave; | 854 | debug_info("device public key follows:\n%.*s", public_key.size, public_key.data); |
| 867 | } | ||
| 868 | debug_info("device public key follows:\n%.*s", public_key.size, public_key.data); | ||
| 869 | 855 | ||
| 870 | userpref_device_record_set_value(client->udid, USERPREF_SYSTEM_BUID_KEY, plist_new_string(system_buid)); | 856 | host_id = generate_uuid(); |
| 871 | 857 | ||
| 872 | ret = lockdownd_gen_pair_cert_for_udid(client->udid, public_key, &device_cert, &host_cert, &root_cert); | 858 | *pair_record = plist_new_dict(); |
| 859 | |||
| 860 | userpref_error_t uret = USERPREF_E_SUCCESS; | ||
| 861 | uret = pair_record_generate_keys_and_certs(pair_record); | ||
| 862 | switch(uret) { | ||
| 863 | case USERPREF_E_INVALID_ARG: | ||
| 864 | ret = LOCKDOWN_E_INVALID_ARG; | ||
| 865 | break; | ||
| 866 | case USERPREF_E_INVALID_CONF: | ||
| 867 | ret = LOCKDOWN_E_INVALID_CONF; | ||
| 868 | break; | ||
| 869 | case USERPREF_E_SSL_ERROR: | ||
| 870 | ret = LOCKDOWN_E_SSL_ERROR; | ||
| 871 | default: | ||
| 872 | break; | ||
| 873 | } | ||
| 874 | |||
| 875 | uret = pair_record_generate_from_device_public_key(pair_record, public_key); | ||
| 876 | switch(uret) { | ||
| 877 | case USERPREF_E_INVALID_ARG: | ||
| 878 | ret = LOCKDOWN_E_INVALID_ARG; | ||
| 879 | break; | ||
| 880 | case USERPREF_E_INVALID_CONF: | ||
| 881 | ret = LOCKDOWN_E_INVALID_CONF; | ||
| 882 | break; | ||
| 883 | case USERPREF_E_SSL_ERROR: | ||
| 884 | ret = LOCKDOWN_E_SSL_ERROR; | ||
| 885 | default: | ||
| 886 | break; | ||
| 873 | } | 887 | } |
| 874 | 888 | ||
| 889 | /* get systembuid and host id */ | ||
| 890 | userpref_read_system_buid(&system_buid); | ||
| 891 | |||
| 892 | pair_record_set_host_id(pair_record, host_id); | ||
| 893 | |||
| 875 | if (ret != LOCKDOWN_E_SUCCESS) { | 894 | if (ret != LOCKDOWN_E_SUCCESS) { |
| 876 | goto leave; | 895 | goto leave; |
| 877 | } | 896 | } |
| 878 | 897 | ||
| 879 | /* setup request plist */ | ||
| 880 | *pair_record_plist = plist_new_dict(); | ||
| 881 | plist_dict_set_item(*pair_record_plist, "DeviceCertificate", plist_new_data((const char*)device_cert.data, device_cert.size)); | ||
| 882 | plist_dict_set_item(*pair_record_plist, "HostCertificate", plist_new_data((const char*)host_cert.data, host_cert.size)); | ||
| 883 | plist_dict_set_item(*pair_record_plist, "HostID", plist_new_string(host_id)); | ||
| 884 | plist_dict_set_item(*pair_record_plist, "RootCertificate", plist_new_data((const char*)root_cert.data, root_cert.size)); | ||
| 885 | plist_dict_set_item(*pair_record_plist, "SystemBUID", plist_new_string(system_buid)); | ||
| 886 | |||
| 887 | leave: | 898 | leave: |
| 888 | if (host_id) | 899 | if (host_id) |
| 889 | free(host_id); | 900 | free(host_id); |
| 890 | if (system_buid) | 901 | if (system_buid) |
| 891 | free(system_buid); | 902 | free(system_buid); |
| 892 | if (public_key.data) | ||
| 893 | free(public_key.data); | ||
| 894 | if (device_cert.data) | ||
| 895 | free(device_cert.data); | ||
| 896 | if (host_cert.data) | ||
| 897 | free(host_cert.data); | ||
| 898 | if (root_cert.data) | ||
| 899 | free(root_cert.data); | ||
| 900 | 903 | ||
| 901 | return ret; | 904 | return ret; |
| 902 | } | 905 | } |
| @@ -923,7 +926,7 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ | |||
| 923 | 926 | ||
| 924 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | 927 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 925 | plist_t dict = NULL; | 928 | plist_t dict = NULL; |
| 926 | plist_t dict_record = NULL; | 929 | plist_t pair_record_plist = NULL; |
| 927 | int pairing_mode = 0; /* 0 = libimobiledevice, 1 = external */ | 930 | int pairing_mode = 0; /* 0 = libimobiledevice, 1 = external */ |
| 928 | 931 | ||
| 929 | if (pair_record && pair_record->system_buid && pair_record->host_id) { | 932 | if (pair_record && pair_record->system_buid && pair_record->host_id) { |
| @@ -933,36 +936,39 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ | |||
| 933 | } | 936 | } |
| 934 | 937 | ||
| 935 | /* use passed pair_record */ | 938 | /* use passed pair_record */ |
| 936 | dict_record = lockdownd_pair_record_to_plist(pair_record); | 939 | pair_record_plist = lockdownd_pair_record_to_plist(pair_record); |
| 937 | 940 | ||
| 938 | pairing_mode = 1; | 941 | pairing_mode = 1; |
| 939 | } else { | 942 | } else { |
| 940 | ret = generate_pair_record_plist(client, &dict_record); | 943 | /* generate a new pair record if pairing */ |
| 941 | 944 | if (!strcmp("Pair", verb)) { | |
| 942 | if (ret != LOCKDOWN_E_SUCCESS) { | 945 | ret = pair_record_generate(client, &pair_record_plist); |
| 943 | if (dict_record) | 946 | |
| 944 | plist_free(dict_record); | 947 | if (ret != LOCKDOWN_E_SUCCESS) { |
| 945 | return ret; | 948 | if (pair_record_plist) |
| 949 | plist_free(pair_record_plist); | ||
| 950 | return ret; | ||
| 951 | } | ||
| 952 | } else { | ||
| 953 | /* use existing pair record */ | ||
| 954 | if (userpref_has_pair_record(client->udid)) { | ||
| 955 | userpref_read_pair_record(client->udid, &pair_record_plist); | ||
| 956 | } else { | ||
| 957 | return LOCKDOWN_E_PAIRING_FAILED; | ||
| 958 | } | ||
| 946 | } | 959 | } |
| 947 | } | 960 | } |
| 948 | 961 | ||
| 949 | if (!strcmp("Pair", verb)) { | 962 | plist_t request_pair_record = plist_copy(pair_record_plist); |
| 950 | /* get wifi mac */ | ||
| 951 | plist_t wifi_mac_node = NULL; | ||
| 952 | lockdownd_get_value(client, NULL, "WiFiAddress", &wifi_mac_node); | ||
| 953 | 963 | ||
| 954 | /* save wifi mac address in config */ | 964 | /* remove stuff that is private */ |
| 955 | if (wifi_mac_node) { | 965 | plist_dict_remove_item(request_pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY); |
| 956 | userpref_device_record_set_value(client->udid, USERPREF_WIFI_MAC_ADDRESS_KEY, plist_copy(wifi_mac_node)); | 966 | plist_dict_remove_item(request_pair_record, USERPREF_HOST_PRIVATE_KEY_KEY); |
| 957 | plist_free(wifi_mac_node); | ||
| 958 | wifi_mac_node = NULL; | ||
| 959 | } | ||
| 960 | } | ||
| 961 | 967 | ||
| 962 | /* setup pair request plist */ | 968 | /* setup pair request plist */ |
| 963 | dict = plist_new_dict(); | 969 | dict = plist_new_dict(); |
| 964 | plist_dict_add_label(dict, client->label); | 970 | plist_dict_add_label(dict, client->label); |
| 965 | plist_dict_set_item(dict, "PairRecord", plist_copy(dict_record)); | 971 | plist_dict_set_item(dict, "PairRecord", request_pair_record); |
| 966 | plist_dict_set_item(dict, "Request", plist_new_string(verb)); | 972 | plist_dict_set_item(dict, "Request", plist_new_string(verb)); |
| 967 | plist_dict_set_item(dict, "ProtocolVersion", plist_new_string(LOCKDOWN_PROTOCOL_VERSION)); | 973 | plist_dict_set_item(dict, "ProtocolVersion", plist_new_string(LOCKDOWN_PROTOCOL_VERSION)); |
| 968 | 974 | ||
| @@ -976,7 +982,7 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ | |||
| 976 | dict = NULL; | 982 | dict = NULL; |
| 977 | 983 | ||
| 978 | if (ret != LOCKDOWN_E_SUCCESS) { | 984 | if (ret != LOCKDOWN_E_SUCCESS) { |
| 979 | plist_free(dict_record); | 985 | plist_free(pair_record_plist); |
| 980 | return ret; | 986 | return ret; |
| 981 | } | 987 | } |
| 982 | 988 | ||
| @@ -984,7 +990,7 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ | |||
| 984 | ret = lockdownd_receive(client, &dict); | 990 | ret = lockdownd_receive(client, &dict); |
| 985 | 991 | ||
| 986 | if (ret != LOCKDOWN_E_SUCCESS) { | 992 | if (ret != LOCKDOWN_E_SUCCESS) { |
| 987 | plist_free(dict_record); | 993 | plist_free(pair_record_plist); |
| 988 | return ret; | 994 | return ret; |
| 989 | } | 995 | } |
| 990 | 996 | ||
| @@ -1007,24 +1013,32 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ | |||
| 1007 | debug_info("internal pairing mode"); | 1013 | debug_info("internal pairing mode"); |
| 1008 | if (!strcmp("Unpair", verb)) { | 1014 | if (!strcmp("Unpair", verb)) { |
| 1009 | /* remove public key from config */ | 1015 | /* remove public key from config */ |
| 1010 | userpref_remove_device_record(client->udid); | 1016 | userpref_delete_pair_record(client->udid); |
| 1011 | } else { | 1017 | } else { |
| 1012 | if (!strcmp("Pair", verb)) { | 1018 | if (!strcmp("Pair", verb)) { |
| 1013 | debug_info("getting EscrowBag from response"); | 1019 | debug_info("Saving EscrowBag from response in pair record"); |
| 1014 | 1020 | ||
| 1015 | /* add returned escrow bag if available */ | 1021 | /* add returned escrow bag if available */ |
| 1016 | plist_t escrow_bag = plist_dict_get_item(dict, "EscrowBag"); | 1022 | plist_t extra_node = plist_dict_get_item(dict, USERPREF_ESCROW_BAG_KEY); |
| 1017 | if (escrow_bag && plist_get_node_type(escrow_bag) == PLIST_DATA) { | 1023 | if (extra_node && plist_get_node_type(extra_node) == PLIST_DATA) { |
| 1018 | userpref_device_record_set_value(client->udid, USERPREF_ESCROW_BAG_KEY, plist_copy(escrow_bag)); | 1024 | plist_dict_set_item(pair_record_plist, USERPREF_ESCROW_BAG_KEY, plist_copy(extra_node)); |
| 1019 | plist_free(escrow_bag); | 1025 | plist_free(extra_node); |
| 1020 | escrow_bag = NULL; | 1026 | extra_node = NULL; |
| 1021 | } | 1027 | } |
| 1022 | 1028 | ||
| 1023 | /* store DeviceCertificate upon successful pairing */ | 1029 | debug_info("Saving WiFiAddress from device in pair record"); |
| 1024 | plist_t devcrt = plist_dict_get_item(dict_record, USERPREF_DEVICE_CERTIFICATE_KEY); | 1030 | |
| 1025 | if (devcrt && plist_get_node_type(devcrt) == PLIST_DATA) { | 1031 | /* get wifi mac */ |
| 1026 | userpref_device_record_set_value(client->udid, USERPREF_DEVICE_CERTIFICATE_KEY, plist_copy(devcrt)); | 1032 | lockdownd_get_value(client, NULL, "WiFiAddress", &extra_node); |
| 1033 | |||
| 1034 | /* save wifi mac address in config */ | ||
| 1035 | if (extra_node) { | ||
| 1036 | plist_dict_set_item(pair_record_plist, USERPREF_WIFI_MAC_ADDRESS_KEY, plist_copy(extra_node)); | ||
| 1037 | plist_free(extra_node); | ||
| 1038 | extra_node = NULL; | ||
| 1027 | } | 1039 | } |
| 1040 | |||
| 1041 | userpref_save_pair_record(client->udid, pair_record_plist); | ||
| 1028 | } | 1042 | } |
| 1029 | } | 1043 | } |
| 1030 | } else { | 1044 | } else { |
| @@ -1057,9 +1071,9 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ | |||
| 1057 | } | 1071 | } |
| 1058 | } | 1072 | } |
| 1059 | 1073 | ||
| 1060 | if (dict_record) { | 1074 | if (pair_record_plist) { |
| 1061 | plist_free(dict_record); | 1075 | plist_free(pair_record_plist); |
| 1062 | dict_record = NULL; | 1076 | pair_record_plist = NULL; |
| 1063 | } | 1077 | } |
| 1064 | 1078 | ||
| 1065 | plist_free(dict); | 1079 | plist_free(dict); |
| @@ -1206,332 +1220,6 @@ lockdownd_error_t lockdownd_goodbye(lockdownd_client_t client) | |||
| 1206 | } | 1220 | } |
| 1207 | 1221 | ||
| 1208 | /** | 1222 | /** |
| 1209 | * Generates the device certificate from the public key as well as the host | ||
| 1210 | * and root certificates. | ||
| 1211 | * | ||
| 1212 | * @param public_key The public key of the device to use for generation. | ||
| 1213 | * @param odevice_cert Holds the generated device certificate. | ||
| 1214 | * @param ohost_cert Holds the generated host certificate. | ||
| 1215 | * @param oroot_cert Holds the generated root certificate. | ||
| 1216 | * | ||
| 1217 | * @return LOCKDOWN_E_SUCCESS on success, LOCKDOWN_E_INVALID_ARG when a | ||
| 1218 | * parameter is NULL, LOCKDOWN_E_INVALID_CONF if the internal configuration | ||
| 1219 | * system failed, LOCKDOWN_E_SSL_ERROR if the certificates could not be | ||
| 1220 | * generated | ||
| 1221 | */ | ||
| 1222 | lockdownd_error_t lockdownd_gen_pair_cert_for_udid(const char *udid, key_data_t public_key, key_data_t * odevice_cert, | ||
| 1223 | key_data_t * ohost_cert, key_data_t * oroot_cert) | ||
| 1224 | { | ||
| 1225 | if (!public_key.data || !odevice_cert || !ohost_cert || !oroot_cert) | ||
| 1226 | return LOCKDOWN_E_INVALID_ARG; | ||
| 1227 | |||
| 1228 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | ||
| 1229 | userpref_error_t uret = USERPREF_E_UNKNOWN_ERROR; | ||
| 1230 | |||
| 1231 | #ifdef HAVE_OPENSSL | ||
| 1232 | BIO *membio = BIO_new_mem_buf(public_key.data, public_key.size); | ||
| 1233 | RSA *pubkey = NULL; | ||
| 1234 | if (!PEM_read_bio_RSAPublicKey(membio, &pubkey, NULL, NULL)) { | ||
| 1235 | debug_info("Could not read public key"); | ||
| 1236 | } | ||
| 1237 | BIO_free(membio); | ||
| 1238 | |||
| 1239 | /* now generate certificates */ | ||
| 1240 | key_data_t root_privkey, host_privkey; | ||
| 1241 | key_data_t root_cert, host_cert; | ||
| 1242 | X509* dev_cert; | ||
| 1243 | |||
| 1244 | root_cert.data = NULL; | ||
| 1245 | root_cert.size = 0; | ||
| 1246 | host_cert.data = NULL; | ||
| 1247 | host_cert.size = 0; | ||
| 1248 | |||
| 1249 | dev_cert = X509_new(); | ||
| 1250 | |||
| 1251 | root_privkey.data = NULL; | ||
| 1252 | root_privkey.size = 0; | ||
| 1253 | host_privkey.data = NULL; | ||
| 1254 | host_privkey.size = 0; | ||
| 1255 | |||
| 1256 | uret = userpref_device_record_get_keys_and_certs(udid, &root_privkey, &root_cert, &host_privkey, &host_cert); | ||
| 1257 | if (USERPREF_E_SUCCESS == uret) { | ||
| 1258 | /* generate device certificate */ | ||
| 1259 | ASN1_INTEGER* sn = ASN1_INTEGER_new(); | ||
| 1260 | ASN1_INTEGER_set(sn, 0); | ||
| 1261 | X509_set_serialNumber(dev_cert, sn); | ||
| 1262 | ASN1_INTEGER_free(sn); | ||
| 1263 | X509_set_version(dev_cert, 2); | ||
| 1264 | |||
| 1265 | X509_EXTENSION* ext; | ||
| 1266 | if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, (char*)"critical,CA:FALSE"))) { | ||
| 1267 | debug_info("ERROR: X509V3_EXT_conf_nid failed for Basic Constraints"); | ||
| 1268 | } | ||
| 1269 | X509_add_ext(dev_cert, ext, -1); | ||
| 1270 | X509_EXTENSION_free(ext); | ||
| 1271 | |||
| 1272 | ASN1_TIME* asn1time = ASN1_TIME_new(); | ||
| 1273 | ASN1_TIME_set(asn1time, time(NULL)); | ||
| 1274 | X509_set_notBefore(dev_cert, asn1time); | ||
| 1275 | ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10)); | ||
| 1276 | X509_set_notAfter(dev_cert, asn1time); | ||
| 1277 | ASN1_TIME_free(asn1time); | ||
| 1278 | |||
| 1279 | BIO* membp; | ||
| 1280 | |||
| 1281 | X509* rootCert = NULL; | ||
| 1282 | membp = BIO_new_mem_buf(root_cert.data, root_cert.size); | ||
| 1283 | PEM_read_bio_X509(membp, &rootCert, NULL, NULL); | ||
| 1284 | BIO_free(membp); | ||
| 1285 | if (!rootCert) { | ||
| 1286 | debug_info("Could not read RootCertificate"); | ||
| 1287 | } else { | ||
| 1288 | debug_info("RootCertificate loaded"); | ||
| 1289 | EVP_PKEY* pkey = EVP_PKEY_new(); | ||
| 1290 | EVP_PKEY_assign_RSA(pkey, pubkey); | ||
| 1291 | X509_set_pubkey(dev_cert, pkey); | ||
| 1292 | EVP_PKEY_free(pkey); | ||
| 1293 | X509_free(rootCert); | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | X509V3_CTX ctx; | ||
| 1297 | X509V3_set_ctx_nodb(&ctx); | ||
| 1298 | X509V3_set_ctx(&ctx, NULL, dev_cert, NULL, NULL, 0); | ||
| 1299 | |||
| 1300 | if (!(ext = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_key_identifier, (char*)"hash"))) { | ||
| 1301 | debug_info("ERROR: X509V3_EXT_conf_nid failed for Subject Key identifier"); | ||
| 1302 | } | ||
| 1303 | X509_add_ext(dev_cert, ext, -1); | ||
| 1304 | X509_EXTENSION_free(ext); | ||
| 1305 | |||
| 1306 | if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, (char*)"critical,digitalSignature,keyEncipherment"))) { | ||
| 1307 | debug_info("ERROR: X509V3_EXT_conf_nid failed for Key Usage"); | ||
| 1308 | } | ||
| 1309 | X509_add_ext(dev_cert, ext, -1); | ||
| 1310 | X509_EXTENSION_free(ext); | ||
| 1311 | |||
| 1312 | EVP_PKEY* rootPriv = NULL; | ||
| 1313 | membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size); | ||
| 1314 | PEM_read_bio_PrivateKey(membp, &rootPriv, NULL, NULL); | ||
| 1315 | BIO_free(membp); | ||
| 1316 | if (!rootPriv) { | ||
| 1317 | debug_info("Could not read RootPrivateKey"); | ||
| 1318 | } else { | ||
| 1319 | debug_info("RootPrivateKey loaded"); | ||
| 1320 | if (X509_sign(dev_cert, rootPriv, EVP_sha1())) { | ||
| 1321 | ret = LOCKDOWN_E_SUCCESS; | ||
| 1322 | } else { | ||
| 1323 | debug_info("signing failed"); | ||
| 1324 | } | ||
| 1325 | EVP_PKEY_free(rootPriv); | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | if (LOCKDOWN_E_SUCCESS == ret) { | ||
| 1329 | /* if everything went well, export in PEM format */ | ||
| 1330 | key_data_t pem_root_cert = { NULL, 0 }; | ||
| 1331 | key_data_t pem_host_cert = { NULL, 0 }; | ||
| 1332 | |||
| 1333 | uret = userpref_device_record_get_certs_as_pem(udid, &pem_root_cert, &pem_host_cert, NULL); | ||
| 1334 | if (USERPREF_E_SUCCESS == uret) { | ||
| 1335 | /* copy buffer for output */ | ||
| 1336 | membp = BIO_new(BIO_s_mem()); | ||
| 1337 | if (membp && PEM_write_bio_X509(membp, dev_cert) > 0) { | ||
| 1338 | void *datap; | ||
| 1339 | odevice_cert->size = BIO_get_mem_data(membp, &datap); | ||
| 1340 | odevice_cert->data = malloc(odevice_cert->size); | ||
| 1341 | memcpy(odevice_cert->data, datap, odevice_cert->size); | ||
| 1342 | } | ||
| 1343 | if (membp) | ||
| 1344 | BIO_free(membp); | ||
| 1345 | |||
| 1346 | ohost_cert->data = malloc(pem_host_cert.size); | ||
| 1347 | memcpy(ohost_cert->data, pem_host_cert.data, pem_host_cert.size); | ||
| 1348 | ohost_cert->size = pem_host_cert.size; | ||
| 1349 | |||
| 1350 | oroot_cert->data = malloc(pem_root_cert.size); | ||
| 1351 | memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size); | ||
| 1352 | oroot_cert->size = pem_root_cert.size; | ||
| 1353 | |||
| 1354 | free(pem_root_cert.data); | ||
| 1355 | free(pem_host_cert.data); | ||
| 1356 | } | ||
| 1357 | } | ||
| 1358 | } | ||
| 1359 | X509V3_EXT_cleanup(); | ||
| 1360 | X509_free(dev_cert); | ||
| 1361 | |||
| 1362 | switch(uret) { | ||
| 1363 | case USERPREF_E_INVALID_ARG: | ||
| 1364 | ret = LOCKDOWN_E_INVALID_ARG; | ||
| 1365 | break; | ||
| 1366 | case USERPREF_E_INVALID_CONF: | ||
| 1367 | ret = LOCKDOWN_E_INVALID_CONF; | ||
| 1368 | break; | ||
| 1369 | case USERPREF_E_SSL_ERROR: | ||
| 1370 | ret = LOCKDOWN_E_SSL_ERROR; | ||
| 1371 | default: | ||
| 1372 | break; | ||
| 1373 | } | ||
| 1374 | |||
| 1375 | if (root_cert.data) | ||
| 1376 | free(root_cert.data); | ||
| 1377 | if (host_cert.data) | ||
| 1378 | free(host_cert.data); | ||
| 1379 | if (root_privkey.data) | ||
| 1380 | free(root_privkey.data); | ||
| 1381 | if (host_privkey.data) | ||
| 1382 | free(host_privkey.data); | ||
| 1383 | #else | ||
| 1384 | gnutls_datum_t modulus = { NULL, 0 }; | ||
| 1385 | gnutls_datum_t exponent = { NULL, 0 }; | ||
| 1386 | |||
| 1387 | /* now decode the PEM encoded key */ | ||
| 1388 | gnutls_datum_t der_pub_key; | ||
| 1389 | if (GNUTLS_E_SUCCESS == gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key)) { | ||
| 1390 | |||
| 1391 | /* initalize asn.1 parser */ | ||
| 1392 | ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY; | ||
| 1393 | if (ASN1_SUCCESS == asn1_array2tree(pkcs1_asn1_tab, &pkcs1, NULL)) { | ||
| 1394 | |||
| 1395 | ASN1_TYPE asn1_pub_key = ASN1_TYPE_EMPTY; | ||
| 1396 | asn1_create_element(pkcs1, "PKCS1.RSAPublicKey", &asn1_pub_key); | ||
| 1397 | |||
| 1398 | if (ASN1_SUCCESS == asn1_der_decoding(&asn1_pub_key, der_pub_key.data, der_pub_key.size, NULL)) { | ||
| 1399 | |||
| 1400 | /* get size to read */ | ||
| 1401 | int ret1 = asn1_read_value(asn1_pub_key, "modulus", NULL, (int*)&modulus.size); | ||
| 1402 | int ret2 = asn1_read_value(asn1_pub_key, "publicExponent", NULL, (int*)&exponent.size); | ||
| 1403 | |||
| 1404 | modulus.data = gnutls_malloc(modulus.size); | ||
| 1405 | exponent.data = gnutls_malloc(exponent.size); | ||
| 1406 | |||
| 1407 | ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, (int*)&modulus.size); | ||
| 1408 | ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, (int*)&exponent.size); | ||
| 1409 | if (ASN1_SUCCESS == ret1 && ASN1_SUCCESS == ret2) | ||
| 1410 | ret = LOCKDOWN_E_SUCCESS; | ||
| 1411 | } | ||
| 1412 | if (asn1_pub_key) | ||
| 1413 | asn1_delete_structure(&asn1_pub_key); | ||
| 1414 | } | ||
| 1415 | if (pkcs1) | ||
| 1416 | asn1_delete_structure(&pkcs1); | ||
| 1417 | } | ||
| 1418 | |||
| 1419 | /* now generate certificates */ | ||
| 1420 | if (LOCKDOWN_E_SUCCESS == ret && 0 != modulus.size && 0 != exponent.size) { | ||
| 1421 | |||
| 1422 | gnutls_global_init(); | ||
| 1423 | gnutls_datum_t essentially_null = { (unsigned char*)strdup("abababababababab"), strlen("abababababababab") }; | ||
| 1424 | |||
| 1425 | gnutls_x509_privkey_t fake_privkey, root_privkey, host_privkey; | ||
| 1426 | gnutls_x509_crt_t dev_cert, root_cert, host_cert; | ||
| 1427 | |||
| 1428 | gnutls_x509_privkey_init(&fake_privkey); | ||
| 1429 | gnutls_x509_privkey_init(&root_privkey); | ||
| 1430 | gnutls_x509_privkey_init(&host_privkey); | ||
| 1431 | |||
| 1432 | gnutls_x509_crt_init(&dev_cert); | ||
| 1433 | gnutls_x509_crt_init(&root_cert); | ||
| 1434 | gnutls_x509_crt_init(&host_cert); | ||
| 1435 | |||
| 1436 | if (GNUTLS_E_SUCCESS == | ||
| 1437 | gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &essentially_null, &essentially_null, | ||
| 1438 | &essentially_null, &essentially_null)) { | ||
| 1439 | |||
| 1440 | uret = userpref_device_record_get_keys_and_certs(udid, root_privkey, root_cert, host_privkey, host_cert); | ||
| 1441 | |||
| 1442 | if (USERPREF_E_SUCCESS == uret) { | ||
| 1443 | /* generate device certificate */ | ||
| 1444 | gnutls_x509_crt_set_key(dev_cert, fake_privkey); | ||
| 1445 | gnutls_x509_crt_set_serial(dev_cert, "\x00", 1); | ||
| 1446 | gnutls_x509_crt_set_version(dev_cert, 3); | ||
| 1447 | gnutls_x509_crt_set_ca_status(dev_cert, 0); | ||
| 1448 | gnutls_x509_crt_set_activation_time(dev_cert, time(NULL)); | ||
| 1449 | gnutls_x509_crt_set_expiration_time(dev_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); | ||
| 1450 | |||
| 1451 | /* use custom hash generation for compatibility with the "Apple ecosystem" */ | ||
| 1452 | const gnutls_digest_algorithm_t dig_sha1 = GNUTLS_DIG_SHA1; | ||
| 1453 | size_t hash_size = gnutls_hash_get_len(dig_sha1); | ||
| 1454 | unsigned char hash[hash_size]; | ||
| 1455 | if (gnutls_hash_fast(dig_sha1, der_pub_key.data, der_pub_key.size, (unsigned char*)&hash) < 0) { | ||
| 1456 | debug_info("ERROR: Failed to generate SHA1 for public key"); | ||
| 1457 | } else { | ||
| 1458 | gnutls_x509_crt_set_subject_key_id(dev_cert, hash, hash_size); | ||
| 1459 | } | ||
| 1460 | |||
| 1461 | gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT); | ||
| 1462 | gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey); | ||
| 1463 | |||
| 1464 | if (LOCKDOWN_E_SUCCESS == ret) { | ||
| 1465 | /* if everything went well, export in PEM format */ | ||
| 1466 | size_t export_size = 0; | ||
| 1467 | gnutls_datum_t dev_pem = { NULL, 0 }; | ||
| 1468 | gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &export_size); | ||
| 1469 | dev_pem.data = gnutls_malloc(export_size); | ||
| 1470 | gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_pem.data, &export_size); | ||
| 1471 | dev_pem.size = export_size; | ||
| 1472 | |||
| 1473 | gnutls_datum_t pem_root_cert = { NULL, 0 }; | ||
| 1474 | gnutls_datum_t pem_host_cert = { NULL, 0 }; | ||
| 1475 | |||
| 1476 | uret = userpref_device_record_get_certs_as_pem(udid, &pem_root_cert, &pem_host_cert, NULL); | ||
| 1477 | |||
| 1478 | if (USERPREF_E_SUCCESS == uret) { | ||
| 1479 | /* copy buffer for output */ | ||
| 1480 | odevice_cert->data = malloc(dev_pem.size); | ||
| 1481 | memcpy(odevice_cert->data, dev_pem.data, dev_pem.size); | ||
| 1482 | odevice_cert->size = dev_pem.size; | ||
| 1483 | |||
| 1484 | ohost_cert->data = malloc(pem_host_cert.size); | ||
| 1485 | memcpy(ohost_cert->data, pem_host_cert.data, pem_host_cert.size); | ||
| 1486 | ohost_cert->size = pem_host_cert.size; | ||
| 1487 | |||
| 1488 | oroot_cert->data = malloc(pem_root_cert.size); | ||
| 1489 | memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size); | ||
| 1490 | oroot_cert->size = pem_root_cert.size; | ||
| 1491 | |||
| 1492 | gnutls_free(pem_root_cert.data); | ||
| 1493 | gnutls_free(pem_host_cert.data); | ||
| 1494 | |||
| 1495 | if (dev_pem.data) | ||
| 1496 | gnutls_free(dev_pem.data); | ||
| 1497 | } | ||
| 1498 | } | ||
| 1499 | } | ||
| 1500 | |||
| 1501 | switch(uret) { | ||
| 1502 | case USERPREF_E_INVALID_ARG: | ||
| 1503 | ret = LOCKDOWN_E_INVALID_ARG; | ||
| 1504 | break; | ||
| 1505 | case USERPREF_E_INVALID_CONF: | ||
| 1506 | ret = LOCKDOWN_E_INVALID_CONF; | ||
| 1507 | break; | ||
| 1508 | case USERPREF_E_SSL_ERROR: | ||
| 1509 | ret = LOCKDOWN_E_SSL_ERROR; | ||
| 1510 | default: | ||
| 1511 | break; | ||
| 1512 | } | ||
| 1513 | } | ||
| 1514 | |||
| 1515 | if (essentially_null.data) | ||
| 1516 | free(essentially_null.data); | ||
| 1517 | gnutls_x509_crt_deinit(dev_cert); | ||
| 1518 | gnutls_x509_crt_deinit(root_cert); | ||
| 1519 | gnutls_x509_crt_deinit(host_cert); | ||
| 1520 | gnutls_x509_privkey_deinit(fake_privkey); | ||
| 1521 | gnutls_x509_privkey_deinit(root_privkey); | ||
| 1522 | gnutls_x509_privkey_deinit(host_privkey); | ||
| 1523 | |||
| 1524 | } | ||
| 1525 | |||
| 1526 | gnutls_free(modulus.data); | ||
| 1527 | gnutls_free(exponent.data); | ||
| 1528 | |||
| 1529 | gnutls_free(der_pub_key.data); | ||
| 1530 | #endif | ||
| 1531 | return ret; | ||
| 1532 | } | ||
| 1533 | |||
| 1534 | /** | ||
| 1535 | * Opens a session with lockdownd and switches to SSL mode if device wants it. | 1223 | * Opens a session with lockdownd and switches to SSL mode if device wants it. |
| 1536 | * | 1224 | * |
| 1537 | * @param client The lockdownd client | 1225 | * @param client The lockdownd client |
| @@ -1569,7 +1257,7 @@ lockdownd_error_t lockdownd_start_session(lockdownd_client_t client, const char | |||
| 1569 | 1257 | ||
| 1570 | /* add system buid */ | 1258 | /* add system buid */ |
| 1571 | char *system_buid = NULL; | 1259 | char *system_buid = NULL; |
| 1572 | userpref_get_system_buid(&system_buid); | 1260 | userpref_read_system_buid(&system_buid); |
| 1573 | if (system_buid) { | 1261 | if (system_buid) { |
| 1574 | plist_dict_set_item(dict, "SystemBUID", plist_new_string(system_buid)); | 1262 | plist_dict_set_item(dict, "SystemBUID", plist_new_string(system_buid)); |
| 1575 | if (system_buid) { | 1263 | if (system_buid) { |
| @@ -1671,8 +1359,14 @@ lockdownd_error_t lockdownd_start_service(lockdownd_client_t client, const char | |||
| 1671 | (*service)->ssl_enabled = 0; | 1359 | (*service)->ssl_enabled = 0; |
| 1672 | } | 1360 | } |
| 1673 | 1361 | ||
| 1362 | plist_t pair_record = NULL; | ||
| 1363 | userpref_read_pair_record(client->udid, &pair_record); | ||
| 1364 | |||
| 1674 | char *host_id = NULL; | 1365 | char *host_id = NULL; |
| 1675 | userpref_device_record_get_host_id(client->udid, &host_id); | 1366 | pair_record_get_host_id(pair_record, &host_id); |
| 1367 | |||
| 1368 | plist_free(pair_record); | ||
| 1369 | |||
| 1676 | if (!host_id) | 1370 | if (!host_id) |
| 1677 | return LOCKDOWN_E_INVALID_CONF; | 1371 | return LOCKDOWN_E_INVALID_CONF; |
| 1678 | 1372 | ||
diff --git a/src/lockdown.h b/src/lockdown.h index 9c2be44..a09e89b 100644 --- a/src/lockdown.h +++ b/src/lockdown.h | |||
| @@ -22,8 +22,6 @@ | |||
| 22 | #ifndef __LOCKDOWND_H | 22 | #ifndef __LOCKDOWND_H |
| 23 | #define __LOCKDOWND_H | 23 | #define __LOCKDOWND_H |
| 24 | 24 | ||
| 25 | #include "common/userpref.h" | ||
| 26 | |||
| 27 | #include "libimobiledevice/lockdown.h" | 25 | #include "libimobiledevice/lockdown.h" |
| 28 | #include "property_list_service.h" | 26 | #include "property_list_service.h" |
| 29 | 27 | ||
| @@ -37,7 +35,4 @@ struct lockdownd_client_private { | |||
| 37 | char *label; | 35 | char *label; |
| 38 | }; | 36 | }; |
| 39 | 37 | ||
| 40 | lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, key_data_t * public_key); | ||
| 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); | ||
| 42 | |||
| 43 | #endif | 38 | #endif |
