freerdp: fix sending of TLS alert on NLA failure, add better handling of server-side NLA in shadow server

This commit is contained in:
Marc-André Moreau 2016-07-21 17:53:20 -04:00
parent 05d63c6874
commit 1ffbd774e9
9 changed files with 156 additions and 18 deletions

View File

@ -110,6 +110,7 @@ struct rdp_shadow_server
HANDLE thread;
HANDLE StopEvent;
wArrayList* clients;
rdpSettings* settings;
rdpShadowScreen* screen;
rdpShadowSurface* surface;
rdpShadowSurface* lobby;

View File

@ -1044,12 +1044,12 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
{
if (settings->NlaSecurity && !settings->TlsSecurity)
{
WLog_ERR(TAG, "server supports only NLA Security");
WLog_WARN(TAG, "server supports only NLA Security");
nego->SelectedProtocol |= HYBRID_REQUIRED_BY_SERVER;
}
else
{
WLog_ERR(TAG, "server supports only a SSL based Security (TLS or NLA)");
WLog_WARN(TAG, "server supports only a SSL based Security (TLS or NLA)");
nego->SelectedProtocol |= SSL_REQUIRED_BY_SERVER;
}
}

View File

@ -476,6 +476,10 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
return -1;
}
client->settings->NlaSecurity = (rdp->nego->SelectedProtocol & PROTOCOL_NLA) ? TRUE : FALSE;
client->settings->TlsSecurity = (rdp->nego->SelectedProtocol & PROTOCOL_TLS) ? TRUE : FALSE;
client->settings->RdpSecurity = (rdp->nego->SelectedProtocol & PROTOCOL_RDP) ? TRUE : FALSE;
if (rdp->nego->SelectedProtocol & PROTOCOL_NLA)
{
sspi_CopyAuthIdentity(&client->identity, rdp->nego->transport->nla->identity);
@ -686,6 +690,7 @@ BOOL freerdp_peer_context_new(freerdp_peer* client)
context->peer = client;
context->ServerMode = TRUE;
context->settings = client->settings;
if (!(context->metrics = metrics_new(context)))
goto fail_metrics;

View File

@ -363,6 +363,7 @@ BOOL transport_accept_nla(rdpTransport* transport)
nla_free(transport->nla);
transport->nla = NULL;
tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
tls_send_alert(transport->tls);
return FALSE;
}

View File

@ -1011,10 +1011,10 @@ BOOL tls_send_alert(rdpTls* tls)
if (tls->ssl->s3->wbuf.left == 0)
tls->ssl->method->ssl_dispatch_alert(tls->ssl);
}
return TRUE;
}
BIO *findBufferedBio(BIO *front)
{
BIO *ret = front;
@ -1067,7 +1067,6 @@ int tls_set_alert_code(rdpTls* tls, int level, int description)
{
tls->alertLevel = level;
tls->alertDescription = description;
return 0;
}

View File

@ -42,6 +42,7 @@ int main(int argc, char** argv)
MSG msg;
int status = 0;
DWORD dwExitCode;
rdpSettings* settings;
rdpShadowServer* server;
shadow_subsystem_set_entry_builtin(NULL);
@ -54,6 +55,12 @@ int main(int argc, char** argv)
goto fail_server_new;
}
settings = server->settings;
settings->NlaSecurity = FALSE;
settings->TlsSecurity = TRUE;
settings->RdpSecurity = TRUE;
#ifdef WITH_SHADOW_X11
server->authentication = TRUE;
#else
@ -86,8 +93,7 @@ int main(int argc, char** argv)
if (!GetExitCodeThread(server->thread, &dwExitCode))
status = -1;
else
status = (int)dwExitCode;
status = (int) dwExitCode;
fail_server_start:
shadow_server_uninit(server);

View File

