summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/idevice.c106
-rw-r--r--src/idevice.h2
2 files changed, 66 insertions, 42 deletions
diff --git a/src/idevice.c b/src/idevice.c
index ecc0418..a2a4d0b 100644
--- a/src/idevice.c
+++ b/src/idevice.c
@@ -432,6 +432,8 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connect(idevice_t device, uint16_t
432 new_connection->data = (void*)(long)sfd; 432 new_connection->data = (void*)(long)sfd;
433 new_connection->ssl_data = NULL; 433 new_connection->ssl_data = NULL;
434 new_connection->device = device; 434 new_connection->device = device;
435 new_connection->ssl_recv_timeout = (unsigned int)-1;
436 new_connection->status = IDEVICE_E_SUCCESS;
435 *connection = new_connection; 437 *connection = new_connection;
436 return IDEVICE_E_SUCCESS; 438 return IDEVICE_E_SUCCESS;
437 } else if (device->conn_type == CONNECTION_NETWORK) { 439 } else if (device->conn_type == CONNECTION_NETWORK) {
@@ -478,6 +480,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connect(idevice_t device, uint16_t
478 new_connection->data = (void*)(long)sfd; 480 new_connection->data = (void*)(long)sfd;
479 new_connection->ssl_data = NULL; 481 new_connection->ssl_data = NULL;
480 new_connection->device = device; 482 new_connection->device = device;
483 new_connection->ssl_recv_timeout = (unsigned int)-1;
481 484
482 *connection = new_connection; 485 *connection = new_connection;
483 486
@@ -558,15 +561,10 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_send(idevice_connection_
558 } 561 }
559 562
560 if (connection->ssl_data) { 563 if (connection->ssl_data) {
564 connection->status = IDEVICE_E_SUCCESS;
561 uint32_t sent = 0; 565 uint32_t sent = 0;
562 while (sent < len) { 566 while (sent < len) {
563#ifdef HAVE_OPENSSL 567#ifdef HAVE_OPENSSL
564 int c = socket_check_fd((int)(long)connection->data, FDM_WRITE, 100);
565 if (c == 0 || c == -ETIMEDOUT || c == -EAGAIN) {
566 continue;
567 } else if (c < 0) {
568 break;
569 }
570 int s = SSL_write(connection->ssl_data->session, (const void*)(data+sent), (int)(len-sent)); 568 int s = SSL_write(connection->ssl_data->session, (const void*)(data+sent), (int)(len-sent));
571 if (s <= 0) { 569 if (s <= 0) {
572 int sslerr = SSL_get_error(connection->ssl_data->session, s); 570 int sslerr = SSL_get_error(connection->ssl_data->session, s);
@@ -586,7 +584,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_send(idevice_connection_
586 debug_info("SSL_write %d, sent %d", len, sent); 584 debug_info("SSL_write %d, sent %d", len, sent);
587 if (sent < len) { 585 if (sent < len) {
588 *sent_bytes = 0; 586 *sent_bytes = 0;
589 return IDEVICE_E_SSL_ERROR; 587 return connection->status == IDEVICE_E_SUCCESS ? IDEVICE_E_SSL_ERROR : connection->status;
590 } 588 }
591 *sent_bytes = sent; 589 *sent_bytes = sent;
592 return IDEVICE_E_SUCCESS; 590 return IDEVICE_E_SUCCESS;
@@ -670,30 +668,17 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_
670 668
671 if (connection->ssl_data) { 669 if (connection->ssl_data) {
672 uint32_t received = 0; 670 uint32_t received = 0;
673 int do_select = 1;
674 idevice_error_t error = IDEVICE_E_SSL_ERROR;
675 671
672 if (connection->ssl_recv_timeout != (unsigned int)-1) {
673 debug_info("WARNING: ssl_recv_timeout was not properly reset in idevice_connection_receive_timeout");
674 }
675
676 // this should be reset after the SSL_read call on all codepaths, as
677 // the supplied timeout should only apply to the current read.
678 connection->ssl_recv_timeout = timeout;
679 connection->status = IDEVICE_E_SUCCESS;
676 while (received < len) { 680 while (received < len) {
677#ifdef HAVE_OPENSSL 681#ifdef HAVE_OPENSSL
678 do_select = (SSL_pending(connection->ssl_data->session) == 0);
679#endif
680 if (do_select) {
681 int conn_error = socket_check_fd((int)(long)connection->data, FDM_READ, timeout);
682 error = socket_recv_to_idevice_error(conn_error, len, received);
683 switch (error) {
684 case IDEVICE_E_SUCCESS:
685 case IDEVICE_E_TIMEOUT:
686 break;
687 case IDEVICE_E_UNKNOWN_ERROR:
688 default:
689 debug_info("ERROR: socket_check_fd returned %d (%s)", conn_error, strerror(-conn_error));
690 return error;
691 }
692 }
693 if (error == IDEVICE_E_TIMEOUT) {
694 break;
695 }
696#ifdef HAVE_OPENSSL
697 int r = SSL_read(connection->ssl_data->session, (void*)((char*)(data+received)), (int)len-received); 682 int r = SSL_read(connection->ssl_data->session, (void*)((char*)(data+received)), (int)len-received);
698 if (r > 0) { 683 if (r > 0) {
699 received += r; 684 received += r;
@@ -713,11 +698,12 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_
713 } 698 }
714#endif 699#endif
715 } 700 }
701 connection->ssl_recv_timeout = (unsigned int)-1;
716 702
717 debug_info("SSL_read %d, received %d", len, received); 703 debug_info("SSL_read %d, received %d", len, received);
718 if (received < len) { 704 if (received < len) {
719 *recv_bytes = received; 705 *recv_bytes = received;
720 return error; 706 return connection->status == IDEVICE_E_SUCCESS ? IDEVICE_E_SSL_ERROR : connection->status;
721 } 707 }
722 708
723 *recv_bytes = received; 709 *recv_bytes = received;
@@ -763,6 +749,10 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive(idevice_connecti
763 } 749 }
764 750
765 if (connection->ssl_data) { 751 if (connection->ssl_data) {
752 if (connection->ssl_recv_timeout != (unsigned int)-1) {
753 debug_info("WARNING: ssl_recv_timeout was not properly reset in idevice_connection_receive_timeout");
754 connection->ssl_recv_timeout = (unsigned int)-1;
755 }
766#ifdef HAVE_OPENSSL 756#ifdef HAVE_OPENSSL
767 int received = SSL_read(connection->ssl_data->session, (void*)data, (int)len); 757 int received = SSL_read(connection->ssl_data->session, (void*)data, (int)len);
768 debug_info("SSL_read %d, received %d", len, received); 758 debug_info("SSL_read %d, received %d", len, received);
@@ -816,28 +806,36 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_get_udid(idevice_t device, char **u
816 return IDEVICE_E_SUCCESS; 806 return IDEVICE_E_SUCCESS;
817} 807}
818 808
819#ifndef HAVE_OPENSSL
820/** 809/**
821 * Internally used gnutls callback function for receiving encrypted data. 810 * Internally used SSL callback function for receiving encrypted data.
822 */ 811 */
823static ssize_t internal_ssl_read(gnutls_transport_ptr_t transport, char *buffer, size_t length) 812static ssize_t internal_ssl_read(idevice_connection_t connection, char *buffer, size_t length)
824{ 813{
825 int bytes = 0, pos_start_fill = 0; 814 int bytes = 0, pos_start_fill = 0;
826 size_t tbytes = 0; 815 size_t tbytes = 0;
827 int this_len = length; 816 int this_len = length;
828 idevice_error_t res; 817 idevice_error_t res;
829 idevice_connection_t connection = (idevice_connection_t)transport;
830 char *recv_buffer; 818 char *recv_buffer;
831 819
832 debug_info("pre-read client wants %zi bytes", length); 820 debug_info("pre-read client wants %zi bytes", length);
833 821
834 recv_buffer = (char *)malloc(sizeof(char) * this_len); 822 recv_buffer = (char *)malloc(sizeof(char) * this_len);
835 823
824 unsigned int timeout = connection->ssl_recv_timeout;
825
836 /* repeat until we have the full data or an error occurs */ 826 /* repeat until we have the full data or an error occurs */
837 do { 827 do {
838 if ((res = internal_connection_receive(connection, recv_buffer, this_len, (uint32_t*)&bytes)) != IDEVICE_E_SUCCESS) { 828 if (timeout == (unsigned int)-1) {
839 debug_info("ERROR: idevice_connection_receive returned %d", res); 829 res = internal_connection_receive(connection, recv_buffer, this_len, (uint32_t*)&bytes);
840 return res; 830 } else {
831 res = internal_connection_receive_timeout(connection, recv_buffer, this_len, (uint32_t*)&bytes, (unsigned int)timeout);
832 }
833 if (res != IDEVICE_E_SUCCESS) {
834 if (res != IDEVICE_E_TIMEOUT) {
835 debug_info("ERROR: %s returned %d", (timeout == (unsigned int)-1) ? "internal_connection_receive" : "internal_connection_receive_timeout", res);
836 }
837 connection->status = res;
838 return -1;
841 } 839 }
842 debug_info("post-read we got %i bytes", bytes); 840 debug_info("post-read we got %i bytes", bytes);
843 841
@@ -863,22 +861,21 @@ static ssize_t internal_ssl_read(gnutls_transport_ptr_t transport, char *buffer,
863} 861}
864 862
865/** 863/**
866 * Internally used gnutls callback function for sending encrypted data. 864 * Internally used SSL callback function for sending encrypted data.
867 */ 865 */
868static ssize_t internal_ssl_write(gnutls_transport_ptr_t transport, char *buffer, size_t length) 866static ssize_t internal_ssl_write(idevice_connection_t connection, const char *buffer, size_t length)
869{ 867{
870 uint32_t bytes = 0; 868 uint32_t bytes = 0;
871 idevice_error_t res; 869 idevice_error_t res;
872 idevice_connection_t connection = (idevice_connection_t)transport;
873 debug_info("pre-send length = %zi", length); 870 debug_info("pre-send length = %zi", length);
874 if ((res = internal_connection_send(connection, buffer, length, &bytes)) != IDEVICE_E_SUCCESS) { 871 if ((res = internal_connection_send(connection, buffer, length, &bytes)) != IDEVICE_E_SUCCESS) {
875 debug_info("ERROR: internal_connection_send returned %d", res); 872 debug_info("ERROR: internal_connection_send returned %d", res);
873 connection->status = res;
876 return -1; 874 return -1;
877 } 875 }
878 debug_info("post-send sent %i bytes", bytes); 876 debug_info("post-send sent %i bytes", bytes);
879 return bytes; 877 return bytes;
880} 878}
881#endif
882 879
883/** 880/**
884 * Internally used function for cleaning up SSL stuff. 881 * Internally used function for cleaning up SSL stuff.
@@ -918,6 +915,32 @@ static void internal_ssl_cleanup(ssl_data_t ssl_data)
918} 915}
919 916
920#ifdef HAVE_OPENSSL 917#ifdef HAVE_OPENSSL
918static long ssl_idevice_bio_callback(BIO *b, int oper, const char *argp, int argi, long argl, long retvalue)
919{
920 idevice_connection_t conn = (idevice_connection_t)BIO_get_callback_arg(b);
921 size_t len = (size_t)argi;
922 switch (oper) {
923 case (BIO_CB_READ|BIO_CB_RETURN):
924 return argp ? (long)internal_ssl_read(conn, (char *)argp, len) : 0;
925 case (BIO_CB_PUTS|BIO_CB_RETURN):
926 len = strlen(argp);
927 // fallthrough
928 case (BIO_CB_WRITE|BIO_CB_RETURN):
929 return (long)internal_ssl_write(conn, argp, len);
930 default:
931 return retvalue;
932 }
933}
934
935static BIO *ssl_idevice_bio_new(idevice_connection_t conn)
936{
937 BIO *b = BIO_new(BIO_s_null());
938 if (!b) return NULL;
939 BIO_set_callback_arg(b, (char *)conn);
940 BIO_set_callback(b, ssl_idevice_bio_callback);
941 return b;
942}
943
921static int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) 944static int ssl_verify_callback(int ok, X509_STORE_CTX *ctx)
922{ 945{
923 return 1; 946 return 1;
@@ -1009,12 +1032,11 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne
1009 if (pair_record) 1032 if (pair_record)
1010 plist_free(pair_record); 1033 plist_free(pair_record);
1011 1034
1012 BIO *ssl_bio = BIO_new(BIO_s_socket()); 1035 BIO *ssl_bio = ssl_idevice_bio_new(connection);
1013 if (!ssl_bio) { 1036 if (!ssl_bio) {
1014 debug_info("ERROR: Could not create SSL bio."); 1037 debug_info("ERROR: Could not create SSL bio.");
1015 return ret; 1038 return ret;
1016 } 1039 }
1017 BIO_set_fd(ssl_bio, (int)(long)connection->data, BIO_NOCLOSE);
1018 1040
1019 SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method()); 1041 SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
1020 if (ssl_ctx == NULL) { 1042 if (ssl_ctx == NULL) {
diff --git a/src/idevice.h b/src/idevice.h
index 8709c9a..4e53a7f 100644
--- a/src/idevice.h
+++ b/src/idevice.h
@@ -68,6 +68,8 @@ struct idevice_connection_private {
68 enum idevice_connection_type type; 68 enum idevice_connection_type type;
69 void *data; 69 void *data;
70 ssl_data_t ssl_data; 70 ssl_data_t ssl_data;
71 unsigned int ssl_recv_timeout;
72 idevice_error_t status;
71}; 73};
72 74
73struct idevice_private { 75struct idevice_private {