libfreerdp-core: improve http parsing

This commit is contained in:
Marc-André Moreau 2015-02-02 17:16:32 -05:00
parent e4f99834d0
commit e0b0c77ecb
10 changed files with 313 additions and 206 deletions

View File

@ -273,7 +273,7 @@ BOOL rdp_client_connect(rdpRdp* rdp)
return FALSE; return FALSE;
} }
if ((rdp->nego->selected_protocol & PROTOCOL_TLS) || (rdp->nego->selected_protocol == PROTOCOL_RDP)) if ((rdp->nego->SelectedProtocol & PROTOCOL_TLS) || (rdp->nego->SelectedProtocol == PROTOCOL_RDP))
{ {
if ((settings->Username != NULL) && ((settings->Password != NULL) || if ((settings->Username != NULL) && ((settings->Password != NULL) ||
(settings->RedirectionPassword != NULL && settings->RedirectionPasswordLength > 0))) (settings->RedirectionPassword != NULL && settings->RedirectionPasswordLength > 0)))
@ -973,26 +973,26 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
if (!nego_read_request(nego, s)) if (!nego_read_request(nego, s))
return FALSE; return FALSE;
nego->selected_protocol = 0; nego->SelectedProtocol = 0;
WLog_INFO(TAG, "Client Security: NLA:%d TLS:%d RDP:%d", WLog_INFO(TAG, "Client Security: NLA:%d TLS:%d RDP:%d",
(nego->requested_protocols & PROTOCOL_NLA) ? 1 : 0, (nego->RequestedProtocols & PROTOCOL_NLA) ? 1 : 0,
(nego->requested_protocols & PROTOCOL_TLS) ? 1 : 0, (nego->RequestedProtocols & PROTOCOL_TLS) ? 1 : 0,
(nego->requested_protocols == PROTOCOL_RDP) ? 1 : 0 (nego->RequestedProtocols == PROTOCOL_RDP) ? 1 : 0
); );
WLog_INFO(TAG, "Server Security: NLA:%d TLS:%d RDP:%d", WLog_INFO(TAG, "Server Security: NLA:%d TLS:%d RDP:%d",
settings->NlaSecurity, settings->TlsSecurity, settings->RdpSecurity); settings->NlaSecurity, settings->TlsSecurity, settings->RdpSecurity);
if ((settings->NlaSecurity) && (nego->requested_protocols & PROTOCOL_NLA)) if ((settings->NlaSecurity) && (nego->RequestedProtocols & PROTOCOL_NLA))
{ {
nego->selected_protocol = PROTOCOL_NLA; nego->SelectedProtocol = PROTOCOL_NLA;
} }
else if ((settings->TlsSecurity) && (nego->requested_protocols & PROTOCOL_TLS)) else if ((settings->TlsSecurity) && (nego->RequestedProtocols & PROTOCOL_TLS))
{ {
nego->selected_protocol = PROTOCOL_TLS; nego->SelectedProtocol = PROTOCOL_TLS;
} }
else if ((settings->RdpSecurity) && (nego->selected_protocol == PROTOCOL_RDP)) else if ((settings->RdpSecurity) && (nego->SelectedProtocol == PROTOCOL_RDP))
{ {
nego->selected_protocol = PROTOCOL_RDP; nego->SelectedProtocol = PROTOCOL_RDP;
} }
else else
{ {
@ -1000,9 +1000,9 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
} }
WLog_INFO(TAG, "Negotiated Security: NLA:%d TLS:%d RDP:%d", WLog_INFO(TAG, "Negotiated Security: NLA:%d TLS:%d RDP:%d",
(nego->selected_protocol & PROTOCOL_NLA) ? 1 : 0, (nego->SelectedProtocol & PROTOCOL_NLA) ? 1 : 0,
(nego->selected_protocol & PROTOCOL_TLS) ? 1 : 0, (nego->SelectedProtocol & PROTOCOL_TLS) ? 1 : 0,
(nego->selected_protocol == PROTOCOL_RDP) ? 1: 0 (nego->SelectedProtocol == PROTOCOL_RDP) ? 1: 0
); );
if (!nego_send_negotiation_response(nego)) if (!nego_send_negotiation_response(nego))
@ -1010,11 +1010,11 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
status = FALSE; status = FALSE;
if (nego->selected_protocol & PROTOCOL_NLA) if (nego->SelectedProtocol & PROTOCOL_NLA)
status = transport_accept_nla(rdp->transport); status = transport_accept_nla(rdp->transport);
else if (nego->selected_protocol & PROTOCOL_TLS) else if (nego->SelectedProtocol & PROTOCOL_TLS)
status = transport_accept_tls(rdp->transport); status = transport_accept_tls(rdp->transport);
else if (nego->selected_protocol == PROTOCOL_RDP) /* 0 */ else if (nego->SelectedProtocol == PROTOCOL_RDP) /* 0 */
status = transport_accept_rdp(rdp->transport); status = transport_accept_rdp(rdp->transport);
if (!status) if (!status)

View File

@ -34,6 +34,51 @@
#define TAG "gateway" #define TAG "gateway"
static char* string_strnstr(const char* str1, const char* str2, size_t slen)
{
char c, sc;
size_t len;
if ((c = *str2++) != '\0')
{
len = strlen(str2);
do
{
do
{
if (slen-- < 1 || (sc = *str1++) == '\0')
return NULL;
}
while(sc != c);
if (len > slen)
return NULL;
}
while(strncmp(str1, str2, len) != 0);
str1--;
}
return ((char*) str1);
}
static BOOL strings_equals_nocase(void* obj1, void* obj2)
{
if (!obj1 || !obj2)
return FALSE;
return _stricmp(obj1, obj2) == 0;
}
static void string_free(void* obj1)
{
if (!obj1)
return;
free(obj1);
}
HttpContext* http_context_new() HttpContext* http_context_new()
{ {
return (HttpContext*) calloc(1, sizeof(HttpContext)); return (HttpContext*) calloc(1, sizeof(HttpContext));
@ -397,6 +442,13 @@ BOOL http_response_parse_header_field(HttpResponse* response, char* name, char*
{ {
response->ContentLength = atoi(value); response->ContentLength = atoi(value);
} }
else if (_stricmp(name, "Content-Type") == 0)
{
response->ContentType = _strdup(value);
if (!response->ContentType)
return FALSE;
}
else if (_stricmp(name, "WWW-Authenticate") == 0) else if (_stricmp(name, "WWW-Authenticate") == 0)
{ {
char* separator = NULL; char* separator = NULL;
@ -440,6 +492,7 @@ BOOL http_response_parse_header_field(HttpResponse* response, char* name, char*
BOOL http_response_parse_header(HttpResponse* response) BOOL http_response_parse_header(HttpResponse* response)
{ {
char c;
int count; int count;
char* line; char* line;
char* name; char* name;
@ -447,7 +500,6 @@ BOOL http_response_parse_header(HttpResponse* response)
char* colon_pos; char* colon_pos;
char* end_of_header; char* end_of_header;
char end_of_header_char; char end_of_header_char;
char c;
if (!response) if (!response)
return FALSE; return FALSE;
@ -522,22 +574,29 @@ void http_response_print(HttpResponse* response)
HttpResponse* http_response_recv(rdpTls* tls) HttpResponse* http_response_recv(rdpTls* tls)
{ {
int nbytes; wStream* s;
int length; int size;
int count;
int status; int status;
BYTE* buffer; int position;
char* content; char* line;
char* header_end; char* buffer;
char* header;
char* payload;
int bodyLength;
int payloadOffset;
HttpResponse* response; HttpResponse* response;
nbytes = 0; size = 1024;
length = 10000; payload = NULL;
content = NULL; payloadOffset = 0;
buffer = calloc(length, 1); s = Stream_New(NULL, size);
if (!buffer) if (!s)
return NULL; goto out_free;
buffer = (char*) Stream_Buffer(s);
response = http_response_new(); response = http_response_new();
@ -548,9 +607,9 @@ HttpResponse* http_response_recv(rdpTls* tls)
while (TRUE) while (TRUE)
{ {
while (nbytes < 5) while (!payloadOffset)
{ {
status = BIO_read(tls->bio, &buffer[nbytes], length - nbytes); status = BIO_read(tls->bio, Stream_Pointer(s), Stream_Capacity(s) - Stream_GetPosition(s));
if (status <= 0) if (status <= 0)
{ {
@ -564,34 +623,40 @@ HttpResponse* http_response_recv(rdpTls* tls)
#ifdef HAVE_VALGRIND_MEMCHECK_H #ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(p, status); VALGRIND_MAKE_MEM_DEFINED(p, status);
#endif #endif
nbytes += status;
}
header_end = strstr((char*) buffer, "\r\n\r\n"); Stream_Seek(s, status);
if (!header_end) if (Stream_GetRemainingLength(s) < 1024)
{
WLog_ERR(TAG, "invalid response");
winpr_HexDump(TAG, WLOG_ERROR, buffer, status);
goto out_error;
}
header_end += 2;
if (header_end)
{
int count;
char* line;
header_end[0] = '\0';
header_end[1] = '\0';
content = header_end + 2;
count = 0;
line = (char*) buffer;
while ((line = strstr(line, "\r\n")) != NULL)
{ {
line++; Stream_EnsureRemainingCapacity(s, 1024);
buffer = (char*) Stream_Buffer(s);
payload = &buffer[payloadOffset];
}
position = Stream_GetPosition(s);
if (position >= 4)
{
line = string_strnstr(buffer, "\r\n\r\n", position);
if (line)
{
payloadOffset = (line - buffer) + 4;
payload = &buffer[payloadOffset];
}
}
}
if (payloadOffset)
{
count = 0;
line = buffer;
position = Stream_GetPosition(s);
while ((line = string_strnstr(line, "\r\n", payloadOffset - (line - buffer) - 2)))
{
line += 2;
count++; count++;
} }
@ -605,8 +670,17 @@ HttpResponse* http_response_recv(rdpTls* tls)
goto out_error; goto out_error;
} }
header = (char*) malloc(payloadOffset);
if (!header)
goto out_error;
CopyMemory(header, buffer, payloadOffset);
header[payloadOffset - 1] = '\0';
header[payloadOffset - 2] = '\0';
count = 0; count = 0;
line = strtok((char*) buffer, "\r\n"); line = strtok(header, "\r\n");
while (line && response->lines) while (line && response->lines)
{ {
@ -619,10 +693,12 @@ HttpResponse* http_response_recv(rdpTls* tls)
count++; count++;
} }
free(header);
if (!http_response_parse_header(response)) if (!http_response_parse_header(response))
goto out_error; goto out_error;
response->BodyLength = nbytes - (content - (char*) buffer); response->BodyLength = Stream_GetPosition(s) - payloadOffset;
if (response->BodyLength > 0) if (response->BodyLength > 0)
{ {
@ -631,44 +707,45 @@ HttpResponse* http_response_recv(rdpTls* tls)
if (!response->BodyContent) if (!response->BodyContent)
goto out_error; goto out_error;
CopyMemory(response->BodyContent, content, response->BodyLength); CopyMemory(response->BodyContent, payload, response->BodyLength);
}
bodyLength = 0; /* expected body length */
if (response->ContentType)
{
if (_stricmp(response->ContentType, "text/plain") == 0)
{
bodyLength = response->ContentLength;
}
}
if (bodyLength != response->BodyLength)
{
WLog_WARN(TAG, "http_response_recv: %s unexpected body length: actual: %d, expected: %d",
response->ContentType, response->ContentLength, response->BodyLength);
} }
break; break;
} }
if ((length - nbytes) <= 0) if (Stream_GetRemainingLength(s) < 1024)
{ {
length *= 2; Stream_EnsureRemainingCapacity(s, 1024);
buffer = realloc(buffer, length); buffer = (char*) Stream_Buffer(s);
payload = &buffer[payloadOffset];
} }
} }
free(buffer); Stream_Free(s, TRUE);
return response; return response;
out_error: out_error:
http_response_free(response); http_response_free(response);
out_free: out_free:
free(buffer); Stream_Free(s, TRUE);
return NULL; return NULL;
} }
static BOOL strings_equals_nocase(void* obj1, void* obj2)
{
if (!obj1 || !obj2)
return FALSE;
return _stricmp(obj1, obj2) == 0;
}
static void string_free(void* obj1)
{
if (!obj1)
return;
free(obj1);
}
HttpResponse* http_response_new() HttpResponse* http_response_new()
{ {
HttpResponse* response = (HttpResponse*) calloc(1, sizeof(HttpResponse)); HttpResponse* response = (HttpResponse*) calloc(1, sizeof(HttpResponse));
@ -703,6 +780,8 @@ void http_response_free(HttpResponse* response)
free(response->lines); free(response->lines);
free(response->ReasonPhrase); free(response->ReasonPhrase);
free(response->ContentType);
ListDictionary_Free(response->Authenticates); ListDictionary_Free(response->Authenticates);
if (response->ContentLength > 0) if (response->ContentLength > 0)

View File

@ -83,6 +83,7 @@ struct _http_response
char* ReasonPhrase; char* ReasonPhrase;
int ContentLength; int ContentLength;
char* ContentType;
int BodyLength; int BodyLength;
BYTE* BodyContent; BYTE* BodyContent;

View File

@ -243,19 +243,19 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc)
int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc) int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc)
{ {
char* token64; char* token64;
HttpResponse* response;
int ntlm_token_length = 0; int ntlm_token_length = 0;
BYTE* ntlm_token_data = NULL; BYTE* ntlm_token_data = NULL;
HttpResponse* http_response;
rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm; rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm;
http_response = http_response_recv(rpc->TlsOut); response = http_response_recv(rpc->TlsOut);
if (!http_response) if (!response)
return -1; return -1;
if (ListDictionary_Contains(http_response->Authenticates, "NTLM")) if (ListDictionary_Contains(response->Authenticates, "NTLM"))
{ {
token64 = ListDictionary_GetItemValue(http_response->Authenticates, "NTLM"); token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM");
if (!token64) if (!token64)
goto out; goto out;
@ -266,7 +266,7 @@ int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc)
out: out:
ntlm->inputBuffer[0].pvBuffer = ntlm_token_data; ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
ntlm->inputBuffer[0].cbBuffer = ntlm_token_length; ntlm->inputBuffer[0].cbBuffer = ntlm_token_length;
http_response_free(http_response); http_response_free(response);
return 1; return 1;
} }
@ -297,15 +297,24 @@ BOOL rpc_ntlm_http_out_connect(rdpRpc* rpc)
/* Send OUT Channel Request */ /* Send OUT Channel Request */
if (rpc_ncacn_http_send_out_channel_request(rpc) <= 0) if (rpc_ncacn_http_send_out_channel_request(rpc) <= 0)
{
WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
goto out; goto out;
}
/* Receive OUT Channel Response */ /* Receive OUT Channel Response */
if (rpc_ncacn_http_recv_out_channel_response(rpc) <= 0) if (rpc_ncacn_http_recv_out_channel_response(rpc) <= 0)
{
WLog_ERR(TAG, "rpc_ncacn_http_recv_out_channel_response failure");
goto out; goto out;
}
/* Send OUT Channel Request */ /* Send OUT Channel Request */
if (rpc_ncacn_http_send_out_channel_request(rpc) <= 0) if (rpc_ncacn_http_send_out_channel_request(rpc) <= 0)
{
WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
goto out; goto out;
}
status = TRUE; status = TRUE;

View File

@ -126,6 +126,11 @@ BOOL rts_connect(rdpRpc* rpc)
return FALSE; return FALSE;
} }
WLog_DBG(TAG, "HTTP Body (%d):", response->BodyLength);
if (response->BodyLength)
winpr_HexDump(TAG, WLOG_DEBUG, response->BodyContent, response->BodyLength);
http_response_free(response); http_response_free(response);
rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_WAIT_A3W; rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_WAIT_A3W;

View File

@ -1367,7 +1367,7 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port)
if (!rts_connect(rpc)) if (!rts_connect(rpc))
{ {
WLog_ERR(TAG, "rts_connect error!"); WLog_ERR(TAG, "rts_connect error!");
return -1; return FALSE;
} }
ReadEvent = NULL; ReadEvent = NULL;

View File

@ -74,19 +74,19 @@ BOOL nego_connect(rdpNego* nego)
if (nego->state == NEGO_STATE_INITIAL) if (nego->state == NEGO_STATE_INITIAL)
{ {
if (nego->enabled_protocols[PROTOCOL_EXT]) if (nego->EnabledProtocols[PROTOCOL_EXT])
{ {
nego->state = NEGO_STATE_EXT; nego->state = NEGO_STATE_EXT;
} }
else if (nego->enabled_protocols[PROTOCOL_NLA]) else if (nego->EnabledProtocols[PROTOCOL_NLA])
{ {
nego->state = NEGO_STATE_NLA; nego->state = NEGO_STATE_NLA;
} }
else if (nego->enabled_protocols[PROTOCOL_TLS]) else if (nego->EnabledProtocols[PROTOCOL_TLS])
{ {
nego->state = NEGO_STATE_TLS; nego->state = NEGO_STATE_TLS;
} }
else if (nego->enabled_protocols[PROTOCOL_RDP]) else if (nego->EnabledProtocols[PROTOCOL_RDP])
{ {
nego->state = NEGO_STATE_RDP; nego->state = NEGO_STATE_RDP;
} }
@ -102,39 +102,42 @@ BOOL nego_connect(rdpNego* nego)
WLog_DBG(TAG, "Security Layer Negotiation is disabled"); WLog_DBG(TAG, "Security Layer Negotiation is disabled");
/* attempt only the highest enabled protocol (see nego_attempt_*) */ /* attempt only the highest enabled protocol (see nego_attempt_*) */
nego->enabled_protocols[PROTOCOL_NLA] = FALSE; nego->EnabledProtocols[PROTOCOL_NLA] = FALSE;
nego->enabled_protocols[PROTOCOL_TLS] = FALSE; nego->EnabledProtocols[PROTOCOL_TLS] = FALSE;
nego->enabled_protocols[PROTOCOL_RDP] = FALSE; nego->EnabledProtocols[PROTOCOL_RDP] = FALSE;
nego->enabled_protocols[PROTOCOL_EXT] = FALSE; nego->EnabledProtocols[PROTOCOL_EXT] = FALSE;
if (nego->state == NEGO_STATE_EXT) if (nego->state == NEGO_STATE_EXT)
{ {
nego->enabled_protocols[PROTOCOL_EXT] = TRUE; nego->EnabledProtocols[PROTOCOL_EXT] = TRUE;
nego->enabled_protocols[PROTOCOL_NLA] = TRUE; nego->EnabledProtocols[PROTOCOL_NLA] = TRUE;
nego->selected_protocol = PROTOCOL_EXT; nego->SelectedProtocol = PROTOCOL_EXT;
} }
else if (nego->state == NEGO_STATE_NLA) else if (nego->state == NEGO_STATE_NLA)
{ {
nego->enabled_protocols[PROTOCOL_NLA] = TRUE; nego->EnabledProtocols[PROTOCOL_NLA] = TRUE;
nego->selected_protocol = PROTOCOL_NLA; nego->SelectedProtocol = PROTOCOL_NLA;
} }
else if (nego->state == NEGO_STATE_TLS) else if (nego->state == NEGO_STATE_TLS)
{ {
nego->enabled_protocols[PROTOCOL_TLS] = TRUE; nego->EnabledProtocols[PROTOCOL_TLS] = TRUE;
nego->selected_protocol = PROTOCOL_TLS; nego->SelectedProtocol = PROTOCOL_TLS;
} }
else if (nego->state == NEGO_STATE_RDP) else if (nego->state == NEGO_STATE_RDP)
{ {
nego->enabled_protocols[PROTOCOL_RDP] = TRUE; nego->EnabledProtocols[PROTOCOL_RDP] = TRUE;
nego->selected_protocol = PROTOCOL_RDP; nego->SelectedProtocol = PROTOCOL_RDP;
} }
} }
if (!nego_send_preconnection_pdu(nego)) if (nego->SendPreconnectionPdu)
{ {
WLog_ERR(TAG, "Failed to send preconnection pdu"); if (!nego_send_preconnection_pdu(nego))
nego->state = NEGO_STATE_FINAL; {
return FALSE; WLog_ERR(TAG, "Failed to send preconnection pdu");
nego->state = NEGO_STATE_FINAL;
return FALSE;
}
} }
} }
@ -153,14 +156,14 @@ BOOL nego_connect(rdpNego* nego)
} }
while (nego->state != NEGO_STATE_FINAL); while (nego->state != NEGO_STATE_FINAL);
WLog_DBG(TAG, "Negotiated %s security", PROTOCOL_SECURITY_STRINGS[nego->selected_protocol]); WLog_DBG(TAG, "Negotiated %s security", PROTOCOL_SECURITY_STRINGS[nego->SelectedProtocol]);
/* update settings with negotiated protocol security */ /* update settings with negotiated protocol security */
settings->RequestedProtocols = nego->requested_protocols; settings->RequestedProtocols = nego->RequestedProtocols;
settings->SelectedProtocol = nego->selected_protocol; settings->SelectedProtocol = nego->SelectedProtocol;
settings->NegotiationFlags = nego->flags; settings->NegotiationFlags = nego->flags;
if (nego->selected_protocol == PROTOCOL_RDP) if (nego->SelectedProtocol == PROTOCOL_RDP)
{ {
settings->UseRdpSecurityLayer = TRUE; settings->UseRdpSecurityLayer = TRUE;
@ -177,7 +180,7 @@ BOOL nego_connect(rdpNego* nego)
/* finally connect security layer (if not already done) */ /* finally connect security layer (if not already done) */
if (!nego_security_connect(nego)) if (!nego_security_connect(nego))
{ {
WLog_DBG(TAG, "Failed to connect with %s security", PROTOCOL_SECURITY_STRINGS[nego->selected_protocol]); WLog_DBG(TAG, "Failed to connect with %s security", PROTOCOL_SECURITY_STRINGS[nego->SelectedProtocol]);
return FALSE; return FALSE;
} }
@ -196,26 +199,26 @@ BOOL nego_disconnect(rdpNego* nego)
/* connect to selected security layer */ /* connect to selected security layer */
BOOL nego_security_connect(rdpNego* nego) BOOL nego_security_connect(rdpNego* nego)
{ {
if (!nego->tcp_connected) if (!nego->TcpConnected)
{ {
nego->security_connected = FALSE; nego->SecurityConnected = FALSE;
} }
else if (!nego->security_connected) else if (!nego->SecurityConnected)
{ {
if (nego->selected_protocol == PROTOCOL_NLA) if (nego->SelectedProtocol == PROTOCOL_NLA)
{ {
WLog_DBG(TAG, "nego_security_connect with PROTOCOL_NLA"); WLog_DBG(TAG, "nego_security_connect with PROTOCOL_NLA");
nego->security_connected = transport_connect_nla(nego->transport); nego->SecurityConnected = transport_connect_nla(nego->transport);
} }
else if (nego->selected_protocol == PROTOCOL_TLS) else if (nego->SelectedProtocol == PROTOCOL_TLS)
{ {
WLog_DBG(TAG, "nego_security_connect with PROTOCOL_TLS"); WLog_DBG(TAG, "nego_security_connect with PROTOCOL_TLS");
nego->security_connected = transport_connect_tls(nego->transport); nego->SecurityConnected = transport_connect_tls(nego->transport);
} }
else if (nego->selected_protocol == PROTOCOL_RDP) else if (nego->SelectedProtocol == PROTOCOL_RDP)
{ {
WLog_DBG(TAG, "nego_security_connect with PROTOCOL_RDP"); WLog_DBG(TAG, "nego_security_connect with PROTOCOL_RDP");
nego->security_connected = transport_connect_rdp(nego->transport); nego->SecurityConnected = transport_connect_rdp(nego->transport);
} }
else else
{ {
@ -223,7 +226,7 @@ BOOL nego_security_connect(rdpNego* nego)
} }
} }
return nego->security_connected; return nego->SecurityConnected;
} }
/** /**
@ -234,7 +237,7 @@ BOOL nego_security_connect(rdpNego* nego)
BOOL nego_tcp_connect(rdpNego* nego) BOOL nego_tcp_connect(rdpNego* nego)
{ {
if (!nego->tcp_connected) if (!nego->TcpConnected)
{ {
if (nego->GatewayEnabled) if (nego->GatewayEnabled)
{ {
@ -244,22 +247,22 @@ BOOL nego_tcp_connect(rdpNego* nego)
WLog_INFO(TAG, "Detecting if host can be reached locally. - This might take some time."); WLog_INFO(TAG, "Detecting if host can be reached locally. - This might take some time.");
WLog_INFO(TAG, "To disable auto detection use /gateway-usage-method:direct"); WLog_INFO(TAG, "To disable auto detection use /gateway-usage-method:direct");
transport_set_gateway_enabled(nego->transport, FALSE); transport_set_gateway_enabled(nego->transport, FALSE);
nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port, 1); nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port, 1);
} }
if (!nego->tcp_connected) if (!nego->TcpConnected)
{ {
transport_set_gateway_enabled(nego->transport, TRUE); transport_set_gateway_enabled(nego->transport, TRUE);
nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port, 15); nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port, 15);
} }
} }
else else
{ {
nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port, 15); nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port, 15);
} }
} }
return nego->tcp_connected; return nego->TcpConnected;
} }
/** /**
@ -272,10 +275,10 @@ BOOL nego_transport_connect(rdpNego* nego)
{ {
nego_tcp_connect(nego); nego_tcp_connect(nego);
if (nego->tcp_connected && !nego->NegotiateSecurityLayer) if (nego->TcpConnected && !nego->NegotiateSecurityLayer)
return nego_security_connect(nego); return nego_security_connect(nego);
return nego->tcp_connected; return nego->TcpConnected;
} }
/** /**
@ -286,11 +289,11 @@ BOOL nego_transport_connect(rdpNego* nego)
BOOL nego_transport_disconnect(rdpNego* nego) BOOL nego_transport_disconnect(rdpNego* nego)
{ {
if (nego->tcp_connected) if (nego->TcpConnected)
transport_disconnect(nego->transport); transport_disconnect(nego->transport);
nego->tcp_connected = FALSE; nego->TcpConnected = FALSE;
nego->security_connected = FALSE; nego->SecurityConnected = FALSE;
return TRUE; return TRUE;
} }
@ -308,9 +311,6 @@ BOOL nego_send_preconnection_pdu(rdpNego* nego)
UINT16 cchPCB = 0; UINT16 cchPCB = 0;
WCHAR* wszPCB = NULL; WCHAR* wszPCB = NULL;
if (!nego->send_preconnection_pdu)
return TRUE;
WLog_DBG(TAG, "Sending preconnection PDU"); WLog_DBG(TAG, "Sending preconnection PDU");
if (!nego_tcp_connect(nego)) if (!nego_tcp_connect(nego))
@ -319,9 +319,9 @@ BOOL nego_send_preconnection_pdu(rdpNego* nego)
/* it's easier to always send the version 2 PDU, and it's just 2 bytes overhead */ /* it's easier to always send the version 2 PDU, and it's just 2 bytes overhead */
cbSize = PRECONNECTION_PDU_V2_MIN_SIZE; cbSize = PRECONNECTION_PDU_V2_MIN_SIZE;
if (nego->preconnection_blob) if (nego->PreconnectionBlob)
{ {
cchPCB = (UINT16) ConvertToUnicode(CP_UTF8, 0, nego->preconnection_blob, -1, &wszPCB, 0); cchPCB = (UINT16) ConvertToUnicode(CP_UTF8, 0, nego->PreconnectionBlob, -1, &wszPCB, 0);
cchPCB += 1; /* zero-termination */ cchPCB += 1; /* zero-termination */
cbSize += cchPCB * 2; cbSize += cchPCB * 2;
} }
@ -331,7 +331,7 @@ BOOL nego_send_preconnection_pdu(rdpNego* nego)
Stream_Write_UINT32(s, cbSize); /* cbSize */ Stream_Write_UINT32(s, cbSize); /* cbSize */
Stream_Write_UINT32(s, 0); /* Flags */ Stream_Write_UINT32(s, 0); /* Flags */
Stream_Write_UINT32(s, PRECONNECTION_PDU_V2); /* Version */ Stream_Write_UINT32(s, PRECONNECTION_PDU_V2); /* Version */
Stream_Write_UINT32(s, nego->preconnection_id); /* Id */ Stream_Write_UINT32(s, nego->PreconnectionId); /* Id */
Stream_Write_UINT16(s, cchPCB); /* cchPCB */ Stream_Write_UINT16(s, cchPCB); /* cchPCB */
if (wszPCB) if (wszPCB)
@ -360,7 +360,7 @@ BOOL nego_send_preconnection_pdu(rdpNego* nego)
void nego_attempt_ext(rdpNego* nego) void nego_attempt_ext(rdpNego* nego)
{ {
nego->requested_protocols = PROTOCOL_NLA | PROTOCOL_TLS | PROTOCOL_EXT; nego->RequestedProtocols = PROTOCOL_NLA | PROTOCOL_TLS | PROTOCOL_EXT;
WLog_DBG(TAG, "Attempting NLA extended security"); WLog_DBG(TAG, "Attempting NLA extended security");
@ -388,11 +388,11 @@ void nego_attempt_ext(rdpNego* nego)
{ {
nego_transport_disconnect(nego); nego_transport_disconnect(nego);
if (nego->enabled_protocols[PROTOCOL_NLA]) if (nego->EnabledProtocols[PROTOCOL_NLA])
nego->state = NEGO_STATE_NLA; nego->state = NEGO_STATE_NLA;
else if (nego->enabled_protocols[PROTOCOL_TLS]) else if (nego->EnabledProtocols[PROTOCOL_TLS])
nego->state = NEGO_STATE_TLS; nego->state = NEGO_STATE_TLS;
else if (nego->enabled_protocols[PROTOCOL_RDP]) else if (nego->EnabledProtocols[PROTOCOL_RDP])
nego->state = NEGO_STATE_RDP; nego->state = NEGO_STATE_RDP;
else else
nego->state = NEGO_STATE_FAIL; nego->state = NEGO_STATE_FAIL;
@ -406,7 +406,7 @@ void nego_attempt_ext(rdpNego* nego)
void nego_attempt_nla(rdpNego* nego) void nego_attempt_nla(rdpNego* nego)
{ {
nego->requested_protocols = PROTOCOL_NLA | PROTOCOL_TLS; nego->RequestedProtocols = PROTOCOL_NLA | PROTOCOL_TLS;
WLog_DBG(TAG, "Attempting NLA security"); WLog_DBG(TAG, "Attempting NLA security");
@ -434,9 +434,9 @@ void nego_attempt_nla(rdpNego* nego)
{ {
nego_transport_disconnect(nego); nego_transport_disconnect(nego);
if (nego->enabled_protocols[PROTOCOL_TLS]) if (nego->EnabledProtocols[PROTOCOL_TLS])
nego->state = NEGO_STATE_TLS; nego->state = NEGO_STATE_TLS;
else if (nego->enabled_protocols[PROTOCOL_RDP]) else if (nego->EnabledProtocols[PROTOCOL_RDP])
nego->state = NEGO_STATE_RDP; nego->state = NEGO_STATE_RDP;
else else
nego->state = NEGO_STATE_FAIL; nego->state = NEGO_STATE_FAIL;
@ -450,7 +450,7 @@ void nego_attempt_nla(rdpNego* nego)
void nego_attempt_tls(rdpNego* nego) void nego_attempt_tls(rdpNego* nego)
{ {
nego->requested_protocols = PROTOCOL_TLS; nego->RequestedProtocols = PROTOCOL_TLS;
WLog_DBG(TAG, "Attempting TLS security"); WLog_DBG(TAG, "Attempting TLS security");
@ -476,7 +476,7 @@ void nego_attempt_tls(rdpNego* nego)
{ {
nego_transport_disconnect(nego); nego_transport_disconnect(nego);
if (nego->enabled_protocols[PROTOCOL_RDP]) if (nego->EnabledProtocols[PROTOCOL_RDP])
nego->state = NEGO_STATE_RDP; nego->state = NEGO_STATE_RDP;
else else
nego->state = NEGO_STATE_FAIL; nego->state = NEGO_STATE_FAIL;
@ -490,7 +490,7 @@ void nego_attempt_tls(rdpNego* nego)
void nego_attempt_rdp(rdpNego* nego) void nego_attempt_rdp(rdpNego* nego)
{ {
nego->requested_protocols = PROTOCOL_RDP; nego->RequestedProtocols = PROTOCOL_RDP;
WLog_DBG(TAG, "Attempting RDP security"); WLog_DBG(TAG, "Attempting RDP security");
@ -580,24 +580,24 @@ int nego_recv(rdpTransport* transport, wStream* s, void* extra)
case TYPE_RDP_NEG_RSP: case TYPE_RDP_NEG_RSP:
nego_process_negotiation_response(nego, s); nego_process_negotiation_response(nego, s);
WLog_DBG(TAG, "selected_protocol: %d", nego->selected_protocol); WLog_DBG(TAG, "selected_protocol: %d", nego->SelectedProtocol);
/* enhanced security selected ? */ /* enhanced security selected ? */
if (nego->selected_protocol) if (nego->SelectedProtocol)
{ {
if ((nego->selected_protocol == PROTOCOL_NLA) && if ((nego->SelectedProtocol == PROTOCOL_NLA) &&
(!nego->enabled_protocols[PROTOCOL_NLA])) (!nego->EnabledProtocols[PROTOCOL_NLA]))
{ {
nego->state = NEGO_STATE_FAIL; nego->state = NEGO_STATE_FAIL;
} }
if ((nego->selected_protocol == PROTOCOL_TLS) && if ((nego->SelectedProtocol == PROTOCOL_TLS) &&
(!nego->enabled_protocols[PROTOCOL_TLS])) (!nego->EnabledProtocols[PROTOCOL_TLS]))
{ {
nego->state = NEGO_STATE_FAIL; nego->state = NEGO_STATE_FAIL;
} }
} }
else if (!nego->enabled_protocols[PROTOCOL_RDP]) else if (!nego->EnabledProtocols[PROTOCOL_RDP])
{ {
nego->state = NEGO_STATE_FAIL; nego->state = NEGO_STATE_FAIL;
} }
@ -612,7 +612,7 @@ int nego_recv(rdpTransport* transport, wStream* s, void* extra)
{ {
WLog_DBG(TAG, "no rdpNegData"); WLog_DBG(TAG, "no rdpNegData");
if (!nego->enabled_protocols[PROTOCOL_RDP]) if (!nego->EnabledProtocols[PROTOCOL_RDP])
nego->state = NEGO_STATE_FAIL; nego->state = NEGO_STATE_FAIL;
else else
nego->state = NEGO_STATE_FINAL; nego->state = NEGO_STATE_FINAL;
@ -645,7 +645,7 @@ BOOL nego_read_request(rdpNego* nego, wStream* s)
if (li != Stream_GetRemainingLength(s) + 6) if (li != Stream_GetRemainingLength(s) + 6)
{ {
WLog_ERR(TAG, "Incorrect TPDU length indicator."); WLog_ERR(TAG, "Incorrect TPDU length indicator.");
return FALSE; return FALSE;
} }
@ -677,7 +677,7 @@ BOOL nego_read_request(rdpNego* nego, wStream* s)
if (type != TYPE_RDP_NEG_REQ) if (type != TYPE_RDP_NEG_REQ)
{ {
WLog_ERR(TAG, "Incorrect negotiation request type %d", type); WLog_ERR(TAG, "Incorrect negotiation request type %d", type);
return FALSE; return FALSE;
} }
@ -730,8 +730,12 @@ BOOL nego_send_negotiation_request(rdpNego* nego)
if (nego->RoutingToken) if (nego->RoutingToken)
{ {
Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength); Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength);
/* Ensure Routing Token is correctly terminated - may already be present in string */ /* Ensure Routing Token is correctly terminated - may already be present in string */
if (nego->RoutingTokenLength>2 && (nego->RoutingToken[nego->RoutingTokenLength-2]==0x0D && nego->RoutingToken[nego->RoutingTokenLength-1]==0x0A))
if ((nego->RoutingTokenLength > 2) &&
(nego->RoutingToken[nego->RoutingTokenLength - 2] == 0x0D) &&
(nego->RoutingToken[nego->RoutingTokenLength - 1] == 0x0A))
{ {
WLog_DBG(TAG, "Routing token looks correctly terminated - use verbatim"); WLog_DBG(TAG, "Routing token looks correctly terminated - use verbatim");
length +=nego->RoutingTokenLength; length +=nego->RoutingTokenLength;
@ -748,8 +752,8 @@ BOOL nego_send_negotiation_request(rdpNego* nego)
{ {
cookie_length = strlen(nego->cookie); cookie_length = strlen(nego->cookie);
if (cookie_length > (int) nego->cookie_max_length) if (cookie_length > (int) nego->CookieMaxLength)
cookie_length = nego->cookie_max_length; cookie_length = nego->CookieMaxLength;
Stream_Write(s, "Cookie: mstshash=", 17); Stream_Write(s, "Cookie: mstshash=", 17);
Stream_Write(s, (BYTE*) nego->cookie, cookie_length); Stream_Write(s, (BYTE*) nego->cookie, cookie_length);
@ -758,9 +762,9 @@ BOOL nego_send_negotiation_request(rdpNego* nego)
length += cookie_length + 19; length += cookie_length + 19;
} }
WLog_DBG(TAG, "RequestedProtocols: %d", nego->requested_protocols); WLog_DBG(TAG, "RequestedProtocols: %d", nego->RequestedProtocols);
if ((nego->requested_protocols > PROTOCOL_RDP) || (nego->sendNegoData)) if ((nego->RequestedProtocols > PROTOCOL_RDP) || (nego->sendNegoData))
{ {
/* RDP_NEG_DATA must be present for TLS and NLA */ /* RDP_NEG_DATA must be present for TLS and NLA */
@ -770,7 +774,7 @@ BOOL nego_send_negotiation_request(rdpNego* nego)
Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ); Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ);
Stream_Write_UINT8(s, flags); Stream_Write_UINT8(s, flags);
Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */
Stream_Write_UINT32(s, nego->requested_protocols); /* requestedProtocols */ Stream_Write_UINT32(s, nego->RequestedProtocols); /* requestedProtocols */
length += 8; length += 8;
} }
@ -806,9 +810,9 @@ void nego_process_negotiation_request(rdpNego* nego, wStream* s)
Stream_Read_UINT8(s, flags); Stream_Read_UINT8(s, flags);
Stream_Read_UINT16(s, length); Stream_Read_UINT16(s, length);
Stream_Read_UINT32(s, nego->requested_protocols); Stream_Read_UINT32(s, nego->RequestedProtocols);
WLog_DBG(TAG, "RDP_NEG_REQ: RequestedProtocol: 0x%04X", nego->requested_protocols); WLog_DBG(TAG, "RDP_NEG_REQ: RequestedProtocol: 0x%04X", nego->RequestedProtocols);
nego->state = NEGO_STATE_FINAL; nego->state = NEGO_STATE_FINAL;
} }
@ -834,7 +838,7 @@ void nego_process_negotiation_response(rdpNego* nego, wStream* s)
Stream_Read_UINT8(s, nego->flags); Stream_Read_UINT8(s, nego->flags);
Stream_Read_UINT16(s, length); Stream_Read_UINT16(s, length);
Stream_Read_UINT32(s, nego->selected_protocol); Stream_Read_UINT32(s, nego->SelectedProtocol);
nego->state = NEGO_STATE_FINAL; nego->state = NEGO_STATE_FINAL;
} }
@ -914,7 +918,7 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
bm = Stream_GetPosition(s); bm = Stream_GetPosition(s);
Stream_Seek(s, length); Stream_Seek(s, length);
if ((nego->selected_protocol == PROTOCOL_RDP) && !settings->RdpSecurity) if ((nego->SelectedProtocol == PROTOCOL_RDP) && !settings->RdpSecurity)
{ {
flags = 0; flags = 0;
@ -926,7 +930,7 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
* TODO: Check for other possibilities, * TODO: Check for other possibilities,
* like SSL_NOT_ALLOWED_BY_SERVER. * like SSL_NOT_ALLOWED_BY_SERVER.
*/ */
WLog_ERR(TAG, "client supports only Standard RDP Security"); WLog_ERR(TAG, "client supports only Standard RDP Security");
Stream_Write_UINT32(s, SSL_REQUIRED_BY_SERVER); Stream_Write_UINT32(s, SSL_REQUIRED_BY_SERVER);
length += 8; length += 8;
status = FALSE; status = FALSE;
@ -942,7 +946,7 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP); Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP);
Stream_Write_UINT8(s, flags); /* flags */ Stream_Write_UINT8(s, flags); /* flags */
Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */
Stream_Write_UINT32(s, nego->selected_protocol); /* selectedProtocol */ Stream_Write_UINT32(s, nego->SelectedProtocol); /* selectedProtocol */
length += 8; length += 8;
} }
@ -965,8 +969,8 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
if (status) if (status)
{ {
/* update settings with negotiated protocol security */ /* update settings with negotiated protocol security */
settings->RequestedProtocols = nego->requested_protocols; settings->RequestedProtocols = nego->RequestedProtocols;
settings->SelectedProtocol = nego->selected_protocol; settings->SelectedProtocol = nego->SelectedProtocol;
if (settings->SelectedProtocol == PROTOCOL_RDP) if (settings->SelectedProtocol == PROTOCOL_RDP)
{ {
@ -1032,10 +1036,10 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
void nego_init(rdpNego* nego) void nego_init(rdpNego* nego)
{ {
nego->state = NEGO_STATE_INITIAL; nego->state = NEGO_STATE_INITIAL;
nego->requested_protocols = PROTOCOL_RDP; nego->RequestedProtocols = PROTOCOL_RDP;
nego->transport->ReceiveCallback = nego_recv; nego->transport->ReceiveCallback = nego_recv;
nego->transport->ReceiveExtra = (void*) nego; nego->transport->ReceiveExtra = (void*) nego;
nego->cookie_max_length = DEFAULT_COOKIE_MAX_LENGTH; nego->CookieMaxLength = DEFAULT_COOKIE_MAX_LENGTH;
nego->sendNegoData = FALSE; nego->sendNegoData = FALSE;
nego->flags = 0; nego->flags = 0;
} }
@ -1127,7 +1131,7 @@ void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal)
void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp) void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp)
{ {
WLog_DBG(TAG, "Enabling RDP security: %s", enable_rdp ? "TRUE" : "FALSE"); WLog_DBG(TAG, "Enabling RDP security: %s", enable_rdp ? "TRUE" : "FALSE");
nego->enabled_protocols[PROTOCOL_RDP] = enable_rdp; nego->EnabledProtocols[PROTOCOL_RDP] = enable_rdp;
} }
/** /**
@ -1139,7 +1143,7 @@ void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp)
void nego_enable_tls(rdpNego* nego, BOOL enable_tls) void nego_enable_tls(rdpNego* nego, BOOL enable_tls)
{ {
WLog_DBG(TAG, "Enabling TLS security: %s", enable_tls ? "TRUE" : "FALSE"); WLog_DBG(TAG, "Enabling TLS security: %s", enable_tls ? "TRUE" : "FALSE");
nego->enabled_protocols[PROTOCOL_TLS] = enable_tls; nego->EnabledProtocols[PROTOCOL_TLS] = enable_tls;
} }
/** /**
@ -1151,7 +1155,7 @@ void nego_enable_tls(rdpNego* nego, BOOL enable_tls)
void nego_enable_nla(rdpNego* nego, BOOL enable_nla) void nego_enable_nla(rdpNego* nego, BOOL enable_nla)
{ {
WLog_DBG(TAG, "Enabling NLA security: %s", enable_nla ? "TRUE" : "FALSE"); WLog_DBG(TAG, "Enabling NLA security: %s", enable_nla ? "TRUE" : "FALSE");
nego->enabled_protocols[PROTOCOL_NLA] = enable_nla; nego->EnabledProtocols[PROTOCOL_NLA] = enable_nla;
} }
/** /**
@ -1163,7 +1167,7 @@ void nego_enable_nla(rdpNego* nego, BOOL enable_nla)
void nego_enable_ext(rdpNego* nego, BOOL enable_ext) void nego_enable_ext(rdpNego* nego, BOOL enable_ext)
{ {
WLog_DBG(TAG, "Enabling NLA extended security: %s", enable_ext ? "TRUE" : "FALSE"); WLog_DBG(TAG, "Enabling NLA extended security: %s", enable_ext ? "TRUE" : "FALSE");
nego->enabled_protocols[PROTOCOL_EXT] = enable_ext; nego->EnabledProtocols[PROTOCOL_EXT] = enable_ext;
} }
/** /**
@ -1210,12 +1214,12 @@ BOOL nego_set_cookie(rdpNego* nego, char* cookie)
/** /**
* Set cookie maximum length * Set cookie maximum length
* @param nego * @param nego
* @param cookie_max_length * @param CookieMaxLength
*/ */
void nego_set_cookie_max_length(rdpNego* nego, UINT32 cookie_max_length) void nego_set_cookie_max_length(rdpNego* nego, UINT32 CookieMaxLength)
{ {
nego->cookie_max_length = cookie_max_length; nego->CookieMaxLength = CookieMaxLength;
} }
/** /**
@ -1224,9 +1228,9 @@ void nego_set_cookie_max_length(rdpNego* nego, UINT32 cookie_max_length)
* @param send_pcpdu * @param send_pcpdu
*/ */
void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL send_pcpdu) void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL SendPreconnectionPdu)
{ {
nego->send_preconnection_pdu = send_pcpdu; nego->SendPreconnectionPdu = SendPreconnectionPdu;
} }
/** /**
@ -1235,9 +1239,9 @@ void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL send_pcpdu)
* @param id * @param id
*/ */
void nego_set_preconnection_id(rdpNego* nego, UINT32 id) void nego_set_preconnection_id(rdpNego* nego, UINT32 PreconnectionId)
{ {
nego->preconnection_id = id; nego->PreconnectionId = PreconnectionId;
} }
/** /**
@ -1246,7 +1250,7 @@ void nego_set_preconnection_id(rdpNego* nego, UINT32 id)
* @param blob * @param blob
*/ */
void nego_set_preconnection_blob(rdpNego* nego, char* blob) void nego_set_preconnection_blob(rdpNego* nego, char* PreconnectionBlob)
{ {
nego->preconnection_blob = blob; nego->PreconnectionBlob = PreconnectionBlob;
} }

View File

@ -95,20 +95,20 @@ struct rdp_nego
char* cookie; char* cookie;
BYTE* RoutingToken; BYTE* RoutingToken;
DWORD RoutingTokenLength; DWORD RoutingTokenLength;
BOOL send_preconnection_pdu; BOOL SendPreconnectionPdu;
UINT32 preconnection_id; UINT32 PreconnectionId;
char* preconnection_blob; char* PreconnectionBlob;
NEGO_STATE state; NEGO_STATE state;
BOOL tcp_connected; BOOL TcpConnected;
BOOL security_connected; BOOL SecurityConnected;
UINT32 cookie_max_length; UINT32 CookieMaxLength;
BOOL sendNegoData; BOOL sendNegoData;
UINT32 selected_protocol; UINT32 SelectedProtocol;
UINT32 requested_protocols; UINT32 RequestedProtocols;
BOOL NegotiateSecurityLayer; BOOL NegotiateSecurityLayer;
BYTE enabled_protocols[16]; BYTE EnabledProtocols[16];
BOOL RestrictedAdminModeRequired; BOOL RestrictedAdminModeRequired;
BOOL GatewayEnabled; BOOL GatewayEnabled;
BOOL GatewayBypassLocal; BOOL GatewayBypassLocal;
@ -143,7 +143,7 @@ void nego_free(rdpNego* nego);
void nego_init(rdpNego* nego); void nego_init(rdpNego* nego);
void nego_set_target(rdpNego* nego, char* hostname, int port); void nego_set_target(rdpNego* nego, char* hostname, int port);
void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer_enabled); void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer);
void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdminModeRequired); void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdminModeRequired);
void nego_set_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled); void nego_set_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled);
void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal); void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal);
@ -153,9 +153,9 @@ void nego_enable_nla(rdpNego* nego, BOOL enable_nla);
void nego_enable_ext(rdpNego* nego, BOOL enable_ext); void nego_enable_ext(rdpNego* nego, BOOL enable_ext);
BOOL nego_set_routing_token(rdpNego* nego, BYTE* RoutingToken, DWORD RoutingTokenLength); BOOL nego_set_routing_token(rdpNego* nego, BYTE* RoutingToken, DWORD RoutingTokenLength);
BOOL nego_set_cookie(rdpNego* nego, char* cookie); BOOL nego_set_cookie(rdpNego* nego, char* cookie);
void nego_set_cookie_max_length(rdpNego* nego, UINT32 cookie_max_length); void nego_set_cookie_max_length(rdpNego* nego, UINT32 CookieMaxLength);
void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL send_pcpdu); void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL SendPreconnectionPdu);
void nego_set_preconnection_id(rdpNego* nego, UINT32 id); void nego_set_preconnection_id(rdpNego* nego, UINT32 PreconnectionId);
void nego_set_preconnection_blob(rdpNego* nego, char* blob); void nego_set_preconnection_blob(rdpNego* nego, char* PreconnectionBlob);
#endif /* __NEGO_H */ #endif /* __NEGO_H */

View File

@ -251,7 +251,6 @@ int credssp_client_authenticate(rdpCredssp* credssp)
BOOL have_context; BOOL have_context;
BOOL have_input_buffer; BOOL have_input_buffer;
BOOL have_pub_key_auth; BOOL have_pub_key_auth;
sspi_GlobalInit();
if (credssp_ntlm_client_init(credssp) == 0) if (credssp_ntlm_client_init(credssp) == 0)
return 0; return 0;
@ -423,7 +422,6 @@ int credssp_server_authenticate(rdpCredssp* credssp)
BOOL have_context; BOOL have_context;
BOOL have_input_buffer; BOOL have_input_buffer;
BOOL have_pub_key_auth; BOOL have_pub_key_auth;
sspi_GlobalInit();
if (credssp_ntlm_server_init(credssp) == 0) if (credssp_ntlm_server_init(credssp) == 0)
return 0; return 0;
@ -846,7 +844,9 @@ void credssp_read_ts_credentials(rdpCredssp* credssp, PSecBuffer ts_credentials)
wStream* s; wStream* s;
int length; int length;
int ts_password_creds_length; int ts_password_creds_length;
s = Stream_New(ts_credentials->pvBuffer, ts_credentials->cbBuffer); s = Stream_New(ts_credentials->pvBuffer, ts_credentials->cbBuffer);
/* TSCredentials (SEQUENCE) */ /* TSCredentials (SEQUENCE) */
ber_read_sequence_tag(s, &length); ber_read_sequence_tag(s, &length);
/* [0] credType (INTEGER) */ /* [0] credType (INTEGER) */
@ -855,7 +855,9 @@ void credssp_read_ts_credentials(rdpCredssp* credssp, PSecBuffer ts_credentials)
/* [1] credentials (OCTET STRING) */ /* [1] credentials (OCTET STRING) */
ber_read_contextual_tag(s, 1, &length, TRUE); ber_read_contextual_tag(s, 1, &length, TRUE);
ber_read_octet_string_tag(s, &ts_password_creds_length); ber_read_octet_string_tag(s, &ts_password_creds_length);
credssp_read_ts_password_creds(credssp, s); credssp_read_ts_password_creds(credssp, s);
Stream_Free(s, FALSE); Stream_Free(s, FALSE);
} }
@ -889,6 +891,7 @@ void credssp_encode_ts_credentials(rdpCredssp* credssp)
int DomainLength; int DomainLength;
int UserLength; int UserLength;
int PasswordLength; int PasswordLength;
DomainLength = credssp->identity.DomainLength; DomainLength = credssp->identity.DomainLength;
UserLength = credssp->identity.UserLength; UserLength = credssp->identity.UserLength;
PasswordLength = credssp->identity.PasswordLength; PasswordLength = credssp->identity.PasswordLength;
@ -920,7 +923,9 @@ SECURITY_STATUS credssp_encrypt_ts_credentials(rdpCredssp* credssp)
SecBuffer Buffers[2]; SecBuffer Buffers[2];
SecBufferDesc Message; SecBufferDesc Message;
SECURITY_STATUS status; SECURITY_STATUS status;
credssp_encode_ts_credentials(credssp); credssp_encode_ts_credentials(credssp);
Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */ Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
sspi_SecBufferAlloc(&credssp->authInfo, credssp->ContextSizes.cbMaxSignature + credssp->ts_credentials.cbBuffer); sspi_SecBufferAlloc(&credssp->authInfo, credssp->ContextSizes.cbMaxSignature + credssp->ts_credentials.cbBuffer);
@ -930,9 +935,11 @@ SECURITY_STATUS credssp_encrypt_ts_credentials(rdpCredssp* credssp)
Buffers[1].cbBuffer = credssp->ts_credentials.cbBuffer; Buffers[1].cbBuffer = credssp->ts_credentials.cbBuffer;
Buffers[1].pvBuffer = &((BYTE*) credssp->authInfo.pvBuffer)[Buffers[0].cbBuffer]; Buffers[1].pvBuffer = &((BYTE*) credssp->authInfo.pvBuffer)[Buffers[0].cbBuffer];
CopyMemory(Buffers[1].pvBuffer, credssp->ts_credentials.pvBuffer, Buffers[1].cbBuffer); CopyMemory(Buffers[1].pvBuffer, credssp->ts_credentials.pvBuffer, Buffers[1].cbBuffer);
Message.cBuffers = 2; Message.cBuffers = 2;
Message.ulVersion = SECBUFFER_VERSION; Message.ulVersion = SECBUFFER_VERSION;
Message.pBuffers = (PSecBuffer) &Buffers; Message.pBuffers = (PSecBuffer) &Buffers;
status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, credssp->send_seq_num++); status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, credssp->send_seq_num++);
if (status != SEC_E_OK) if (status != SEC_E_OK)
@ -1084,7 +1091,9 @@ int credssp_recv(rdpCredssp* credssp)
int length; int length;
int status; int status;
UINT32 version; UINT32 version;
s = Stream_New(NULL, 4096); s = Stream_New(NULL, 4096);
status = transport_read_pdu(credssp->transport, s); status = transport_read_pdu(credssp->transport, s);
if (status < 0) if (status < 0)

View File

@ -451,7 +451,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
if (!rdp_server_accept_nego(rdp, s)) if (!rdp_server_accept_nego(rdp, s))
return -1; return -1;
if (rdp->nego->selected_protocol & PROTOCOL_NLA) if (rdp->nego->SelectedProtocol & PROTOCOL_NLA)
{ {
sspi_CopyAuthIdentity(&client->identity, &(rdp->nego->transport->credssp->identity)); sspi_CopyAuthIdentity(&client->identity, &(rdp->nego->transport->credssp->identity));
IFCALLRET(client->Logon, client->authenticated, client, &client->identity, TRUE); IFCALLRET(client->Logon, client->authenticated, client, &client->identity, TRUE);