diff options
Diffstat (limited to 'libfreerdp/core/gateway/rdg.c')
-rw-r--r-- | libfreerdp/core/gateway/rdg.c | 77 |
1 files changed, 44 insertions, 33 deletions
diff --git a/libfreerdp/core/gateway/rdg.c b/libfreerdp/core/gateway/rdg.c index f9ed72501..72019ede8 100644 --- a/libfreerdp/core/gateway/rdg.c +++ b/libfreerdp/core/gateway/rdg.c @@ -139,6 +139,7 @@ typedef struct WEBSOCKET_STATE state; wStream* responseStreamBuffer; } rdg_http_websocket_context; + typedef enum _CHUNK_STATE { ChunkStateLenghHeader, @@ -358,12 +359,15 @@ static BOOL rdg_write_chunked(BIO* bio, wStream* sPacket) len = Stream_Length(sChunk); if (len > INT_MAX) + { + Stream_Free(sChunk, TRUE); return FALSE; + } status = BIO_write(bio, Stream_Buffer(sChunk), (int)len); Stream_Free(sChunk, TRUE); - if (status != len) + if (status != (SSIZE_T)len) return FALSE; return TRUE; @@ -437,7 +441,7 @@ static BOOL rdg_write_websocket(BIO* bio, wStream* sPacket, WEBSOCKET_OPCODE opc status = BIO_write(bio, Stream_Buffer(sWS), Stream_Length(sWS)); Stream_Free(sWS, TRUE); - if (status != fullLen) + if (status != (SSIZE_T)fullLen) return FALSE; return TRUE; @@ -559,11 +563,13 @@ static BOOL rdg_websocket_reply_close(BIO* bio, wStream* s) { uint16_t data; Stream_Read_UINT16(s, data); - Stream_Write_UINT16(s, data ^ maskingKey1); + Stream_Write_UINT16(closeFrame, data ^ maskingKey1); } Stream_SealLength(closeFrame); status = BIO_write(bio, Stream_Buffer(closeFrame), Stream_Length(closeFrame)); + Stream_Free(closeFrame, TRUE); + /* server MUST close socket now. The server is not allowed anymore to * send frames but if he does, nothing bad would happen */ if (status < 0) @@ -742,7 +748,6 @@ static int rdg_websocket_read(BIO* bio, BYTE* pBuffer, size_t size, TAG, "Websocket Server sends data with masking key. This is against RFC 6455."); return -1; } - break; case WebSocketStatePayload: { status = rdg_websocket_handle_payload(bio, pBuffer, size, encodingContext); @@ -761,6 +766,7 @@ static int rdg_websocket_read(BIO* bio, BYTE* pBuffer, size_t size, /* should be unreachable */ return -1; } + static int rdg_chuncked_read(BIO* bio, BYTE* pBuffer, size_t size, rdg_http_encoding_chunked_context* encodingContext) { @@ -832,9 +838,7 @@ static int rdg_chuncked_read(BIO* bio, BYTE* pBuffer, size_t size, else return (effectiveDataLen > 0 ? effectiveDataLen : status); } - *dst = '\0'; - /* strtoul is tricky, error are reported via errno, we also need * to ensure the result does not overflow */ errno = 0; @@ -868,10 +872,12 @@ static int rdg_socket_read(BIO* bio, BYTE* pBuffer, size_t size, rdg_http_encoding_context* encodingContext) { assert(encodingContext != NULL); + if (encodingContext->isWebsocketTransport) { return rdg_websocket_read(bio, pBuffer, size, &encodingContext->context.websocket); } + switch (encodingContext->httpTransferEncoding) { case TransferEncodingIdentity: @@ -881,7 +887,6 @@ static int rdg_socket_read(BIO* bio, BYTE* pBuffer, size_t size, default: return -1; } - return -1; /* should not be reached */ } static BOOL rdg_read_all(rdpTls* tls, BYTE* buffer, size_t size, @@ -893,7 +898,6 @@ static BOOL rdg_read_all(rdpTls* tls, BYTE* buffer, size_t size, while (readCount < size) { int status = rdg_socket_read(tls->bio, pBuffer, size - readCount, transferEncoding); - if (status <= 0) { if (!BIO_should_retry(tls->bio)) @@ -1169,7 +1173,7 @@ static wStream* rdg_build_http_request(rdpRdg* rdg, const char* method, goto out; } - http_request_set_transfer_encoding(request, transferEncoding); + http_request_set_transfer_encoding(request, transferEncoding); s = http_request_write(rdg->http, request); out: @@ -1186,7 +1190,7 @@ static BOOL rdg_handle_ntlm_challenge(rdpNtlm* ntlm, HttpResponse* response) BOOL continueNeeded = FALSE; size_t len; const char* token64 = NULL; - int ntlmTokenLength = 0; + size_t ntlmTokenLength = 0; BYTE* ntlmTokenData = NULL; long StatusCode; @@ -1852,7 +1856,6 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char* rdg->transferEncoding.context.websocket.responseStreamBuffer = NULL; return TRUE; - break; default: return FALSE; } @@ -1899,6 +1902,9 @@ static BOOL rdg_tunnel_connect(rdpRdg* rdg) if (!status) { + assert(rdg); + assert(rdg->context); + assert(rdg->context->rdp); rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED; return FALSE; } @@ -1937,6 +1943,9 @@ BOOL rdg_connect(rdpRdg* rdg, DWORD timeout, BOOL* rpcFallback) if (!status) { + assert(rdg); + assert(rdg->context); + assert(rdg->context->rdp); rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED; return FALSE; } @@ -2013,7 +2022,7 @@ static int rdg_write_websocket_data_packet(rdpRdg* rdg, const BYTE* buf, int isi /* mask as much as possible with 32bit access */ for (streamPos = 0; streamPos + 4 <= isize; streamPos += 4) { - uint32_t masked = *((uint32_t*)((BYTE*)buf + streamPos)) ^ maskingKey; + uint32_t masked = *((const uint32_t*)((const BYTE*)buf + streamPos)) ^ maskingKey; Stream_Write_UINT32(sWS, masked); } @@ -2021,7 +2030,7 @@ static int rdg_write_websocket_data_packet(rdpRdg* rdg, const BYTE* buf, int isi for (; streamPos < isize; streamPos++) { BYTE* partialMask = (BYTE*)(&maskingKey) + streamPos % 4; - BYTE masked = *((BYTE*)((BYTE*)buf + streamPos)) ^ *partialMask; + BYTE masked = *((const BYTE*)((const BYTE*)buf + streamPos)) ^ *partialMask; Stream_Write_UINT8(sWS, masked); } @@ -2068,7 +2077,10 @@ static int rdg_write_chunked_data_packet(rdpRdg* rdg, const BYTE* buf, int isize len = Stream_Length(sChunk); if (len > INT_MAX) + { + Stream_Free(sChunk, TRUE); return -1; + } status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), (int)len); Stream_Free(sChunk, TRUE); @@ -2089,8 +2101,6 @@ static int rdg_write_data_packet(rdpRdg* rdg, const BYTE* buf, int isize) } else return rdg_write_chunked_data_packet(rdg, buf, isize); - - return -1; } static BOOL rdg_process_close_packet(rdpRdg* rdg, wStream* s) @@ -2402,10 +2412,10 @@ static int rdg_bio_gets(BIO* bio, char* str, int size) return -2; } -static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2) +static long rdg_bio_ctrl(BIO* in_bio, int cmd, long arg1, void* arg2) { long status = -1; - rdpRdg* rdg = (rdpRdg*)BIO_get_data(bio); + rdpRdg* rdg = (rdpRdg*)BIO_get_data(in_bio); rdpTls* tlsOut = rdg->tlsOut; rdpTls* tlsIn = rdg->tlsIn; @@ -2422,42 +2432,42 @@ static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2) } else if (cmd == BIO_C_READ_BLOCKED) { - BIO* bio = tlsOut->bio; - status = BIO_read_blocked(bio); + BIO* cbio = tlsOut->bio; + status = BIO_read_blocked(cbio); } else if (cmd == BIO_C_WRITE_BLOCKED) { - BIO* bio = tlsIn->bio; + BIO* cbio = tlsIn->bio; if (rdg->transferEncoding.isWebsocketTransport) - bio = tlsOut->bio; + cbio = tlsOut->bio; - status = BIO_write_blocked(bio); + status = BIO_write_blocked(cbio); } else if (cmd == BIO_C_WAIT_READ) { int timeout = (int)arg1; - BIO* bio = tlsOut->bio; + BIO* cbio = 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); + if (BIO_read_blocked(cbio)) + return BIO_wait_read(cbio, timeout); + else if (BIO_write_blocked(cbio)) + return BIO_wait_write(cbio, timeout); else status = 1; } else if (cmd == BIO_C_WAIT_WRITE) { int timeout = (int)arg1; - BIO* bio = tlsIn->bio; + BIO* cbio = tlsIn->bio; if (rdg->transferEncoding.isWebsocketTransport) - bio = tlsOut->bio; + cbio = tlsOut->bio; - if (BIO_write_blocked(bio)) - status = BIO_wait_write(bio, timeout); - else if (BIO_read_blocked(bio)) - status = BIO_wait_read(bio, timeout); + if (BIO_write_blocked(cbio)) + status = BIO_wait_write(cbio, timeout); + else if (BIO_read_blocked(cbio)) + status = BIO_wait_read(cbio, timeout); else status = 1; } @@ -2619,6 +2629,7 @@ void rdg_free(rdpRdg* rdg) BIO_free_all(rdg->frontBio); DeleteCriticalSection(&rdg->writeSection); + if (rdg->transferEncoding.isWebsocketTransport) { if (rdg->transferEncoding.context.websocket.responseStreamBuffer != NULL) |