libfreerdp-core: replace all OpenSSL built-in BIOs by new full duplex BIOs
This commit is contained in:
parent
1172596d59
commit
04968b18c4
@ -148,7 +148,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
|||||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||||
MODULE winpr
|
MODULE winpr
|
||||||
MODULES winpr-registry winpr-utils winpr-interlocked winpr-dsparse winpr-sspi winpr-rpc winpr-wtsapi winpr-handle winpr-crt)
|
MODULES winpr-registry winpr-utils winpr-interlocked winpr-dsparse winpr-sspi winpr-rpc winpr-wtsapi winpr-handle winpr-winsock winpr-crt)
|
||||||
|
|
||||||
if(MONOLITHIC_BUILD)
|
if(MONOLITHIC_BUILD)
|
||||||
set(FREERDP_LIBS ${FREERDP_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)
|
set(FREERDP_LIBS ${FREERDP_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)
|
||||||
|
@ -319,8 +319,7 @@ int rpc_out_read(rdpRpc* rpc, BYTE* data, int length)
|
|||||||
int status;
|
int status;
|
||||||
|
|
||||||
status = BIO_read(rpc->TlsOut->bio, data, length);
|
status = BIO_read(rpc->TlsOut->bio, data, length);
|
||||||
/* fprintf(stderr, "%s: length=%d => status=%d shouldRetry=%d\n", __FUNCTION__, length,
|
|
||||||
* status, BIO_should_retry(rpc->TlsOut->bio)); */
|
|
||||||
if (status > 0) {
|
if (status > 0) {
|
||||||
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||||
VALGRIND_MAKE_MEM_DEFINED(data, status);
|
VALGRIND_MAKE_MEM_DEFINED(data, status);
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include <winpr/crt.h>
|
#include <winpr/crt.h>
|
||||||
|
#include <winpr/winsock.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
@ -55,9 +56,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
|
||||||
#define SHUT_RDWR SD_BOTH
|
|
||||||
#define close(_fd) closesocket(_fd)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <freerdp/utils/tcp.h>
|
#include <freerdp/utils/tcp.h>
|
||||||
@ -66,6 +64,185 @@
|
|||||||
|
|
||||||
#include "tcp.h"
|
#include "tcp.h"
|
||||||
|
|
||||||
|
/* Simple Socket BIO */
|
||||||
|
|
||||||
|
static int transport_bio_simple_new(BIO* bio);
|
||||||
|
static int transport_bio_simple_free(BIO* bio);
|
||||||
|
|
||||||
|
long transport_bio_simple_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int transport_bio_simple_write(BIO* bio, const char* buf, int size)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
|
||||||
|
|
||||||
|
status = _send((SOCKET) bio->num, buf, size, 0);
|
||||||
|
|
||||||
|
if (status <= 0)
|
||||||
|
{
|
||||||
|
error = WSAGetLastError();
|
||||||
|
|
||||||
|
if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) ||
|
||||||
|
(error == WSAEINPROGRESS) || (error == WSAEALREADY))
|
||||||
|
{
|
||||||
|
BIO_set_flags(bio, (BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int transport_bio_simple_read(BIO* bio, char* buf, int size)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_READ);
|
||||||
|
|
||||||
|
status = _recv((SOCKET) bio->num, buf, size, 0);
|
||||||
|
|
||||||
|
if (status <= 0)
|
||||||
|
{
|
||||||
|
error = WSAGetLastError();
|
||||||
|
|
||||||
|
if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) ||
|
||||||
|
(error == WSAEINPROGRESS) || (error == WSAEALREADY))
|
||||||
|
{
|
||||||
|
BIO_set_flags(bio, (BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int transport_bio_simple_puts(BIO* bio, const char* str)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int transport_bio_simple_gets(BIO* bio, char* str, int size)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||||
|
{
|
||||||
|
int status = -1;
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case BIO_C_SET_FD:
|
||||||
|
if (arg2)
|
||||||
|
{
|
||||||
|
transport_bio_simple_free(bio);
|
||||||
|
bio->flags = BIO_FLAGS_SHOULD_RETRY;
|
||||||
|
bio->num = *((int*) arg2);
|
||||||
|
bio->shutdown = (int) arg1;
|
||||||
|
bio->init = 1;
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_C_GET_FD:
|
||||||
|
if (bio->init)
|
||||||
|
{
|
||||||
|
if (arg2)
|
||||||
|
*((int*) arg2) = bio->num;
|
||||||
|
status = bio->num;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_GET_CLOSE:
|
||||||
|
status = bio->shutdown;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_SET_CLOSE:
|
||||||
|
bio->shutdown = (int) arg1;
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_DUP:
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_FLUSH:
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
status = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int transport_bio_simple_new(BIO* bio)
|
||||||
|
{
|
||||||
|
bio->init = 0;
|
||||||
|
bio->num = 0;
|
||||||
|
bio->ptr = NULL;
|
||||||
|
bio->flags = BIO_FLAGS_SHOULD_RETRY;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int transport_bio_simple_free(BIO* bio)
|
||||||
|
{
|
||||||
|
if (!bio)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (bio->shutdown)
|
||||||
|
{
|
||||||
|
if (bio->init)
|
||||||
|
closesocket((SOCKET) bio->num);
|
||||||
|
|
||||||
|
bio->init = 0;
|
||||||
|
bio->flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BIO_METHOD transport_bio_simple_socket_methods =
|
||||||
|
{
|
||||||
|
BIO_TYPE_SIMPLE,
|
||||||
|
"SimpleSocket",
|
||||||
|
transport_bio_simple_write,
|
||||||
|
transport_bio_simple_read,
|
||||||
|
transport_bio_simple_puts,
|
||||||
|
transport_bio_simple_gets,
|
||||||
|
transport_bio_simple_ctrl,
|
||||||
|
transport_bio_simple_new,
|
||||||
|
transport_bio_simple_free,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
BIO_METHOD* BIO_s_simple_socket(void)
|
||||||
|
{
|
||||||
|
return &transport_bio_simple_socket_methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buffered Socket BIO */
|
||||||
|
|
||||||
long transport_bio_buffered_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
|
long transport_bio_buffered_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
@ -80,7 +257,7 @@ static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
|
|||||||
|
|
||||||
ret = num;
|
ret = num;
|
||||||
tcp->writeBlocked = FALSE;
|
tcp->writeBlocked = FALSE;
|
||||||
BIO_clear_retry_flags(bio);
|
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
|
||||||
|
|
||||||
/* we directly append extra bytes in the xmit buffer, this could be prevented
|
/* we directly append extra bytes in the xmit buffer, this could be prevented
|
||||||
* but for now it makes the code more simple.
|
* but for now it makes the code more simple.
|
||||||
@ -99,21 +276,22 @@ static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
|
|||||||
while (chunks[i].size)
|
while (chunks[i].size)
|
||||||
{
|
{
|
||||||
status = BIO_write(bio->next_bio, chunks[i].data, chunks[i].size);
|
status = BIO_write(bio->next_bio, chunks[i].data, chunks[i].size);
|
||||||
/*fprintf(stderr, "%s: i=%d/%d size=%d/%d status=%d retry=%d\n", __FUNCTION__, i, nchunks,
|
|
||||||
chunks[i].size, ringbuffer_used(&tcp->xmitBuffer), status,
|
|
||||||
BIO_should_retry(bio->next_bio)
|
|
||||||
);*/
|
|
||||||
if (status <= 0)
|
if (status <= 0)
|
||||||
{
|
{
|
||||||
if (BIO_should_retry(bio->next_bio))
|
if (!BIO_should_retry(bio->next_bio))
|
||||||
{
|
{
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
ret = -1; /* fatal error */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BIO_should_write(bio->next_bio))
|
||||||
|
{
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_WRITE);
|
||||||
tcp->writeBlocked = TRUE;
|
tcp->writeBlocked = TRUE;
|
||||||
goto out; /* EWOULDBLOCK */
|
goto out; /* EWOULDBLOCK */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* any other is an error, but we still have to commit written bytes */
|
|
||||||
ret = -1;
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
committedBytes += status;
|
committedBytes += status;
|
||||||
@ -133,17 +311,30 @@ static int transport_bio_buffered_read(BIO* bio, char* buf, int size)
|
|||||||
rdpTcp* tcp = (rdpTcp*) bio->ptr;
|
rdpTcp* tcp = (rdpTcp*) bio->ptr;
|
||||||
|
|
||||||
tcp->readBlocked = FALSE;
|
tcp->readBlocked = FALSE;
|
||||||
BIO_clear_retry_flags(bio);
|
BIO_clear_flags(bio, BIO_FLAGS_READ);
|
||||||
|
|
||||||
status = BIO_read(bio->next_bio, buf, size);
|
status = BIO_read(bio->next_bio, buf, size);
|
||||||
/*fprintf(stderr, "%s: size=%d status=%d shouldRetry=%d\n", __FUNCTION__, size, status, BIO_should_retry(bio->next_bio)); */
|
|
||||||
|
|
||||||
if (status <= 0 && BIO_should_retry(bio->next_bio))
|
if (status <= 0)
|
||||||
{
|
{
|
||||||
BIO_set_retry_read(bio);
|
if (!BIO_should_retry(bio->next_bio))
|
||||||
tcp->readBlocked = TRUE;
|
{
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
status = -1;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
|
||||||
|
if (BIO_should_read(bio->next_bio))
|
||||||
|
{
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_READ);
|
||||||
|
tcp->readBlocked = TRUE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,18 +350,20 @@ static int transport_bio_buffered_gets(BIO* bio, char* str, int size)
|
|||||||
|
|
||||||
static long transport_bio_buffered_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
static long transport_bio_buffered_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||||
{
|
{
|
||||||
rdpTcp *tcp = (rdpTcp *)bio->ptr;
|
rdpTcp* tcp = (rdpTcp*) bio->ptr;
|
||||||
|
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case BIO_CTRL_FLUSH:
|
case BIO_CTRL_FLUSH:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case BIO_CTRL_WPENDING:
|
case BIO_CTRL_WPENDING:
|
||||||
return ringbuffer_used(&tcp->xmitBuffer);
|
return ringbuffer_used(&tcp->xmitBuffer);
|
||||||
|
|
||||||
case BIO_CTRL_PENDING:
|
case BIO_CTRL_PENDING:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/*fprintf(stderr, "%s: passing to next BIO, bio=%p cmd=%d arg1=%d arg2=%p\n", __FUNCTION__, bio, cmd, arg1, arg2); */
|
|
||||||
return BIO_ctrl(bio->next_bio, cmd, arg1, arg2);
|
return BIO_ctrl(bio->next_bio, cmd, arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,8 +375,7 @@ static int transport_bio_buffered_new(BIO* bio)
|
|||||||
bio->init = 1;
|
bio->init = 1;
|
||||||
bio->num = 0;
|
bio->num = 0;
|
||||||
bio->ptr = NULL;
|
bio->ptr = NULL;
|
||||||
bio->flags = 0;
|
bio->flags = BIO_FLAGS_SHOULD_RETRY;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +384,6 @@ static int transport_bio_buffered_free(BIO* bio)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static BIO_METHOD transport_bio_buffered_socket_methods =
|
static BIO_METHOD transport_bio_buffered_socket_methods =
|
||||||
{
|
{
|
||||||
BIO_TYPE_BUFFERED,
|
BIO_TYPE_BUFFERED,
|
||||||
@ -214,18 +405,17 @@ BIO_METHOD* BIO_s_buffered_socket(void)
|
|||||||
|
|
||||||
BOOL transport_bio_buffered_drain(BIO *bio)
|
BOOL transport_bio_buffered_drain(BIO *bio)
|
||||||
{
|
{
|
||||||
rdpTcp *tcp = (rdpTcp *)bio->ptr;
|
|
||||||
int status;
|
int status;
|
||||||
|
rdpTcp* tcp = (rdpTcp*) bio->ptr;
|
||||||
|
|
||||||
if (!ringbuffer_used(&tcp->xmitBuffer))
|
if (!ringbuffer_used(&tcp->xmitBuffer))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
status = transport_bio_buffered_write(bio, NULL, 0);
|
status = transport_bio_buffered_write(bio, NULL, 0);
|
||||||
|
|
||||||
return status >= 0;
|
return status >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void tcp_get_ip_address(rdpTcp* tcp)
|
void tcp_get_ip_address(rdpTcp* tcp)
|
||||||
{
|
{
|
||||||
BYTE* ip;
|
BYTE* ip;
|
||||||
@ -346,6 +536,16 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout)
|
|||||||
return FALSE; /* timeout */
|
return FALSE; /* timeout */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIO_set_close(tcp->socketBio, BIO_NOCLOSE);
|
||||||
|
BIO_free(tcp->socketBio);
|
||||||
|
|
||||||
|
tcp->socketBio = BIO_new(BIO_s_simple_socket());
|
||||||
|
|
||||||
|
if (!tcp->socketBio)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
BIO_set_fd(tcp->socketBio, tcp->sockfd, BIO_CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetEventFileDescriptor(tcp->event, tcp->sockfd);
|
SetEventFileDescriptor(tcp->event, tcp->sockfd);
|
||||||
@ -504,9 +704,12 @@ int tcp_attach(rdpTcp* tcp, int sockfd)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tcp->socketBio = BIO_new_socket(sockfd, 1);
|
tcp->socketBio = BIO_new(BIO_s_simple_socket());
|
||||||
|
|
||||||
if (!tcp->socketBio)
|
if (!tcp->socketBio)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
BIO_set_fd(tcp->socketBio, sockfd, BIO_CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tcp->bufferedBio)
|
if (!tcp->bufferedBio)
|
||||||
|
@ -38,7 +38,8 @@
|
|||||||
#define MSG_NOSIGNAL 0
|
#define MSG_NOSIGNAL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BIO_TYPE_BUFFERED 66
|
#define BIO_TYPE_SIMPLE 66
|
||||||
|
#define BIO_TYPE_BUFFERED 67
|
||||||
|
|
||||||
typedef struct rdp_tcp rdpTcp;
|
typedef struct rdp_tcp rdpTcp;
|
||||||
|
|
||||||
|
@ -133,17 +133,20 @@ static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
|
|||||||
|
|
||||||
tsg = (rdpTsg*) bio->ptr;
|
tsg = (rdpTsg*) bio->ptr;
|
||||||
|
|
||||||
BIO_clear_retry_flags(bio);
|
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
|
||||||
|
|
||||||
status = tsg_write(tsg, (BYTE*) buf, num);
|
status = tsg_write(tsg, (BYTE*) buf, num);
|
||||||
|
|
||||||
if (status == 0)
|
if (status < 0)
|
||||||
BIO_set_retry_write(bio);
|
{
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
if (status > 0)
|
return status >= 0 ? status : -1;
|
||||||
return status;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
|
static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
|
||||||
@ -153,18 +156,17 @@ static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
|
|||||||
|
|
||||||
tsg = (rdpTsg*) bio->ptr;
|
tsg = (rdpTsg*) bio->ptr;
|
||||||
|
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_READ);
|
||||||
|
|
||||||
status = tsg_read(bio->ptr, (BYTE*) buf, size);
|
status = tsg_read(bio->ptr, (BYTE*) buf, size);
|
||||||
|
|
||||||
BIO_clear_retry_flags(bio);
|
if (status < 0)
|
||||||
|
|
||||||
if (status == 0)
|
|
||||||
{
|
{
|
||||||
BIO_set_retry_read(bio);
|
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
status = -1;
|
|
||||||
}
|
}
|
||||||
else if (status == -1)
|
else
|
||||||
{
|
{
|
||||||
status = 0;
|
BIO_set_flags(bio, BIO_FLAGS_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status >= 0 ? status : -1;
|
return status >= 0 ? status : -1;
|
||||||
@ -195,8 +197,7 @@ static int transport_bio_tsg_new(BIO* bio)
|
|||||||
bio->init = 1;
|
bio->init = 1;
|
||||||
bio->num = 0;
|
bio->num = 0;
|
||||||
bio->ptr = NULL;
|
bio->ptr = NULL;
|
||||||
bio->flags = 0;
|
bio->flags = BIO_FLAGS_SHOULD_RETRY;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,8 +227,6 @@ BIO_METHOD* BIO_s_tsg(void)
|
|||||||
return &transport_bio_tsg_methods;
|
return &transport_bio_tsg_methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOL transport_connect_tls(rdpTransport* transport)
|
BOOL transport_connect_tls(rdpTransport* transport)
|
||||||
{
|
{
|
||||||
rdpSettings *settings = transport->settings;
|
rdpSettings *settings = transport->settings;
|
||||||
@ -708,7 +707,6 @@ static int transport_wait_for_write(rdpTransport* transport)
|
|||||||
return select(tcpOut->sockfd + 1, rsetPtr, wsetPtr, NULL, &tv);
|
return select(tcpOut->sockfd + 1, rsetPtr, wsetPtr, NULL, &tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes)
|
int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes)
|
||||||
{
|
{
|
||||||
int read = 0;
|
int read = 0;
|
||||||
@ -724,13 +722,7 @@ int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes)
|
|||||||
{
|
{
|
||||||
status = BIO_read(transport->frontBio, data + read, bytes - read);
|
status = BIO_read(transport->frontBio, data + read, bytes - read);
|
||||||
|
|
||||||
if (!status)
|
if (status <= 0)
|
||||||
{
|
|
||||||
transport->layer = TRANSPORT_LAYER_CLOSED;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status < 0)
|
|
||||||
{
|
{
|
||||||
if (!transport->frontBio || !BIO_should_retry(transport->frontBio))
|
if (!transport->frontBio || !BIO_should_retry(transport->frontBio))
|
||||||
{
|
{
|
||||||
@ -763,8 +755,6 @@ int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes)
|
|||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int transport_read(rdpTransport* transport, wStream* s)
|
int transport_read(rdpTransport* transport, wStream* s)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
@ -33,6 +33,445 @@
|
|||||||
#include <freerdp/crypto/tls.h>
|
#include <freerdp/crypto/tls.h>
|
||||||
#include "../core/tcp.h"
|
#include "../core/tcp.h"
|
||||||
|
|
||||||
|
struct _BIO_RDP_TLS
|
||||||
|
{
|
||||||
|
SSL* ssl;
|
||||||
|
};
|
||||||
|
typedef struct _BIO_RDP_TLS BIO_RDP_TLS;
|
||||||
|
|
||||||
|
long bio_rdp_tls_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bio_rdp_tls_write(BIO* bio, const char* buf, int size)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
BIO_RDP_TLS* tls = (BIO_RDP_TLS*) bio->ptr;
|
||||||
|
|
||||||
|
if (!buf || !tls)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL);
|
||||||
|
|
||||||
|
status = SSL_write(tls->ssl, buf, size);
|
||||||
|
|
||||||
|
if (status <= 0)
|
||||||
|
{
|
||||||
|
switch (SSL_get_error(tls->ssl, status))
|
||||||
|
{
|
||||||
|
case SSL_ERROR_NONE:
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_WRITE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_READ);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
|
||||||
|
bio->retry_reason = BIO_RR_SSL_X509_LOOKUP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_WANT_CONNECT:
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
|
||||||
|
bio->retry_reason = BIO_RR_CONNECT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_SYSCALL:
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_SSL:
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bio_rdp_tls_read(BIO* bio, char* buf, int size)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
BIO_RDP_TLS* tls = (BIO_RDP_TLS*) bio->ptr;
|
||||||
|
|
||||||
|
if (!buf || !tls)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL);
|
||||||
|
|
||||||
|
status = SSL_read(tls->ssl, buf, size);
|
||||||
|
|
||||||
|
if (status <= 0)
|
||||||
|
{
|
||||||
|
switch (SSL_get_error(tls->ssl, status))
|
||||||
|
{
|
||||||
|
case SSL_ERROR_NONE:
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_READ);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_WRITE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
|
||||||
|
bio->retry_reason = BIO_RR_SSL_X509_LOOKUP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_WANT_ACCEPT:
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
|
||||||
|
bio->retry_reason = BIO_RR_ACCEPT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_WANT_CONNECT:
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
|
||||||
|
bio->retry_reason = BIO_RR_CONNECT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_SSL:
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_SYSCALL:
|
||||||
|
status = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bio_rdp_tls_puts(BIO* bio, const char* str)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if (!str)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
size = strlen(str);
|
||||||
|
status = BIO_write(bio, str, size);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bio_rdp_tls_gets(BIO* bio, char* str, int size)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr)
|
||||||
|
{
|
||||||
|
BIO* rbio;
|
||||||
|
int status = -1;
|
||||||
|
BIO_RDP_TLS* tls = (BIO_RDP_TLS*) bio->ptr;
|
||||||
|
|
||||||
|
if (!tls)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!tls->ssl && (cmd != BIO_C_SET_SSL))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case BIO_CTRL_RESET:
|
||||||
|
SSL_shutdown(tls->ssl);
|
||||||
|
|
||||||
|
if (tls->ssl->handshake_func == tls->ssl->method->ssl_connect)
|
||||||
|
SSL_set_connect_state(tls->ssl);
|
||||||
|
else if (tls->ssl->handshake_func == tls->ssl->method->ssl_accept)
|
||||||
|
SSL_set_accept_state(tls->ssl);
|
||||||
|
|
||||||
|
SSL_clear(tls->ssl);
|
||||||
|
|
||||||
|
if (bio->next_bio)
|
||||||
|
status = BIO_ctrl(bio->next_bio, cmd, num, ptr);
|
||||||
|
else if (tls->ssl->rbio)
|
||||||
|
status = BIO_ctrl(tls->ssl->rbio, cmd, num, ptr);
|
||||||
|
else
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_C_GET_FD:
|
||||||
|
status = BIO_ctrl(tls->ssl->rbio, cmd, num, ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_INFO:
|
||||||
|
status = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_SET_CALLBACK:
|
||||||
|
status = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_GET_CALLBACK:
|
||||||
|
*((ULONG_PTR*) ptr) = (ULONG_PTR) SSL_get_info_callback(tls->ssl);
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_C_SSL_MODE:
|
||||||
|
if (num)
|
||||||
|
SSL_set_connect_state(tls->ssl);
|
||||||
|
else
|
||||||
|
SSL_set_accept_state(tls->ssl);
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_GET_CLOSE:
|
||||||
|
status = bio->shutdown;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_SET_CLOSE:
|
||||||
|
bio->shutdown = (int) num;
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_WPENDING:
|
||||||
|
status = BIO_ctrl(tls->ssl->wbio, cmd, num, ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_PENDING:
|
||||||
|
status = SSL_pending(tls->ssl);
|
||||||
|
if (status == 0)
|
||||||
|
status = BIO_pending(tls->ssl->rbio);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_FLUSH:
|
||||||
|
BIO_clear_retry_flags(bio);
|
||||||
|
status = BIO_ctrl(tls->ssl->wbio, cmd, num, ptr);
|
||||||
|
BIO_copy_next_retry(bio);
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_PUSH:
|
||||||
|
if (bio->next_bio && (bio->next_bio != tls->ssl->rbio))
|
||||||
|
{
|
||||||
|
SSL_set_bio(tls->ssl, bio->next_bio, bio->next_bio);
|
||||||
|
CRYPTO_add(&(bio->next_bio->references), 1, CRYPTO_LOCK_BIO);
|
||||||
|
}
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_CTRL_POP:
|
||||||
|
if (bio == ptr)
|
||||||
|
{
|
||||||
|
if (tls->ssl->rbio != tls->ssl->wbio)
|
||||||
|
BIO_free_all(tls->ssl->wbio);
|
||||||
|
|
||||||
|
if (bio->next_bio)
|
||||||
|
CRYPTO_add(&(bio->next_bio->references), -1, CRYPTO_LOCK_BIO);
|
||||||
|
|
||||||
|
tls->ssl->wbio = tls->ssl->rbio = NULL;
|
||||||
|
}
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_C_GET_SSL:
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
*((SSL**) ptr) = tls->ssl;
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_C_SET_SSL:
|
||||||
|
bio->shutdown = (int) num;
|
||||||
|
|
||||||
|
if (ptr)
|
||||||
|
tls->ssl = (SSL*) ptr;
|
||||||
|
|
||||||
|
rbio = SSL_get_rbio(tls->ssl);
|
||||||
|
|
||||||
|
if (rbio)
|
||||||
|
{
|
||||||
|
if (bio->next_bio)
|
||||||
|
BIO_push(rbio, bio->next_bio);
|
||||||
|
|
||||||
|
bio->next_bio = rbio;
|
||||||
|
CRYPTO_add(&(rbio->references), 1, CRYPTO_LOCK_BIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
bio->init = 1;
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BIO_C_DO_STATE_MACHINE:
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_WRITE | BIO_FLAGS_IO_SPECIAL);
|
||||||
|
bio->retry_reason = 0;
|
||||||
|
|
||||||
|
status = SSL_do_handshake(tls->ssl);
|
||||||
|
|
||||||
|
if (status <= 0)
|
||||||
|
{
|
||||||
|
switch (SSL_get_error(tls->ssl, status))
|
||||||
|
{
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_ERROR_WANT_CONNECT:
|
||||||
|
BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
bio->retry_reason = bio->next_bio->retry_reason;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
status = BIO_ctrl(tls->ssl->rbio, cmd, num, ptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bio_rdp_tls_new(BIO* bio)
|
||||||
|
{
|
||||||
|
BIO_RDP_TLS* tls;
|
||||||
|
|
||||||
|
bio->init = 0;
|
||||||
|
bio->num = 0;
|
||||||
|
bio->flags = BIO_FLAGS_SHOULD_RETRY;
|
||||||
|
bio->next_bio = NULL;
|
||||||
|
|
||||||
|
tls = calloc(1, sizeof(BIO_RDP_TLS));
|
||||||
|
|
||||||
|
if (!tls)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bio->ptr = (void*) tls;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bio_rdp_tls_free(BIO* bio)
|
||||||
|
{
|
||||||
|
BIO_RDP_TLS* tls;
|
||||||
|
|
||||||
|
if (!bio)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
tls = (BIO_RDP_TLS*) bio->ptr;
|
||||||
|
|
||||||
|
if (!tls)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (bio->shutdown)
|
||||||
|
{
|
||||||
|
if (bio->init && tls->ssl)
|
||||||
|
{
|
||||||
|
SSL_shutdown(tls->ssl);
|
||||||
|
SSL_free(tls->ssl);
|
||||||
|
}
|
||||||
|
|
||||||
|
bio->init = 0;
|
||||||
|
bio->flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(tls);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long bio_rdp_tls_callback_ctrl(BIO* bio, int cmd, bio_info_cb* fp)
|
||||||
|
{
|
||||||
|
int status = 0;
|
||||||
|
BIO_RDP_TLS* tls;
|
||||||
|
|
||||||
|
if (!bio)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
tls = (BIO_RDP_TLS*) bio->ptr;
|
||||||
|
|
||||||
|
if (!tls)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case BIO_CTRL_SET_CALLBACK:
|
||||||
|
SSL_set_info_callback(tls->ssl, (void (*)(const SSL *, int, int)) fp);
|
||||||
|
status = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
status = BIO_callback_ctrl(tls->ssl->rbio, cmd, fp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BIO_TYPE_RDP_TLS 68
|
||||||
|
|
||||||
|
static BIO_METHOD bio_rdp_tls_methods =
|
||||||
|
{
|
||||||
|
BIO_TYPE_RDP_TLS,
|
||||||
|
"RdpTls",
|
||||||
|
bio_rdp_tls_write,
|
||||||
|
bio_rdp_tls_read,
|
||||||
|
bio_rdp_tls_puts,
|
||||||
|
bio_rdp_tls_gets,
|
||||||
|
bio_rdp_tls_ctrl,
|
||||||
|
bio_rdp_tls_new,
|
||||||
|
bio_rdp_tls_free,
|
||||||
|
bio_rdp_tls_callback_ctrl,
|
||||||
|
};
|
||||||
|
|
||||||
|
BIO_METHOD* BIO_s_rdp_tls(void)
|
||||||
|
{
|
||||||
|
return &bio_rdp_tls_methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
BIO* BIO_new_rdp_tls(SSL_CTX* ctx, int client)
|
||||||
|
{
|
||||||
|
BIO* bio;
|
||||||
|
SSL* ssl;
|
||||||
|
|
||||||
|
bio = BIO_new(BIO_s_rdp_tls());
|
||||||
|
|
||||||
|
if (!bio)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ssl = SSL_new(ctx);
|
||||||
|
|
||||||
|
if (!ssl)
|
||||||
|
{
|
||||||
|
BIO_free(bio);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client)
|
||||||
|
SSL_set_connect_state(ssl);
|
||||||
|
else
|
||||||
|
SSL_set_accept_state(ssl);
|
||||||
|
|
||||||
|
BIO_set_ssl(bio, ssl, BIO_CLOSE);
|
||||||
|
|
||||||
|
return bio;
|
||||||
|
}
|
||||||
|
|
||||||
static CryptoCert tls_get_certificate(rdpTls* tls, BOOL peer)
|
static CryptoCert tls_get_certificate(rdpTls* tls, BOOL peer)
|
||||||
{
|
{
|
||||||
CryptoCert cert;
|
CryptoCert cert;
|
||||||
@ -127,7 +566,8 @@ BOOL tls_prepare(rdpTls* tls, BIO *underlying, const SSL_METHOD *method, int opt
|
|||||||
SSL_CTX_set_options(tls->ctx, options);
|
SSL_CTX_set_options(tls->ctx, options);
|
||||||
SSL_CTX_set_read_ahead(tls->ctx, 1);
|
SSL_CTX_set_read_ahead(tls->ctx, 1);
|
||||||
|
|
||||||
tls->bio = BIO_new_ssl(tls->ctx, clientMode);
|
tls->bio = BIO_new_rdp_tls(tls->ctx, clientMode);
|
||||||
|
|
||||||
if (BIO_get_ssl(tls->bio, &tls->ssl) < 0)
|
if (BIO_get_ssl(tls->bio, &tls->ssl) < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: unable to retrieve the SSL of the connection\n", __FUNCTION__);
|
fprintf(stderr, "%s: unable to retrieve the SSL of the connection\n", __FUNCTION__);
|
||||||
@ -135,6 +575,7 @@ BOOL tls_prepare(rdpTls* tls, BIO *underlying, const SSL_METHOD *method, int opt
|
|||||||
}
|
}
|
||||||
|
|
||||||
BIO_push(tls->bio, underlying);
|
BIO_push(tls->bio, underlying);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,8 +591,10 @@ int tls_do_handshake(rdpTls* tls, BOOL clientMode)
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
status = BIO_do_handshake(tls->bio);
|
status = BIO_do_handshake(tls->bio);
|
||||||
|
|
||||||
if (status == 1)
|
if (status == 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!BIO_should_retry(tls->bio))
|
if (!BIO_should_retry(tls->bio))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -160,6 +603,7 @@ int tls_do_handshake(rdpTls* tls, BOOL clientMode)
|
|||||||
FD_ZERO(&rset);
|
FD_ZERO(&rset);
|
||||||
|
|
||||||
fd = BIO_get_fd(tls->bio, NULL);
|
fd = BIO_get_fd(tls->bio, NULL);
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: unable to retrieve BIO fd\n", __FUNCTION__);
|
fprintf(stderr, "%s: unable to retrieve BIO fd\n", __FUNCTION__);
|
||||||
@ -171,6 +615,7 @@ int tls_do_handshake(rdpTls* tls, BOOL clientMode)
|
|||||||
tv.tv_usec = 10 * 1000; /* 10ms */
|
tv.tv_usec = 10 * 1000; /* 10ms */
|
||||||
|
|
||||||
status = select(fd + 1, &rset, NULL, NULL, &tv);
|
status = select(fd + 1, &rset, NULL, NULL, &tv);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: error during select()\n", __FUNCTION__);
|
fprintf(stderr, "%s: error during select()\n", __FUNCTION__);
|
||||||
@ -383,7 +828,7 @@ int tls_write_all(rdpTls* tls, const BYTE* data, int length)
|
|||||||
fd_set rset, wset;
|
fd_set rset, wset;
|
||||||
fd_set *rsetPtr, *wsetPtr;
|
fd_set *rsetPtr, *wsetPtr;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
BIO *bio = tls->bio;
|
BIO* bio = tls->bio;
|
||||||
DataChunk chunks[2];
|
DataChunk chunks[2];
|
||||||
|
|
||||||
BIO* bufferedBio = findBufferedBio(bio);
|
BIO* bufferedBio = findBufferedBio(bio);
|
||||||
@ -399,7 +844,7 @@ int tls_write_all(rdpTls* tls, const BYTE* data, int length)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
status = BIO_write(bio, data, length);
|
status = BIO_write(bio, data, length);
|
||||||
/*fprintf(stderr, "%s: BIO_write(len=%d) = %d (retry=%d)\n", __FUNCTION__, length, status, BIO_should_retry(bio));*/
|
|
||||||
if (status > 0)
|
if (status > 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -408,6 +853,7 @@ int tls_write_all(rdpTls* tls, const BYTE* data, int length)
|
|||||||
|
|
||||||
/* we try to handle SSL want_read and want_write nicely */
|
/* we try to handle SSL want_read and want_write nicely */
|
||||||
rsetPtr = wsetPtr = 0;
|
rsetPtr = wsetPtr = 0;
|
||||||
|
|
||||||
if (tcp->writeBlocked)
|
if (tcp->writeBlocked)
|
||||||
{
|
{
|
||||||
wsetPtr = &wset;
|
wsetPtr = &wset;
|
||||||
@ -431,6 +877,7 @@ int tls_write_all(rdpTls* tls, const BYTE* data, int length)
|
|||||||
tv.tv_usec = 100 * 1000;
|
tv.tv_usec = 100 * 1000;
|
||||||
|
|
||||||
status = select(tcp->sockfd + 1, rsetPtr, wsetPtr, NULL, &tv);
|
status = select(tcp->sockfd + 1, rsetPtr, wsetPtr, NULL, &tv);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -447,6 +894,7 @@ int tls_write_all(rdpTls* tls, const BYTE* data, int length)
|
|||||||
while (chunks[i].size)
|
while (chunks[i].size)
|
||||||
{
|
{
|
||||||
status = BIO_write(tcp->socketBio, chunks[i].data, chunks[i].size);
|
status = BIO_write(tcp->socketBio, chunks[i].data, chunks[i].size);
|
||||||
|
|
||||||
if (status > 0)
|
if (status > 0)
|
||||||
{
|
{
|
||||||
chunks[i].size -= status;
|
chunks[i].size -= status;
|
||||||
@ -457,12 +905,14 @@ int tls_write_all(rdpTls* tls, const BYTE* data, int length)
|
|||||||
|
|
||||||
if (!BIO_should_retry(tcp->socketBio))
|
if (!BIO_should_retry(tcp->socketBio))
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
|
|
||||||
FD_ZERO(&rset);
|
FD_ZERO(&rset);
|
||||||
FD_SET(tcp->sockfd, &rset);
|
FD_SET(tcp->sockfd, &rset);
|
||||||
tv.tv_sec = 0;
|
tv.tv_sec = 0;
|
||||||
tv.tv_usec = 100 * 1000;
|
tv.tv_usec = 100 * 1000;
|
||||||
|
|
||||||
status = select(tcp->sockfd + 1, &rset, NULL, NULL, &tv);
|
status = select(tcp->sockfd + 1, &rset, NULL, NULL, &tv);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
@ -478,8 +928,6 @@ out_fail:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int tls_set_alert_code(rdpTls* tls, int level, int description)
|
int tls_set_alert_code(rdpTls* tls, int level, int description)
|
||||||
{
|
{
|
||||||
tls->alertLevel = level;
|
tls->alertLevel = level;
|
||||||
|
@ -255,6 +255,10 @@ PCSTR inet_ntop(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize)
|
|||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#ifndef MSG_NOSIGNAL
|
||||||
|
#define MSG_NOSIGNAL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
int WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)
|
int WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)
|
||||||
{
|
{
|
||||||
ZeroMemory(lpWSAData, sizeof(WSADATA));
|
ZeroMemory(lpWSAData, sizeof(WSADATA));
|
||||||
@ -423,6 +427,17 @@ int WSAGetLastError(void)
|
|||||||
iError = WSAEREMOTE;
|
iError = WSAEREMOTE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Special cases */
|
||||||
|
|
||||||
|
#if (EAGAIN != EWOULDBLOCK)
|
||||||
|
case EAGAIN:
|
||||||
|
iError = WSAEWOULDBLOCK;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case EPROTO:
|
||||||
|
iError = WSAECONNRESET;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -445,7 +460,7 @@ int WSAGetLastError(void)
|
|||||||
* WSAEREFUSED
|
* WSAEREFUSED
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return 0;
|
return iError;
|
||||||
}
|
}
|
||||||
|
|
||||||
SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen)
|
SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen)
|
||||||
@ -607,6 +622,8 @@ int _send(SOCKET s, const char* buf, int len, int flags)
|
|||||||
int status;
|
int status;
|
||||||
int fd = (int) s;
|
int fd = (int) s;
|
||||||
|
|
||||||
|
flags |= MSG_NOSIGNAL;
|
||||||
|
|
||||||
status = (int) send(fd, (void*) buf, (size_t) len, flags);
|
status = (int) send(fd, (void*) buf, (size_t) len, flags);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
Loading…
Reference in New Issue
Block a user