diff --git a/libfreerdp/core/gateway/rdg.c b/libfreerdp/core/gateway/rdg.c index f5cf3cf45..cee1e0995 100644 --- a/libfreerdp/core/gateway/rdg.c +++ b/libfreerdp/core/gateway/rdg.c @@ -162,7 +162,6 @@ BOOL rdg_send_handshake(rdpRdg* rdg) rdg->state = RDG_CLIENT_STATE_HANDSHAKE; } - WLog_WARN(TAG, "Handshake sent"); return status; } @@ -194,8 +193,6 @@ BOOL rdg_send_tunnel_request(rdpRdg* rdg) rdg->state = RDG_CLIENT_STATE_TUNNEL_CREATE; } - WLog_WARN(TAG, "Tunnel sent"); - return status; } @@ -236,8 +233,6 @@ BOOL rdg_send_tunnel_authorization(rdpRdg* rdg) rdg->state = RDG_CLIENT_STATE_TUNNEL_AUTHORIZE; } - WLog_WARN(TAG, "Tunnel authorization sent"); - return status; } @@ -260,9 +255,9 @@ BOOL rdg_send_channel_create(rdpRdg* rdg) Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */ Stream_Write_UINT8(s, 1); /* Number of resources. (1 byte) */ - Stream_Write_UINT8(s, 0); /* Number of alternative resources. (1 byte) */ - Stream_Write_UINT16(s, 3389); /* Port, this seems to be the standard... ? (2 bytes) */ - Stream_Write_UINT16(s, 3); /* Protocol number, set according to an example... ? (2 bytes) */ + Stream_Write_UINT8(s, 0); /* Number of alternative resources (1 byte) */ + Stream_Write_UINT16(s, rdg->settings->ServerPort); /* Resource port (2 bytes) */ + Stream_Write_UINT16(s, 3); /* Protocol number (2 bytes) */ Stream_Write_UINT16(s, serverNameLen * 2); for (i = 0; i < serverNameLen; i++) @@ -281,8 +276,6 @@ BOOL rdg_send_channel_create(rdpRdg* rdg) rdg->state = RDG_CLIENT_STATE_CHANNEL_CREATE; } - WLog_WARN(TAG, "Channel create sent"); - return status; } @@ -293,7 +286,7 @@ wStream* rdg_build_http_request(rdpRdg* rdg, char* method) SecBuffer* ntlmToken = NULL; char* base64NtlmToken = NULL; - assert(rdg != NULL && method != NULL); + assert(method != NULL); request = http_request_new(); @@ -346,6 +339,15 @@ BOOL rdg_process_out_channel_response(rdpRdg* rdg, HttpResponse* response) BYTE* ntlmTokenData = NULL; rdpNtlm* ntlm = rdg->ntlm; + if (response->StatusCode != HTTP_STATUS_DENIED) + { + WLog_INFO(TAG, "RDG not supported"); + rdg->state = RDG_CLIENT_STATE_NOT_FOUND; + return FALSE; + } + + WLog_INFO(TAG, "Out Channel authorization required"); + if (ListDictionary_Contains(response->Authenticates, "NTLM")) { token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM"); @@ -396,6 +398,7 @@ BOOL rdg_process_out_channel_authorization(rdpRdg* rdg, HttpResponse* response) return FALSE; } + WLog_INFO(TAG, "Out Channel authorization complete"); rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZED; return TRUE; @@ -410,6 +413,8 @@ BOOL rdg_process_in_channel_response(rdpRdg* rdg, HttpResponse* response) BYTE* ntlmTokenData = NULL; rdpNtlm* ntlm = rdg->ntlm; + WLog_INFO(TAG, "In Channel authorization required"); + if (ListDictionary_Contains(response->Authenticates, "NTLM")) { token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM"); @@ -465,6 +470,7 @@ BOOL rdg_process_in_channel_authorization(rdpRdg* rdg, HttpResponse* response) return FALSE; } + WLog_INFO(TAG, "In Channel authorization complete"); rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZED; s = rdg_build_http_request(rdg, "RDG_IN_DATA"); @@ -482,7 +488,7 @@ BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s) { HRESULT errorCode; - WLog_WARN(TAG, "Handshake response received"); + WLog_INFO(TAG, "Handshake response recieved"); if (rdg->state != RDG_CLIENT_STATE_HANDSHAKE) { @@ -494,6 +500,7 @@ BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s) if (FAILED(errorCode)) { + WLog_INFO(TAG, "Handshake error %x", errorCode); return FALSE; } @@ -504,7 +511,7 @@ BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s) { HRESULT errorCode; - WLog_WARN(TAG, "Tunnel response received"); + WLog_INFO(TAG, "Tunnel response received"); if (rdg->state != RDG_CLIENT_STATE_TUNNEL_CREATE) { @@ -516,6 +523,7 @@ BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s) if (FAILED(errorCode)) { + WLog_INFO(TAG, "Tunnel creation error %x", errorCode); return FALSE; } @@ -526,7 +534,7 @@ BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s) { HRESULT errorCode; - WLog_WARN(TAG, "Tunnel authorization response received"); + WLog_INFO(TAG, "Tunnel authorization received"); if (rdg->state != RDG_CLIENT_STATE_TUNNEL_AUTHORIZE) { @@ -538,6 +546,7 @@ BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s) if (FAILED(errorCode)) { + WLog_INFO(TAG, "Tunnel authorization error %x", errorCode); return FALSE; } @@ -548,7 +557,7 @@ BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s) { HRESULT errorCode; - WLog_WARN(TAG, "Channel create response received"); + WLog_INFO(TAG, "Channel response received"); if (rdg->state != RDG_CLIENT_STATE_CHANNEL_CREATE) { @@ -560,6 +569,7 @@ BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s) if (FAILED(errorCode)) { + WLog_INFO(TAG, "Channel error %x", errorCode); return FALSE; } @@ -597,7 +607,7 @@ BOOL rdg_process_packet(rdpRdg* rdg, wStream* s) case PKT_TYPE_DATA: assert(FALSE); - break; + return FALSE; } return status; @@ -679,6 +689,8 @@ UINT32 rdg_get_event_handles(rdpRdg* rdg, HANDLE* events) { UINT32 nCount = 0; + assert(rdg != NULL); + if (events) events[nCount] = rdg->readEvent; nCount++; @@ -704,6 +716,8 @@ BOOL rdg_check_event_handles(rdpRdg* rdg) { HANDLE event = NULL; + assert(rdg != NULL); + BIO_get_event(rdg->tlsOut->bio, &event); if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0) @@ -767,8 +781,6 @@ BOOL rdg_send_out_channel_request(rdpRdg*rdg) wStream* s = NULL; int status; - assert(rdg != NULL); - rdg->ntlm = ntlm_new(); if (!rdg->ntlm) @@ -806,8 +818,6 @@ BOOL rdg_send_in_channel_request(rdpRdg*rdg) int status; wStream* s = NULL; - assert(rdg != NULL); - rdg->ntlm = ntlm_new(); if (!rdg->ntlm) @@ -848,7 +858,7 @@ BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int tim BIO* bufferedBio = NULL; rdpSettings* settings = rdg->settings; - assert(rdg != NULL && hostname != NULL); + assert(hostname != NULL); sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout); @@ -875,11 +885,12 @@ BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int tim } bufferedBio = BIO_push(bufferedBio, socketBio); - rdg->bioOut = bufferedBio; + bufferedBio = bufferedBio; status = BIO_set_nonblock(bufferedBio, TRUE); if (!status) { + BIO_free_all(bufferedBio); return FALSE; } @@ -904,7 +915,7 @@ BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int time BIO* bufferedBio = NULL; rdpSettings* settings = rdg->settings; - assert(rdg != NULL && hostname != NULL); + assert(hostname != NULL); sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout); @@ -929,11 +940,12 @@ BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int time } bufferedBio = BIO_push(bufferedBio, socketBio); - rdg->bioIn = bufferedBio; + bufferedBio = bufferedBio; status = BIO_set_nonblock(bufferedBio, TRUE); if (!status) { + BIO_free_all(bufferedBio); return FALSE; } @@ -956,7 +968,7 @@ BOOL rdg_out_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int UINT32 nCount; HANDLE events[8]; - assert(rdg != NULL && hostname != NULL); + assert(hostname != NULL); status = rdg_tls_out_connect(rdg, hostname, port, timeout); @@ -991,7 +1003,7 @@ BOOL rdg_in_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int UINT32 nCount; HANDLE events[8]; - assert(rdg != NULL && hostname != NULL); + assert(hostname != NULL); status = rdg_tls_in_connect(rdg, hostname, port, timeout); @@ -1049,6 +1061,8 @@ BOOL rdg_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout) { BOOL status; + assert(rdg != NULL); + status = rdg_out_channel_connect(rdg, hostname, port, timeout); if (!status) @@ -1067,7 +1081,6 @@ BOOL rdg_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout) return TRUE; } - int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size) { int status; @@ -1106,6 +1119,76 @@ int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size) return size; } +BOOL rdg_process_close_packet(rdpRdg* rdg) +{ + BYTE buffer[sizeof(RdgPacketHeader) + 4]; + RdgPacketHeader* header = (RdgPacketHeader*)buffer; + + memset(buffer, 0, sizeof(buffer)); + header->type = PKT_TYPE_CLOSE_CHANNEL_RESPONSE; + header->packetLength = sizeof(buffer); + + WLog_INFO(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_unknown_packet(rdpRdg* rdg, int type) +{ + WLog_WARN(TAG, "Unknown Control Packet received: %X", type); + + return TRUE; +} + +BOOL rdg_process_control_packet(rdpRdg* rdg, int type, int packetLength) +{ + wStream* s; + int readCount = 0; + int status; + int payloadSize = packetLength - sizeof(RdgPacketHeader); + + if (payloadSize) + { + s = Stream_New(NULL, payloadSize); + if (!s) + { + return FALSE; + } + + while (readCount < payloadSize) + { + status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), sizeof(RdgPacketHeader) - readCount); + + if (status <= 0) + { + if (!BIO_should_retry(rdg->tlsOut->bio)) + { + Stream_Free(s, TRUE); + return FALSE; + } + continue; + } + + Stream_Seek(s, status); + readCount += status; + } + } + + switch (type) + { + case PKT_TYPE_CLOSE_CHANNEL: + return rdg_process_close_packet(rdg); + break; + default: + rdg_process_unknown_packet(rdg, type); + break; + } + + Stream_Free(s, TRUE); + + return TRUE; +} + int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) { RdgPacketHeader header; @@ -1138,7 +1221,11 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) if (header.type != PKT_TYPE_DATA) { - /* Add better handling here !!! */ + status = rdg_process_control_packet(rdg, header.type, header.packetLength); + if (!status) + { + return -1; + } return 0; } @@ -1161,10 +1248,9 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) } } - readCount = 0; readSize = (rdg->packetRemainingCount < size ? rdg->packetRemainingCount : size); - status = BIO_read(rdg->tlsOut->bio, buffer + readCount, readSize - readCount); + status = BIO_read(rdg->tlsOut->bio, buffer, readSize); if (status < 0) { @@ -1174,9 +1260,7 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) } } - readCount += status; - - rdg->packetRemainingCount -= readCount; + rdg->packetRemainingCount -= status; pending = BIO_pending(rdg->tlsOut->bio); @@ -1185,7 +1269,7 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) else ResetEvent(rdg->readEvent); - return readSize; + return status; } long rdg_bio_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret) @@ -1275,51 +1359,31 @@ static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2) { if (arg2) { - //*((ULONG_PTR*)arg2) = (ULONG_PTR)tsg->rpc->client->PipeEvent; - //status = 1; BIO_get_event(rdg->tlsOut->bio, arg2); status = 1; } } else if (cmd == BIO_C_SET_NONBLOCK) { - //return BIO_ctrl(tlsOut->bio, cmd, arg1, arg2); - rdg->nonBlocking = arg1; status = 1; } else if (cmd == BIO_C_READ_BLOCKED) { - //status = BIO_read_blocked(tlsOut->bio); - //status = 0; + status = 0; } else if (cmd == BIO_C_WRITE_BLOCKED) { - //status = BIO_write_blocked(tlsIn->bio); - //status = 0; + status = 0; } else if (cmd == BIO_C_WAIT_READ) { int timeout = (int)arg1; return BIO_wait_read(tlsOut->bio, timeout); - - //if (BIO_read_blocked(tlsOut->bio)) - // return BIO_wait_read(tlsOut->bio, timeout); - //else if (BIO_write_blocked(tlsIn->bio)) - // return BIO_wait_write(tlsIn->bio, timeout); - //else - // status = 0; } else if (cmd == BIO_C_WAIT_WRITE) { - //int timeout = (int)arg1; - - //if (BIO_write_blocked(tlsIn->bio)) - // status = BIO_wait_write(tlsIn->bio, timeout); - //else if (BIO_read_blocked(tlsOut->bio)) - // status = BIO_wait_read(tlsOut->bio, timeout); - //else - // status = 0; + status = 0; } return status; diff --git a/libfreerdp/core/gateway/rdg.h b/libfreerdp/core/gateway/rdg.h index 3c5a9bf5f..05f9127e3 100644 --- a/libfreerdp/core/gateway/rdg.h +++ b/libfreerdp/core/gateway/rdg.h @@ -117,6 +117,7 @@ enum RDG_CLIENT_STATE_OPENED, RDG_CLIENT_STATE_CLOSE, RDG_CLIENT_STATE_CLOSED, + RDG_CLIENT_STATE_NOT_FOUND, }; @@ -127,8 +128,6 @@ struct rdp_rdg { rdpContext* context; rdpSettings* settings; - BIO* bioIn; - BIO* bioOut; BIO* frontBio; rdpTls* tlsIn; rdpTls* tlsOut; @@ -138,14 +137,8 @@ struct rdp_rdg UUID guid; - //UINT32 tunnelId; - //UINT32 negotiatedCapsFlags; - //UUID nonce; - //LPWSTR serverCert; - //LPWSTR consentMsg; - int state; - int packetRemainingCount; + UINT16 packetRemainingCount; int nonBlocking; int timeout; }; diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 1b9b63db2..5ee7e514e 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -214,26 +214,34 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por return FALSE; } status = rdg_connect(transport->rdg, hostname, port, timeout); - if (!status) + if (status) { - return FALSE; + transport->frontBio = transport->rdg->frontBio; + BIO_set_nonblock(transport->frontBio, 0); + transport->layer = TRANSPORT_LAYER_TSG; + + status = TRUE; } - transport->frontBio = transport->rdg->frontBio; - BIO_set_nonblock(transport->frontBio, 0); - transport->layer = TRANSPORT_LAYER_TSG; + else + { + if (transport->rdg->state != RDG_CLIENT_STATE_NOT_FOUND) + { + return FALSE; + } - //transport->tsg = tsg_new(transport); + transport->tsg = tsg_new(transport); - //if (!transport->tsg) - // return FALSE; + if (!transport->tsg) + return FALSE; - //if (!tsg_connect(transport->tsg, hostname, port, timeout)) - // return FALSE; + if (!tsg_connect(transport->tsg, hostname, port, timeout)) + return FALSE; - //transport->frontBio = transport->tsg->bio; - //transport->layer = TRANSPORT_LAYER_TSG; + transport->frontBio = transport->tsg->bio; + transport->layer = TRANSPORT_LAYER_TSG; - status = TRUE; + status = TRUE; + } } else {