@ -70,10 +70,6 @@ BOOL shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
settings->CompressionLevel = PACKET_COMPR_TYPE_RDP6;
settings->RdpSecurity = TRUE;
settings->TlsSecurity = TRUE;
settings->NlaSecurity = FALSE;
if (!(settings->CertificateFile = _strdup(server->CertificateFile)))
goto fail_cert_file;
if (!(settings->PrivateKeyFile = _strdup(server->PrivateKeyFile)))
@ -146,7 +142,7 @@ void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
WTSCloseServer((HANDLE) client->vcm);
/* Clear queued messages and free resource */
/* Clear queued messages and free resource */
MessageQueue_Clear(client->MsgQueue);
MessageQueue_Free(client->MsgQueue);
@ -250,17 +246,14 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
if (settings->Username && settings->Password)
settings->AutoLogonEnabled = TRUE;
if (server->authentication)
if (server->authentication && !settings->NlaSecurity)
{
if (subsystem->Authenticate)
{
authStatus = subsystem->Authenticate(subsystem, client,
settings->Username, settings->Domain, settings->Password);
}
}
if (server->authentication)
{
if (authStatus < 0)
{
WLog_ERR(TAG, "client authentication failure: %d", authStatus);
@ -385,6 +378,64 @@ BOOL shadow_client_activate(freerdp_peer* peer)
return shadow_client_refresh_rect(client, 0, NULL);
}
BOOL shadow_client_logon(freerdp_peer* peer, SEC_WINNT_AUTH_IDENTITY* identity, BOOL automatic)
{
char* user = NULL;
char* domain = NULL;
char* password = NULL;
rdpSettings* settings = peer->settings;
if (identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
{
if (identity->User)
ConvertFromUnicode(CP_UTF8, 0, identity->User, identity->UserLength, &user, 0, NULL, NULL);
if (identity->Domain)
ConvertFromUnicode(CP_UTF8, 0, identity->Domain, identity->DomainLength, &domain, 0, NULL, NULL);
if (identity->Password)
ConvertFromUnicode(CP_UTF8, 0, identity->Password, identity->PasswordLength, &user, 0, NULL, NULL);
}
else
{
if (identity->User)
user = _strdup((char*) identity->User);
if (identity->Domain)
domain = _strdup((char*) identity->Domain);
if (identity->Password)
password = _strdup((char*) identity->Password);
}
if (user)
{
free(settings->Username);
settings->Username = user;
user = NULL;
}
if (domain)
{
free(settings->Domain);
settings->Domain = domain;
user = NULL;
}
if (password)
{
free(settings->Password);
settings->Password = password;
password = NULL;
}
free(user);
free(domain);
free(password);
return TRUE;
}
BOOL shadow_client_surface_frame_acknowledge(rdpShadowClient* client, UINT32 frameId)
{
/*
@ -993,6 +1044,7 @@ void* shadow_client_thread(rdpShadowClient* client)
peer->Capabilities = shadow_client_capabilities;
peer->PostConnect = shadow_client_post_connect;
peer->Activate = shadow_client_activate;
peer->Logon = shadow_client_logon;
shadow_input_register_callbacks(peer->input);
@ -1199,6 +1251,8 @@ BOOL shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
peer->ContextNew = (psPeerContextNew) shadow_client_context_new;
peer->ContextFree = (psPeerContextFree) shadow_client_context_free;
peer->settings = freerdp_settings_clone(server->settings);
if (!freerdp_peer_context_new(peer))
return FALSE;

View File

@ -50,6 +50,11 @@ static COMMAND_LINE_ARGUMENT_A shadow_args[] =
{ "auth", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Clients must authenticate" },
{ "may-view", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Clients may view without prompt" },
{ "may-interact", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Clients may interact without prompt" },
{ "sec", COMMAND_LINE_VALUE_REQUIRED, "<rdp|tls|nla|ext>", NULL, NULL, -1, NULL, "force specific protocol security" },
{ "sec-rdp", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "rdp protocol security" },
{ "sec-tls", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "tls protocol security" },
{ "sec-nla", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "nla protocol security" },
{ "sec-ext", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "nla extended protocol security" },
{ "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, NULL, "Print version" },
{ "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, NULL, NULL, NULL, -1, "?", "Print help" },
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
@ -149,6 +154,7 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
int status;
DWORD flags;
COMMAND_LINE_ARGUMENT_A* arg;
rdpSettings* settings = server->settings;
if (argc < 2)
return 1;
@ -253,6 +259,58 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
{
server->authentication = arg->Value ? TRUE : FALSE;
}
CommandLineSwitchCase(arg, "sec")
{
if (strcmp("rdp", arg->Value) == 0) /* Standard RDP */
{
settings->RdpSecurity = TRUE;
settings->TlsSecurity = FALSE;
settings->NlaSecurity = FALSE;
settings->ExtSecurity = FALSE;
settings->UseRdpSecurityLayer = TRUE;
}
else if (strcmp("tls", arg->Value) == 0) /* TLS */
{
settings->RdpSecurity = FALSE;
settings->TlsSecurity = TRUE;
settings->NlaSecurity = FALSE;
settings->ExtSecurity = FALSE;
}
else if (strcmp("nla", arg->Value) == 0) /* NLA */
{
settings->RdpSecurity = FALSE;
settings->TlsSecurity = FALSE;
settings->NlaSecurity = TRUE;
settings->ExtSecurity = FALSE;
}
else if (strcmp("ext", arg->Value) == 0) /* NLA Extended */
{
settings->RdpSecurity = FALSE;
settings->TlsSecurity = FALSE;
settings->NlaSecurity = FALSE;
settings->ExtSecurity = TRUE;
}
else
{
WLog_ERR(TAG, "unknown protocol security: %s", arg->Value);
}
}
CommandLineSwitchCase(arg, "sec-rdp")
{
settings->RdpSecurity = arg->Value ? TRUE : FALSE;
}
CommandLineSwitchCase(arg, "sec-tls")
{
settings->TlsSecurity = arg->Value ? TRUE : FALSE;
}
CommandLineSwitchCase(arg, "sec-nla")
{
settings->NlaSecurity = arg->Value ? TRUE : FALSE;
}
CommandLineSwitchCase(arg, "sec-ext")
{
settings->ExtSecurity = arg->Value ? TRUE : FALSE;
}
CommandLineSwitchDefault(arg)
{
@ -708,6 +766,11 @@ rdpShadowServer* shadow_server_new()
server->authentication = FALSE;
server->settings = freerdp_settings_new(FREERDP_SETTINGS_SERVER_MODE);
if (!server)
return NULL;
return server;
}
@ -716,8 +779,17 @@ void shadow_server_free(rdpShadowServer* server)
if (!server)
return;
free(server->ipcSocket);
server->ipcSocket = NULL;
if (server->ipcSocket)
{
free(server->ipcSocket);
server->ipcSocket = NULL;
}
if (server->settings)
{
freerdp_settings_free(server->settings);
server->settings = NULL;
}
free(server);
}

View File

@ -28,7 +28,7 @@
#include "../sspi.h"
#include "../log.h"
#define TAG WINPR_TAG("negociate")
#define TAG WINPR_TAG("negotiate")
extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA;
extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW;