summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Martin Szulecki2014-03-21 00:16:29 +0100
committerGravatar Martin Szulecki2014-03-21 00:16:29 +0100
commitd1ccd4eeebc94dac11140ae77b73392d0763d3a4 (patch)
treefb5fa6cab2bdaf55b28004921960d331db59bf7b /src
parent88ce6113593158944630435678e689bf155d9a03 (diff)
downloadlibimobiledevice-d1ccd4eeebc94dac11140ae77b73392d0763d3a4.tar.gz
libimobiledevice-d1ccd4eeebc94dac11140ae77b73392d0763d3a4.tar.bz2
Refactor pair record handling to use new usbmuxd pair record interface
This refactoring is mandatory as libimobiledevice should not interact with the pair record configuration directory which is owned by the usbmuxd user. This change also adds compatibility for the native usbmuxd and thus pair records saved by iTunes.
Diffstat (limited to 'src')
-rw-r--r--src/idevice.c31
-rw-r--r--src/lockdown.c530
-rw-r--r--src/lockdown.h5
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 */
640static 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) 640static 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
61const 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 */
621lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, key_data_t * public_key) 611static 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 */
839static lockdownd_error_t generate_pair_record_plist(lockdownd_client_t client, plist_t *pair_record_plist) 840static 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
887leave: 898leave:
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 */
1222lockdownd_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
40lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, key_data_t * public_key);
41lockdownd_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