libfreerdp-core: gateway connection refactoring

This commit is contained in:
Marc-André Moreau 2015-02-11 14:27:29 -05:00
parent aa8b843250
commit 70fab69347
9 changed files with 155 additions and 135 deletions

View File

@ -129,14 +129,22 @@ int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc, HttpResponse* response)
int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel)
{
rdpTls* tls = NULL;
rdpNtlm* ntlm = NULL;
rdpContext* context = rpc->context;
rdpSettings* settings = rpc->settings;
freerdp* instance = (freerdp*) rpc->settings->instance;
freerdp* instance = context->instance;
if (channel == TSG_CHANNEL_IN)
{
ntlm = rpc->NtlmHttpIn->ntlm;
tls = rpc->VirtualConnection->DefaultInChannel->tls;
}
else if (channel == TSG_CHANNEL_OUT)
{
ntlm = rpc->NtlmHttpOut->ntlm;
tls = rpc->VirtualConnection->DefaultOutChannel->tls;
}
if (!settings->GatewayPassword || !settings->GatewayUsername ||
!strlen(settings->GatewayPassword) || !strlen(settings->GatewayUsername))
@ -149,7 +157,7 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel)
if (!proceed)
{
connectErrorCode = CANCELEDBYUSER;
freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
return 0;
}
@ -163,7 +171,7 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel)
}
if (!ntlm_client_init(ntlm, TRUE, settings->GatewayUsername,
settings->GatewayDomain, settings->GatewayPassword, rpc->TlsIn->Bindings))
settings->GatewayDomain, settings->GatewayPassword, tls->Bindings))
{
return 0;
}

View File

