libfreerdp-core: fix NTLM HTTP authentication
This commit is contained in:
parent
88b8380b4c
commit
1961412941
@ -121,13 +121,13 @@ STREAM* http_request_write(HttpContext* http_context, HttpRequest* http_request)
|
||||
http_request->lines = (char**) xmalloc(sizeof(char*) * http_request->count);
|
||||
|
||||
http_encode_line(http_request->lines[0], "%s %s HTTP/1.1", http_request->Method, http_request->URI);
|
||||
http_encode_line(http_request->lines[1], "Accept: %s", http_context->Accept);
|
||||
http_encode_line(http_request->lines[2], "Cache-Control: %s", http_context->CacheControl);
|
||||
http_encode_line(http_request->lines[3], "Connection: %s", http_context->Connection);
|
||||
http_encode_line(http_request->lines[4], "Content-Length: %d", http_request->ContentLength);
|
||||
http_encode_line(http_request->lines[1], "Cache-Control: %s", http_context->CacheControl);
|
||||
http_encode_line(http_request->lines[2], "Connection: %s", http_context->Connection);
|
||||
http_encode_line(http_request->lines[3], "Pragma: %s", http_context->Pragma);
|
||||
http_encode_line(http_request->lines[4], "Accept: %s", http_context->Accept);
|
||||
http_encode_line(http_request->lines[5], "User-Agent: %s", http_context->UserAgent);
|
||||
http_encode_line(http_request->lines[6], "Host: %s", http_context->Host);
|
||||
http_encode_line(http_request->lines[7], "Pragma: %s", http_context->Pragma);
|
||||
http_encode_line(http_request->lines[6], "Content-Length: %d", http_request->ContentLength);
|
||||
http_encode_line(http_request->lines[7], "Host: %s", http_context->Host);
|
||||
|
||||
if (http_request->Authorization != NULL)
|
||||
{
|
||||
@ -366,6 +366,13 @@ HttpResponse* http_response_recv(rdpTls* tls)
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ((length - nbytes) <= 0)
|
||||
{
|
||||
length *= 2;
|
||||
buffer = xrealloc(buffer, length);
|
||||
p = (uint8*) &buffer[nbytes];
|
||||
}
|
||||
}
|
||||
|
||||
return http_response;
|
||||
|
@ -113,6 +113,14 @@ boolean ntlm_authenticate(rdpNtlm* ntlm)
|
||||
ntlm->outputBuffer.cbBuffer = ntlm->cbMaxToken;
|
||||
ntlm->outputBuffer.pvBuffer = xmalloc(ntlm->outputBuffer.cbBuffer);
|
||||
|
||||
if (ntlm->haveInputBuffer)
|
||||
{
|
||||
ntlm->inputBufferDesc.ulVersion = SECBUFFER_VERSION;
|
||||
ntlm->inputBufferDesc.cBuffers = 1;
|
||||
ntlm->inputBufferDesc.pBuffers = &ntlm->inputBuffer;
|
||||
ntlm->inputBuffer.BufferType = SECBUFFER_TOKEN;
|
||||
}
|
||||
|
||||
status = ntlm->table->InitializeSecurityContext(&ntlm->credentials,
|
||||
(ntlm->haveContext) ? &ntlm->context : NULL,
|
||||
NULL, ntlm->fContextReq, 0, SECURITY_NATIVE_DREP,
|
||||
@ -120,6 +128,14 @@ boolean ntlm_authenticate(rdpNtlm* ntlm)
|
||||
0, &ntlm->context, &ntlm->outputBufferDesc,
|
||||
&ntlm->pfContextAttr, &ntlm->expiration);
|
||||
|
||||
#ifdef WITH_DEBUG_RPC
|
||||
if (ntlm->haveInputBuffer)
|
||||
{
|
||||
printf("NTLM Token (%d)\n", ntlm->inputBuffer.cbBuffer);
|
||||
freerdp_hexdump(ntlm->inputBuffer.pvBuffer, ntlm->inputBuffer.cbBuffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || (status == SEC_E_OK))
|
||||
{
|
||||
if (ntlm->table->CompleteAuthToken != NULL)
|
||||
@ -176,6 +192,11 @@ STREAM* rpc_ntlm_http_data(rdpRpc* rpc, char* command, SecBuffer* ntlm_token, ui
|
||||
HttpContext* http_context;
|
||||
HttpRequest* http_request;
|
||||
|
||||
#ifdef WITH_DEBUG_RPC
|
||||
printf("NTLM Token (%d):\n", ntlm_token->cbBuffer);
|
||||
freerdp_hexdump(ntlm_token->pvBuffer, ntlm_token->cbBuffer);
|
||||
#endif
|
||||
|
||||
base64_ntlm_token = crypto_encode_base64(ntlm_token->pvBuffer, ntlm_token->cbBuffer);
|
||||
|
||||
if (strcmp(command, "RPC_IN_DATA") == 0)
|
||||
@ -209,7 +230,7 @@ boolean rpc_out_connect_http(rdpRpc* rpc)
|
||||
rdpRpcHTTP* http_out = rpc->http_out;
|
||||
rdpNtlm* http_out_ntlm = http_out->ntlm;
|
||||
|
||||
ntlm_client_init(http_out_ntlm, settings->username, settings->password, settings->domain);
|
||||
ntlm_client_init(http_out_ntlm, settings->username, settings->domain, settings->password);
|
||||
|
||||
ntlm_authenticate(http_out_ntlm);
|
||||
|
||||
@ -251,7 +272,7 @@ boolean rpc_in_connect_http(rdpRpc* rpc)
|
||||
rdpRpcHTTP* http_in = rpc->http_in;
|
||||
rdpNtlm* http_in_ntlm = http_in->ntlm;
|
||||
|
||||
ntlm_client_init(http_in_ntlm, settings->username, settings->password, settings->domain);
|
||||
ntlm_client_init(http_in_ntlm, settings->username, settings->domain, settings->password);
|
||||
|
||||
ntlm_authenticate(http_in_ntlm);
|
||||
|
||||
@ -270,7 +291,7 @@ boolean rpc_in_connect_http(rdpRpc* rpc)
|
||||
|
||||
ntlm_authenticate(http_in_ntlm);
|
||||
|
||||
http_stream = rpc_ntlm_http_data(rpc, "RPC_IN_DATA", &http_in_ntlm->outputBuffer, NULL, 1073741824);
|
||||
http_stream = rpc_ntlm_http_data(rpc, "RPC_IN_DATA", &http_in_ntlm->outputBuffer, NULL, 0x40000000);
|
||||
|
||||
DEBUG_RPC("%s", http_stream->data);
|
||||
tls_write_all(tls_in, http_stream->data, http_stream->size);
|
||||
@ -902,8 +923,14 @@ int rpc_out_read(rdpRpc* rpc, uint8* data, int length)
|
||||
|
||||
memcpy(data, pdu, frag_length);
|
||||
|
||||
if (strncmp((char*) pdu, "HTTP", 4) == 0)
|
||||
{
|
||||
printf("Unexpected HTTP response, likely caused by an NTLM HTTP authentication failure\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef WITH_DEBUG_RPC
|
||||
printf("rpc_out_recv(): length: %d\n", frag_length);
|
||||
printf("rpc_out_read(): length: %d\n", frag_length);
|
||||
freerdp_hexdump(data, frag_length);
|
||||
printf("\n");
|
||||
#endif
|
||||
@ -1040,8 +1067,8 @@ int rpc_read(rdpRpc* rpc, uint8* data, int length)
|
||||
{
|
||||
if (rpc->read_buffer_len > length)
|
||||
{
|
||||
/*TODO fix read_buffer is too long problem */
|
||||
printf("ERROR! RPCH Stores data in read_buffer fits not in data on rpc_read.\n");
|
||||
/* TODO fix read_buffer is too long problem */
|
||||
printf("ERROR! RPC Stores data in read_buffer fits not in data on rpc_read.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1179,8 +1206,7 @@ rdpRpc* rpc_new(rdpSettings* settings)
|
||||
http_context_set_user_agent(rpc->http_in->context, "MSRPC");
|
||||
http_context_set_host(rpc->http_in->context, settings->tsg_hostname);
|
||||
http_context_set_pragma(rpc->http_in->context,
|
||||
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, "
|
||||
"SessionId=33ad20ac-7469-4f63-946d-113eac21a23c");
|
||||
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729");
|
||||
|
||||
rpc->http_out->context = http_context_new();
|
||||
http_context_set_method(rpc->http_out->context, "RPC_OUT_DATA");
|
||||
@ -1191,8 +1217,7 @@ rdpRpc* rpc_new(rdpSettings* settings)
|
||||
http_context_set_user_agent(rpc->http_out->context, "MSRPC");
|
||||
http_context_set_host(rpc->http_out->context, settings->tsg_hostname);
|
||||
http_context_set_pragma(rpc->http_out->context,
|
||||
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, "
|
||||
"SessionId=33ad20ac-7469-4f63-946d-113eac21a23c");
|
||||
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729");
|
||||
|
||||
rpc->read_buffer = NULL;
|
||||
rpc->write_buffer = NULL;
|
||||
|
@ -195,27 +195,25 @@ DWORD TsProxySendToServer(byte pRpcMessage[])
|
||||
|
||||
boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
|
||||
{
|
||||
uint8* data;
|
||||
uint32 length;
|
||||
int status = -1;
|
||||
|
||||
rdpRpc* rpch = tsg->rpch;
|
||||
rdpRpc* rpc = tsg->rpc;
|
||||
rdpTransport* transport = tsg->transport;
|
||||
|
||||
uint32 length;
|
||||
uint8* data;
|
||||
|
||||
if (!rpc_attach(rpch, transport->tcp_in, transport->tcp_out, transport->tls_in, transport->tls_out))
|
||||
if (!rpc_attach(rpc, transport->tcp_in, transport->tcp_out, transport->tls_in, transport->tls_out))
|
||||
{
|
||||
printf("rpch_attach failed!\n");
|
||||
printf("rpc_attach failed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rpc_connect(rpch))
|
||||
if (!rpc_connect(rpc))
|
||||
{
|
||||
printf("rpch_connect failed!\n");
|
||||
printf("rpc_connect failed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_TSG("rpch_connect success");
|
||||
DEBUG_TSG("rpc_connect success");
|
||||
|
||||
/**
|
||||
* OpNum = 1
|
||||
@ -229,21 +227,21 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
|
||||
*/
|
||||
|
||||
DEBUG_TSG("TsProxyCreateTunnel");
|
||||
status = rpc_write(rpch, tsg_packet1, sizeof(tsg_packet1), 1);
|
||||
status = rpc_write(rpc, tsg_packet1, sizeof(tsg_packet1), 1);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
printf("rpch_write opnum=1 failed!\n");
|
||||
printf("rpc_write opnum=1 failed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
length = 0x8FFF;
|
||||
data = xmalloc(length);
|
||||
status = rpc_read(rpch, data, length);
|
||||
status = rpc_read(rpc, data, length);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
printf("rpch_recv failed!\n");
|
||||
printf("rpc_recv failed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -270,19 +268,19 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
|
||||
*/
|
||||
|
||||
DEBUG_TSG("TsProxyAuthorizeTunnel");
|
||||
status = rpc_write(rpch, tsg_packet2, sizeof(tsg_packet2), 2);
|
||||
status = rpc_write(rpc, tsg_packet2, sizeof(tsg_packet2), 2);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
printf("rpch_write opnum=2 failed!\n");
|
||||
printf("rpc_write opnum=2 failed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
status = rpc_read(rpch, data, length);
|
||||
status = rpc_read(rpc, data, length);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
printf("rpch_recv failed!\n");
|
||||
printf("rpc_recv failed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -300,11 +298,11 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
|
||||
*/
|
||||
|
||||
DEBUG_TSG("TsProxyMakeTunnelCall");
|
||||
status = rpc_write(rpch, tsg_packet3, sizeof(tsg_packet3), 3);
|
||||
status = rpc_write(rpc, tsg_packet3, sizeof(tsg_packet3), 3);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
printf("rpch_write opnum=3 failed!\n");
|
||||
printf("rpc_write opnum=3 failed!\n");
|
||||
return false;
|
||||
}
|
||||
status = -1;
|
||||
@ -337,20 +335,20 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
|
||||
*/
|
||||
|
||||
DEBUG_TSG("TsProxyCreateChannel");
|
||||
status = rpc_write(rpch, s_p4->data, s_p4->size, 4);
|
||||
status = rpc_write(rpc, s_p4->data, s_p4->size, 4);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
printf("rpch_write opnum=4 failed!\n");
|
||||
printf("rpc_write opnum=4 failed!\n");
|
||||
return false;
|
||||
}
|
||||
xfree(dest_addr_unic);
|
||||
|
||||
status = rpc_read(rpch, data, length);
|
||||
status = rpc_read(rpc, data, length);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
printf("rpch_recv failed!\n");
|
||||
printf("rpc_recv failed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -374,51 +372,53 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
|
||||
*/
|
||||
|
||||
DEBUG_TSG("TsProxySetupReceivePipe");
|
||||
status = rpc_write(rpch, tsg_packet5, sizeof(tsg_packet5), 8);
|
||||
status = rpc_write(rpc, tsg_packet5, sizeof(tsg_packet5), 8);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
printf("rpch_write opnum=8 failed!\n");
|
||||
printf("rpc_write opnum=8 failed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8 pp[8] =
|
||||
{
|
||||
0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
int tsg_write(rdpTsg* tsg, uint8* data, uint32 length)
|
||||
{
|
||||
STREAM* s;
|
||||
uint8* tsg_pkg;
|
||||
int status = -1;
|
||||
|
||||
uint16 opnum = 9;
|
||||
uint32 tsg_length = length + 16 + 4 + 12 + 8;
|
||||
uint32 totalDataBytes = length + 4;
|
||||
|
||||
STREAM* s = stream_new(12);
|
||||
stream_write_uint32_be(s,totalDataBytes);
|
||||
stream_write_uint32_be(s,0x01);
|
||||
stream_write_uint32_be(s,length);
|
||||
s = stream_new(12);
|
||||
stream_write_uint32_be(s, totalDataBytes);
|
||||
stream_write_uint32_be(s, 0x01);
|
||||
stream_write_uint32_be(s, length);
|
||||
|
||||
uint8* tsg_pkg = xmalloc(tsg_length);
|
||||
tsg_pkg = xmalloc(tsg_length);
|
||||
memset(tsg_pkg, 0, 4);
|
||||
memcpy(tsg_pkg + 4, tsg->channelContext, 16);
|
||||
memcpy(tsg_pkg + 20, s->data, 12);
|
||||
memcpy(tsg_pkg + 32, data, length);
|
||||
|
||||
uint8 pp[8] =
|
||||
{
|
||||
0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
memcpy(tsg_pkg + 32 + length, pp, 8);
|
||||
|
||||
status = rpc_write(tsg->rpch, tsg_pkg, tsg_length, opnum);
|
||||
status = rpc_write(tsg->rpc, tsg_pkg, tsg_length, opnum);
|
||||
|
||||
xfree(tsg_pkg);
|
||||
stream_free(s);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
printf("rpch_write failed!\n");
|
||||
printf("rpc_write failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -429,7 +429,7 @@ int tsg_read(rdpTsg* tsg, uint8* data, uint32 length)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = rpc_read(tsg->rpch, data, length);
|
||||
status = rpc_read(tsg->rpc, data, length);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -440,7 +440,7 @@ rdpTsg* tsg_new(rdpSettings* settings)
|
||||
tsg = (rdpTsg*) xzalloc(sizeof(rdpTsg));
|
||||
|
||||
tsg->settings = settings;
|
||||
tsg->rpch = rpc_new(settings);
|
||||
tsg->rpc = rpc_new(settings);
|
||||
|
||||
return tsg;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ typedef struct rdp_tsg rdpTsg;
|
||||
|
||||
struct rdp_tsg
|
||||
{
|
||||
rdpRpc* rpch;
|
||||
rdpRpc* rpc;
|
||||
uint8* tunnelContext;
|
||||
uint8* channelContext;
|
||||
rdpSettings* settings;
|
||||
|
@ -548,7 +548,7 @@ char* crypto_encode_base64(uint8* data, int length)
|
||||
|
||||
base64_string = xmalloc(bptr->length);
|
||||
memcpy(base64_string, bptr->data, bptr->length - 1);
|
||||
base64_string[bptr->length] = '\0';
|
||||
base64_string[bptr->length - 1] = '\0';
|
||||
|
||||
BIO_free_all(b64);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user