Merge pull request #2889 from dvincent-devolutions/gateway
Fix RDP8 gateway disconnections
This commit is contained in:
commit
48c7a8dc1d
@ -575,8 +575,7 @@ static BOOL wf_gw_authenticate(freerdp* instance,
|
||||
char** username, char** password, char** domain)
|
||||
{
|
||||
char tmp[MAX_PATH];
|
||||
|
||||
sprintf(tmp, sizeof(tmp), "Gateway %s", instance->settings->GatewayHostname);
|
||||
sprintf_s(tmp, sizeof(tmp), "Gateway %s", instance->settings->GatewayHostname);
|
||||
return wf_authenticate_raw(instance, tmp, username, password, domain);
|
||||
}
|
||||
|
||||
|
@ -325,6 +325,7 @@ wStream* rdg_build_http_request(rdpRdg* rdg, char* method)
|
||||
|
||||
if (s)
|
||||
Stream_SealLength(s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -379,9 +380,7 @@ BOOL rdg_process_out_channel_response(rdpRdg* rdg, HttpResponse* response)
|
||||
rdg->ntlm = NULL;
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE;
|
||||
|
||||
@ -446,9 +445,7 @@ BOOL rdg_process_in_channel_response(rdpRdg* rdg, HttpResponse* response)
|
||||
rdg->ntlm = NULL;
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZE;
|
||||
|
||||
@ -475,12 +472,12 @@ BOOL rdg_process_in_channel_authorization(rdpRdg* rdg, HttpResponse* response)
|
||||
return FALSE;
|
||||
|
||||
status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s));
|
||||
if (status <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
if (status <= 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1169,16 +1166,62 @@ int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size)
|
||||
|
||||
BOOL rdg_process_close_packet(rdpRdg* rdg)
|
||||
{
|
||||
BYTE buffer[sizeof(RdgPacketHeader) + 4];
|
||||
RdgPacketHeader* header = (RdgPacketHeader*)buffer;
|
||||
int status;
|
||||
wStream* sChunk;
|
||||
int packetSize = 12;
|
||||
char chunkSize[11];
|
||||
|
||||
sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
|
||||
|
||||
sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
|
||||
|
||||
if (!sChunk)
|
||||
return FALSE;
|
||||
|
||||
Stream_Write(sChunk, chunkSize, strlen(chunkSize));
|
||||
|
||||
Stream_Write_UINT16(sChunk, PKT_TYPE_CLOSE_CHANNEL_RESPONSE); /* Type */
|
||||
Stream_Write_UINT16(sChunk, 0); /* Reserved */
|
||||
Stream_Write_UINT32(sChunk, packetSize); /* Packet length */
|
||||
|
||||
Stream_Write_UINT32(sChunk, 0); /* Status code */
|
||||
|
||||
Stream_Write(sChunk, "\r\n", 2);
|
||||
Stream_SealLength(sChunk);
|
||||
|
||||
status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
|
||||
Stream_Free(sChunk, TRUE);
|
||||
|
||||
return (status < 0 ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
header->type = PKT_TYPE_CLOSE_CHANNEL_RESPONSE;
|
||||
header->packetLength = sizeof(buffer);
|
||||
|
||||
WLog_DBG(TAG, "Channel Close requested");
|
||||
rdg->state = RDG_CLIENT_STATE_CLOSED;
|
||||
return (rdg_write_data_packet(rdg, buffer, sizeof(buffer)) > 0 ? TRUE : FALSE);
|
||||
BOOL rdg_process_keep_alive_packet(rdpRdg* rdg)
|
||||
{
|
||||
int status;
|
||||
wStream* sChunk;
|
||||
int packetSize = 8;
|
||||
char chunkSize[11];
|
||||
|
||||
sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
|
||||
|
||||
sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
|
||||
|
||||
if (!sChunk)
|
||||
return FALSE;
|
||||
|
||||
Stream_Write(sChunk, chunkSize, strlen(chunkSize));
|
||||
|
||||
Stream_Write_UINT16(sChunk, PKT_TYPE_KEEPALIVE); /* Type */
|
||||
Stream_Write_UINT16(sChunk, 0); /* Reserved */
|
||||
Stream_Write_UINT32(sChunk, packetSize); /* Packet length */
|
||||
|
||||
Stream_Write(sChunk, "\r\n", 2);
|
||||
Stream_SealLength(sChunk);
|
||||
|
||||
status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
|
||||
Stream_Free(sChunk, TRUE);
|
||||
|
||||
return (status < 0 ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
BOOL rdg_process_unknown_packet(rdpRdg* rdg, int type)
|
||||
@ -1198,10 +1241,9 @@ BOOL rdg_process_control_packet(rdpRdg* rdg, int type, int packetLength)
|
||||
if (payloadSize)
|
||||
{
|
||||
s = Stream_New(NULL, payloadSize);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (readCount < payloadSize)
|
||||
{
|
||||
@ -1224,17 +1266,26 @@ BOOL rdg_process_control_packet(rdpRdg* rdg, int type, int packetLength)
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PKT_TYPE_CLOSE_CHANNEL:
|
||||
return rdg_process_close_packet(rdg);
|
||||
break;
|
||||
default:
|
||||
rdg_process_unknown_packet(rdg, type);
|
||||
break;
|
||||
case PKT_TYPE_CLOSE_CHANNEL:
|
||||
EnterCriticalSection(&rdg->writeSection);
|
||||
status = rdg_process_close_packet(rdg);
|
||||
LeaveCriticalSection(&rdg->writeSection);
|
||||
break;
|
||||
|
||||
case PKT_TYPE_KEEPALIVE:
|
||||
EnterCriticalSection(&rdg->writeSection);
|
||||
status = rdg_process_keep_alive_packet(rdg);
|
||||
LeaveCriticalSection(&rdg->writeSection);
|
||||
break;
|
||||
|
||||
default:
|
||||
status = rdg_process_unknown_packet(rdg, type);
|
||||
break;
|
||||
}
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return TRUE;
|
||||
return status;
|
||||
}
|
||||
|
||||
int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
|
||||
@ -1257,10 +1308,11 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (rdg->nonBlocking && !readCount)
|
||||
if (!readCount)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
BIO_wait_read(rdg->tlsOut->bio, 50);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1289,6 +1341,7 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
BIO_wait_read(rdg->tlsOut->bio, 50);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1300,12 +1353,13 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
|
||||
|
||||
status = BIO_read(rdg->tlsOut->bio, buffer, readSize);
|
||||
|
||||
if (status < 0)
|
||||
if (status <= 0)
|
||||
{
|
||||
if (!BIO_should_retry(rdg->tlsOut->bio))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
rdg->packetRemainingCount -= status;
|
||||
@ -1328,11 +1382,13 @@ long rdg_bio_callback(BIO* bio, int mode, const char* argp, int argi, long argl,
|
||||
static int rdg_bio_write(BIO* bio, const char* buf, int num)
|
||||
{
|
||||
int status;
|
||||
rdpRdg* rdg = (rdpRdg*)bio->ptr;
|
||||
rdpRdg* rdg = (rdpRdg*) bio->ptr;
|
||||
|
||||
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
|
||||
|
||||
EnterCriticalSection(&rdg->writeSection);
|
||||
status = rdg_write_data_packet(rdg, (BYTE*) buf, num);
|
||||
LeaveCriticalSection(&rdg->writeSection);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
@ -1346,7 +1402,7 @@ static int rdg_bio_write(BIO* bio, const char* buf, int num)
|
||||
}
|
||||
else
|
||||
{
|
||||
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
|
||||
BIO_set_flags(bio, BIO_FLAGS_WRITE);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -1355,25 +1411,24 @@ static int rdg_bio_write(BIO* bio, const char* buf, int num)
|
||||
static int rdg_bio_read(BIO* bio, char* buf, int size)
|
||||
{
|
||||
int status;
|
||||
rdpRdg* rdg = (rdpRdg*)bio->ptr;
|
||||
|
||||
BIO_clear_flags(bio, BIO_FLAGS_READ);
|
||||
rdpRdg* rdg = (rdpRdg*) bio->ptr;
|
||||
|
||||
status = rdg_read_data_packet(rdg, (BYTE*) buf, size);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
BIO_clear_retry_flags(bio);
|
||||
return -1;
|
||||
}
|
||||
else if (status < size)
|
||||
else if (status == 0)
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_READ);
|
||||
BIO_set_retry_read(bio);
|
||||
WSASetLastError(WSAEWOULDBLOCK);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
BIO_clear_flags(bio, BIO_FLAGS_READ);
|
||||
BIO_set_flags(bio, BIO_FLAGS_READ);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -1381,12 +1436,12 @@ static int rdg_bio_read(BIO* bio, char* buf, int size)
|
||||
|
||||
static int rdg_bio_puts(BIO* bio, const char* str)
|
||||
{
|
||||
return 1;
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int rdg_bio_gets(BIO* bio, char* str, int size)
|
||||
{
|
||||
return 1;
|
||||
return -2;
|
||||
}
|
||||
|
||||
static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
@ -1412,25 +1467,41 @@ static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
}
|
||||
else if (cmd == BIO_C_SET_NONBLOCK)
|
||||
{
|
||||
rdg->nonBlocking = arg1;
|
||||
status = 1;
|
||||
}
|
||||
else if (cmd == BIO_C_READ_BLOCKED)
|
||||
{
|
||||
status = 0;
|
||||
BIO* bio = tlsOut->bio;
|
||||
status = BIO_read_blocked(bio);
|
||||
}
|
||||
else if (cmd == BIO_C_WRITE_BLOCKED)
|
||||
{
|
||||
status = 0;
|
||||
BIO* bio = tlsIn->bio;
|
||||
status = BIO_write_blocked(bio);
|
||||
}
|
||||
else if (cmd == BIO_C_WAIT_READ)
|
||||
{
|
||||
int timeout = (int)arg1;
|
||||
return BIO_wait_read(tlsOut->bio, timeout);
|
||||
int timeout = (int) arg1;
|
||||
BIO* bio = tlsOut->bio;
|
||||
|
||||
if (BIO_read_blocked(bio))
|
||||
return BIO_wait_read(bio, timeout);
|
||||
else if (BIO_write_blocked(bio))
|
||||
return BIO_wait_write(bio, timeout);
|
||||
else
|
||||
status = 1;
|
||||
}
|
||||
else if (cmd == BIO_C_WAIT_WRITE)
|
||||
{
|
||||
status = 0;
|
||||
int timeout = (int) arg1;
|
||||
BIO* bio = tlsIn->bio;
|
||||
|
||||
if (BIO_write_blocked(bio))
|
||||
status = BIO_wait_write(bio, timeout);
|
||||
else if (BIO_read_blocked(bio))
|
||||
status = BIO_wait_read(bio, timeout);
|
||||
else
|
||||
status = 1;
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -1538,6 +1609,8 @@ rdpRdg* rdg_new(rdpTransport* transport)
|
||||
|
||||
if (!rdg->readEvent)
|
||||
goto rdg_alloc_error;
|
||||
|
||||
InitializeCriticalSection(&rdg->writeSection);
|
||||
}
|
||||
|
||||
return rdg;
|
||||
@ -1581,6 +1654,8 @@ void rdg_free(rdpRdg* rdg)
|
||||
CloseHandle(rdg->readEvent);
|
||||
rdg->readEvent = NULL;
|
||||
}
|
||||
|
||||
DeleteCriticalSection(&rdg->writeSection);
|
||||
|
||||
free(rdg);
|
||||
}
|
||||
|
@ -132,12 +132,12 @@ struct rdp_rdg
|
||||
rdpNtlm* ntlm;
|
||||
HttpContext* http;
|
||||
HANDLE readEvent;
|
||||
CRITICAL_SECTION writeSection;
|
||||
|
||||
UUID guid;
|
||||
|
||||
int state;
|
||||
UINT16 packetRemainingCount;
|
||||
int nonBlocking;
|
||||
int timeout;
|
||||
};
|
||||
|
||||
|
@ -48,6 +48,7 @@
|
||||
struct _BIO_RDP_TLS
|
||||
{
|
||||
SSL* ssl;
|
||||
CRITICAL_SECTION lock;
|
||||
};
|
||||
typedef struct _BIO_RDP_TLS BIO_RDP_TLS;
|
||||
|
||||
@ -58,6 +59,7 @@ long bio_rdp_tls_callback(BIO* bio, int mode, const char* argp, int argi, long a
|
||||
|
||||
static int bio_rdp_tls_write(BIO* bio, const char* buf, int size)
|
||||
{
|
||||
int error;
|
||||
int status;
|
||||
BIO_RDP_TLS* tls = (BIO_RDP_TLS*) bio->ptr;
|
||||
|
||||
@ -65,12 +67,17 @@ static int bio_rdp_tls_write(BIO* bio, const char* buf, int size)
|
||||
return 0;
|
||||
|
||||
BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL);
|
||||
|
||||
EnterCriticalSection(&tls->lock);
|
||||
|
||||
status = SSL_write(tls->ssl, buf, size);
|
||||
error = SSL_get_error(tls->ssl, status);
|
||||
|
||||
LeaveCriticalSection(&tls->lock);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
switch (SSL_get_error(tls->ssl, status))
|
||||
switch (error)
|
||||
{
|
||||
case SSL_ERROR_NONE:
|
||||
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
@ -109,6 +116,7 @@ static int bio_rdp_tls_write(BIO* bio, const char* buf, int size)
|
||||
|
||||
static int bio_rdp_tls_read(BIO* bio, char* buf, int size)
|
||||
{
|
||||
int error;
|
||||
int status;
|
||||
BIO_RDP_TLS* tls = (BIO_RDP_TLS*) bio->ptr;
|
||||
|
||||
@ -117,11 +125,16 @@ static int bio_rdp_tls_read(BIO* bio, char* buf, int size)
|
||||
|
||||
BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL);
|
||||
|
||||
EnterCriticalSection(&tls->lock);
|
||||
|
||||
status = SSL_read(tls->ssl, buf, size);
|
||||
error = SSL_get_error(tls->ssl, status);
|
||||
|
||||
LeaveCriticalSection(&tls->lock);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
switch (SSL_get_error(tls->ssl, status))
|
||||
switch (error)
|
||||
{
|
||||
case SSL_ERROR_NONE:
|
||||
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
@ -381,6 +394,8 @@ static int bio_rdp_tls_new(BIO* bio)
|
||||
return 0;
|
||||
|
||||
bio->ptr = (void*) tls;
|
||||
|
||||
InitializeCriticalSectionAndSpinCount(&tls->lock, 4000);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -409,6 +424,8 @@ static int bio_rdp_tls_free(BIO* bio)
|
||||
bio->flags = 0;
|
||||
}
|
||||
|
||||
DeleteCriticalSection(&tls->lock);
|
||||
|
||||
free(tls);
|
||||
|
||||
return 1;
|
||||
|
Loading…
Reference in New Issue
Block a user