mirror of https://github.com/FreeRDP/FreeRDP
Merge pull request #1562 from dbungert/tlstls
Enable NLA and TLS negotiation with Gateway
This commit is contained in:
commit
c44591d363
|
@ -832,6 +832,10 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
|
|||
|
||||
if (file->GatewayUsageMethod == TSC_PROXY_MODE_DIRECT)
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, TRUE);
|
||||
else if (file->GatewayUsageMethod == TSC_PROXY_MODE_DETECT)
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, TRUE);
|
||||
else if (file->GatewayUsageMethod == TSC_PROXY_MODE_DEFAULT)
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, TRUE);
|
||||
else if (file->GatewayUsageMethod == TSC_PROXY_MODE_NONE_DETECT)
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, FALSE);
|
||||
}
|
||||
|
|
|
@ -39,9 +39,12 @@ typedef struct rdp_tls rdpTls;
|
|||
struct rdp_tls
|
||||
{
|
||||
SSL* ssl;
|
||||
BIO* bio;
|
||||
void* tsg;
|
||||
int sockfd;
|
||||
SSL_CTX* ctx;
|
||||
BYTE* PublicKey;
|
||||
BIO_METHOD* methods;
|
||||
DWORD PublicKeyLength;
|
||||
rdpSettings* settings;
|
||||
SecPkgContext_Bindings* Bindings;
|
||||
|
|
|
@ -209,14 +209,6 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
|||
|
||||
nego_set_cookie(rdp->nego, cookie);
|
||||
free(cookie);
|
||||
|
||||
settings->RdpSecurity = TRUE;
|
||||
settings->TlsSecurity = FALSE;
|
||||
settings->NlaSecurity = FALSE;
|
||||
settings->ExtSecurity = FALSE;
|
||||
|
||||
//settings->TlsSecurity = TRUE;
|
||||
//settings->NlaSecurity = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -161,7 +161,7 @@ int rpc_client_on_fragment_received_event(rdpRpc* rpc)
|
|||
if (StubLength == 4)
|
||||
{
|
||||
//fprintf(stderr, "Ignoring TsProxySendToServer Response\n");
|
||||
printf("Got stub length 4 with flags %d and callid %d\n", header->common.pfc_flags, header->common.call_id);
|
||||
//printf("Got stub length 4 with flags %d and callid %d\n", header->common.pfc_flags, header->common.call_id);
|
||||
|
||||
/* received a disconnect request from the server? */
|
||||
if ((header->common.call_id == rpc->PipeCallId) && (header->common.pfc_flags & PFC_LAST_FRAG))
|
||||
|
|
|
@ -43,11 +43,16 @@ static const char* const NEGO_STATE_STRINGS[] =
|
|||
"NEGO_STATE_FINAL"
|
||||
};
|
||||
|
||||
static const char PROTOCOL_SECURITY_STRINGS[4][4] =
|
||||
static const char PROTOCOL_SECURITY_STRINGS[9][4] =
|
||||
{
|
||||
"RDP",
|
||||
"TLS",
|
||||
"NLA",
|
||||
"UNK",
|
||||
"UNK",
|
||||
"UNK",
|
||||
"UNK",
|
||||
"UNK",
|
||||
"EXT"
|
||||
};
|
||||
|
||||
|
|
|
@ -137,8 +137,18 @@ int credssp_ntlm_client_init(rdpCredssp* credssp)
|
|||
(char*) credssp->identity.User, (char*) credssp->identity.Domain, (char*) credssp->identity.Password);
|
||||
#endif
|
||||
|
||||
sspi_SecBufferAlloc(&credssp->PublicKey, credssp->transport->TlsIn->PublicKeyLength);
|
||||
CopyMemory(credssp->PublicKey.pvBuffer, credssp->transport->TlsIn->PublicKey, credssp->transport->TlsIn->PublicKeyLength);
|
||||
rdpTls *tls = NULL;
|
||||
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 {
|
||||
fprintf(stderr, "Unknown NLA transport layer\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sspi_SecBufferAlloc(&credssp->PublicKey, tls->PublicKeyLength);
|
||||
CopyMemory(credssp->PublicKey.pvBuffer, tls->PublicKey, tls->PublicKeyLength);
|
||||
|
||||
length = sizeof(TERMSRV_SPN_PREFIX) + strlen(settings->ServerHostname);
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ BOOL transport_disconnect(rdpTransport* transport)
|
|||
if (transport->layer == TRANSPORT_LAYER_TLS)
|
||||
status &= tls_disconnect(transport->TlsIn);
|
||||
|
||||
if (transport->layer == TRANSPORT_LAYER_TSG)
|
||||
if (transport->layer == TRANSPORT_LAYER_TSG || transport->layer == TRANSPORT_LAYER_TSG_TLS)
|
||||
{
|
||||
tsg_disconnect(transport->tsg);
|
||||
}
|
||||
|
@ -104,10 +104,126 @@ BOOL transport_connect_rdp(rdpTransport* transport)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
long transport_bio_tsg_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
|
||||
{
|
||||
int status;
|
||||
rdpTsg* tsg;
|
||||
|
||||
tsg = (rdpTsg*) bio->ptr;
|
||||
status = tsg_write(tsg, (BYTE*) buf, num);
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
BIO_set_retry_write(bio);
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
|
||||
{
|
||||
int status;
|
||||
rdpTsg* tsg;
|
||||
|
||||
tsg = (rdpTsg*) bio->ptr;
|
||||
status = tsg_read(bio->ptr, (BYTE*) buf, size);
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
BIO_set_retry_read(bio);
|
||||
}
|
||||
|
||||
return status > 0 ? status : -1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_puts(BIO* bio, const char* str)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_gets(BIO* bio, char* str, int size)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
{
|
||||
if(cmd == BIO_CTRL_FLUSH) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_new(BIO* bio)
|
||||
{
|
||||
bio->init = 1;
|
||||
bio->num = 0;
|
||||
bio->ptr = NULL;
|
||||
bio->flags = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_free(BIO* bio)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define BIO_TYPE_TSG 65
|
||||
|
||||
static BIO_METHOD transport_bio_tsg_methods =
|
||||
{
|
||||
BIO_TYPE_TSG,
|
||||
"TSGateway",
|
||||
transport_bio_tsg_write,
|
||||
transport_bio_tsg_read,
|
||||
transport_bio_tsg_puts,
|
||||
transport_bio_tsg_gets,
|
||||
transport_bio_tsg_ctrl,
|
||||
transport_bio_tsg_new,
|
||||
transport_bio_tsg_free,
|
||||
NULL,
|
||||
};
|
||||
|
||||
BIO_METHOD* BIO_s_tsg(void)
|
||||
{
|
||||
return &transport_bio_tsg_methods;
|
||||
}
|
||||
|
||||
BOOL transport_connect_tls(rdpTransport* transport)
|
||||
{
|
||||
if (transport->layer == TRANSPORT_LAYER_TSG)
|
||||
{
|
||||
transport->TsgTls = tls_new(transport->settings);
|
||||
|
||||
transport->TsgTls->methods = BIO_s_tsg();
|
||||
transport->TsgTls->tsg = (void*) transport->tsg;
|
||||
|
||||
transport->layer = TRANSPORT_LAYER_TSG_TLS;
|
||||
|
||||
if (tls_connect(transport->TsgTls) != TRUE)
|
||||
{
|
||||
if (!connectErrorCode)
|
||||
connectErrorCode = TLSCONNECTERROR;
|
||||
|
||||
tls_free(transport->TsgTls);
|
||||
|
||||
transport->TsgTls = NULL;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (transport->TlsIn == NULL)
|
||||
transport->TlsIn = tls_new(transport->settings);
|
||||
|
@ -141,9 +257,6 @@ BOOL transport_connect_nla(rdpTransport* transport)
|
|||
freerdp* instance;
|
||||
rdpSettings* settings;
|
||||
|
||||
if (transport->layer == TRANSPORT_LAYER_TSG)
|
||||
return TRUE;
|
||||
|
||||
if (!transport_connect_tls(transport))
|
||||
return FALSE;
|
||||
|
||||
|
@ -385,6 +498,9 @@ int transport_read_layer(rdpTransport* transport, UINT8* data, int bytes)
|
|||
status = tcp_read(transport->TcpIn, data + read, bytes - read);
|
||||
else if (transport->layer == TRANSPORT_LAYER_TSG)
|
||||
status = tsg_read(transport->tsg, data + read, bytes - read);
|
||||
else if (transport->layer == TRANSPORT_LAYER_TSG_TLS) {
|
||||
status = tls_read(transport->TsgTls, data + read, bytes - read);
|
||||
}
|
||||
|
||||
/* blocking means that we can't continue until this is read */
|
||||
|
||||
|
@ -540,6 +656,8 @@ int transport_write(rdpTransport* transport, wStream* s)
|
|||
status = tcp_write(transport->TcpOut, Stream_Pointer(s), length);
|
||||
else if (transport->layer == TRANSPORT_LAYER_TSG)
|
||||
status = tsg_write(transport->tsg, Stream_Pointer(s), length);
|
||||
else if (transport->layer == TRANSPORT_LAYER_TSG_TLS)
|
||||
status = tls_write(transport->TsgTls, Stream_Pointer(s), length);
|
||||
|
||||
if (status < 0)
|
||||
break; /* error occurred */
|
||||
|
@ -558,6 +676,8 @@ int transport_write(rdpTransport* transport, wStream* s)
|
|||
tls_wait_write(transport->TlsOut);
|
||||
else if (transport->layer == TRANSPORT_LAYER_TCP)
|
||||
tcp_wait_write(transport->TcpOut);
|
||||
else if (transport->layer == TRANSPORT_LAYER_TSG_TLS)
|
||||
tls_wait_write(transport->TsgTls);
|
||||
else
|
||||
USleep(transport->SleepInterval);
|
||||
}
|
||||
|
@ -784,7 +904,7 @@ BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking)
|
|||
status &= tcp_set_blocking_mode(transport->TcpIn, blocking);
|
||||
}
|
||||
|
||||
if (transport->layer == TRANSPORT_LAYER_TSG)
|
||||
if (transport->layer == TRANSPORT_LAYER_TSG || transport->layer == TRANSPORT_LAYER_TSG_TLS)
|
||||
{
|
||||
tsg_set_blocking_mode(transport->tsg, blocking);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ typedef enum
|
|||
TRANSPORT_LAYER_TCP,
|
||||
TRANSPORT_LAYER_TLS,
|
||||
TRANSPORT_LAYER_TSG,
|
||||
TRANSPORT_LAYER_TSG_TLS,
|
||||
TRANSPORT_LAYER_CLOSED
|
||||
} TRANSPORT_LAYER;
|
||||
|
||||
|
@ -57,6 +58,7 @@ struct rdp_transport
|
|||
rdpTcp* TcpOut;
|
||||
rdpTls* TlsIn;
|
||||
rdpTls* TlsOut;
|
||||
rdpTls* TsgTls;
|
||||
rdpCredssp* credssp;
|
||||
rdpSettings* settings;
|
||||
UINT32 SleepInterval;
|
||||
|
|
|
@ -97,6 +97,14 @@ SecPkgContext_Bindings* tls_get_channel_bindings(X509* cert)
|
|||
return ContextBindings;
|
||||
}
|
||||
|
||||
static void tls_ssl_info_callback(const SSL* ssl, int type, int val)
|
||||
{
|
||||
if (type & SSL_CB_HANDSHAKE_START)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
BOOL tls_connect(rdpTls* tls)
|
||||
{
|
||||
CryptoCert cert;
|
||||
|
@ -106,7 +114,7 @@ BOOL tls_connect(rdpTls* tls)
|
|||
|
||||
tls->ctx = SSL_CTX_new(TLSv1_client_method());
|
||||
|
||||
if (tls->ctx == NULL)
|
||||
if (!tls->ctx)
|
||||
{
|
||||
fprintf(stderr, "SSL_CTX_new failed\n");
|
||||
return FALSE;
|
||||
|
@ -147,16 +155,35 @@ BOOL tls_connect(rdpTls* tls)
|
|||
|
||||
tls->ssl = SSL_new(tls->ctx);
|
||||
|
||||
if (tls->ssl == NULL)
|
||||
if (!tls->ssl)
|
||||
{
|
||||
fprintf(stderr, "SSL_new failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (SSL_set_fd(tls->ssl, tls->sockfd) < 1)
|
||||
if (tls->tsg)
|
||||
{
|
||||
fprintf(stderr, "SSL_set_fd failed\n");
|
||||
return FALSE;
|
||||
tls->bio = BIO_new(tls->methods);
|
||||
|
||||
if (!tls->bio)
|
||||
{
|
||||
fprintf(stderr, "BIO_new failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tls->bio->ptr = tls->tsg;
|
||||
|
||||
SSL_set_bio(tls->ssl, tls->bio, tls->bio);
|
||||
|
||||
SSL_CTX_set_info_callback(tls->ctx, tls_ssl_info_callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SSL_set_fd(tls->ssl, tls->sockfd) < 1)
|
||||
{
|
||||
fprintf(stderr, "SSL_set_fd failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
connection_status = SSL_connect(tls->ssl);
|
||||
|
|
Loading…
Reference in New Issue