diff --git a/libfreerdp-core/http.c b/libfreerdp-core/http.c index de982d6c4..ddba2c17c 100644 --- a/libfreerdp-core/http.c +++ b/libfreerdp-core/http.c @@ -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; diff --git a/libfreerdp-core/rpc.c b/libfreerdp-core/rpc.c index a247adfed..a63e1f0f6 100644 --- a/libfreerdp-core/rpc.c +++ b/libfreerdp-core/rpc.c @@ -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; diff --git a/libfreerdp-core/tsg.c b/libfreerdp-core/tsg.c index c9042be46..7c28db3ac 100644 --- a/libfreerdp-core/tsg.c +++ b/libfreerdp-core/tsg.c @@ -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; } diff --git a/libfreerdp-core/tsg.h b/libfreerdp-core/tsg.h index 18a477929..76b9f9512 100644 --- a/libfreerdp-core/tsg.h +++ b/libfreerdp-core/tsg.h @@ -36,7 +36,7 @@ typedef struct rdp_tsg rdpTsg; struct rdp_tsg { - rdpRpc* rpch; + rdpRpc* rpc; uint8* tunnelContext; uint8* channelContext; rdpSettings* settings; diff --git a/libfreerdp-crypto/crypto.c b/libfreerdp-crypto/crypto.c index 12a1d6c53..3b38a0c28 100644 --- a/libfreerdp-crypto/crypto.c +++ b/libfreerdp-crypto/crypto.c @@ -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);