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;
}
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) ||
(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))
return FALSE;
nego->selected_protocol = 0;
nego->SelectedProtocol = 0;
WLog_INFO(TAG, "Client Security: NLA:%d TLS:%d RDP:%d",
(nego->requested_protocols & PROTOCOL_NLA) ? 1 : 0,
(nego->requested_protocols & PROTOCOL_TLS) ? 1 : 0,
(nego->requested_protocols == PROTOCOL_RDP) ? 1 : 0
(nego->RequestedProtocols & PROTOCOL_NLA) ? 1 : 0,
(nego->RequestedProtocols & PROTOCOL_TLS) ? 1 : 0,
(nego->RequestedProtocols == PROTOCOL_RDP) ? 1 : 0
);
WLog_INFO(TAG, "Server Security: NLA:%d TLS:%d RDP:%d",
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
{
@ -1000,9 +1000,9 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
}
WLog_INFO(TAG, "Negotiated Security: NLA:%d TLS:%d RDP:%d",
(nego->selected_protocol & PROTOCOL_NLA) ? 1 : 0,
(nego->selected_protocol & PROTOCOL_TLS) ? 1 : 0,
(nego->selected_protocol == PROTOCOL_RDP) ? 1: 0
(nego->SelectedProtocol & PROTOCOL_NLA) ? 1 : 0,
(nego->SelectedProtocol & PROTOCOL_TLS) ? 1 : 0,
(nego->SelectedProtocol == PROTOCOL_RDP) ? 1: 0
);
if (!nego_send_negotiation_response(nego))
@ -1010,11 +1010,11 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
status = FALSE;
if (nego->selected_protocol & PROTOCOL_NLA)
if (nego->SelectedProtocol & PROTOCOL_NLA)
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);
else if (nego->selected_protocol == PROTOCOL_RDP) /* 0 */
else if (nego->SelectedProtocol == PROTOCOL_RDP) /* 0 */
status = transport_accept_rdp(rdp->transport);
if (!status)

View File

