summaryrefslogtreecommitdiffstats
path: root/src/lockdown.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lockdown.c')
-rw-r--r--src/lockdown.c530
1 files changed, 112 insertions, 418 deletions
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