summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Martin Szulecki2010-01-13 01:26:25 +0100
committerGravatar Martin Szulecki2010-01-13 01:26:25 +0100
commitde6251f720b242d42a434bb3aa614d3c5bee65df (patch)
treed005f46635d9034e4656074cd72d6eb1d3bbb460 /src
parentbdc857bcd4488b8e135b189022e210b5b841e409 (diff)
downloadlibimobiledevice-de6251f720b242d42a434bb3aa614d3c5bee65df.tar.gz
libimobiledevice-de6251f720b242d42a434bb3aa614d3c5bee65df.tar.bz2
Refactor pairing to allow implementations to fully handle pairing
Implementations can now supply a full pair record and thus use their own preferred method of managing pairing records if needed.
Diffstat (limited to 'src')
-rw-r--r--src/lockdown.c164
1 files changed, 108 insertions, 56 deletions
diff --git a/src/lockdown.c b/src/lockdown.c
index ea161bc..a85f8ae 100644
--- a/src/lockdown.c
+++ b/src/lockdown.c
@@ -656,10 +656,10 @@ lockdownd_error_t lockdownd_client_new_with_handshake(iphone_device_t device, lo
656 } 656 }
657 657
658 if (LOCKDOWN_E_SUCCESS == ret && !userpref_has_device_public_key(client_loc->uuid)) 658 if (LOCKDOWN_E_SUCCESS == ret && !userpref_has_device_public_key(client_loc->uuid))
659 ret = lockdownd_pair(client_loc, host_id); 659 ret = lockdownd_pair(client_loc, NULL);
660 660
661 /* in any case, we need to validate pairing to receive trusted host status */ 661 /* in any case, we need to validate pairing to receive trusted host status */
662 ret = lockdownd_validate_pair(client_loc, host_id); 662 ret = lockdownd_validate_pair(client_loc, NULL);
663 663
664 if (LOCKDOWN_E_SUCCESS == ret) { 664 if (LOCKDOWN_E_SUCCESS == ret) {
665 ret = lockdownd_start_session(client_loc, host_id, NULL, NULL); 665 ret = lockdownd_start_session(client_loc, host_id, NULL, NULL);
@@ -682,57 +682,109 @@ lockdownd_error_t lockdownd_client_new_with_handshake(iphone_device_t device, lo
682 return ret; 682 return ret;
683} 683}
684 684
685static plist_t lockdownd_pair_record_to_plist(lockdownd_pair_record_t pair_record)
686{
687 if (!pair_record)
688 return NULL;
689
690 char *host_id_loc = pair_record->host_id;
691
692 /* setup request plist */
693 plist_t dict = plist_new_dict();
694 plist_dict_insert_item(dict, "DeviceCertificate", plist_new_data(pair_record->device_certificate, strlen(pair_record->device_certificate)));
695 plist_dict_insert_item(dict, "HostCertificate", plist_new_data(pair_record->host_certificate, strlen(pair_record->host_certificate)));
696 if (!pair_record->host_id)
697 userpref_get_host_id(&host_id_loc);
698 plist_dict_insert_item(dict, "HostID", plist_new_string(host_id_loc));
699 plist_dict_insert_item(dict, "RootCertificate", plist_new_data(pair_record->root_certificate, strlen(pair_record->root_certificate)));
700
701 if (!pair_record->host_id)
702 free(host_id_loc);
703
704 return dict;
705}
706
707static lockdownd_error_t generate_pair_record_plist(gnutls_datum_t public_key, char *host_id, plist_t *pair_record_plist)
708{
709 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
710
711 gnutls_datum_t device_cert = { NULL, 0 };
712 gnutls_datum_t host_cert = { NULL, 0 };
713 gnutls_datum_t root_cert = { NULL, 0 };
714
715 ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert);
716 if (ret != LOCKDOWN_E_SUCCESS) {
717 return ret;
718 }
719
720 char *host_id_loc = host_id;
721
722 if (!host_id)
723 userpref_get_host_id(&host_id_loc);
724
725 /* setup request plist */
726 *pair_record_plist = plist_new_dict();
727 plist_dict_insert_item(*pair_record_plist, "DeviceCertificate", plist_new_data((const char*)device_cert.data, device_cert.size));
728 plist_dict_insert_item(*pair_record_plist, "HostCertificate", plist_new_data((const char*)host_cert.data, host_cert.size));
729 plist_dict_insert_item(*pair_record_plist, "HostID", plist_new_string(host_id_loc));
730 plist_dict_insert_item(*pair_record_plist, "RootCertificate", plist_new_data((const char*)root_cert.data, root_cert.size));
731
732 if (!host_id)
733 free(host_id_loc);
734
735 return ret;
736}
737
685/** Function used internally by lockdownd_pair() and lockdownd_validate_pair() 738/** Function used internally by lockdownd_pair() and lockdownd_validate_pair()
686 * 739 *
687 * @param client The lockdown client to pair with. 740 * @param client The lockdown client to pair with.
688 * @param host_id The HostID to use for pairing. If NULL is passed, then 741 * @param pair_record The pair record to use for pairing. If NULL is passed, then
689 * the HostID of the current machine is used. A new HostID will be 742 * the pair records from the current machine are used. New records will be
690 * generated automatically when pairing is done for the first time. 743 * generated automatically when pairing is done for the first time.
691 * @param verb This is either "Pair" or "ValidatePair". 744 * @param verb This is either "Pair", "ValidatePair" or "Unpair".
692 * 745 *
693 * @return an error code (LOCKDOWN_E_SUCCESS on success) 746 * @return an error code (LOCKDOWN_E_SUCCESS on success)
694 */ 747 */
695static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, char *host_id, const char *verb) 748static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record, const char *verb)
696{ 749{
697 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; 750 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
698 plist_t dict = NULL; 751 plist_t dict = NULL;
699 plist_t dict_record = NULL; 752 plist_t dict_record = NULL;
700
701 gnutls_datum_t device_cert = { NULL, 0 };
702 gnutls_datum_t host_cert = { NULL, 0 };
703 gnutls_datum_t root_cert = { NULL, 0 };
704 gnutls_datum_t public_key = { NULL, 0 }; 753 gnutls_datum_t public_key = { NULL, 0 };
754 int pairing_mode = 0; /* 0 = libiphone, 1 = external */
705 755
706 char *host_id_loc = host_id; 756 if (pair_record && pair_record->host_id) {
707 757 /* valid pair_record passed? */
708 ret = lockdownd_get_device_public_key(client, &public_key); 758 if (!pair_record->device_certificate || !pair_record->host_certificate || !pair_record->root_certificate) {
709 if (ret != LOCKDOWN_E_SUCCESS) { 759 return LOCKDOWN_E_PLIST_ERROR;
710 debug_info("device refused to send public key."); 760 }
711 return ret;
712 }
713 debug_info("device public key follows:\n%s", public_key.data);
714 761
715 ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert); 762 /* use passed pair_record */
716 if (ret != LOCKDOWN_E_SUCCESS) { 763 dict_record = lockdownd_pair_record_to_plist(pair_record);
717 free(public_key.data);
718 return ret;
719 }
720 764
721 if (!host_id) { 765 pairing_mode = 1;
722 userpref_get_host_id(&host_id_loc); 766 } else {
767 ret = lockdownd_get_device_public_key(client, &public_key);
768 if (ret != LOCKDOWN_E_SUCCESS) {
769 if (public_key.data)
770 free(public_key.data);
771 debug_info("device refused to send public key.");
772 return ret;
773 }
774 debug_info("device public key follows:\n%s", public_key.data);
775 /* get libiphone pair_record */
776 ret = generate_pair_record_plist(public_key, NULL, &dict_record);
777 if (ret != LOCKDOWN_E_SUCCESS) {
778 if (dict_record)
779 plist_free(dict_record);
780 return ret;
781 }
723 } 782 }
724 783
725 /* Setup Pair request plist */ 784 /* Setup Pair request plist */
726 dict = plist_new_dict(); 785 dict = plist_new_dict();
727 dict_record = plist_new_dict();
728 plist_dict_add_label(dict, client->label); 786 plist_dict_add_label(dict, client->label);
729 plist_dict_insert_item(dict,"PairRecord", dict_record); 787 plist_dict_insert_item(dict,"PairRecord", dict_record);
730
731 plist_dict_insert_item(dict_record, "DeviceCertificate", plist_new_data((const char*)device_cert.data, device_cert.size));
732 plist_dict_insert_item(dict_record, "HostCertificate", plist_new_data((const char*)host_cert.data, host_cert.size));
733 plist_dict_insert_item(dict_record, "HostID", plist_new_string(host_id_loc));
734 plist_dict_insert_item(dict_record, "RootCertificate", plist_new_data((const char*)root_cert.data, root_cert.size));
735
736 plist_dict_insert_item(dict, "Request", plist_new_string(verb)); 788 plist_dict_insert_item(dict, "Request", plist_new_string(verb));
737 789
738 /* send to iPhone */ 790 /* send to iPhone */
@@ -740,10 +792,6 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, char *host
740 plist_free(dict); 792 plist_free(dict);
741 dict = NULL; 793 dict = NULL;
742 794
743 if (!host_id) {
744 free(host_id_loc);
745 }
746
747 if (ret != LOCKDOWN_E_SUCCESS) 795 if (ret != LOCKDOWN_E_SUCCESS)
748 return ret; 796 return ret;
749 797
@@ -760,12 +808,14 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, char *host
760 /* if pairing succeeded */ 808 /* if pairing succeeded */
761 if (ret == LOCKDOWN_E_SUCCESS) { 809 if (ret == LOCKDOWN_E_SUCCESS) {
762 debug_info("%s success", verb); 810 debug_info("%s success", verb);
763 if (!strcmp("Unpair", verb)) { 811 if (!pairing_mode) {
764 /* remove public key from config */ 812 if (!strcmp("Unpair", verb)) {
765 userpref_remove_device_public_key(client->uuid); 813 /* remove public key from config */
766 } else { 814 userpref_remove_device_public_key(client->uuid);
767 /* store public key in config */ 815 } else {
768 userpref_set_device_public_key(client->uuid, public_key); 816 /* store public key in config */
817 userpref_set_device_public_key(client->uuid, public_key);
818 }
769 } 819 }
770 } else { 820 } else {
771 debug_info("%s failure", verb); 821 debug_info("%s failure", verb);
@@ -786,7 +836,8 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, char *host
786 } 836 }
787 plist_free(dict); 837 plist_free(dict);
788 dict = NULL; 838 dict = NULL;
789 free(public_key.data); 839 if (public_key.data)
840 free(public_key.data);
790 return ret; 841 return ret;
791} 842}
792 843
@@ -795,15 +846,15 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, char *host
795 * It's part of the lockdownd handshake. 846 * It's part of the lockdownd handshake.
796 * 847 *
797 * @param client The lockdown client to pair with. 848 * @param client The lockdown client to pair with.
798 * @param host_id The HostID to use for pairing. If NULL is passed, then 849 * @param pair_record The pair record to use for pairing. If NULL is passed, then
799 * the HostID of the current machine is used. A new HostID will be 850 * the pair records from the current machine are used. New records will be
800 * generated automatically when pairing is done for the first time. 851 * generated automatically when pairing is done for the first time.
801 * 852 *
802 * @return an error code (LOCKDOWN_E_SUCCESS on success) 853 * @return an error code (LOCKDOWN_E_SUCCESS on success)
803 */ 854 */
804lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *host_id) 855lockdownd_error_t lockdownd_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record)
805{ 856{
806 return lockdownd_do_pair(client, host_id, "Pair"); 857 return lockdownd_do_pair(client, pair_record, "Pair");
807} 858}
808 859
809/** 860/**
@@ -812,15 +863,16 @@ lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *host_id)
812 * It's part of the lockdownd handshake. 863 * It's part of the lockdownd handshake.
813 * 864 *
814 * @param client The lockdown client to pair with. 865 * @param client The lockdown client to pair with.
815 * @param host_id The HostID to use for pairing. If NULL is passed, then 866 * @param pair_record The pair record to validate pairing with. If NULL is
816 * the HostID of the current machine is used. A new HostID will be 867 * passed, then the pair records from the current machine are used.
817 * generated automatically when pairing is done for the first time. 868 * New records will be generated automatically when pairing is done
869 * for the first time.
818 * 870 *
819 * @return an error code (LOCKDOWN_E_SUCCESS on success) 871 * @return an error code (LOCKDOWN_E_SUCCESS on success)
820 */ 872 */
821lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, char *host_id) 873lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record)
822{ 874{
823 return lockdownd_do_pair(client, host_id, "ValidatePair"); 875 return lockdownd_do_pair(client, pair_record, "ValidatePair");
824} 876}
825 877
826/** 878/**
@@ -828,14 +880,14 @@ lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, char *host_
828 * from the device and host. 880 * from the device and host.
829 * 881 *
830 * @param client The lockdown client to pair with. 882 * @param client The lockdown client to pair with.
831 * @param host_id The HostID to use for unpairing. If NULL is passed, then 883 * @param pair_record The pair record to use for unpair. If NULL is passed, then
832 * the HostID of the current machine is used. 884 * the pair records from the current machine are used.
833 * 885 *
834 * @return an error code (LOCKDOWN_E_SUCCESS on success) 886 * @return an error code (LOCKDOWN_E_SUCCESS on success)
835 */ 887 */
836lockdownd_error_t lockdownd_unpair(lockdownd_client_t client, char *host_id) 888lockdownd_error_t lockdownd_unpair(lockdownd_client_t client, lockdownd_pair_record_t pair_record)
837{ 889{
838 return lockdownd_do_pair(client, host_id, "Unpair"); 890 return lockdownd_do_pair(client, pair_record, "Unpair");
839} 891}
840 892
841/** 893/**