summaryrefslogtreecommitdiffstats
path: root/src/lockdown.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lockdown.c')
-rw-r--r--src/lockdown.c164
1 files changed, 105 insertions, 59 deletions
diff --git a/src/lockdown.c b/src/lockdown.c
index b182706..fb5f8f5 100644
--- a/src/lockdown.c
+++ b/src/lockdown.c
@@ -115,18 +115,23 @@ static int lockdown_check_result(plist_t dict, const char *query_match)
115 * 115 *
116 * @return an error code (LOCKDOWN_E_SUCCESS on success) 116 * @return an error code (LOCKDOWN_E_SUCCESS on success)
117 */ 117 */
118lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client, const char *session_id) 118lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client)
119{ 119{
120 if (!client) 120 if (!client)
121 return LOCKDOWN_E_INVALID_ARG; 121 return LOCKDOWN_E_INVALID_ARG;
122 122
123 if (!client->session_id) {
124 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: no session_id given, cannot stop session\n", __func__);
125 return LOCKDOWN_E_INVALID_ARG;
126 }
127
123 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; 128 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
124 129
125 plist_t dict = plist_new_dict(); 130 plist_t dict = plist_new_dict();
126 plist_dict_insert_item(dict,"Request", plist_new_string("StopSession")); 131 plist_dict_insert_item(dict,"Request", plist_new_string("StopSession"));
127 plist_dict_insert_item(dict,"SessionID", plist_new_string(session_id)); 132 plist_dict_insert_item(dict,"SessionID", plist_new_string(client->session_id));
128 133
129 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: called\n", __func__); 134 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: stopping session %s\n", __func__, client->session_id);
130 135
131 ret = lockdownd_send(client, dict); 136 ret = lockdownd_send(client, dict);
132 137
@@ -148,6 +153,9 @@ lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client, const char *
148 plist_free(dict); 153 plist_free(dict);
149 dict = NULL; 154 dict = NULL;
150 155
156 free(client->session_id);
157 client->session_id = NULL;
158
151 return ret; 159 return ret;
152} 160}
153 161
@@ -170,7 +178,7 @@ static lockdownd_error_t lockdownd_stop_ssl_session(lockdownd_client_t client)
170 178
171 if (client->in_SSL) { 179 if (client->in_SSL) {
172 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: stopping SSL session\n", __func__); 180 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: stopping SSL session\n", __func__);
173 ret = lockdownd_stop_session(client, client->session_id); 181 ret = lockdownd_stop_session(client);
174 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: sending SSL close notify\n", __func__); 182 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: sending SSL close notify\n", __func__);
175 gnutls_bye(client->ssl_session, GNUTLS_SHUT_RDWR); 183 gnutls_bye(client->ssl_session, GNUTLS_SHUT_RDWR);
176 } 184 }
@@ -209,6 +217,13 @@ lockdownd_error_t lockdownd_client_free(lockdownd_client_t client)
209 } 217 }
210 } 218 }
211 219
220 if (client->session_id) {
221 free(client->session_id);
222 }
223 if (client->uuid) {
224 free(client->uuid);
225 }
226
212 free(client); 227 free(client);
213 return ret; 228 return ret;
214} 229}
@@ -642,31 +657,27 @@ lockdownd_error_t lockdownd_client_new(iphone_device_t device, lockdownd_client_
642 client_loc->ssl_session = NULL; 657 client_loc->ssl_session = NULL;
643 client_loc->ssl_certificate = NULL; 658 client_loc->ssl_certificate = NULL;
644 client_loc->in_SSL = 0; 659 client_loc->in_SSL = 0;
660 client_loc->session_id = NULL;
661 client_loc->uuid = NULL;
645 662
646 if (LOCKDOWN_E_SUCCESS != lockdownd_query_type(client_loc)) { 663 if (LOCKDOWN_E_SUCCESS != lockdownd_query_type(client_loc)) {
647 log_debug_msg("%s: QueryType failed in the lockdownd client.\n", __func__); 664 log_debug_msg("%s: QueryType failed in the lockdownd client.\n", __func__);
648 ret = LOCKDOWN_E_NOT_ENOUGH_DATA; 665 ret = LOCKDOWN_E_NOT_ENOUGH_DATA;
649 } 666 }
650 667
651 char *uuid = NULL; 668 ret = iphone_device_get_uuid(device, &client_loc->uuid);
652 ret = iphone_device_get_uuid(device, &uuid);
653 if (LOCKDOWN_E_SUCCESS != ret) { 669 if (LOCKDOWN_E_SUCCESS != ret) {
654 log_debug_msg("%s: failed to get device uuid.\n", __func__); 670 log_debug_msg("%s: failed to get device uuid.\n", __func__);
655 } 671 }
656 log_debug_msg("%s: device uuid: %s\n", __func__, uuid); 672 log_debug_msg("%s: device uuid: %s\n", __func__, client_loc->uuid);
657 673
658 userpref_get_host_id(&host_id); 674 userpref_get_host_id(&host_id);
659 if (LOCKDOWN_E_SUCCESS == ret && !host_id) { 675 if (LOCKDOWN_E_SUCCESS == ret && !host_id) {
660 ret = LOCKDOWN_E_INVALID_CONF; 676 ret = LOCKDOWN_E_INVALID_CONF;
661 } 677 }
662 678
663 if (LOCKDOWN_E_SUCCESS == ret && !userpref_has_device_public_key(uuid)) 679 if (LOCKDOWN_E_SUCCESS == ret && !userpref_has_device_public_key(client_loc->uuid))
664 ret = lockdownd_pair(client_loc, uuid, host_id); 680 ret = lockdownd_pair(client_loc, host_id);
665
666 if (uuid) {
667 free(uuid);
668 uuid = NULL;
669 }
670 681
671 if (LOCKDOWN_E_SUCCESS == ret) { 682 if (LOCKDOWN_E_SUCCESS == ret) {
672 ret = lockdownd_start_ssl_session(client_loc, host_id); 683 ret = lockdownd_start_ssl_session(client_loc, host_id);
@@ -687,12 +698,17 @@ lockdownd_error_t lockdownd_client_new(iphone_device_t device, lockdownd_client_
687 return ret; 698 return ret;
688} 699}
689 700
690/** Generates the appropriate keys and pairs the device. It's part of the 701/** Function used internally by lockdownd_pair() and lockdownd_validate_pair()
691 * lockdownd handshake. 702 *
703 * @param client The lockdown client to pair with.
704 * @param host_id The HostID to use for pairing. If NULL is passed, then
705 * the HostID of the current machine is used. A new HostID will be
706 * generated automatically when pairing is done for the first time.
707 * @param verb This is either "Pair" or "ValidatePair".
692 * 708 *
693 * @return an error code (LOCKDOWN_E_SUCCESS on success) 709 * @return an error code (LOCKDOWN_E_SUCCESS on success)
694 */ 710 */
695lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *uuid, char *host_id) 711static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, char *host_id, const char *verb)
696{ 712{
697 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; 713 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
698 plist_t dict = NULL; 714 plist_t dict = NULL;
@@ -703,6 +719,8 @@ lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *uuid, char *ho
703 gnutls_datum_t root_cert = { NULL, 0 }; 719 gnutls_datum_t root_cert = { NULL, 0 };
704 gnutls_datum_t public_key = { NULL, 0 }; 720 gnutls_datum_t public_key = { NULL, 0 };
705 721
722 char *host_id_loc = host_id;
723
706 ret = lockdownd_get_device_public_key(client, &public_key); 724 ret = lockdownd_get_device_public_key(client, &public_key);
707 if (ret != LOCKDOWN_E_SUCCESS) { 725 if (ret != LOCKDOWN_E_SUCCESS) {
708 log_debug_msg("%s: device refused to send public key.\n", __func__); 726 log_debug_msg("%s: device refused to send public key.\n", __func__);
@@ -716,6 +734,10 @@ lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *uuid, char *ho
716 return ret; 734 return ret;
717 } 735 }
718 736
737 if (!host_id) {
738 userpref_get_host_id(&host_id_loc);
739 }
740
719 /* Setup Pair request plist */ 741 /* Setup Pair request plist */
720 dict = plist_new_dict(); 742 dict = plist_new_dict();
721 dict_record = plist_new_dict(); 743 dict_record = plist_new_dict();
@@ -723,16 +745,20 @@ lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *uuid, char *ho
723 745
724 plist_dict_insert_item(dict_record, "DeviceCertificate", plist_new_data((const char*)device_cert.data, device_cert.size)); 746 plist_dict_insert_item(dict_record, "DeviceCertificate", plist_new_data((const char*)device_cert.data, device_cert.size));
725 plist_dict_insert_item(dict_record, "HostCertificate", plist_new_data((const char*)host_cert.data, host_cert.size)); 747 plist_dict_insert_item(dict_record, "HostCertificate", plist_new_data((const char*)host_cert.data, host_cert.size));
726 plist_dict_insert_item(dict_record, "HostID", plist_new_string(host_id)); 748 plist_dict_insert_item(dict_record, "HostID", plist_new_string(host_id_loc));
727 plist_dict_insert_item(dict_record, "RootCertificate", plist_new_data((const char*)root_cert.data, root_cert.size)); 749 plist_dict_insert_item(dict_record, "RootCertificate", plist_new_data((const char*)root_cert.data, root_cert.size));
728 750
729 plist_dict_insert_item(dict, "Request", plist_new_string("Pair")); 751 plist_dict_insert_item(dict, "Request", plist_new_string(verb));
730 752
731 /* send to iPhone */ 753 /* send to iPhone */
732 ret = lockdownd_send(client, dict); 754 ret = lockdownd_send(client, dict);
733 plist_free(dict); 755 plist_free(dict);
734 dict = NULL; 756 dict = NULL;
735 757
758 if (!host_id) {
759 free(host_id_loc);
760 }
761
736 if (ret != LOCKDOWN_E_SUCCESS) 762 if (ret != LOCKDOWN_E_SUCCESS)
737 return ret; 763 return ret;
738 764
@@ -742,24 +768,56 @@ lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *uuid, char *ho
742 if (ret != LOCKDOWN_E_SUCCESS) 768 if (ret != LOCKDOWN_E_SUCCESS)
743 return ret; 769 return ret;
744 770
745 if (lockdown_check_result(dict, "Pair") == RESULT_SUCCESS) { 771 if (lockdown_check_result(dict, verb) != RESULT_SUCCESS) {
746 ret = LOCKDOWN_E_SUCCESS; 772 ret = LOCKDOWN_E_PAIRING_FAILED;
747 } 773 }
748 plist_free(dict); 774 plist_free(dict);
749 dict = NULL; 775 dict = NULL;
750 776
751 /* store public key in config if pairing succeeded */ 777 /* store public key in config if pairing succeeded */
752 if (ret == LOCKDOWN_E_SUCCESS) { 778 if (ret == LOCKDOWN_E_SUCCESS) {
753 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: pair success\n", __func__); 779 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: %s success\n", __func__, verb);
754 userpref_set_device_public_key(uuid, public_key); 780 userpref_set_device_public_key(client->uuid, public_key);
755 } else { 781 } else {
756 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: pair failure\n", __func__); 782 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: %s failure\n", __func__, verb);
757 ret = LOCKDOWN_E_PAIRING_FAILED;
758 } 783 }
759 free(public_key.data); 784 free(public_key.data);
760 return ret; 785 return ret;
761} 786}
762 787
788/**
789 * Pairs the device with the given HostID.
790 * It's part of the lockdownd handshake.
791 *
792 * @param client The lockdown client to pair with.
793 * @param host_id The HostID to use for pairing. If NULL is passed, then
794 * the HostID of the current machine is used. A new HostID will be
795 * generated automatically when pairing is done for the first time.
796 *
797 * @return an error code (LOCKDOWN_E_SUCCESS on success)
798 */
799lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *host_id)
800{
801 return lockdownd_do_pair(client, host_id, "Pair");
802}
803
804/**
805 * Pairs the device with the given HostID. The difference to lockdownd_pair()
806 * is that the specified host will become trusted host of the device.
807 * It's part of the lockdownd handshake.
808 *
809 * @param client The lockdown client to pair with.
810 * @param host_id The HostID to use for pairing. If NULL is passed, then
811 * the HostID of the current machine is used. A new HostID will be
812 * generated automatically when pairing is done for the first time.
813 *
814 * @return an error code (LOCKDOWN_E_SUCCESS on success)
815 */
816lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, char *host_id)
817{
818 return lockdownd_do_pair(client, host_id, "ValidatePair");
819}
820
763/** 821/**
764 * Tells the device to immediately enter recovery mode. 822 * Tells the device to immediately enter recovery mode.
765 * 823 *
@@ -985,7 +1043,10 @@ lockdownd_error_t lockdownd_start_ssl_session(lockdownd_client_t client, const c
985 uint32_t return_me = 0; 1043 uint32_t return_me = 0;
986 1044
987 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; 1045 lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
988 client->session_id[0] = '\0'; 1046 if (client->session_id) {
1047 free(client->session_id);
1048 client->session_id = NULL;
1049 }
989 1050
990 /* Setup DevicePublicKey request plist */ 1051 /* Setup DevicePublicKey request plist */
991 dict = plist_new_dict(); 1052 dict = plist_new_dict();
@@ -1012,26 +1073,22 @@ lockdownd_error_t lockdownd_start_ssl_session(lockdownd_client_t client, const c
1012 1073
1013 if (!strcmp(error, "InvalidHostID")) { 1074 if (!strcmp(error, "InvalidHostID")) {
1014 /* hostid is unknown. Pair and try again */ 1075 /* hostid is unknown. Pair and try again */
1015 char *uuid = NULL;
1016 char *host_id = NULL; 1076 char *host_id = NULL;
1017 userpref_get_host_id(&host_id); 1077 userpref_get_host_id(&host_id);
1018 1078
1019 if (LOCKDOWN_E_SUCCESS == lockdownd_get_device_uuid(client, &uuid) ) { 1079 if (LOCKDOWN_E_SUCCESS == lockdownd_pair(client, host_id) ) {
1020 if (LOCKDOWN_E_SUCCESS == lockdownd_pair(client, uuid, host_id) ) { 1080 /* start session again */
1021 /* start session again */ 1081 plist_free(dict);
1022 plist_free(dict); 1082 dict = plist_new_dict();
1023 dict = plist_new_dict(); 1083 plist_dict_insert_item(dict,"HostID", plist_new_string(HostID));
1024 plist_dict_insert_item(dict,"HostID", plist_new_string(HostID)); 1084 plist_dict_insert_item(dict,"Request", plist_new_string("StartSession"));
1025 plist_dict_insert_item(dict,"Request", plist_new_string("StartSession"));
1026 1085
1027 ret = lockdownd_send(client, dict); 1086 ret = lockdownd_send(client, dict);
1028 plist_free(dict); 1087 plist_free(dict);
1029 dict = NULL; 1088 dict = NULL;
1030 1089
1031 ret = lockdownd_recv(client, &dict); 1090 ret = lockdownd_recv(client, &dict);
1032 }
1033 } 1091 }
1034 free(uuid);
1035 free(host_id); 1092 free(host_id);
1036 } 1093 }
1037 free(error); 1094 free(error);
@@ -1100,27 +1157,16 @@ lockdownd_error_t lockdownd_start_ssl_session(lockdownd_client_t client, const c
1100 ret = LOCKDOWN_E_SUCCESS; 1157 ret = LOCKDOWN_E_SUCCESS;
1101 } 1158 }
1102 } 1159 }
1103 /* store session id */ 1160 /* store session id, we need it for StopSession */
1104 plist_t session_node = plist_dict_get_item(dict, "SessionID"); 1161 plist_t session_node = plist_dict_get_item(dict, "SessionID");
1105 if (session_node) { 1162 if (session_node && (plist_get_node_type(session_node) == PLIST_STRING)) {
1106 1163 plist_get_string_val(session_node, &client->session_id);
1107 plist_type session_node_type = plist_get_node_type(session_node); 1164 }
1108 1165 if (client->session_id) {
1109 if (session_node_type == PLIST_STRING) { 1166 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: SessionID: %s\n", __func__, client->session_id);
1110 1167 } else {
1111 char *session_id = NULL;
1112 plist_get_string_val(session_node, &session_id);
1113
1114 if (session_node_type == PLIST_STRING && session_id) {
1115 /* we need to store the session ID for StopSession */
1116 strcpy(client->session_id, session_id);
1117 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: SessionID: %s\n", __func__, client->session_id);
1118 }
1119 if (session_id)
1120 free(session_id);
1121 }
1122 } else
1123 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: Failed to get SessionID!\n", __func__); 1168 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: Failed to get SessionID!\n", __func__);
1169 }
1124 plist_free(dict); 1170 plist_free(dict);
1125 dict = NULL; 1171 dict = NULL;
1126 1172