libfreerdp-core: add more IN/OUT gateway channel states
This commit is contained in:
parent
7b25f9130b
commit
1bf0e2ee03
@ -101,20 +101,14 @@ int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc)
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
|
||||
int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc)
|
||||
int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc, HttpResponse* response)
|
||||
{
|
||||
int status = -1;
|
||||
char* token64 = NULL;
|
||||
HttpResponse* response;
|
||||
int ntlmTokenLength = 0;
|
||||
BYTE* ntlmTokenData = NULL;
|
||||
rdpNtlm* ntlm = rpc->NtlmHttpIn->ntlm;
|
||||
|
||||
response = http_response_recv(rpc->TlsIn);
|
||||
|
||||
if (!response)
|
||||
return -1;
|
||||
|
||||
if (ListDictionary_Contains(response->Authenticates, "NTLM"))
|
||||
{
|
||||
token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM");
|
||||
@ -203,35 +197,6 @@ void rpc_ncacn_http_ntlm_uninit(rdpRpc* rpc, TSG_CHANNEL channel)
|
||||
}
|
||||
}
|
||||
|
||||
BOOL rpc_ntlm_http_in_connect(rdpRpc* rpc)
|
||||
{
|
||||
BOOL status = FALSE;
|
||||
|
||||
if (rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_IN) < 0)
|
||||
goto out;
|
||||
|
||||
/* Send IN Channel Request */
|
||||
|
||||
if (rpc_ncacn_http_send_in_channel_request(rpc) < 0)
|
||||
goto out;
|
||||
|
||||
/* Receive IN Channel Response */
|
||||
|
||||
if (rpc_ncacn_http_recv_in_channel_response(rpc) < 0)
|
||||
goto out;
|
||||
|
||||
/* Send IN Channel Request */
|
||||
|
||||
if (rpc_ncacn_http_send_in_channel_request(rpc) < 0)
|
||||
goto out;
|
||||
|
||||
status = TRUE;
|
||||
|
||||
out:
|
||||
rpc_ncacn_http_ntlm_uninit(rpc, TSG_CHANNEL_IN);
|
||||
return status;
|
||||
}
|
||||
|
||||
int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc)
|
||||
{
|
||||
wStream* s;
|
||||
@ -256,20 +221,14 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc)
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
|
||||
int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc)
|
||||
int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc, HttpResponse* response)
|
||||
{
|
||||
int status = -1;
|
||||
char* token64 = NULL;
|
||||
HttpResponse* response;
|
||||
int ntlmTokenLength = 0;
|
||||
BYTE* ntlmTokenData = NULL;
|
||||
rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm;
|
||||
|
||||
response = http_response_recv(rpc->TlsOut);
|
||||
|
||||
if (!response)
|
||||
return -1;
|
||||
|
||||
if (ListDictionary_Contains(response->Authenticates, "NTLM"))
|
||||
{
|
||||
token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM");
|
||||
@ -312,41 +271,6 @@ int rpc_http_send_replacement_out_channel_request(rdpRpc* rpc)
|
||||
return (status > 0) ? 1 : -1;
|
||||
}
|
||||
|
||||
BOOL rpc_ntlm_http_out_connect(rdpRpc* rpc)
|
||||
{
|
||||
BOOL status = FALSE;
|
||||
|
||||
if (rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_OUT) < 0)
|
||||
goto out;
|
||||
|
||||
/* Send OUT Channel Request */
|
||||
if (rpc_ncacn_http_send_out_channel_request(rpc) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Receive OUT Channel Response */
|
||||
if (rpc_ncacn_http_recv_out_channel_response(rpc) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_recv_out_channel_response failure");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Send OUT Channel Request */
|
||||
if (rpc_ncacn_http_send_out_channel_request(rpc) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = TRUE;
|
||||
|
||||
out:
|
||||
rpc_ncacn_http_ntlm_uninit(rpc, TSG_CHANNEL_OUT);
|
||||
return status;
|
||||
}
|
||||
|
||||
void rpc_ntlm_http_init_channel(rdpRpc* rpc, rdpNtlmHttp* ntlm_http, TSG_CHANNEL channel)
|
||||
{
|
||||
if (channel == TSG_CHANNEL_IN)
|
||||
@ -363,11 +287,13 @@ void rpc_ntlm_http_init_channel(rdpRpc* rpc, rdpNtlmHttp* ntlm_http, TSG_CHANNEL
|
||||
|
||||
if (channel == TSG_CHANNEL_IN)
|
||||
{
|
||||
http_context_set_pragma(ntlm_http->context, "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729");
|
||||
http_context_set_pragma(ntlm_http->context,
|
||||
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729");
|
||||
}
|
||||
else if (channel == TSG_CHANNEL_OUT)
|
||||
{
|
||||
http_context_set_pragma(ntlm_http->context, "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, "
|
||||
http_context_set_pragma(ntlm_http->context,
|
||||
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, "
|
||||
"SessionId=fbd9c34f-397d-471d-a109-1b08cc554624");
|
||||
}
|
||||
}
|
||||
|
@ -26,17 +26,19 @@
|
||||
#include <freerdp/crypto/tls.h>
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
|
||||
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include "rpc.h"
|
||||
#include "http.h"
|
||||
|
||||
int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel);
|
||||
void rpc_ncacn_http_ntlm_uninit(rdpRpc* rpc, TSG_CHANNEL channel);
|
||||
|
||||
BOOL rpc_ntlm_http_out_connect(rdpRpc* rpc);
|
||||
BOOL rpc_ntlm_http_in_connect(rdpRpc* rpc);
|
||||
int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc);
|
||||
int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc, HttpResponse* response);
|
||||
|
||||
int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc);
|
||||
int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc, HttpResponse* response);
|
||||
|
||||
void rpc_ntlm_http_init_channel(rdpRpc* rpc, rdpNtlmHttp* ntlm_http, TSG_CHANNEL channel);
|
||||
|
||||
|
@ -31,14 +31,11 @@ typedef struct rdp_ntlm_http rdpNtlmHttp;
|
||||
#include "rts.h"
|
||||
#include "http.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <winpr/sspi.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/crypto/tls.h>
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
|
||||
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/stream.h>
|
||||
|
@ -469,6 +469,98 @@ out_free_pdu:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rpc_client_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state)
|
||||
{
|
||||
int status = 1;
|
||||
const char* str = "CLIENT_IN_CHANNEL_STATE_UNKNOWN";
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case CLIENT_IN_CHANNEL_STATE_INITIAL:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_INITIAL";
|
||||
break;
|
||||
|
||||
case CLIENT_IN_CHANNEL_STATE_CONNECTED:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_CONNECTED";
|
||||
break;
|
||||
|
||||
case CLIENT_IN_CHANNEL_STATE_SECURITY:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_SECURITY";
|
||||
break;
|
||||
|
||||
case CLIENT_IN_CHANNEL_STATE_NEGOTIATED:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_NEGOTIATED";
|
||||
break;
|
||||
|
||||
case CLIENT_IN_CHANNEL_STATE_OPENED:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_OPENED";
|
||||
break;
|
||||
|
||||
case CLIENT_IN_CHANNEL_STATE_OPENED_A4W:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_OPENED_A4W";
|
||||
break;
|
||||
|
||||
case CLIENT_IN_CHANNEL_STATE_FINAL:
|
||||
str = "CLIENT_IN_CHANNEL_STATE_FINAL";
|
||||
break;
|
||||
}
|
||||
|
||||
inChannel->State = state;
|
||||
WLog_DBG(TAG, "%s", str);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int rpc_client_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state)
|
||||
{
|
||||
int status = 1;
|
||||
const char* str = "CLIENT_OUT_CHANNEL_STATE_UNKNOWN";
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case CLIENT_OUT_CHANNEL_STATE_INITIAL:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_INITIAL";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_CONNECTED:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_CONNECTED";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_SECURITY:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_SECURITY";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_NEGOTIATED:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_NEGOTIATED";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_OPENED:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_OPENED";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_OPENED_A6W:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_OPENED_A6W";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_OPENED_A10W:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_OPENED_A10W";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_OPENED_B3W:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_OPENED_B3W";
|
||||
break;
|
||||
|
||||
case CLIENT_OUT_CHANNEL_STATE_FINAL:
|
||||
str = "CLIENT_OUT_CHANNEL_STATE_FINAL";
|
||||
break;
|
||||
}
|
||||
|
||||
outChannel->State = state;
|
||||
WLog_DBG(TAG, "%s", str);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int rpc_client_virtual_connection_transition_to_state(rdpRpc* rpc,
|
||||
RpcVirtualConnection* connection, VIRTUAL_CONNECTION_STATE state)
|
||||
{
|
||||
|
@ -606,6 +606,9 @@ typedef struct rpc_ping_originator RpcPingOriginator;
|
||||
enum _CLIENT_IN_CHANNEL_STATE
|
||||
{
|
||||
CLIENT_IN_CHANNEL_STATE_INITIAL,
|
||||
CLIENT_IN_CHANNEL_STATE_CONNECTED,
|
||||
CLIENT_IN_CHANNEL_STATE_SECURITY,
|
||||
CLIENT_IN_CHANNEL_STATE_NEGOTIATED,
|
||||
CLIENT_IN_CHANNEL_STATE_OPENED,
|
||||
CLIENT_IN_CHANNEL_STATE_OPENED_A4W,
|
||||
CLIENT_IN_CHANNEL_STATE_FINAL
|
||||
@ -635,6 +638,9 @@ typedef struct rpc_in_channel RpcInChannel;
|
||||
enum _CLIENT_OUT_CHANNEL_STATE
|
||||
{
|
||||
CLIENT_OUT_CHANNEL_STATE_INITIAL,
|
||||
CLIENT_OUT_CHANNEL_STATE_CONNECTED,
|
||||
CLIENT_OUT_CHANNEL_STATE_SECURITY,
|
||||
CLIENT_OUT_CHANNEL_STATE_NEGOTIATED,
|
||||
CLIENT_OUT_CHANNEL_STATE_OPENED,
|
||||
CLIENT_OUT_CHANNEL_STATE_OPENED_A6W,
|
||||
CLIENT_OUT_CHANNEL_STATE_OPENED_A10W,
|
||||
@ -773,6 +779,9 @@ int rpc_in_write(rdpRpc* rpc, const BYTE* data, int length);
|
||||
|
||||
BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* header, UINT32* offset, UINT32* length);
|
||||
|
||||
int rpc_client_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state);
|
||||
int rpc_client_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state);
|
||||
|
||||
int rpc_client_virtual_connection_transition_to_state(rdpRpc* rpc,
|
||||
RpcVirtualConnection* connection, VIRTUAL_CONNECTION_STATE state);
|
||||
|
||||
|
@ -174,7 +174,7 @@ int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
|
||||
rpcconn_rts_hdr_t* rts;
|
||||
rdpTsg* tsg = rpc->transport->tsg;
|
||||
|
||||
if (rpc->State < RPC_CLIENT_STATE_ESTABLISHED)
|
||||
if (rpc->VirtualConnection->State < VIRTUAL_CONNECTION_STATE_OPENED)
|
||||
{
|
||||
switch (rpc->VirtualConnection->State)
|
||||
{
|
||||
|
@ -88,12 +88,49 @@ BOOL rts_connect(rdpRpc* rpc)
|
||||
rpc_client_virtual_connection_transition_to_state(rpc,
|
||||
rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_INITIAL);
|
||||
|
||||
if (!rpc_ntlm_http_out_connect(rpc))
|
||||
rpc_client_out_channel_transition_to_state(rpc->VirtualConnection->DefaultOutChannel,
|
||||
CLIENT_OUT_CHANNEL_STATE_CONNECTED);
|
||||
|
||||
if (rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_OUT) < 0)
|
||||
return FALSE;
|
||||
|
||||
/* Send OUT Channel Request */
|
||||
|
||||
if (rpc_ncacn_http_send_out_channel_request(rpc) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_out_connect_http error!");
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rpc_client_out_channel_transition_to_state(rpc->VirtualConnection->DefaultOutChannel,
|
||||
CLIENT_OUT_CHANNEL_STATE_SECURITY);
|
||||
|
||||
/* Receive OUT Channel Response */
|
||||
|
||||
response = http_response_recv(rpc->TlsOut);
|
||||
|
||||
if (!response)
|
||||
return FALSE;
|
||||
|
||||
if (rpc_ncacn_http_recv_out_channel_response(rpc, response) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_recv_out_channel_response failure");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Send OUT Channel Request */
|
||||
|
||||
if (rpc_ncacn_http_send_out_channel_request(rpc) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rpc_ncacn_http_ntlm_uninit(rpc, TSG_CHANNEL_OUT);
|
||||
|
||||
rpc_client_out_channel_transition_to_state(rpc->VirtualConnection->DefaultOutChannel,
|
||||
CLIENT_OUT_CHANNEL_STATE_NEGOTIATED);
|
||||
|
||||
/* Send CONN/A1 PDU over OUT channel */
|
||||
|
||||
if (rts_send_CONN_A1_pdu(rpc) < 0)
|
||||
@ -102,12 +139,52 @@ BOOL rts_connect(rdpRpc* rpc)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!rpc_ntlm_http_in_connect(rpc))
|
||||
rpc_client_out_channel_transition_to_state(rpc->VirtualConnection->DefaultOutChannel,
|
||||
CLIENT_OUT_CHANNEL_STATE_OPENED);
|
||||
|
||||
rpc_client_in_channel_transition_to_state(rpc->VirtualConnection->DefaultInChannel,
|
||||
CLIENT_IN_CHANNEL_STATE_CONNECTED);
|
||||
|
||||
if (rpc_ncacn_http_ntlm_init(rpc, TSG_CHANNEL_IN) < 0)
|
||||
return FALSE;
|
||||
|
||||
/* Send IN Channel Request */
|
||||
|
||||
if (rpc_ncacn_http_send_in_channel_request(rpc) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_in_connect_http error!");
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_send_in_channel_request failure");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rpc_client_in_channel_transition_to_state(rpc->VirtualConnection->DefaultInChannel,
|
||||
CLIENT_IN_CHANNEL_STATE_SECURITY);
|
||||
|
||||
/* Receive IN Channel Response */
|
||||
|
||||
response = http_response_recv(rpc->TlsIn);
|
||||
|
||||
if (!response)
|
||||
return FALSE;
|
||||
|
||||
if (rpc_ncacn_http_recv_in_channel_response(rpc, response) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_recv_in_channel_response failure");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Send IN Channel Request */
|
||||
|
||||
if (rpc_ncacn_http_send_in_channel_request(rpc) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "rpc_ncacn_http_send_in_channel_request failure");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rpc_ncacn_http_ntlm_uninit(rpc, TSG_CHANNEL_IN);
|
||||
|
||||
rpc_client_in_channel_transition_to_state(rpc->VirtualConnection->DefaultInChannel,
|
||||
CLIENT_IN_CHANNEL_STATE_NEGOTIATED);
|
||||
|
||||
/* Send CONN/B1 PDU over IN channel */
|
||||
|
||||
if (rts_send_CONN_B1_pdu(rpc) < 0)
|
||||
@ -116,6 +193,9 @@ BOOL rts_connect(rdpRpc* rpc)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rpc_client_in_channel_transition_to_state(rpc->VirtualConnection->DefaultInChannel,
|
||||
CLIENT_IN_CHANNEL_STATE_OPENED);
|
||||
|
||||
rpc_client_virtual_connection_transition_to_state(rpc,
|
||||
rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT);
|
||||
|
||||
@ -138,9 +218,7 @@ BOOL rts_connect(rdpRpc* rpc)
|
||||
if (response->StatusCode == HTTP_STATUS_DENIED)
|
||||
{
|
||||
if (!connectErrorCode)
|
||||
{
|
||||
connectErrorCode = AUTHENTICATIONERROR;
|
||||
}
|
||||
|
||||
if (!freerdp_get_last_error(context))
|
||||
{
|
||||
|
@ -1434,9 +1434,9 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port)
|
||||
{
|
||||
if (WaitForSingleObject(ReadEvent, 100) == WAIT_OBJECT_0)
|
||||
{
|
||||
if (rpc_client_recv(rpc) < 0)
|
||||
if (tsg_check(tsg) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "tsg_connect: rpc_client_recv failure");
|
||||
WLog_ERR(TAG, "tsg_check failure");
|
||||
rpc->transport->layer = TRANSPORT_LAYER_CLOSED;
|
||||
return FALSE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user