@ -393,8 +393,9 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* l
int rpc_out_read(rdpRpc* rpc, BYTE* data, int length)
{
int status;
RpcOutChannel* outChannel = rpc->VirtualConnection->DefaultOutChannel;
status = BIO_read(rpc->TlsOut->bio, data, length);
status = BIO_read(outChannel->tls->bio, data, length);
if (status > 0)
{
@ -404,7 +405,7 @@ int rpc_out_read(rdpRpc* rpc, BYTE* data, int length)
return status;
}
if (BIO_should_retry(rpc->TlsOut->bio))
if (BIO_should_retry(outChannel->tls->bio))
return 0;
return -1;
@ -413,14 +414,20 @@ int rpc_out_read(rdpRpc* rpc, BYTE* data, int length)
int rpc_out_write(rdpRpc* rpc, const BYTE* data, int length)
{
int status;
status = tls_write_all(rpc->TlsOut, data, length);
RpcOutChannel* outChannel = rpc->VirtualConnection->DefaultOutChannel;
status = tls_write_all(outChannel->tls, data, length);
return status;
}
int rpc_in_write(rdpRpc* rpc, const BYTE* data, int length)
{
int status;
status = tls_write_all(rpc->TlsIn, data, length);
RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel;
status = tls_write_all(inChannel->tls, data, length);
return status;
}
@ -776,6 +783,7 @@ rdpRpc* rpc_new(rdpTransport* transport)
rpc->StubFragCount = 0;
rpc->rpc_vers = 5;
rpc->rpc_vers_minor = 0;
/* little-endian data representation */
rpc->packed_drep[0] = 0x10;
rpc->packed_drep[1] = 0x00;
@ -783,9 +791,9 @@ rdpRpc* rpc_new(rdpTransport* transport)
rpc->packed_drep[3] = 0x00;
rpc->max_xmit_frag = 0x0FF8;
rpc->max_recv_frag = 0x0FF8;
rpc->ReceiveWindow = 0x00010000;
rpc->ChannelLifetime = 0x40000000;
rpc->ChannelLifetimeSet = 0;
rpc->KeepAliveInterval = 300000;
rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval;
rpc->CurrentKeepAliveTime = 0;

View File

@ -619,6 +619,9 @@ struct rpc_in_channel
{
/* Sending Channel */
rdpTcp* tcp;
rdpTls* tls;
CLIENT_IN_CHANNEL_STATE State;
UINT32 PlugState;
@ -651,6 +654,9 @@ typedef enum _CLIENT_OUT_CHANNEL_STATE CLIENT_OUT_CHANNEL_STATE;
struct rpc_out_channel
{
rdpTcp* tcp;
rdpTls* tls;
/* Receiving Channel */
CLIENT_OUT_CHANNEL_STATE State;
@ -724,9 +730,6 @@ struct rdp_rpc
UINT32 result;
rdpTls* TlsIn;
rdpTls* TlsOut;
rdpNtlm* ntlm;
int SendSeqNum;
@ -753,10 +756,7 @@ struct rdp_rpc
UINT16 max_recv_frag;
UINT32 ReceiveWindow;
UINT32 ChannelLifetime;
UINT32 ChannelLifetimeSet;
UINT32 KeepAliveInterval;
UINT32 CurrentKeepAliveTime;
UINT32 CurrentKeepAliveInterval;

View File

@ -540,7 +540,7 @@ int rpc_client_out_channel_recv(rdpRpc* rpc)
if (outChannel->State < CLIENT_OUT_CHANNEL_STATE_OPENED)
{
response = http_response_recv(rpc->TlsOut);
response = http_response_recv(outChannel->tls);
if (!response)
return -1;
@ -594,7 +594,7 @@ int rpc_client_out_channel_recv(rdpRpc* rpc)
{
/* Receive OUT channel response */
response = http_response_recv(rpc->TlsOut);
response = http_response_recv(outChannel->tls);
if (!response)
return -1;
@ -645,14 +645,14 @@ int rpc_client_in_channel_recv(rdpRpc* rpc)
inChannel = rpc->VirtualConnection->DefaultInChannel;
outChannel = rpc->VirtualConnection->DefaultOutChannel;
BIO_get_event(rpc->TlsIn->bio, &InChannelEvent);
BIO_get_event(inChannel->tls->bio, &InChannelEvent);
if (WaitForSingleObject(InChannelEvent, 0) != WAIT_OBJECT_0)
return 1;
if (inChannel->State < CLIENT_IN_CHANNEL_STATE_OPENED)
{
response = http_response_recv(rpc->TlsIn);
response = http_response_recv(inChannel->tls);
if (!response)
return -1;

View File

@ -1412,91 +1412,18 @@ int tsg_check(rdpTsg* tsg)
BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout)
{
int tls_status;
int tlsStatus;
HANDLE events[2];
rdpRpc* rpc = tsg->rpc;
RpcInChannel* inChannel;
RpcOutChannel* outChannel;
RpcVirtualConnection* connection;
rdpSettings* settings = rpc->settings;
rdpTransport* transport = rpc->transport;
rdpContext* context = rpc->context;
transport->layer = TRANSPORT_LAYER_TSG;
transport->SplitInputOutput = TRUE;
transport->TcpIn = freerdp_tcp_new(settings);
transport->TcpOut = freerdp_tcp_new(settings);
if (!freerdp_tcp_connect(transport->TcpIn, settings->GatewayHostname, settings->GatewayPort, timeout) ||
!freerdp_tcp_set_blocking_mode(transport->TcpIn, FALSE))
return FALSE;
if (!freerdp_tcp_connect(transport->TcpOut, settings->GatewayHostname, settings->GatewayPort, timeout) ||
!freerdp_tcp_set_blocking_mode(transport->TcpOut, FALSE))
return FALSE;
tsg->transport = transport;
transport->tsg = tsg;
transport->SplitInputOutput = TRUE;
transport->TlsIn = tls_new(settings);
if (!transport->TlsIn)
return FALSE;
transport->TlsOut = tls_new(settings);
if (!transport->TlsOut)
return FALSE;
/* put a decent default value for gateway port */
if (!settings->GatewayPort)
settings->GatewayPort = 443;
transport->TlsIn->hostname = transport->TlsOut->hostname = settings->GatewayHostname;
transport->TlsIn->port = transport->TlsOut->port = settings->GatewayPort;
transport->TlsIn->isGatewayTransport = TRUE;
tls_status = tls_connect(transport->TlsIn, transport->TcpIn->bufferedBio);
if (tls_status < 1)
{
if (tls_status < 0)
{
if (!freerdp_get_last_error(context))
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
}
else
{
if (!freerdp_get_last_error(context))
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
}
return FALSE;
}
transport->TlsOut->isGatewayTransport = TRUE;
tls_status = tls_connect(transport->TlsOut, transport->TcpOut->bufferedBio);
if (tls_status < 1)
{
if (tls_status < 0)
{
if (!freerdp_get_last_error(context))
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
}
else
{
if (!freerdp_get_last_error(context))
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
}
return FALSE;
}
tsg->Port = port;
rpc->TlsIn = transport->TlsIn;
rpc->TlsOut = transport->TlsOut;
tsg->transport = transport;
free(tsg->Hostname);
tsg->Hostname = NULL;
@ -1506,14 +1433,84 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout)
tsg->MachineName = NULL;
ConvertToUnicode(CP_UTF8, 0, settings->ComputerName, -1, &tsg->MachineName, 0);
connection = rpc->VirtualConnection;
inChannel = connection->DefaultInChannel;
outChannel = connection->DefaultOutChannel;
inChannel->tcp = freerdp_tcp_new(settings);
outChannel->tcp = freerdp_tcp_new(settings);
if (!freerdp_tcp_connect(inChannel->tcp, settings->GatewayHostname, settings->GatewayPort, timeout) ||
!freerdp_tcp_set_blocking_mode(inChannel->tcp, FALSE))
return FALSE;
if (!freerdp_tcp_connect(outChannel->tcp, settings->GatewayHostname, settings->GatewayPort, timeout) ||
!freerdp_tcp_set_blocking_mode(outChannel->tcp, FALSE))
return FALSE;
inChannel->tls = tls_new(settings);
if (!inChannel->tls)
return FALSE;
outChannel->tls = tls_new(settings);
if (!outChannel->tls)
return FALSE;
/* put a decent default value for gateway port */
if (!settings->GatewayPort)
settings->GatewayPort = 443;
inChannel->tls->hostname = outChannel->tls->hostname = settings->GatewayHostname;
inChannel->tls->port = outChannel->tls->port = settings->GatewayPort;
inChannel->tls->isGatewayTransport = TRUE;
tlsStatus = tls_connect(inChannel->tls, inChannel->tcp->bufferedBio);
if (tlsStatus < 1)
{
if (tlsStatus < 0)
{
if (!freerdp_get_last_error(context))
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
}
else
{
if (!freerdp_get_last_error(context))
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
}
return FALSE;
}
outChannel->tls->isGatewayTransport = TRUE;
tlsStatus = tls_connect(outChannel->tls, outChannel->tcp->bufferedBio);
if (tlsStatus < 1)
{
if (tlsStatus < 0)
{
if (!freerdp_get_last_error(context))
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
}
else
{
if (!freerdp_get_last_error(context))
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
}
return FALSE;
}
if (!rpc_connect(rpc))
{
WLog_ERR(TAG, "rpc_connect error!");
return FALSE;
}
BIO_get_event(rpc->TlsIn->bio, &events[0]);
BIO_get_event(rpc->TlsOut->bio, &events[1]);
BIO_get_event(inChannel->tls->bio, &events[0]);
BIO_get_event(outChannel->tls->bio, &events[1]);
while (tsg->state != TSG_STATE_PIPE_CREATED)
{
@ -1522,18 +1519,28 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout)
if (tsg_check(tsg) < 0)
{
WLog_ERR(TAG, "tsg_check failure");
rpc->transport->layer = TRANSPORT_LAYER_CLOSED;
transport->layer = TRANSPORT_LAYER_CLOSED;
return FALSE;
}
}
WLog_INFO(TAG, "TS Gateway Connection Success");
tsg->transport->GatewayEvent = tsg->rpc->client->PipeEvent;
tsg->bio = BIO_new(BIO_s_tsg());
tsg->bio->ptr = tsg;
if (!tsg->bio)
return FALSE;
tsg->bio->ptr = (void*) tsg;
transport->frontBio = tsg->bio;
transport->TcpIn = inChannel->tcp;
transport->TlsIn = inChannel->tls;
transport->TcpOut = outChannel->tcp;
transport->TlsOut = outChannel->tls;
transport->GatewayEvent = rpc->client->PipeEvent;
transport->SplitInputOutput = TRUE;
transport->layer = TRANSPORT_LAYER_TSG;
return TRUE;
}
@ -1679,6 +1686,8 @@ void tsg_free(rdpTsg* tsg)
{
if (tsg)
{
rdpTransport* transport = tsg->transport;
if (tsg->bio)
{
BIO_free(tsg->bio);
@ -1693,6 +1702,19 @@ void tsg_free(rdpTsg* tsg)
free(tsg->Hostname);
free(tsg->MachineName);
if (transport->TlsIn)
tls_free(transport->TlsIn);
if (transport->TcpIn)
freerdp_tcp_free(transport->TcpIn);
if (transport->TlsOut)
tls_free(transport->TlsOut);
if (transport->TcpOut)
freerdp_tcp_free(transport->TcpOut);
free(tsg);
}
}

View File

@ -190,15 +190,9 @@ int credssp_ntlm_client_init(rdpCredssp* credssp)
(char*) credssp->identity.User, (char*) credssp->identity.Domain, (char*) credssp->identity.Password);
#endif
if (credssp->transport->layer == TRANSPORT_LAYER_TLS)
{
tls = credssp->transport->TlsIn;
}
else if (credssp->transport->layer == TRANSPORT_LAYER_TSG_TLS)
{
tls = credssp->transport->TsgTls;
}
else
tls = credssp->transport->tls;
if (!tls)
{
WLog_ERR(TAG, "Unknown NLA transport layer");
return 0;
@ -211,8 +205,7 @@ int credssp_ntlm_client_init(rdpCredssp* credssp)
sprintf(spn, "%s%s", TERMSRV_SPN_PREFIX, settings->ServerHostname);
#ifdef UNICODE
credssp->ServicePrincipalName = (LPTSTR) malloc(length * 2 + 2);
MultiByteToWideChar(CP_UTF8, 0, spn, length,
(LPWSTR) credssp->ServicePrincipalName, length);
MultiByteToWideChar(CP_UTF8, 0, spn, length, (LPWSTR) credssp->ServicePrincipalName, length);
free(spn);
#else
credssp->ServicePrincipalName = spn;

View File

@ -1338,8 +1338,6 @@ rdpRdp* rdp_new(rdpContext* context)
if (!rdp->transport)
goto out_free_settings;
rdp->transport->rdp = rdp;
rdp->license = license_new(rdp);
if (!rdp->license)
@ -1482,7 +1480,6 @@ void rdp_reset(rdpRdp* rdp)
transport_free(rdp->transport);
rdp->transport = transport_new(context);
rdp->transport->rdp = rdp;
rdp->license = license_new(rdp);
rdp->nego = nego_new(rdp->transport);
rdp->mcs = mcs_new(rdp->transport);

View File

@ -109,18 +109,6 @@ BOOL transport_disconnect(rdpTransport* transport)
tsg_free(transport->tsg);
transport->tsg = NULL;
if (transport->TlsIn)
tls_free(transport->TlsIn);
if (transport->TcpIn)
freerdp_tcp_free(transport->TcpIn);
if (transport->TlsOut)
tls_free(transport->TlsOut);
if (transport->TcpOut)
freerdp_tcp_free(transport->TcpOut);
}
else
{
@ -156,7 +144,7 @@ BOOL transport_connect_tls(rdpTransport* transport)
rdpContext* context = transport->context;
rdpSettings* settings = transport->settings;
if (transport->layer == TRANSPORT_LAYER_TSG)
if (transport->GatewayEnabled)
{
transport->TsgTls = tls_new(transport->settings);
transport->layer = TRANSPORT_LAYER_TSG_TLS;
@ -171,6 +159,8 @@ BOOL transport_connect_tls(rdpTransport* transport)
transport->layer = TRANSPORT_LAYER_TLS;
}
transport->tls = targetTls;
targetTls->hostname = settings->ServerHostname;
targetTls->port = settings->ServerPort;
@ -280,6 +270,8 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
if (!tsg)
return FALSE;
transport->tsg = tsg;
if (!tsg_connect(tsg, hostname, port, timeout))
return FALSE;
@ -330,12 +322,14 @@ BOOL transport_accept_rdp(rdpTransport* transport)
BOOL transport_accept_tls(rdpTransport* transport)
{
rdpSettings* settings = transport->settings;
if (!transport->TlsIn)
transport->TlsIn = tls_new(transport->settings);
transport->layer = TRANSPORT_LAYER_TLS;
if (!tls_accept(transport->TlsIn, transport->TcpIn->bufferedBio, transport->settings->CertificateFile, transport->settings->PrivateKeyFile))
if (!tls_accept(transport->TlsIn, transport->TcpIn->bufferedBio, settings->CertificateFile, settings->PrivateKeyFile))
return FALSE;
transport->frontBio = transport->TlsIn->bio;
@ -344,10 +338,8 @@ BOOL transport_accept_tls(rdpTransport* transport)
BOOL transport_accept_nla(rdpTransport* transport)
{
freerdp* instance;
rdpSettings* settings;
settings = transport->settings;
instance = (freerdp*) settings->instance;
rdpSettings* settings = transport->settings;
freerdp* instance = (freerdp*) settings->instance;
if (!transport->TlsIn)
transport->TlsIn = tls_new(transport->settings);
@ -913,7 +905,7 @@ static void* transport_client_thread(void* arg)
HANDLE handles[64];
rdpTransport* transport = (rdpTransport*) arg;
rdpContext* context = transport->context;
rdpRdp* rdp = (rdpRdp*) transport->rdp;
rdpRdp* rdp = context->rdp;
WLog_DBG(TAG, "Starting transport thread");

View File

@ -57,6 +57,7 @@ struct rdp_transport
TRANSPORT_LAYER layer;
BIO* frontBio;
rdpTsg* tsg;
rdpTls* tls;
rdpTcp* TcpIn;
rdpTcp* TcpOut;
rdpTls* TlsIn;
@ -82,7 +83,6 @@ struct rdp_transport
BOOL GatewayEnabled;
CRITICAL_SECTION ReadLock;
CRITICAL_SECTION WriteLock;
void* rdp;
};
wStream* transport_send_stream_init(rdpTransport* transport, int size);