From 219a8db037ec1cc163d2ad4902e6e4578040a2de Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Tue, 12 Jan 2010 17:17:48 +0100 Subject: Refactor lockdown session handling and expose it in public API This splits out SSL code and allows implementations to manually handle session start and stop if needed. Also brings the API closer to the lockdown request protocol. --- include/libiphone/lockdown.h | 13 +- src/lockdown.c | 434 ++++++++++++++++++++++--------------------- src/lockdown.h | 6 - 3 files changed, 227 insertions(+), 226 deletions(-) diff --git a/include/libiphone/lockdown.h b/include/libiphone/lockdown.h index e134f5f..f4b3f6a 100644 --- a/include/libiphone/lockdown.h +++ b/include/libiphone/lockdown.h @@ -47,6 +47,7 @@ extern "C" { #define LOCKDOWN_E_ACTIVATION_FAILED -13 #define LOCKDOWN_E_PASSWORD_PROTECTED -14 #define LOCKDOWN_E_NO_RUNNING_SESSION -15 +#define LOCKDOWN_E_INVALID_HOST_ID -16 #define LOCKDOWN_E_UNKNOWN_ERROR -256 @@ -59,13 +60,14 @@ typedef struct lockdownd_client_int *lockdownd_client_t; lockdownd_error_t lockdownd_client_new(iphone_device_t device, lockdownd_client_t *client, const char *label); lockdownd_error_t lockdownd_client_new_with_handshake(iphone_device_t device, lockdownd_client_t *client, const char *label); lockdownd_error_t lockdownd_client_free(lockdownd_client_t client); -void lockdownd_client_set_label(lockdownd_client_t client, const char *label); + lockdownd_error_t lockdownd_query_type(lockdownd_client_t client, char **type); lockdownd_error_t lockdownd_get_value(lockdownd_client_t client, const char *domain, const char *key, plist_t *value); lockdownd_error_t lockdownd_set_value(lockdownd_client_t client, const char *domain, const char *key, plist_t value); lockdownd_error_t lockdownd_remove_value(lockdownd_client_t client, const char *domain, const char *key); lockdownd_error_t lockdownd_start_service(lockdownd_client_t client, const char *service, int *port); -lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client); +lockdownd_error_t lockdownd_start_session(lockdownd_client_t client, const char *host_id, char **session_id, int *ssl_enabled); +lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client, const char *session_id); lockdownd_error_t lockdownd_send(lockdownd_client_t client, plist_t plist); lockdownd_error_t lockdownd_recv(lockdownd_client_t client, plist_t *plist); lockdownd_error_t lockdownd_pair(lockdownd_client_t client, char *host_id); @@ -73,11 +75,14 @@ lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, char *host_ lockdownd_error_t lockdownd_unpair(lockdownd_client_t client, char *host_id); lockdownd_error_t lockdownd_activate(lockdownd_client_t client, plist_t activation_record); lockdownd_error_t lockdownd_deactivate(lockdownd_client_t client); -lockdownd_error_t lockdownd_get_device_uuid(lockdownd_client_t control, char **uuid); -lockdownd_error_t lockdownd_get_device_name(lockdownd_client_t client, char **device_name); lockdownd_error_t lockdownd_enter_recovery(lockdownd_client_t client); lockdownd_error_t lockdownd_goodbye(lockdownd_client_t client); +/* Helper */ +void lockdownd_client_set_label(lockdownd_client_t client, const char *label); +lockdownd_error_t lockdownd_get_device_uuid(lockdownd_client_t control, char **uuid); +lockdownd_error_t lockdownd_get_device_name(lockdownd_client_t client, char **device_name); + #ifdef __cplusplus } #endif diff --git a/src/lockdown.c b/src/lockdown.c index 11b4fe6..f78fbb4 100644 --- a/src/lockdown.c +++ b/src/lockdown.c @@ -123,69 +123,145 @@ static void plist_dict_add_label(plist_t plist, const char *label) } } -/** - * Closes the lockdownd communication session, by sending - * the StopSession Request to the device. +/** gnutls callback for writing data to the device. * - * @param control The lockdown client + * @param transport It's really the lockdownd client, but the method signature has to match + * @param buffer The data to send + * @param length The length of data to send in bytes * - * @return an error code (LOCKDOWN_E_SUCCESS on success) + * @return The number of bytes sent */ -lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client) +static ssize_t lockdownd_ssl_write(gnutls_transport_ptr_t transport, char *buffer, size_t length) { - if (!client) - return LOCKDOWN_E_INVALID_ARG; + uint32_t bytes = 0; + lockdownd_client_t client; + client = (lockdownd_client_t) transport; + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: pre-send length = %zi\n", __func__, length); + iphone_device_send(property_list_service_get_connection(client->parent), buffer, length, &bytes); + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: post-send sent %i bytes\n", __func__, bytes); + return bytes; +} - if (!client->session_id) { - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: no session_id given, cannot stop session\n", __func__); - return LOCKDOWN_E_INVALID_ARG; - } +/** gnutls callback for reading data from the device. + * + * @param transport It's really the lockdownd client, but the method signature has to match + * @param buffer The buffer to store data in + * @param length The length of data to read in bytes + * + * @return The number of bytes read + */ +static ssize_t lockdownd_ssl_read(gnutls_transport_ptr_t transport, char *buffer, size_t length) +{ + int bytes = 0, pos_start_fill = 0; + size_t tbytes = 0; + int this_len = length; + iphone_error_t res; + lockdownd_client_t client; + client = (lockdownd_client_t) transport; + char *recv_buffer; - lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; + log_debug_msg("%s: pre-read client wants %zi bytes\n", __func__, length); - plist_t dict = plist_new_dict(); - plist_dict_add_label(dict, client->label); - plist_dict_insert_item(dict,"Request", plist_new_string("StopSession")); - plist_dict_insert_item(dict,"SessionID", plist_new_string(client->session_id)); + recv_buffer = (char *) malloc(sizeof(char) * this_len); - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: stopping session %s\n", __func__, client->session_id); + /* repeat until we have the full data or an error occurs */ + do { + if ((res = iphone_device_recv(property_list_service_get_connection(client->parent), recv_buffer, this_len, (uint32_t*)&bytes)) != LOCKDOWN_E_SUCCESS) { + log_debug_msg("%s: ERROR: iphone_device_recv returned %d\n", __func__, res); + return res; + } + log_debug_msg("%s: post-read we got %i bytes\n", __func__, bytes); - ret = lockdownd_send(client, dict); + // increase read count + tbytes += bytes; - plist_free(dict); - dict = NULL; + // fill the buffer with what we got right now + memcpy(buffer + pos_start_fill, recv_buffer, bytes); + pos_start_fill += bytes; - ret = lockdownd_recv(client, &dict); + if (tbytes >= length) { + break; + } - if (!dict) { - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: LOCKDOWN_E_PLIST_ERROR\n", __func__); - return LOCKDOWN_E_PLIST_ERROR; + this_len = length - tbytes; + log_debug_msg("%s: re-read trying to read missing %i bytes\n", __func__, this_len); + } while (tbytes < length); + + if (recv_buffer) { + free(recv_buffer); } - ret = LOCKDOWN_E_UNKNOWN_ERROR; - if (lockdown_check_result(dict, "StopSession") == RESULT_SUCCESS) { - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: success\n", __func__); + return tbytes; +} + +/** Starts communication with lockdownd after the iPhone has been paired, + * and if the device requires it, switches to SSL mode. + * + * @param client The lockdownd client + * + * @return an error code (LOCKDOWN_E_SUCCESS on success) + */ +static lockdownd_error_t lockdownd_ssl_start_session(lockdownd_client_t client) +{ + lockdownd_error_t ret = LOCKDOWN_E_SSL_ERROR; + uint32_t return_me = 0; + + // Set up GnuTLS... + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: enabling SSL mode\n", __func__); + errno = 0; + gnutls_global_init(); + gnutls_certificate_allocate_credentials(&client->ssl_certificate); + gnutls_certificate_set_x509_trust_file(client->ssl_certificate, "hostcert.pem", GNUTLS_X509_FMT_PEM); + gnutls_init(&client->ssl_session, GNUTLS_CLIENT); + { + int protocol_priority[16] = { GNUTLS_SSL3, 0 }; + int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 }; + int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 }; + int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 }; + int comp_priority[16] = { GNUTLS_COMP_NULL, 0 }; + + gnutls_cipher_set_priority(client->ssl_session, cipher_priority); + gnutls_compression_set_priority(client->ssl_session, comp_priority); + gnutls_kx_set_priority(client->ssl_session, kx_priority); + gnutls_protocol_set_priority(client->ssl_session, protocol_priority); + gnutls_mac_set_priority(client->ssl_session, mac_priority); + } + gnutls_credentials_set(client->ssl_session, GNUTLS_CRD_CERTIFICATE, client->ssl_certificate); // this part is killing me. + + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: GnuTLS step 1...\n", __func__); + gnutls_transport_set_ptr(client->ssl_session, (gnutls_transport_ptr_t) client); + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: GnuTLS step 2...\n", __func__); + gnutls_transport_set_push_function(client->ssl_session, (gnutls_push_func) & lockdownd_ssl_write); + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: GnuTLS step 3...\n", __func__); + gnutls_transport_set_pull_function(client->ssl_session, (gnutls_pull_func) & lockdownd_ssl_read); + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: GnuTLS step 4 -- now handshaking...\n", __func__); + if (errno) + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: WARN: errno says %s before handshake!\n", __func__, strerror(errno)); + return_me = gnutls_handshake(client->ssl_session); + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: GnuTLS handshake done...\n", __func__); + + if (return_me != GNUTLS_E_SUCCESS) { + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: GnuTLS reported something wrong.\n", __func__); + gnutls_perror(return_me); + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: oh.. errno says %s\n", __func__, strerror(errno)); + } else { + client->ssl_enabled = 1; ret = LOCKDOWN_E_SUCCESS; + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: SSL mode enabled\n", __func__); } - plist_free(dict); - dict = NULL; - - free(client->session_id); - client->session_id = NULL; return ret; } /** - * Shuts down the SSL session by first calling iphone_lckd_stop_session - * to cleanly close the lockdownd communication session, and then - * performing a close notify, which is done by "gnutls_bye". + * Shuts down the SSL session by performing a close notify, which is done + * by "gnutls_bye". * * @param client The lockdown client * * @return an error code (LOCKDOWN_E_SUCCESS on success) */ -static lockdownd_error_t lockdownd_stop_ssl_session(lockdownd_client_t client) +static lockdownd_error_t lockdownd_ssl_stop_session(lockdownd_client_t client) { if (!client) { log_dbg_msg(DBGMASK_LOCKDOWND, "%s: invalid argument!\n", __func__); @@ -194,19 +270,79 @@ static lockdownd_error_t lockdownd_stop_ssl_session(lockdownd_client_t client) lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; if (client->ssl_enabled) { - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: stopping SSL session\n", __func__); - 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); } if (client->ssl_session) { gnutls_deinit(client->ssl_session); - } - if (client->ssl_certificate) { + } + if (client->ssl_certificate) { gnutls_certificate_free_credentials(client->ssl_certificate); - } + } client->ssl_enabled = 0; + if (client->session_id) + free(client->session_id); + client->session_id = NULL; + + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: SSL mode disabled\n", __func__); + + return ret; +} + +/** + * Closes the lockdownd communication session, by sending the StopSession + * Request to the device. + * + * @see lockdownd_start_session + * + * @param control The lockdown client + * @param session_id The id of a running session + * + * @return an error code (LOCKDOWN_E_SUCCESS on success) + */ +lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client, const char *session_id) +{ + if (!client) + return LOCKDOWN_E_INVALID_ARG; + + if (!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_add_label(dict, client->label); + plist_dict_insert_item(dict,"Request", plist_new_string("StopSession")); + plist_dict_insert_item(dict,"SessionID", plist_new_string(session_id)); + + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: stopping session %s\n", __func__, session_id); + + ret = lockdownd_send(client, dict); + + plist_free(dict); + dict = NULL; + + ret = lockdownd_recv(client, &dict); + + if (!dict) { + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: LOCKDOWN_E_PLIST_ERROR\n", __func__); + return LOCKDOWN_E_PLIST_ERROR; + } + + ret = LOCKDOWN_E_UNKNOWN_ERROR; + if (lockdown_check_result(dict, "StopSession") == RESULT_SUCCESS) { + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: success\n", __func__); + ret = LOCKDOWN_E_SUCCESS; + } + plist_free(dict); + dict = NULL; + + /* stop ssl session */ + lockdownd_ssl_stop_session(client); + return ret; } @@ -222,7 +358,8 @@ lockdownd_error_t lockdownd_client_free(lockdownd_client_t client) return LOCKDOWN_E_INVALID_ARG; lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; - lockdownd_stop_ssl_session(client); + if (client->session_id) + lockdownd_stop_session(client, client->session_id); if (client->parent) { lockdownd_goodbye(client); @@ -232,9 +369,6 @@ lockdownd_error_t lockdownd_client_free(lockdownd_client_t client) } } - if (client->session_id) { - free(client->session_id); - } if (client->uuid) { free(client->uuid); } @@ -712,7 +846,7 @@ lockdownd_error_t lockdownd_client_new_with_handshake(iphone_device_t device, lo ret = lockdownd_validate_pair(client_loc, host_id); if (LOCKDOWN_E_SUCCESS == ret) { - ret = lockdownd_start_ssl_session(client_loc, host_id); + ret = lockdownd_start_session(client_loc, host_id, NULL, NULL); if (LOCKDOWN_E_SUCCESS != ret) { ret = LOCKDOWN_E_SSL_ERROR; log_debug_msg("%s: SSL Session opening failed.\n", __func__); @@ -1012,7 +1146,7 @@ lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datu asn1_delete_structure(&pkcs1); } - /* now generate certifcates */ + /* now generate certificates */ if (LOCKDOWN_E_SUCCESS == ret && 0 != modulus.size && 0 != exponent.size) { gnutls_global_init(); @@ -1106,22 +1240,26 @@ lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datu * and if the device requires it, switches to SSL mode. * * @param client The lockdownd client - * @param HostID The HostID used with this phone + * @param host_id The HostID of the computer + * @param session_id The session_id of the created session + * @param ssl_enabled Whether SSL communication is used in the session * * @return an error code (LOCKDOWN_E_SUCCESS on success) */ -lockdownd_error_t lockdownd_start_ssl_session(lockdownd_client_t client, const char *host_id) +lockdownd_error_t lockdownd_start_session(lockdownd_client_t client, const char *host_id, char **session_id, int *ssl_enabled) { + lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; plist_t dict = NULL; - uint32_t return_me = 0; - lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; + if (!client || !host_id) + ret = LOCKDOWN_E_INVALID_ARG; + + /* if we have a running session, stop current one first */ if (client->session_id) { - free(client->session_id); - client->session_id = NULL; + lockdownd_stop_session(client, client->session_id); } - /* Setup DevicePublicKey request plist */ + /* setup request plist */ dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_insert_item(dict,"HostID", plist_new_string(host_id)); @@ -1144,184 +1282,48 @@ lockdownd_error_t lockdownd_start_ssl_session(lockdownd_client_t client, const c if (error_node && PLIST_STRING == plist_get_node_type(error_node)) { char *error = NULL; plist_get_string_val(error_node, &error); - if (!strcmp(error, "InvalidHostID")) { - /* hostid is unknown. Pair and try again */ - char *host_id_new = NULL; - userpref_get_host_id(&host_id_new); - - if (LOCKDOWN_E_SUCCESS == lockdownd_pair(client, host_id_new) ) { - /* start session again */ - plist_free(dict); - dict = plist_new_dict(); - plist_dict_add_label(dict, client->label); - plist_dict_insert_item(dict,"HostID", plist_new_string(host_id_new)); - plist_dict_insert_item(dict,"Request", plist_new_string("StartSession")); - - ret = lockdownd_send(client, dict); - plist_free(dict); - dict = NULL; - - ret = lockdownd_recv(client, &dict); - } - free(host_id_new); + ret = LOCKDOWN_E_INVALID_HOST_ID; } free(error); } - } - - ret = LOCKDOWN_E_SSL_ERROR; - - int session_ok = 0; - uint8_t UseSSL = 0; + } else { + uint8_t use_ssl = 0; - if (lockdown_check_result(dict, "StartSession") == RESULT_SUCCESS) { plist_t enable_ssl = plist_dict_get_item(dict, "EnableSessionSSL"); if (enable_ssl && (plist_get_node_type(enable_ssl) == PLIST_BOOLEAN)) { - plist_get_bool_val(enable_ssl, &UseSSL); + plist_get_bool_val(enable_ssl, &use_ssl); } log_dbg_msg(DBGMASK_LOCKDOWND, "%s: Session startup OK\n", __func__); - session_ok = 1; - } - if (session_ok && !UseSSL) { - client->ssl_enabled = 0; - ret = LOCKDOWN_E_SUCCESS; - } else if (session_ok) { - // Set up GnuTLS... - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: Switching to SSL mode\n", __func__); - errno = 0; - gnutls_global_init(); - //gnutls_anon_allocate_client_credentials(&anoncred); - gnutls_certificate_allocate_credentials(&client->ssl_certificate); - gnutls_certificate_set_x509_trust_file(client->ssl_certificate, "hostcert.pem", GNUTLS_X509_FMT_PEM); - gnutls_init(&client->ssl_session, GNUTLS_CLIENT); - { - int protocol_priority[16] = { GNUTLS_SSL3, 0 }; - int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 }; - int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 }; - int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 }; - int comp_priority[16] = { GNUTLS_COMP_NULL, 0 }; - - gnutls_cipher_set_priority(client->ssl_session, cipher_priority); - gnutls_compression_set_priority(client->ssl_session, comp_priority); - gnutls_kx_set_priority(client->ssl_session, kx_priority); - gnutls_protocol_set_priority(client->ssl_session, protocol_priority); - gnutls_mac_set_priority(client->ssl_session, mac_priority); + + if (ssl_enabled != NULL) + *ssl_enabled = use_ssl; + + /* store session id, we need it for StopSession */ + plist_t session_node = plist_dict_get_item(dict, "SessionID"); + if (session_node && (plist_get_node_type(session_node) == PLIST_STRING)) { + plist_get_string_val(session_node, &client->session_id); } - gnutls_credentials_set(client->ssl_session, GNUTLS_CRD_CERTIFICATE, client->ssl_certificate); // this part is killing me. - - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: GnuTLS step 1...\n", __func__); - gnutls_transport_set_ptr(client->ssl_session, (gnutls_transport_ptr_t) client); - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: GnuTLS step 2...\n", __func__); - gnutls_transport_set_push_function(client->ssl_session, (gnutls_push_func) & lockdownd_secuwrite); - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: GnuTLS step 3...\n", __func__); - gnutls_transport_set_pull_function(client->ssl_session, (gnutls_pull_func) & lockdownd_securead); - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: GnuTLS step 4 -- now handshaking...\n", __func__); - if (errno) - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: WARN: errno says %s before handshake!\n", __func__, strerror(errno)); - return_me = gnutls_handshake(client->ssl_session); - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: GnuTLS handshake done...\n", __func__); - - if (return_me != GNUTLS_E_SUCCESS) { - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: GnuTLS reported something wrong.\n", __func__); - gnutls_perror(return_me); - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: oh.. errno says %s\n", __func__, strerror(errno)); - return LOCKDOWN_E_SSL_ERROR; + if (client->session_id) { + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: SessionID: %s\n", __func__, client->session_id); + if (session_id != NULL) + *session_id = strdup(client->session_id); } else { - client->ssl_enabled = 1; + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: Failed to get SessionID!\n", __func__); + } + log_dbg_msg(DBGMASK_LOCKDOWND, "%s: Enable SSL Session: %s\n", __func__, (use_ssl?"true":"false")); + if (use_ssl) { + ret = lockdownd_ssl_start_session(client); + } else { + client->ssl_enabled = 0; ret = LOCKDOWN_E_SUCCESS; } } - /* store session id, we need it for StopSession */ - plist_t session_node = plist_dict_get_item(dict, "SessionID"); - 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; - if (ret == LOCKDOWN_E_SUCCESS) - return ret; - - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: Apparently failed negotiating with lockdownd.\n", __func__); - return LOCKDOWN_E_SSL_ERROR; -} - -/** gnutls callback for writing data to the iPhone. - * - * @param transport It's really the lockdownd client, but the method signature has to match - * @param buffer The data to send - * @param length The length of data to send in bytes - * - * @return The number of bytes sent - */ -ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size_t length) -{ - uint32_t bytes = 0; - lockdownd_client_t client; - client = (lockdownd_client_t) transport; - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: called\n", __func__); - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: pre-send length = %zi\n", __func__, length); - iphone_device_send(property_list_service_get_connection(client->parent), buffer, length, &bytes); - log_dbg_msg(DBGMASK_LOCKDOWND, "%s: post-send sent %i bytes\n", __func__, bytes); - return bytes; -} - -/** gnutls callback for reading data from the iPhone - * - * @param transport It's really the lockdownd client, but the method signature has to match - * @param buffer The buffer to store data in - * @param length The length of data to read in bytes - * - * @return The number of bytes read - */ -ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_t length) -{ - int bytes = 0, pos_start_fill = 0; - size_t tbytes = 0; - int this_len = length; - iphone_error_t res; - lockdownd_client_t client; - client = (lockdownd_client_t) transport; - char *recv_buffer; - - log_debug_msg("%s: pre-read client wants %zi bytes\n", __func__, length); - - recv_buffer = (char *) malloc(sizeof(char) * this_len); - - // repeat until we have the full data or an error occurs. - do { - if ((res = iphone_device_recv(property_list_service_get_connection(client->parent), recv_buffer, this_len, (uint32_t*)&bytes)) != LOCKDOWN_E_SUCCESS) { - log_debug_msg("%s: ERROR: usbmux_recv returned %d\n", __func__, res); - return res; - } - log_debug_msg("%s: post-read we got %i bytes\n", __func__, bytes); - - // increase read count - tbytes += bytes; - - // fill the buffer with what we got right now - memcpy(buffer + pos_start_fill, recv_buffer, bytes); - pos_start_fill += bytes; - - if (tbytes >= length) { - break; - } - - this_len = length - tbytes; - log_debug_msg("%s: re-read trying to read missing %i bytes\n", __func__, this_len); - } while (tbytes < length); - - if (recv_buffer) { - free(recv_buffer); - } - - return tbytes; + return ret; } /** Command to start the desired service diff --git a/src/lockdown.h b/src/lockdown.h index d7a18b5..9da3872 100644 --- a/src/lockdown.h +++ b/src/lockdown.h @@ -42,10 +42,4 @@ lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, gnu lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t * device_cert, gnutls_datum_t * host_cert, gnutls_datum_t * root_cert); -/* SSL functions */ -lockdownd_error_t lockdownd_start_ssl_session(lockdownd_client_t client, const char *host_id); -ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_t length); -ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size_t length); - - #endif -- cgit v1.1-32-gdbae