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)
*
* @return an error code (LOCKDOWN_E_SUCCESS on success)
*/
-lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client, const char *session_id)
+lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client)
{
if (!client)
return LOCKDOWN_E_INVALID_ARG;
+ if (!client->session_id) {
+ log_dbg_msg(DBGMASK_LOCKDOWND, "%s: no session_id given, cannot stop session\n", __func__);
+ return LOCKDOWN_E_INVALID_ARG;
+ }
+
lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
plist_t dict = plist_new_dict();
plist_dict_insert_item(dict,"Request", plist_new_string("StopSession"));
- plist_dict_insert_item(dict,"SessionID", plist_new_string(session_id));
+ plist_dict_insert_item(dict,"SessionID", plist_new_string(client->session_id));
- log_dbg_msg(DBGMASK_LOCKDOWND, "%s: called\n", __func__);
+ log_dbg_msg(DBGMASK_LOCKDOWND, "%s: stopping session %s\n", __func__, client->session_id);
ret = lockdownd_send(client, dict);
@@ -148,6 +153,9 @@ lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client, const char *
plist_free(dict);
dict = NULL;
+ free(client->session_id);
+ client->session_id = NULL;
+
return ret;
}
@@ -170,7 +178,7 @@ static lockdownd_error_t lockdownd_stop_ssl_session(lockdownd_client_t client)
if (client->in_SSL) {
log_dbg_msg(DBGMASK_LOCKDOWND, "%s: stopping SSL session\n", __func__);
- ret = lockdownd_stop_session(client, client->session_id);
+ ret = lockdownd_stop_session(client);
log_dbg_msg(DBGMASK_LOCKDOWND, "%s: sending SSL close notify\n", __func__);
gnutls_bye(client->ssl_session, GNUTLS_SHUT_RDWR);
}
@@ -209,6 +217,13 @@ lockdownd_error_t lockdownd_client_free(lockdownd_client_t client)
}
}
+ if (client->session_id) {
+ free(client->session_id);
+ }
+ if (client->uuid) {
+ free(client->uuid);
+ }
+
free(client);
return ret;
}
@@ -642,31 +657,27 @@ lockdownd_error_t lockdownd_client_new(iphone_device_t device, lockdownd_client_
client_loc->ssl_session = NULL;
client_loc->ssl_certificate = NULL;
client_loc->in_SSL = 0;
+ client_loc->session_id = NULL;
+ client_loc->uuid = NULL;
if (LOCKDOWN_E_SUCCESS != lockdownd_query_type(client_loc)) {
log_debug_msg("%s: QueryType failed in the lockdownd client.\n", __func__);
ret = LOCKDOWN_E_NOT_ENOUGH_DATA;
}
- char *uuid = NULL;
- ret = iphone_device_get_uuid(device, &uuid);
+ ret = iphone_device_get_uuid(device, &client_loc->uuid);
if (LOCKDOWN_E_SUCCESS != ret) {
log_debug_msg("%s: failed to get device uuid.\n", __func__);
}
- log_debug_msg("%s: device uuid: %s\n", __func__, uuid);
+ log_debug_msg("%s: device uuid: %s\n", __func__, client_loc->uuid);
userpref_get_host_id(&host_id);
if (LOCKDOWN_E_SUCCESS == ret && !host_id) {
ret = LOCKDOWN_E_INVALID_CONF;
}
- if (LOCKDOWN_E_SUCCESS == ret && !userpref_has_device_public_key(uuid))
- ret = lockdownd_pair(client_loc, uuid, host_id);
-
- if (uuid) {
- free(uuid);
- uuid = NULL;
- }
+ if (LOCKDOWN_E_SUCCESS == ret && !userpref_has_device_public_key(client_loc->uuid))
+ ret = lockdownd_pair(client_loc, host_id);
if (LOCKDOWN_E_SUCCESS == ret) {
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_
return ret;
}
-/** Generates the appropriate keys and pairs the device. It's part of the
- * lockdownd handshake.
+/** Function used internally by lockdownd_pair() and lockdownd_validate_pair()
+ *
+ * @param client The lockdown client to pair with.
+ * @param host_id The HostID to use for pairing. If NULL is passed, then
+ * the HostID of the current machine is used. A new HostID will be
+ * generated automatically when pairing is done for the first time.
+ * @param verb This is either "Pair" or "ValidatePair".
*
* @return an error code (LOCKDOWN_E_SUCCESS on success)
*/
-lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *uuid, char *host_id)
+static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, char *host_id, const char *verb)
{
lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
plist_t dict = NULL;
@@ -703,6 +719,8 @@ lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *uuid, char *ho
gnutls_datum_t root_cert = { NULL, 0 };
gnutls_datum_t public_key = { NULL, 0 };
+ char *host_id_loc = host_id;
+
ret = lockdownd_get_device_public_key(client, &public_key);
if (ret != LOCKDOWN_E_SUCCESS) {
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
return ret;
}
+ if (!host_id) {
+ userpref_get_host_id(&host_id_loc);
+ }
+
/* Setup Pair request plist */
dict = plist_new_dict();
dict_record = plist_new_dict();
@@ -723,16 +745,20 @@ lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *uuid, char *ho
plist_dict_insert_item(dict_record, "DeviceCertificate", plist_new_data((const char*)device_cert.data, device_cert.size));
plist_dict_insert_item(dict_record, "HostCertificate", plist_new_data((const char*)host_cert.data, host_cert.size));
- plist_dict_insert_item(dict_record, "HostID", plist_new_string(host_id));
+ plist_dict_insert_item(dict_record, "HostID", plist_new_string(host_id_loc));
plist_dict_insert_item(dict_record, "RootCertificate", plist_new_data((const char*)root_cert.data, root_cert.size));
- plist_dict_insert_item(dict, "Request", plist_new_string("Pair"));
+ plist_dict_insert_item(dict, "Request", plist_new_string(verb));
/* send to iPhone */
ret = lockdownd_send(client, dict);
plist_free(dict);
dict = NULL;
+ if (!host_id) {
+ free(host_id_loc);
+ }
+
if (ret != LOCKDOWN_E_SUCCESS)
return ret;
@@ -742,24 +768,56 @@ lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *uuid, char *ho
if (ret != LOCKDOWN_E_SUCCESS)
return ret;
- if (lockdown_check_result(dict, "Pair") == RESULT_SUCCESS) {
- ret = LOCKDOWN_E_SUCCESS;
+ if (lockdown_check_result(dict, verb) != RESULT_SUCCESS) {
+ ret = LOCKDOWN_E_PAIRING_FAILED;
}
plist_free(dict);
dict = NULL;
/* store public key in config if pairing succeeded */
if (ret == LOCKDOWN_E_SUCCESS) {
- log_dbg_msg(DBGMASK_LOCKDOWND, "%s: pair success\n", __func__);
- userpref_set_device_public_key(uuid, public_key);
+ log_dbg_msg(DBGMASK_LOCKDOWND, "%s: %s success\n", __func__, verb);
+ userpref_set_device_public_key(client->uuid, public_key);
} else {
- log_dbg_msg(DBGMASK_LOCKDOWND, "%s: pair failure\n", __func__);
- ret = LOCKDOWN_E_PAIRING_FAILED;
+ log_dbg_msg(DBGMASK_LOCKDOWND, "%s: %s failure\n", __func__, verb);
}
free(public_key.data);
return ret;
}
+/**
+ * Pairs the device with the given HostID.
+ * It's part of the lockdownd handshake.
+ *
+ * @param client The lockdown client to pair with.
+ * @param host_id The HostID to use for pairing. If NULL is passed, then
+ * the HostID of the current machine is used. A new HostID will be
+ * generated automatically when pairing is done for the first time.
+ *
+ * @return an error code (LOCKDOWN_E_SUCCESS on success)
+ */
+lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *host_id)
+{
+ return lockdownd_do_pair(client, host_id, "Pair");
+}
+
+/**
+ * Pairs the device with the given HostID. The difference to lockdownd_pair()
+ * is that the specified host will become trusted host of the device.
+ * It's part of the lockdownd handshake.
+ *
+ * @param client The lockdown client to pair with.
+ * @param host_id The HostID to use for pairing. If NULL is passed, then
+ * the HostID of the current machine is used. A new HostID will be
+ * generated automatically when pairing is done for the first time.
+ *
+ * @return an error code (LOCKDOWN_E_SUCCESS on success)
+ */
+lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, char *host_id)
+{
+ return lockdownd_do_pair(client, host_id, "ValidatePair");
+}
+
/**
* Tells the device to immediately enter recovery mode.
*
@@ -985,7 +1043,10 @@ lockdownd_error_t lockdownd_start_ssl_session(lockdownd_client_t client, const c
uint32_t return_me = 0;
lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR;
- client->session_id[0] = '\0';
+ if (client->session_id) {
+ free(client->session_id);
+ client->session_id = NULL;
+ }
/* Setup DevicePublicKey request plist */
dict = plist_new_dict();
@@ -1012,26 +1073,22 @@ lockdownd_error_t lockdownd_start_ssl_session(lockdownd_client_t client, const c
if (!strcmp(error, "InvalidHostID")) {
/* hostid is unknown. Pair and try again */
- char *uuid = NULL;
char *host_id = NULL;
userpref_get_host_id(&host_id);
- if (LOCKDOWN_E_SUCCESS == lockdownd_get_device_uuid(client, &uuid) ) {
- if (LOCKDOWN_E_SUCCESS == lockdownd_pair(client, uuid, host_id) ) {
- /* start session again */
- plist_free(dict);
- dict = plist_new_dict();
- plist_dict_insert_item(dict,"HostID", plist_new_string(HostID));
- plist_dict_insert_item(dict,"Request", plist_new_string("StartSession"));
+ if (LOCKDOWN_E_SUCCESS == lockdownd_pair(client, host_id) ) {
+ /* start session again */
+ plist_free(dict);
+ dict = plist_new_dict();
+ plist_dict_insert_item(dict,"HostID", plist_new_string(HostID));
+ plist_dict_insert_item(dict,"Request", plist_new_string("StartSession"));
- ret = lockdownd_send(client, dict);
- plist_free(dict);
- dict = NULL;
+ ret = lockdownd_send(client, dict);
+ plist_free(dict);
+ dict = NULL;
- ret = lockdownd_recv(client, &dict);
- }
+ ret = lockdownd_recv(client, &dict);
}
- free(uuid);
free(host_id);
}
free(error);
@@ -1100,27 +1157,16 @@ lockdownd_error_t lockdownd_start_ssl_session(lockdownd_client_t client, const c
ret = LOCKDOWN_E_SUCCESS;
}
}
- /* store session id */
+ /* store session id, we need it for StopSession */
plist_t session_node = plist_dict_get_item(dict, "SessionID");
- if (session_node) {
-
- plist_type session_node_type = plist_get_node_type(session_node);
-
- if (session_node_type == PLIST_STRING) {
-
- char *session_id = NULL;
- plist_get_string_val(session_node, &session_id);
-
- if (session_node_type == PLIST_STRING && session_id) {
- /* we need to store the session ID for StopSession */
- strcpy(client->session_id, session_id);
- log_dbg_msg(DBGMASK_LOCKDOWND, "%s: SessionID: %s\n", __func__, client->session_id);
- }
- if (session_id)
- free(session_id);
- }
- } else
+ if (session_node && (plist_get_node_type(session_node) == PLIST_STRING)) {
+ plist_get_string_val(session_node, &client->session_id);
+ }
+ if (client->session_id) {
+ log_dbg_msg(DBGMASK_LOCKDOWND, "%s: SessionID: %s\n", __func__, client->session_id);
+ } else {
log_dbg_msg(DBGMASK_LOCKDOWND, "%s: Failed to get SessionID!\n", __func__);
+ }
plist_free(dict);
dict = NULL;