@ -34,6 +34,51 @@
#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()
{
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);
}
else if (_stricmp(name, "Content-Type") == 0)
{
response->ContentType = _strdup(value);
if (!response->ContentType)
return FALSE;
}
else if (_stricmp(name, "WWW-Authenticate") == 0)
{
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)
{
char c;
int count;
char* line;
char* name;
@ -447,7 +500,6 @@ BOOL http_response_parse_header(HttpResponse* response)
char* colon_pos;
char* end_of_header;
char end_of_header_char;
char c;
if (!response)
return FALSE;
@ -522,22 +574,29 @@ void http_response_print(HttpResponse* response)
HttpResponse* http_response_recv(rdpTls* tls)
{
int nbytes;
int length;
wStream* s;
int size;
int count;
int status;
BYTE* buffer;
char* content;
char* header_end;
int position;
char* line;
char* buffer;
char* header;
char* payload;
int bodyLength;
int payloadOffset;
HttpResponse* response;
nbytes = 0;
length = 10000;
content = NULL;
size = 1024;
payload = NULL;
payloadOffset = 0;
buffer = calloc(length, 1);
s = Stream_New(NULL, size);
if (!buffer)
return NULL;
if (!s)
goto out_free;
buffer = (char*) Stream_Buffer(s);
response = http_response_new();
@ -548,9 +607,9 @@ HttpResponse* http_response_recv(rdpTls* tls)
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)
{
@ -564,34 +623,40 @@ HttpResponse* http_response_recv(rdpTls* tls)
#ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(p, status);
#endif
nbytes += status;
Stream_Seek(s, status);
if (Stream_GetRemainingLength(s) < 1024)
{
Stream_EnsureRemainingCapacity(s, 1024);
buffer = (char*) Stream_Buffer(s);
payload = &buffer[payloadOffset];
}
header_end = strstr((char*) buffer, "\r\n\r\n");
position = Stream_GetPosition(s);
if (!header_end)
if (position >= 4)
{
WLog_ERR(TAG, "invalid response");
winpr_HexDump(TAG, WLOG_ERROR, buffer, status);
goto out_error;
line = string_strnstr(buffer, "\r\n\r\n", position);
if (line)
{
payloadOffset = (line - buffer) + 4;
payload = &buffer[payloadOffset];
}
}
}
header_end += 2;
if (header_end)
if (payloadOffset)
{
int count;
char* line;
header_end[0] = '\0';
header_end[1] = '\0';
content = header_end + 2;
count = 0;
line = (char*) buffer;
line = buffer;
while ((line = strstr(line, "\r\n")) != NULL)
position = Stream_GetPosition(s);
while ((line = string_strnstr(line, "\r\n", payloadOffset - (line - buffer) - 2)))
{
line++;
line += 2;
count++;
}
@ -605,8 +670,17 @@ HttpResponse* http_response_recv(rdpTls* tls)
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;
line = strtok((char*) buffer, "\r\n");
line = strtok(header, "\r\n");
while (line && response->lines)
{
@ -619,10 +693,12 @@ HttpResponse* http_response_recv(rdpTls* tls)
count++;
}
free(header);
if (!http_response_parse_header(response))
goto out_error;
response->BodyLength = nbytes - (content - (char*) buffer);
response->BodyLength = Stream_GetPosition(s) - payloadOffset;
if (response->BodyLength > 0)
{
@ -631,44 +707,45 @@ HttpResponse* http_response_recv(rdpTls* tls)
if (!response->BodyContent)
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;
}
if ((length - nbytes) <= 0)
if (Stream_GetRemainingLength(s) < 1024)
{
length *= 2;
buffer = realloc(buffer, length);
Stream_EnsureRemainingCapacity(s, 1024);
buffer = (char*) Stream_Buffer(s);
payload = &buffer[payloadOffset];
}
}
free(buffer);
Stream_Free(s, TRUE);
return response;
out_error:
http_response_free(response);
out_free:
free(buffer);
Stream_Free(s, TRUE);
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* response = (HttpResponse*) calloc(1, sizeof(HttpResponse));
@ -703,6 +780,8 @@ void http_response_free(HttpResponse* response)
free(response->lines);
free(response->ReasonPhrase);
free(response->ContentType);
ListDictionary_Free(response->Authenticates);
if (response->ContentLength > 0)

View File

@ -83,6 +83,7 @@ struct _http_response
char* ReasonPhrase;
int ContentLength;
char* ContentType;
int BodyLength;
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)
{
char* token64;
HttpResponse* response;
int ntlm_token_length = 0;
BYTE* ntlm_token_data = NULL;
HttpResponse* http_response;
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;
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)
goto out;
@ -266,7 +266,7 @@ int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc)
out:
ntlm->inputBuffer[0].pvBuffer = ntlm_token_data;
ntlm->inputBuffer[0].cbBuffer = ntlm_token_length;
http_response_free(http_response);
http_response_free(response);
return 1;
}
@ -297,15 +297,24 @@ BOOL rpc_ntlm_http_out_connect(rdpRpc* rpc)
/* 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;

View File

@ -126,6 +126,11 @@ BOOL rts_connect(rdpRpc* rpc)
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);
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))
{
WLog_ERR(TAG, "rts_connect error!");
return -1;
return FALSE;
}
ReadEvent = NULL;

View File

@ -74,19 +74,19 @@ BOOL nego_connect(rdpNego* nego)
if (nego->state == NEGO_STATE_INITIAL)
{
if (nego->enabled_protocols[PROTOCOL_EXT])
if (nego->EnabledProtocols[PROTOCOL_EXT])
{
nego->state = NEGO_STATE_EXT;
}
else if (nego->enabled_protocols[PROTOCOL_NLA])
else if (nego->EnabledProtocols[PROTOCOL_NLA])
{
nego->state = NEGO_STATE_NLA;
}
else if (nego->enabled_protocols[PROTOCOL_TLS])
else if (nego->EnabledProtocols[PROTOCOL_TLS])
{
nego->state = NEGO_STATE_TLS;
}
else if (nego->enabled_protocols[PROTOCOL_RDP])
else if (nego->EnabledProtocols[PROTOCOL_RDP])
{
nego->state = NEGO_STATE_RDP;
}
@ -102,34 +102,36 @@ BOOL nego_connect(rdpNego* nego)
WLog_DBG(TAG, "Security Layer Negotiation is disabled");
/* attempt only the highest enabled protocol (see nego_attempt_*) */
nego->enabled_protocols[PROTOCOL_NLA] = FALSE;
nego->enabled_protocols[PROTOCOL_TLS] = FALSE;
nego->enabled_protocols[PROTOCOL_RDP] = FALSE;
nego->enabled_protocols[PROTOCOL_EXT] = FALSE;
nego->EnabledProtocols[PROTOCOL_NLA] = FALSE;
nego->EnabledProtocols[PROTOCOL_TLS] = FALSE;
nego->EnabledProtocols[PROTOCOL_RDP] = FALSE;
nego->EnabledProtocols[PROTOCOL_EXT] = FALSE;
if (nego->state == NEGO_STATE_EXT)
{
nego->enabled_protocols[PROTOCOL_EXT] = TRUE;
nego->enabled_protocols[PROTOCOL_NLA] = TRUE;
nego->selected_protocol = PROTOCOL_EXT;
nego->EnabledProtocols[PROTOCOL_EXT] = TRUE;
nego->EnabledProtocols[PROTOCOL_NLA] = TRUE;
nego->SelectedProtocol = PROTOCOL_EXT;
}
else if (nego->state == NEGO_STATE_NLA)
{
nego->enabled_protocols[PROTOCOL_NLA] = TRUE;
nego->selected_protocol = PROTOCOL_NLA;
nego->EnabledProtocols[PROTOCOL_NLA] = TRUE;
nego->SelectedProtocol = PROTOCOL_NLA;
}
else if (nego->state == NEGO_STATE_TLS)
{
nego->enabled_protocols[PROTOCOL_TLS] = TRUE;
nego->selected_protocol = PROTOCOL_TLS;
nego->EnabledProtocols[PROTOCOL_TLS] = TRUE;
nego->SelectedProtocol = PROTOCOL_TLS;
}
else if (nego->state == NEGO_STATE_RDP)
{
nego->enabled_protocols[PROTOCOL_RDP] = TRUE;
nego->selected_protocol = PROTOCOL_RDP;
nego->EnabledProtocols[PROTOCOL_RDP] = TRUE;
nego->SelectedProtocol = PROTOCOL_RDP;
}
}
if (nego->SendPreconnectionPdu)
{
if (!nego_send_preconnection_pdu(nego))
{
WLog_ERR(TAG, "Failed to send preconnection pdu");
@ -137,6 +139,7 @@ BOOL nego_connect(rdpNego* nego)
return FALSE;
}
}
}
do
{
@ -153,14 +156,14 @@ BOOL nego_connect(rdpNego* nego)
}
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 */
settings->RequestedProtocols = nego->requested_protocols;
settings->SelectedProtocol = nego->selected_protocol;
settings->RequestedProtocols = nego->RequestedProtocols;
settings->SelectedProtocol = nego->SelectedProtocol;
settings->NegotiationFlags = nego->flags;
if (nego->selected_protocol == PROTOCOL_RDP)
if (nego->SelectedProtocol == PROTOCOL_RDP)
{
settings->UseRdpSecurityLayer = TRUE;
@ -177,7 +180,7 @@ BOOL nego_connect(rdpNego* nego)
/* finally connect security layer (if not already done) */
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;
}
@ -196,26 +199,26 @@ BOOL nego_disconnect(rdpNego* nego)
/* connect to selected security layer */
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");
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");
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");
nego->security_connected = transport_connect_rdp(nego->transport);
nego->SecurityConnected = transport_connect_rdp(nego->transport);
}
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)
{
if (!nego->tcp_connected)
if (!nego->TcpConnected)
{
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, "To disable auto detection use /gateway-usage-method:direct");
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);
nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port, 15);
nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port, 15);
}
}
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);
if (nego->tcp_connected && !nego->NegotiateSecurityLayer)
if (nego->TcpConnected && !nego->NegotiateSecurityLayer)
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)
{
if (nego->tcp_connected)
if (nego->TcpConnected)
transport_disconnect(nego->transport);
nego->tcp_connected = FALSE;
nego->security_connected = FALSE;
nego->TcpConnected = FALSE;
nego->SecurityConnected = FALSE;
return TRUE;
}
@ -308,9 +311,6 @@ BOOL nego_send_preconnection_pdu(rdpNego* nego)
UINT16 cchPCB = 0;
WCHAR* wszPCB = NULL;
if (!nego->send_preconnection_pdu)
return TRUE;
WLog_DBG(TAG, "Sending preconnection PDU");
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 */
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 */
cbSize += cchPCB * 2;
}
@ -331,7 +331,7 @@ BOOL nego_send_preconnection_pdu(rdpNego* nego)
Stream_Write_UINT32(s, cbSize); /* cbSize */
Stream_Write_UINT32(s, 0); /* Flags */
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 */
if (wszPCB)
@ -360,7 +360,7 @@ BOOL nego_send_preconnection_pdu(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");
@ -388,11 +388,11 @@ void nego_attempt_ext(rdpNego* nego)
{
nego_transport_disconnect(nego);
if (nego->enabled_protocols[PROTOCOL_NLA])
if (nego->EnabledProtocols[PROTOCOL_NLA])
nego->state = NEGO_STATE_NLA;
else if (nego->enabled_protocols[PROTOCOL_TLS])
else if (nego->EnabledProtocols[PROTOCOL_TLS])
nego->state = NEGO_STATE_TLS;
else if (nego->enabled_protocols[PROTOCOL_RDP])
else if (nego->EnabledProtocols[PROTOCOL_RDP])
nego->state = NEGO_STATE_RDP;
else
nego->state = NEGO_STATE_FAIL;
@ -406,7 +406,7 @@ void nego_attempt_ext(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");
@ -434,9 +434,9 @@ void nego_attempt_nla(rdpNego* nego)
{
nego_transport_disconnect(nego);
if (nego->enabled_protocols[PROTOCOL_TLS])
if (nego->EnabledProtocols[PROTOCOL_TLS])
nego->state = NEGO_STATE_TLS;
else if (nego->enabled_protocols[PROTOCOL_RDP])
else if (nego->EnabledProtocols[PROTOCOL_RDP])
nego->state = NEGO_STATE_RDP;
else
nego->state = NEGO_STATE_FAIL;
@ -450,7 +450,7 @@ void nego_attempt_nla(rdpNego* nego)
void nego_attempt_tls(rdpNego* nego)
{
nego->requested_protocols = PROTOCOL_TLS;
nego->RequestedProtocols = PROTOCOL_TLS;
WLog_DBG(TAG, "Attempting TLS security");
@ -476,7 +476,7 @@ void nego_attempt_tls(rdpNego* nego)
{
nego_transport_disconnect(nego);
if (nego->enabled_protocols[PROTOCOL_RDP])
if (nego->EnabledProtocols[PROTOCOL_RDP])
nego->state = NEGO_STATE_RDP;
else
nego->state = NEGO_STATE_FAIL;
@ -490,7 +490,7 @@ void nego_attempt_tls(rdpNego* nego)
void nego_attempt_rdp(rdpNego* nego)
{
nego->requested_protocols = PROTOCOL_RDP;
nego->RequestedProtocols = PROTOCOL_RDP;
WLog_DBG(TAG, "Attempting RDP security");
@ -580,24 +580,24 @@ int nego_recv(rdpTransport* transport, wStream* s, void* extra)
case TYPE_RDP_NEG_RSP:
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 ? */
if (nego->selected_protocol)
if (nego->SelectedProtocol)
{
if ((nego->selected_protocol == PROTOCOL_NLA) &&
(!nego->enabled_protocols[PROTOCOL_NLA]))
if ((nego->SelectedProtocol == PROTOCOL_NLA) &&
(!nego->EnabledProtocols[PROTOCOL_NLA]))
{
nego->state = NEGO_STATE_FAIL;
}
if ((nego->selected_protocol == PROTOCOL_TLS) &&
(!nego->enabled_protocols[PROTOCOL_TLS]))
if ((nego->SelectedProtocol == PROTOCOL_TLS) &&
(!nego->EnabledProtocols[PROTOCOL_TLS]))
{
nego->state = NEGO_STATE_FAIL;
}
}
else if (!nego->enabled_protocols[PROTOCOL_RDP])
else if (!nego->EnabledProtocols[PROTOCOL_RDP])
{
nego->state = NEGO_STATE_FAIL;
}
@ -612,7 +612,7 @@ int nego_recv(rdpTransport* transport, wStream* s, void* extra)
{
WLog_DBG(TAG, "no rdpNegData");
if (!nego->enabled_protocols[PROTOCOL_RDP])
if (!nego->EnabledProtocols[PROTOCOL_RDP])
nego->state = NEGO_STATE_FAIL;
else
nego->state = NEGO_STATE_FINAL;
@ -730,8 +730,12 @@ BOOL nego_send_negotiation_request(rdpNego* nego)
if (nego->RoutingToken)
{
Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength);
/* 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");
length +=nego->RoutingTokenLength;
@ -748,8 +752,8 @@ BOOL nego_send_negotiation_request(rdpNego* nego)
{
cookie_length = strlen(nego->cookie);
if (cookie_length > (int) nego->cookie_max_length)
cookie_length = nego->cookie_max_length;
if (cookie_length > (int) nego->CookieMaxLength)
cookie_length = nego->CookieMaxLength;
Stream_Write(s, "Cookie: mstshash=", 17);
Stream_Write(s, (BYTE*) nego->cookie, cookie_length);
@ -758,9 +762,9 @@ BOOL nego_send_negotiation_request(rdpNego* nego)
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 */
@ -770,7 +774,7 @@ BOOL nego_send_negotiation_request(rdpNego* nego)
Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ);
Stream_Write_UINT8(s, flags);
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;
}
@ -806,9 +810,9 @@ void nego_process_negotiation_request(rdpNego* nego, wStream* s)
Stream_Read_UINT8(s, flags);
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;
}
@ -834,7 +838,7 @@ void nego_process_negotiation_response(rdpNego* nego, wStream* s)
Stream_Read_UINT8(s, nego->flags);
Stream_Read_UINT16(s, length);
Stream_Read_UINT32(s, nego->selected_protocol);
Stream_Read_UINT32(s, nego->SelectedProtocol);
nego->state = NEGO_STATE_FINAL;
}
@ -914,7 +918,7 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
bm = Stream_GetPosition(s);
Stream_Seek(s, length);
if ((nego->selected_protocol == PROTOCOL_RDP) && !settings->RdpSecurity)
if ((nego->SelectedProtocol == PROTOCOL_RDP) && !settings->RdpSecurity)
{
flags = 0;
@ -942,7 +946,7 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP);
Stream_Write_UINT8(s, flags); /* flags */
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;
}
@ -965,8 +969,8 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
if (status)
{
/* update settings with negotiated protocol security */
settings->RequestedProtocols = nego->requested_protocols;
settings->SelectedProtocol = nego->selected_protocol;
settings->RequestedProtocols = nego->RequestedProtocols;
settings->SelectedProtocol = nego->SelectedProtocol;
if (settings->SelectedProtocol == PROTOCOL_RDP)
{
@ -1032,10 +1036,10 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
void nego_init(rdpNego* nego)
{
nego->state = NEGO_STATE_INITIAL;
nego->requested_protocols = PROTOCOL_RDP;
nego->RequestedProtocols = PROTOCOL_RDP;
nego->transport->ReceiveCallback = nego_recv;
nego->transport->ReceiveExtra = (void*) nego;
nego->cookie_max_length = DEFAULT_COOKIE_MAX_LENGTH;
nego->CookieMaxLength = DEFAULT_COOKIE_MAX_LENGTH;
nego->sendNegoData = FALSE;
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)
{
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)
{
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)
{
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)
{
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
* @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
*/
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
*/
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
*/
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;
BYTE* RoutingToken;
DWORD RoutingTokenLength;
BOOL send_preconnection_pdu;
UINT32 preconnection_id;
char* preconnection_blob;
BOOL SendPreconnectionPdu;
UINT32 PreconnectionId;
char* PreconnectionBlob;
NEGO_STATE state;
BOOL tcp_connected;
BOOL security_connected;
UINT32 cookie_max_length;
BOOL TcpConnected;
BOOL SecurityConnected;
UINT32 CookieMaxLength;
BOOL sendNegoData;
UINT32 selected_protocol;
UINT32 requested_protocols;
UINT32 SelectedProtocol;
UINT32 RequestedProtocols;
BOOL NegotiateSecurityLayer;
BYTE enabled_protocols[16];
BYTE EnabledProtocols[16];
BOOL RestrictedAdminModeRequired;
BOOL GatewayEnabled;
BOOL GatewayBypassLocal;
@ -143,7 +143,7 @@ void nego_free(rdpNego* nego);
void nego_init(rdpNego* nego);
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_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled);
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);
BOOL nego_set_routing_token(rdpNego* nego, BYTE* RoutingToken, DWORD RoutingTokenLength);
BOOL nego_set_cookie(rdpNego* nego, char* cookie);
void nego_set_cookie_max_length(rdpNego* nego, UINT32 cookie_max_length);
void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL send_pcpdu);
void nego_set_preconnection_id(rdpNego* nego, UINT32 id);
void nego_set_preconnection_blob(rdpNego* nego, char* blob);
void nego_set_cookie_max_length(rdpNego* nego, UINT32 CookieMaxLength);
void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL SendPreconnectionPdu);
void nego_set_preconnection_id(rdpNego* nego, UINT32 PreconnectionId);
void nego_set_preconnection_blob(rdpNego* nego, char* PreconnectionBlob);
#endif /* __NEGO_H */

View File

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