201
208
debug_info("success");
202
209
ret = LOCKDOWN_E_SUCCESS;
204
212
plist_free(dict);
215
if (client->session_id) {
216
free(client->session_id);
217
client->session_id = NULL;
206
220
if (client->ssl_enabled) {
207
221
property_list_service_disable_ssl(client->parent);
222
client->ssl_enabled = 0;
213
* Closes the lockdownd client session if one is running and frees up the
214
* lockdownd_client struct.
216
* @param client The lockdown client
218
* @return LOCKDOWN_E_SUCCESS on success, NP_E_INVALID_ARG when client is NULL
220
lockdownd_error_t lockdownd_client_free(lockdownd_client_t client)
228
static lockdownd_error_t lockdownd_client_free_simple(lockdownd_client_t client)
223
231
return LOCKDOWN_E_INVALID_ARG;
224
233
lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
226
if (client->session_id) {
227
lockdownd_stop_session(client, client->session_id);
228
free(client->session_id);
231
235
if (client->parent) {
232
lockdownd_goodbye(client);
234
236
if (property_list_service_client_free(client->parent) == PROPERTY_LIST_SERVICE_E_SUCCESS) {
235
237
ret = LOCKDOWN_E_SUCCESS;
241
if (client->session_id) {
242
free(client->session_id);
243
client->session_id = NULL;
239
245
if (client->udid) {
240
246
free(client->udid);
352
384
ret = LOCKDOWN_E_UNKNOWN_ERROR;
353
if (lockdown_check_result(dict, "QueryType") == RESULT_SUCCESS) {
385
plist_t type_node = plist_dict_get_item(dict, "Type");
386
if (type_node && (plist_get_node_type(type_node) == PLIST_STRING)) {
387
char* typestr = NULL;
388
plist_get_string_val(type_node, &typestr);
389
debug_info("success with type %s", typestr);
354
390
/* return the type if requested */
355
391
if (type != NULL) {
356
plist_t type_node = plist_dict_get_item(dict, "Type");
357
plist_get_string_val(type_node, type);
359
debug_info("success with type %s", *type);
360
396
ret = LOCKDOWN_E_SUCCESS;
398
debug_info("hmm. QueryType response does not contain a type?!");
362
401
plist_free(dict);
772
816
if (!pair_record)
775
char *host_id_loc = pair_record->host_id;
777
819
/* setup request plist */
778
820
plist_t dict = plist_new_dict();
779
821
plist_dict_insert_item(dict, "DeviceCertificate", plist_new_data(pair_record->device_certificate, strlen(pair_record->device_certificate)));
780
822
plist_dict_insert_item(dict, "HostCertificate", plist_new_data(pair_record->host_certificate, strlen(pair_record->host_certificate)));
781
if (!pair_record->host_id)
782
userpref_get_host_id(&host_id_loc);
783
plist_dict_insert_item(dict, "HostID", plist_new_string(host_id_loc));
823
plist_dict_insert_item(dict, "HostID", plist_new_string(pair_record->host_id));
784
824
plist_dict_insert_item(dict, "RootCertificate", plist_new_data(pair_record->root_certificate, strlen(pair_record->root_certificate)));
786
if (!pair_record->host_id)
825
plist_dict_insert_item(dict, "SystemBUID", plist_new_string(pair_record->system_buid));
793
* Generates a new pairing record plist and required certificates for the
794
* supplied public key of the device and the host_id of the caller's host
831
* Generates a pair record plist with required certificates for a specific
832
* device. If a pairing exists, it is loaded from the computer instead of being
797
* @param public_key The public key of the device.
798
* @param host_id The HostID to use for the pair record plist.
799
* @param pair_record_plist Holds the generated pair record.
835
* @param pair_record_plist Holds the pair record.
801
837
* @return LOCKDOWN_E_SUCCESS on success
803
static lockdownd_error_t generate_pair_record_plist(key_data_t public_key, char *host_id, plist_t *pair_record_plist)
839
static lockdownd_error_t generate_pair_record_plist(lockdownd_client_t client, plist_t *pair_record_plist)
805
841
lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
843
char* host_id = NULL;
844
char* system_buid = NULL;
846
key_data_t public_key = { NULL, 0 };
807
847
key_data_t device_cert = { NULL, 0 };
808
848
key_data_t host_cert = { NULL, 0 };
809
849
key_data_t root_cert = { NULL, 0 };
811
ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert);
812
if (ret != LOCKDOWN_E_SUCCESS) {
816
char *host_id_loc = host_id;
819
userpref_get_host_id(&host_id_loc);
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;
857
/* get systembuid and host id */
858
userpref_get_system_buid(&system_buid);
859
userpref_device_record_get_host_id(client->udid, &host_id);
861
/* generate new certificates if needed */
862
if (ret != LOCKDOWN_E_SUCCESS) {
863
ret = lockdownd_get_device_public_key(client, &public_key);
864
if (ret != LOCKDOWN_E_SUCCESS) {
865
debug_info("device refused to send public key.");
868
debug_info("device public key follows:\n%.*s", public_key.size, public_key.data);
870
userpref_device_record_set_value(client->udid, USERPREF_SYSTEM_BUID_KEY, plist_new_string(system_buid));
872
ret = lockdownd_gen_pair_cert_for_udid(client->udid, public_key, &device_cert, &host_cert, &root_cert);
875
if (ret != LOCKDOWN_E_SUCCESS) {
821
879
/* setup request plist */
822
880
*pair_record_plist = plist_new_dict();
823
881
plist_dict_insert_item(*pair_record_plist, "DeviceCertificate", plist_new_data((const char*)device_cert.data, device_cert.size));
824
882
plist_dict_insert_item(*pair_record_plist, "HostCertificate", plist_new_data((const char*)host_cert.data, host_cert.size));
825
plist_dict_insert_item(*pair_record_plist, "HostID", plist_new_string(host_id_loc));
883
plist_dict_insert_item(*pair_record_plist, "HostID", plist_new_string(host_id));
826
884
plist_dict_insert_item(*pair_record_plist, "RootCertificate", plist_new_data((const char*)root_cert.data, root_cert.size));
885
plist_dict_insert_item(*pair_record_plist, "SystemBUID", plist_new_string(system_buid));
893
free(public_key.data);
831
894
if (device_cert.data)
832
895
free(device_cert.data);
833
896
if (host_cert.data)
895
/* Setup Pair request plist */
949
if (!strcmp("Pair", verb)) {
951
plist_t wifi_mac_node = NULL;
952
lockdownd_get_value(client, NULL, "WiFiAddress", &wifi_mac_node);
954
/* save wifi mac address in config */
956
userpref_device_record_set_value(client->udid, USERPREF_WIFI_MAC_ADDRESS_KEY, plist_copy(wifi_mac_node));
957
plist_free(wifi_mac_node);
958
wifi_mac_node = NULL;
962
/* setup pair request plist */
896
963
dict = plist_new_dict();
897
964
plist_dict_add_label(dict, client->label);
898
plist_dict_insert_item(dict,"PairRecord", dict_record);
965
plist_dict_insert_item(dict, "PairRecord", plist_copy(dict_record));
899
966
plist_dict_insert_item(dict, "Request", plist_new_string(verb));
967
plist_dict_insert_item(dict, "ProtocolVersion", plist_new_string(LOCKDOWN_PROTOCOL_VERSION));
969
plist_t options = plist_new_dict();
970
plist_dict_insert_item(options, "ExtendedPairingErrors", plist_new_bool(1));
971
plist_dict_insert_item(dict, "PairingOptions", options);
901
973
/* send to device */
902
974
ret = lockdownd_send(client, dict);
903
975
plist_free(dict);
906
if (ret != LOCKDOWN_E_SUCCESS)
978
if (ret != LOCKDOWN_E_SUCCESS) {
979
plist_free(dict_record);
909
983
/* Now get device's answer */
910
984
ret = lockdownd_receive(client, &dict);
912
if (ret != LOCKDOWN_E_SUCCESS)
986
if (ret != LOCKDOWN_E_SUCCESS) {
987
plist_free(dict_record);
915
991
if (strcmp(verb, "Unpair") == 0) {
916
992
/* workaround for Unpair giving back ValidatePair,
928
1004
if (ret == LOCKDOWN_E_SUCCESS) {
929
1005
debug_info("%s success", verb);
930
1006
if (!pairing_mode) {
1007
debug_info("internal pairing mode");
931
1008
if (!strcmp("Unpair", verb)) {
932
1009
/* remove public key from config */
933
userpref_remove_device_public_key(client->udid);
1010
userpref_remove_device_record(client->udid);
935
/* store public key in config */
936
userpref_set_device_public_key(client->udid, public_key);
1012
if (!strcmp("Pair", verb)) {
1013
debug_info("getting EscrowBag from response");
1015
/* add returned escrow bag if available */
1016
plist_t escrow_bag = plist_dict_get_item(dict, "EscrowBag");
1017
if (escrow_bag && plist_get_node_type(escrow_bag) == PLIST_DATA) {
1018
userpref_device_record_set_value(client->udid, USERPREF_ESCROW_BAG_KEY, plist_copy(escrow_bag));
1019
plist_free(escrow_bag);
1023
/* store DeviceCertificate upon successful pairing */
1024
plist_t devcrt = plist_dict_get_item(dict_record, USERPREF_DEVICE_CERTIFICATE_KEY);
1025
if (devcrt && plist_get_node_type(devcrt) == PLIST_DATA) {
1026
userpref_device_record_set_value(client->udid, USERPREF_DEVICE_CERTIFICATE_KEY, plist_copy(devcrt));
1031
debug_info("external pairing mode");
940
1034
debug_info("%s failure", verb);
1187
1293
X509_free(rootCert);
1297
X509V3_set_ctx_nodb(&ctx);
1298
X509V3_set_ctx(&ctx, NULL, dev_cert, NULL, NULL, 0);
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");
1303
X509_add_ext(dev_cert, ext, -1);
1304
X509_EXTENSION_free(ext);
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");
1309
X509_add_ext(dev_cert, ext, -1);
1310
X509_EXTENSION_free(ext);
1190
1312
EVP_PKEY* rootPriv = NULL;
1191
1313
membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size);
1192
1314
PEM_read_bio_PrivateKey(membp, &rootPriv, NULL, NULL);
1208
1330
key_data_t pem_root_cert = { NULL, 0 };
1209
1331
key_data_t pem_host_cert = { NULL, 0 };
1211
uret = userpref_get_certs_as_pem(&pem_root_cert, &pem_host_cert);
1333
uret = userpref_device_record_get_certs_as_pem(udid, &pem_root_cert, &pem_host_cert, NULL);
1212
1334
if (USERPREF_E_SUCCESS == uret) {
1213
1335
/* copy buffer for output */
1214
1336
membp = BIO_new(BIO_s_mem());
1215
1337
if (membp && PEM_write_bio_X509(membp, dev_cert) > 0) {
1216
odevice_cert->size = BIO_get_mem_data(membp, &odevice_cert->data);
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);
1221
1346
ohost_cert->data = malloc(pem_host_cert.size);
1222
1347
memcpy(ohost_cert->data, pem_host_cert.data, pem_host_cert.size);
1309
1437
gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &essentially_null, &essentially_null,
1310
1438
&essentially_null, &essentially_null)) {
1312
gnutls_x509_privkey_init(&root_privkey);
1313
gnutls_x509_privkey_init(&host_privkey);
1315
uret = userpref_get_keys_and_certs(root_privkey, root_cert, host_privkey, host_cert);
1440
uret = userpref_device_record_get_keys_and_certs(udid, root_privkey, root_cert, host_privkey, host_cert);
1317
1442
if (USERPREF_E_SUCCESS == uret) {
1318
1443
/* generate device certificate */
1322
1447
gnutls_x509_crt_set_ca_status(dev_cert, 0);
1323
1448
gnutls_x509_crt_set_activation_time(dev_cert, time(NULL));
1324
1449
gnutls_x509_crt_set_expiration_time(dev_cert, time(NULL) + (60 * 60 * 24 * 365 * 10));
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");
1458
gnutls_x509_crt_set_subject_key_id(dev_cert, hash, hash_size);
1461
gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT);
1325
1462
gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey);
1327
1464
if (LOCKDOWN_E_SUCCESS == ret) {
1419
1555
/* if we have a running session, stop current one first */
1420
1556
if (client->session_id) {
1421
1557
lockdownd_stop_session(client, client->session_id);
1422
free(client->session_id);
1425
1560
/* setup request plist */
1426
1561
dict = plist_new_dict();
1427
1562
plist_dict_add_label(dict, client->label);
1428
plist_dict_insert_item(dict,"HostID", plist_new_string(host_id));
1429
1563
plist_dict_insert_item(dict,"Request", plist_new_string("StartSession"));
1567
plist_dict_insert_item(dict, "HostID", plist_new_string(host_id));
1570
/* add system buid */
1571
char *system_buid = NULL;
1572
userpref_get_system_buid(&system_buid);
1574
plist_dict_insert_item(dict, "SystemBUID", plist_new_string(system_buid));
1431
1581
ret = lockdownd_send(client, dict);
1432
1582
plist_free(dict);