libfreerdp-core: added fallback to RPC.

This commit is contained in:
Denis Vincent 2015-03-18 16:13:32 -04:00
parent 3c4bee3d95
commit 205ccb70c8
3 changed files with 144 additions and 79 deletions

View File

@ -162,7 +162,6 @@ BOOL rdg_send_handshake(rdpRdg* rdg)
rdg->state = RDG_CLIENT_STATE_HANDSHAKE; rdg->state = RDG_CLIENT_STATE_HANDSHAKE;
} }
WLog_WARN(TAG, "Handshake sent");
return status; return status;
} }
@ -194,8 +193,6 @@ BOOL rdg_send_tunnel_request(rdpRdg* rdg)
rdg->state = RDG_CLIENT_STATE_TUNNEL_CREATE; rdg->state = RDG_CLIENT_STATE_TUNNEL_CREATE;
} }
WLog_WARN(TAG, "Tunnel sent");
return status; return status;
} }
@ -236,8 +233,6 @@ BOOL rdg_send_tunnel_authorization(rdpRdg* rdg)
rdg->state = RDG_CLIENT_STATE_TUNNEL_AUTHORIZE; rdg->state = RDG_CLIENT_STATE_TUNNEL_AUTHORIZE;
} }
WLog_WARN(TAG, "Tunnel authorization sent");
return status; return status;
} }
@ -260,9 +255,9 @@ BOOL rdg_send_channel_create(rdpRdg* rdg)
Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */ Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */
Stream_Write_UINT8(s, 1); /* Number of resources. (1 byte) */ Stream_Write_UINT8(s, 1); /* Number of resources. (1 byte) */
Stream_Write_UINT8(s, 0); /* Number of alternative 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, rdg->settings->ServerPort); /* Resource port (2 bytes) */
Stream_Write_UINT16(s, 3); /* Protocol number, set according to an example... ? (2 bytes) */ Stream_Write_UINT16(s, 3); /* Protocol number (2 bytes) */
Stream_Write_UINT16(s, serverNameLen * 2); Stream_Write_UINT16(s, serverNameLen * 2);
for (i = 0; i < serverNameLen; i++) for (i = 0; i < serverNameLen; i++)
@ -281,8 +276,6 @@ BOOL rdg_send_channel_create(rdpRdg* rdg)
rdg->state = RDG_CLIENT_STATE_CHANNEL_CREATE; rdg->state = RDG_CLIENT_STATE_CHANNEL_CREATE;
} }
WLog_WARN(TAG, "Channel create sent");
return status; return status;
} }
@ -293,7 +286,7 @@ wStream* rdg_build_http_request(rdpRdg* rdg, char* method)
SecBuffer* ntlmToken = NULL; SecBuffer* ntlmToken = NULL;
char* base64NtlmToken = NULL; char* base64NtlmToken = NULL;
assert(rdg != NULL && method != NULL); assert(method != NULL);
request = http_request_new(); request = http_request_new();
@ -346,6 +339,15 @@ BOOL rdg_process_out_channel_response(rdpRdg* rdg, HttpResponse* response)
BYTE* ntlmTokenData = NULL; BYTE* ntlmTokenData = NULL;
rdpNtlm* ntlm = rdg->ntlm; 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")) if (ListDictionary_Contains(response->Authenticates, "NTLM"))
{ {
token64 = ListDictionary_GetItemValue(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; return FALSE;
} }
WLog_INFO(TAG, "Out Channel authorization complete");
rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZED; rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZED;
return TRUE; return TRUE;
@ -410,6 +413,8 @@ BOOL rdg_process_in_channel_response(rdpRdg* rdg, HttpResponse* response)
BYTE* ntlmTokenData = NULL; BYTE* ntlmTokenData = NULL;
rdpNtlm* ntlm = rdg->ntlm; rdpNtlm* ntlm = rdg->ntlm;
WLog_INFO(TAG, "In Channel authorization required");
if (ListDictionary_Contains(response->Authenticates, "NTLM")) if (ListDictionary_Contains(response->Authenticates, "NTLM"))
{ {
token64 = ListDictionary_GetItemValue(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; return FALSE;
} }
WLog_INFO(TAG, "In Channel authorization complete");
rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZED; rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZED;
s = rdg_build_http_request(rdg, "RDG_IN_DATA"); s = rdg_build_http_request(rdg, "RDG_IN_DATA");
@ -482,7 +488,7 @@ BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
{ {
HRESULT errorCode; HRESULT errorCode;
WLog_WARN(TAG, "Handshake response received"); WLog_INFO(TAG, "Handshake response recieved");
if (rdg->state != RDG_CLIENT_STATE_HANDSHAKE) if (rdg->state != RDG_CLIENT_STATE_HANDSHAKE)
{ {
@ -494,6 +500,7 @@ BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
if (FAILED(errorCode)) if (FAILED(errorCode))
{ {
WLog_INFO(TAG, "Handshake error %x", errorCode);
return FALSE; return FALSE;
} }
@ -504,7 +511,7 @@ BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
{ {
HRESULT errorCode; HRESULT errorCode;
WLog_WARN(TAG, "Tunnel response received"); WLog_INFO(TAG, "Tunnel response received");
if (rdg->state != RDG_CLIENT_STATE_TUNNEL_CREATE) if (rdg->state != RDG_CLIENT_STATE_TUNNEL_CREATE)
{ {
@ -516,6 +523,7 @@ BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
if (FAILED(errorCode)) if (FAILED(errorCode))
{ {
WLog_INFO(TAG, "Tunnel creation error %x", errorCode);
return FALSE; return FALSE;
} }
@ -526,7 +534,7 @@ BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s)
{ {
HRESULT errorCode; HRESULT errorCode;
WLog_WARN(TAG, "Tunnel authorization response received"); WLog_INFO(TAG, "Tunnel authorization received");
if (rdg->state != RDG_CLIENT_STATE_TUNNEL_AUTHORIZE) 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)) if (FAILED(errorCode))
{ {
WLog_INFO(TAG, "Tunnel authorization error %x", errorCode);
return FALSE; return FALSE;
} }
@ -548,7 +557,7 @@ BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s)
{ {
HRESULT errorCode; HRESULT errorCode;
WLog_WARN(TAG, "Channel create response received"); WLog_INFO(TAG, "Channel response received");
if (rdg->state != RDG_CLIENT_STATE_CHANNEL_CREATE) if (rdg->state != RDG_CLIENT_STATE_CHANNEL_CREATE)
{ {
@ -560,6 +569,7 @@ BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s)
if (FAILED(errorCode)) if (FAILED(errorCode))
{ {
WLog_INFO(TAG, "Channel error %x", errorCode);
return FALSE; return FALSE;
} }
@ -597,7 +607,7 @@ BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
case PKT_TYPE_DATA: case PKT_TYPE_DATA:
assert(FALSE); assert(FALSE);
break; return FALSE;
} }
return status; return status;
@ -679,6 +689,8 @@ UINT32 rdg_get_event_handles(rdpRdg* rdg, HANDLE* events)
{ {
UINT32 nCount = 0; UINT32 nCount = 0;
assert(rdg != NULL);
if (events) if (events)
events[nCount] = rdg->readEvent; events[nCount] = rdg->readEvent;
nCount++; nCount++;
@ -704,6 +716,8 @@ BOOL rdg_check_event_handles(rdpRdg* rdg)
{ {
HANDLE event = NULL; HANDLE event = NULL;
assert(rdg != NULL);
BIO_get_event(rdg->tlsOut->bio, &event); BIO_get_event(rdg->tlsOut->bio, &event);
if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0) if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0)
@ -767,8 +781,6 @@ BOOL rdg_send_out_channel_request(rdpRdg*rdg)
wStream* s = NULL; wStream* s = NULL;
int status; int status;
assert(rdg != NULL);
rdg->ntlm = ntlm_new(); rdg->ntlm = ntlm_new();
if (!rdg->ntlm) if (!rdg->ntlm)
@ -806,8 +818,6 @@ BOOL rdg_send_in_channel_request(rdpRdg*rdg)
int status; int status;
wStream* s = NULL; wStream* s = NULL;
assert(rdg != NULL);
rdg->ntlm = ntlm_new(); rdg->ntlm = ntlm_new();
if (!rdg->ntlm) if (!rdg->ntlm)
@ -848,7 +858,7 @@ BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int tim
BIO* bufferedBio = NULL; BIO* bufferedBio = NULL;
rdpSettings* settings = rdg->settings; rdpSettings* settings = rdg->settings;
assert(rdg != NULL && hostname != NULL); assert(hostname != NULL);
sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout); 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); bufferedBio = BIO_push(bufferedBio, socketBio);
rdg->bioOut = bufferedBio; bufferedBio = bufferedBio;
status = BIO_set_nonblock(bufferedBio, TRUE); status = BIO_set_nonblock(bufferedBio, TRUE);
if (!status) if (!status)
{ {
BIO_free_all(bufferedBio);
return FALSE; return FALSE;
} }
@ -904,7 +915,7 @@ BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int time
BIO* bufferedBio = NULL; BIO* bufferedBio = NULL;
rdpSettings* settings = rdg->settings; rdpSettings* settings = rdg->settings;
assert(rdg != NULL && hostname != NULL); assert(hostname != NULL);
sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout); 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); bufferedBio = BIO_push(bufferedBio, socketBio);
rdg->bioIn = bufferedBio; bufferedBio = bufferedBio;
status = BIO_set_nonblock(bufferedBio, TRUE); status = BIO_set_nonblock(bufferedBio, TRUE);
if (!status) if (!status)
{ {
BIO_free_all(bufferedBio);
return FALSE; return FALSE;
} }
@ -956,7 +968,7 @@ BOOL rdg_out_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int
UINT32 nCount; UINT32 nCount;
HANDLE events[8]; HANDLE events[8];
assert(rdg != NULL && hostname != NULL); assert(hostname != NULL);
status = rdg_tls_out_connect(rdg, hostname, port, timeout); 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; UINT32 nCount;
HANDLE events[8]; HANDLE events[8];
assert(rdg != NULL && hostname != NULL); assert(hostname != NULL);
status = rdg_tls_in_connect(rdg, hostname, port, timeout); 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; BOOL status;
assert(rdg != NULL);
status = rdg_out_channel_connect(rdg, hostname, port, timeout); status = rdg_out_channel_connect(rdg, hostname, port, timeout);
if (!status) if (!status)
@ -1067,7 +1081,6 @@ BOOL rdg_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
return TRUE; return TRUE;
} }
int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size) int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size)
{ {
int status; int status;
@ -1106,6 +1119,76 @@ int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size)
return 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) int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
{ {
RdgPacketHeader header; RdgPacketHeader header;
@ -1138,7 +1221,11 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
if (header.type != PKT_TYPE_DATA) 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; 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); 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) if (status < 0)
{ {
@ -1174,9 +1260,7 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
} }
} }
readCount += status; rdg->packetRemainingCount -= status;
rdg->packetRemainingCount -= readCount;
pending = BIO_pending(rdg->tlsOut->bio); pending = BIO_pending(rdg->tlsOut->bio);
@ -1185,7 +1269,7 @@ int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
else else
ResetEvent(rdg->readEvent); ResetEvent(rdg->readEvent);
return readSize; return status;
} }
long rdg_bio_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret) 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) if (arg2)
{ {
//*((ULONG_PTR*)arg2) = (ULONG_PTR)tsg->rpc->client->PipeEvent;
//status = 1;
BIO_get_event(rdg->tlsOut->bio, arg2); BIO_get_event(rdg->tlsOut->bio, arg2);
status = 1; status = 1;
} }
} }
else if (cmd == BIO_C_SET_NONBLOCK) else if (cmd == BIO_C_SET_NONBLOCK)
{ {
//return BIO_ctrl(tlsOut->bio, cmd, arg1, arg2);
rdg->nonBlocking = arg1; rdg->nonBlocking = arg1;
status = 1; status = 1;
} }
else if (cmd == BIO_C_READ_BLOCKED) else if (cmd == BIO_C_READ_BLOCKED)
{ {
//status = BIO_read_blocked(tlsOut->bio); status = 0;
//status = 0;
} }
else if (cmd == BIO_C_WRITE_BLOCKED) else if (cmd == BIO_C_WRITE_BLOCKED)
{ {
//status = BIO_write_blocked(tlsIn->bio); status = 0;
//status = 0;
} }
else if (cmd == BIO_C_WAIT_READ) else if (cmd == BIO_C_WAIT_READ)
{ {
int timeout = (int)arg1; int timeout = (int)arg1;
return BIO_wait_read(tlsOut->bio, timeout); 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) else if (cmd == BIO_C_WAIT_WRITE)
{ {
//int timeout = (int)arg1; status = 0;
//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;
} }
return status; return status;

View File

@ -117,6 +117,7 @@ enum
RDG_CLIENT_STATE_OPENED, RDG_CLIENT_STATE_OPENED,
RDG_CLIENT_STATE_CLOSE, RDG_CLIENT_STATE_CLOSE,
RDG_CLIENT_STATE_CLOSED, RDG_CLIENT_STATE_CLOSED,
RDG_CLIENT_STATE_NOT_FOUND,
}; };
@ -127,8 +128,6 @@ struct rdp_rdg
{ {
rdpContext* context; rdpContext* context;
rdpSettings* settings; rdpSettings* settings;
BIO* bioIn;
BIO* bioOut;
BIO* frontBio; BIO* frontBio;
rdpTls* tlsIn; rdpTls* tlsIn;
rdpTls* tlsOut; rdpTls* tlsOut;
@ -138,14 +137,8 @@ struct rdp_rdg
UUID guid; UUID guid;
//UINT32 tunnelId;
//UINT32 negotiatedCapsFlags;
//UUID nonce;
//LPWSTR serverCert;
//LPWSTR consentMsg;
int state; int state;
int packetRemainingCount; UINT16 packetRemainingCount;
int nonBlocking; int nonBlocking;
int timeout; int timeout;
}; };

View File

@ -214,26 +214,34 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
return FALSE; return FALSE;
} }
status = rdg_connect(transport->rdg, hostname, port, timeout); 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; else
BIO_set_nonblock(transport->frontBio, 0); {
transport->layer = TRANSPORT_LAYER_TSG; if (transport->rdg->state != RDG_CLIENT_STATE_NOT_FOUND)
{
return FALSE;
}
//transport->tsg = tsg_new(transport); transport->tsg = tsg_new(transport);
//if (!transport->tsg) if (!transport->tsg)
// return FALSE; return FALSE;
//if (!tsg_connect(transport->tsg, hostname, port, timeout)) if (!tsg_connect(transport->tsg, hostname, port, timeout))
// return FALSE; return FALSE;
//transport->frontBio = transport->tsg->bio; transport->frontBio = transport->tsg->bio;
//transport->layer = TRANSPORT_LAYER_TSG; transport->layer = TRANSPORT_LAYER_TSG;
status = TRUE; status = TRUE;
}
} }
else else
{ {