libfreerdp-core: start using HTTP utils for NTLM HTTP authentication
This commit is contained in:
parent
883b04d51f
commit
fa7900d293
@ -142,6 +142,7 @@ FREERDP_API void crypto_rsa_private_decrypt(const uint8* input, int length, uint
|
|||||||
FREERDP_API void crypto_reverse(uint8* data, int length);
|
FREERDP_API void crypto_reverse(uint8* data, int length);
|
||||||
FREERDP_API void crypto_nonce(uint8* nonce, int size);
|
FREERDP_API void crypto_nonce(uint8* nonce, int size);
|
||||||
|
|
||||||
|
FREERDP_API char* crypto_encode_base64(uint8* data, int length);
|
||||||
FREERDP_API void crypto_base64_encode(uint8* data, int length, uint8** enc_data, int* res_length);
|
FREERDP_API void crypto_base64_encode(uint8* data, int length, uint8** enc_data, int* res_length);
|
||||||
FREERDP_API void crypto_base64_decode(uint8* enc_data, int length, uint8** dec_data, int* res_length);
|
FREERDP_API void crypto_base64_decode(uint8* enc_data, int length, uint8** dec_data, int* res_length);
|
||||||
|
|
||||||
|
@ -97,9 +97,19 @@ void http_request_set_uri(HttpRequest* http_request, char* uri)
|
|||||||
http_request->URI = xstrdup(uri);
|
http_request->URI = xstrdup(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void http_request_set_auth_scheme(HttpRequest* http_request, char* auth_scheme)
|
||||||
|
{
|
||||||
|
http_request->AuthScheme = xstrdup(auth_scheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
void http_request_set_auth_param(HttpRequest* http_request, char* auth_param)
|
||||||
|
{
|
||||||
|
http_request->AuthParam = xstrdup(auth_param);
|
||||||
|
}
|
||||||
|
|
||||||
#define http_encode_line(_str, _fmt, ...) \
|
#define http_encode_line(_str, _fmt, ...) \
|
||||||
_str = xmalloc(snprintf(NULL, 0, _fmt, ## __VA_ARGS__)); \
|
_str = xmalloc(snprintf(NULL, 0, _fmt, ## __VA_ARGS__) + 1); \
|
||||||
snprintf(_str, snprintf(NULL, 0, _fmt, ## __VA_ARGS__), _fmt, ## __VA_ARGS__);
|
snprintf(_str, snprintf(NULL, 0, _fmt, ## __VA_ARGS__) + 1, _fmt, ## __VA_ARGS__);
|
||||||
|
|
||||||
STREAM* http_request_write(HttpContext* http_context, HttpRequest* http_request)
|
STREAM* http_request_write(HttpContext* http_context, HttpRequest* http_request)
|
||||||
{
|
{
|
||||||
@ -107,34 +117,49 @@ STREAM* http_request_write(HttpContext* http_context, HttpRequest* http_request)
|
|||||||
STREAM* s;
|
STREAM* s;
|
||||||
int length = 0;
|
int length = 0;
|
||||||
|
|
||||||
http_request->count = 10;
|
http_request->count = 9;
|
||||||
http_request->lines = (char**) xmalloc(sizeof(char*) * http_request->count);
|
http_request->lines = (char**) xmalloc(sizeof(char*) * http_request->count);
|
||||||
|
|
||||||
http_encode_line(http_request->lines[0], "%s %s HTTP/1.1\n", http_request->Method, http_request->URI);
|
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\n", http_context->Accept);
|
http_encode_line(http_request->lines[1], "Accept: %s", http_context->Accept);
|
||||||
http_encode_line(http_request->lines[2], "Cache-Control: %s\n", http_context->CacheControl);
|
http_encode_line(http_request->lines[2], "Cache-Control: %s", http_context->CacheControl);
|
||||||
http_encode_line(http_request->lines[3], "Connection: %s\n", http_context->Connection);
|
http_encode_line(http_request->lines[3], "Connection: %s", http_context->Connection);
|
||||||
http_encode_line(http_request->lines[4], "Content-Length: %d\n", http_request->ContentLength);
|
http_encode_line(http_request->lines[4], "Content-Length: %d", http_request->ContentLength);
|
||||||
http_encode_line(http_request->lines[5], "User-Agent: %s\n", http_context->UserAgent);
|
http_encode_line(http_request->lines[5], "User-Agent: %s", http_context->UserAgent);
|
||||||
http_encode_line(http_request->lines[6], "Host: %s\n", http_context->Host);
|
http_encode_line(http_request->lines[6], "Host: %s", http_context->Host);
|
||||||
http_encode_line(http_request->lines[7], "Pragma: %s\n", http_context->Pragma);
|
http_encode_line(http_request->lines[7], "Pragma: %s", http_context->Pragma);
|
||||||
http_encode_line(http_request->lines[8], "Authorization: %s\n", http_request->Authorization);
|
|
||||||
http_encode_line(http_request->lines[9], "\n\n");
|
if (http_request->Authorization != NULL)
|
||||||
|
{
|
||||||
|
http_encode_line(http_request->lines[8], "Authorization: %s", http_request->Authorization);
|
||||||
|
}
|
||||||
|
else if ((http_request->AuthScheme != NULL) && (http_request->AuthParam != NULL))
|
||||||
|
{
|
||||||
|
http_encode_line(http_request->lines[8], "Authorization: %s %s",
|
||||||
|
http_request->AuthScheme, http_request->AuthParam);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < http_request->count; i++)
|
for (i = 0; i < http_request->count; i++)
|
||||||
{
|
{
|
||||||
length += strlen(http_request->lines[i]);
|
length += (strlen(http_request->lines[i]) + 1); /* add +1 for each '\n' character */
|
||||||
}
|
}
|
||||||
|
length += 1; /* empty line "\n" at end of header */
|
||||||
|
length += 1; /* null terminator */
|
||||||
|
|
||||||
s = stream_new(length);
|
s = stream_new(length);
|
||||||
|
|
||||||
for (i = 0; i < http_request->count; i++)
|
for (i = 0; i < http_request->count; i++)
|
||||||
{
|
{
|
||||||
stream_write(s, http_request->lines[i], strlen(http_request->lines[i]));
|
stream_write(s, http_request->lines[i], strlen(http_request->lines[i]));
|
||||||
|
stream_write(s, "\n", 1);
|
||||||
xfree(http_request->lines[i]);
|
xfree(http_request->lines[i]);
|
||||||
}
|
}
|
||||||
|
stream_write(s, "\n", 1);
|
||||||
|
|
||||||
xfree(http_request->lines);
|
xfree(http_request->lines);
|
||||||
|
|
||||||
|
stream_write(s, "\0", 1); /* append null terminator */
|
||||||
|
stream_rewind(s, 1); /* don't include null terminator in length */
|
||||||
stream_seal(s);
|
stream_seal(s);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
@ -161,3 +186,228 @@ void http_request_free(HttpRequest* http_request)
|
|||||||
xfree(http_request);
|
xfree(http_request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void http_response_parse_header_status_line(HttpResponse* http_response, char* status_line)
|
||||||
|
{
|
||||||
|
char* separator;
|
||||||
|
char* status_code;
|
||||||
|
char* reason_phrase;
|
||||||
|
|
||||||
|
separator = strchr(status_line, ' ');
|
||||||
|
status_code = separator + 1;
|
||||||
|
|
||||||
|
separator = strchr(status_code, ' ');
|
||||||
|
reason_phrase = separator + 1;
|
||||||
|
|
||||||
|
*separator = '\0';
|
||||||
|
http_response->StatusCode = atoi(status_code);
|
||||||
|
http_response->ReasonPhrase = xstrdup(reason_phrase);
|
||||||
|
*separator = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
void http_response_parse_header_field(HttpResponse* http_response, char* name, char* value)
|
||||||
|
{
|
||||||
|
if (strcmp(name, "Content-Length") == 0)
|
||||||
|
{
|
||||||
|
http_response->ContentLength = atoi(value);
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "Authorization") == 0)
|
||||||
|
{
|
||||||
|
char* separator;
|
||||||
|
|
||||||
|
http_response->Authorization = xstrdup(value);
|
||||||
|
|
||||||
|
separator = strchr(value, ' ');
|
||||||
|
|
||||||
|
if (separator != NULL)
|
||||||
|
{
|
||||||
|
*separator = '\0';
|
||||||
|
http_response->AuthScheme = xstrdup(value);
|
||||||
|
http_response->AuthParam = xstrdup(separator + 1);
|
||||||
|
*separator = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "WWW-Authenticate") == 0)
|
||||||
|
{
|
||||||
|
char* separator;
|
||||||
|
|
||||||
|
separator = strstr(value, "=\"");
|
||||||
|
|
||||||
|
if (separator != NULL)
|
||||||
|
{
|
||||||
|
/* WWW-Authenticate: parameter with spaces="value" */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
separator = strchr(value, ' ');
|
||||||
|
|
||||||
|
if (separator != NULL)
|
||||||
|
{
|
||||||
|
/* WWW-Authenticate: NTLM base64token */
|
||||||
|
|
||||||
|
*separator = '\0';
|
||||||
|
http_response->AuthScheme = xstrdup(value);
|
||||||
|
http_response->AuthParam = xstrdup(separator + 1);
|
||||||
|
*separator = ' ';
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void http_response_parse_header(HttpResponse* http_response)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
char* line;
|
||||||
|
char* name;
|
||||||
|
char* value;
|
||||||
|
char* separator;
|
||||||
|
|
||||||
|
http_response_parse_header_status_line(http_response, http_response->lines[0]);
|
||||||
|
|
||||||
|
for (count = 1; count < http_response->count; count++)
|
||||||
|
{
|
||||||
|
line = http_response->lines[count];
|
||||||
|
|
||||||
|
separator = strstr(line, ": ");
|
||||||
|
|
||||||
|
if (separator == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
separator[0] = '\0';
|
||||||
|
separator[1] = '\0';
|
||||||
|
|
||||||
|
name = line;
|
||||||
|
value = separator + 2;
|
||||||
|
|
||||||
|
printf("%s:%s\n", name, value);
|
||||||
|
|
||||||
|
http_response_parse_header_field(http_response, name, value);
|
||||||
|
|
||||||
|
separator[0] = ':';
|
||||||
|
separator[1] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpResponse* http_response_recv(rdpTls* tls)
|
||||||
|
{
|
||||||
|
uint8* p;
|
||||||
|
int nbytes;
|
||||||
|
int length;
|
||||||
|
int status;
|
||||||
|
uint8* buffer;
|
||||||
|
char* content;
|
||||||
|
char* header_end;
|
||||||
|
HttpResponse* http_response;
|
||||||
|
|
||||||
|
nbytes = 0;
|
||||||
|
length = 2048;
|
||||||
|
buffer = xmalloc(length);
|
||||||
|
http_response = http_response_new();
|
||||||
|
|
||||||
|
p = buffer;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
status = tls_read(tls, p, length - nbytes);
|
||||||
|
|
||||||
|
if (status > 0)
|
||||||
|
{
|
||||||
|
nbytes += status;
|
||||||
|
p = (uint8*) &buffer[nbytes];
|
||||||
|
}
|
||||||
|
else if (status == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
header_end = strstr((char*) buffer, "\r\n\r\n") + 2;
|
||||||
|
|
||||||
|
if (header_end != NULL)
|
||||||
|
{
|
||||||
|
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++;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
http_response->count = count;
|
||||||
|
http_response->lines = (char**) xmalloc(sizeof(char*) * http_response->count);
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
line = strtok((char*) buffer, "\r\n");
|
||||||
|
|
||||||
|
while (line != NULL)
|
||||||
|
{
|
||||||
|
http_response->lines[count] = xstrdup(line);
|
||||||
|
line = strtok(NULL, "\r\n");
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
http_response_parse_header(http_response);
|
||||||
|
|
||||||
|
if (http_response->ContentLength > 0)
|
||||||
|
{
|
||||||
|
http_response->Content = xstrdup(content);
|
||||||
|
|
||||||
|
printf("Content: (%d)\n%s\n", http_response->ContentLength,
|
||||||
|
http_response->Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return http_response;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpResponse* http_response_new()
|
||||||
|
{
|
||||||
|
HttpResponse* http_response = xnew(HttpResponse);
|
||||||
|
|
||||||
|
if (http_response != NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return http_response;
|
||||||
|
}
|
||||||
|
|
||||||
|
void http_response_free(HttpResponse* http_response)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (http_response != NULL)
|
||||||
|
{
|
||||||
|
for (i = 0; i < http_response->count; i++)
|
||||||
|
xfree(http_response->lines[i]);
|
||||||
|
|
||||||
|
xfree(http_response->lines);
|
||||||
|
|
||||||
|
xfree(http_response->ReasonPhrase);
|
||||||
|
|
||||||
|
xfree(http_response->AuthParam);
|
||||||
|
xfree(http_response->AuthScheme);
|
||||||
|
xfree(http_response->Authorization);
|
||||||
|
|
||||||
|
if (http_response->ContentLength > 0)
|
||||||
|
xfree(http_response->Content);
|
||||||
|
|
||||||
|
xfree(http_response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -20,7 +20,12 @@
|
|||||||
#ifndef FREERDP_CORE_HTTP_H
|
#ifndef FREERDP_CORE_HTTP_H
|
||||||
#define FREERDP_CORE_HTTP_H
|
#define FREERDP_CORE_HTTP_H
|
||||||
|
|
||||||
|
typedef struct _http_context HttpContext;
|
||||||
|
typedef struct _http_request HttpRequest;
|
||||||
|
typedef struct _http_response HttpResponse;
|
||||||
|
|
||||||
#include <freerdp/types.h>
|
#include <freerdp/types.h>
|
||||||
|
#include <freerdp/crypto/tls.h>
|
||||||
#include <freerdp/utils/stream.h>
|
#include <freerdp/utils/stream.h>
|
||||||
|
|
||||||
struct _http_context
|
struct _http_context
|
||||||
@ -34,7 +39,6 @@ struct _http_context
|
|||||||
char* Connection;
|
char* Connection;
|
||||||
char* Pragma;
|
char* Pragma;
|
||||||
};
|
};
|
||||||
typedef struct _http_context HttpContext;
|
|
||||||
|
|
||||||
void http_context_set_method(HttpContext* http_context, char* method);
|
void http_context_set_method(HttpContext* http_context, char* method);
|
||||||
void http_context_set_uri(HttpContext* http_context, char* uri);
|
void http_context_set_uri(HttpContext* http_context, char* uri);
|
||||||
@ -55,18 +59,41 @@ struct _http_request
|
|||||||
|
|
||||||
char* Method;
|
char* Method;
|
||||||
char* URI;
|
char* URI;
|
||||||
|
char* AuthScheme;
|
||||||
|
char* AuthParam;
|
||||||
char* Authorization;
|
char* Authorization;
|
||||||
int ContentLength;
|
int ContentLength;
|
||||||
char* Content;
|
char* Content;
|
||||||
};
|
};
|
||||||
typedef struct _http_request HttpRequest;
|
|
||||||
|
|
||||||
void http_request_set_method(HttpRequest* http_request, char* method);
|
void http_request_set_method(HttpRequest* http_request, char* method);
|
||||||
void http_request_set_uri(HttpRequest* http_request, char* uri);
|
void http_request_set_uri(HttpRequest* http_request, char* uri);
|
||||||
|
void http_request_set_auth_scheme(HttpRequest* http_request, char* auth_scheme);
|
||||||
|
void http_request_set_auth_param(HttpRequest* http_request, char* auth_param);
|
||||||
|
|
||||||
STREAM* http_request_write(HttpContext* http_context, HttpRequest* http_request);
|
STREAM* http_request_write(HttpContext* http_context, HttpRequest* http_request);
|
||||||
|
|
||||||
HttpRequest* http_request_new();
|
HttpRequest* http_request_new();
|
||||||
void http_request_free(HttpRequest* http_request);
|
void http_request_free(HttpRequest* http_request);
|
||||||
|
|
||||||
|
struct _http_response
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
char** lines;
|
||||||
|
|
||||||
|
int StatusCode;
|
||||||
|
char* ReasonPhrase;
|
||||||
|
|
||||||
|
char* AuthScheme;
|
||||||
|
char* AuthParam;
|
||||||
|
char* Authorization;
|
||||||
|
int ContentLength;
|
||||||
|
char* Content;
|
||||||
|
};
|
||||||
|
|
||||||
|
HttpResponse* http_response_recv(rdpTls* tls);
|
||||||
|
|
||||||
|
HttpResponse* http_response_new();
|
||||||
|
void http_response_free(HttpResponse* http_response);
|
||||||
|
|
||||||
#endif /* FREERDP_CORE_HTTP_H */
|
#endif /* FREERDP_CORE_HTTP_H */
|
||||||
|
@ -169,62 +169,42 @@ void ntlm_free(rdpNtlm* ntlm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STREAM* rpch_ntlm_http_data(rdpRpch* rpch, char* command, SecBuffer* ntlm_token, uint8* content, int length)
|
STREAM* rpc_ntlm_http_data(rdpRpch* rpch, char* command, SecBuffer* ntlm_token, uint8* content, int length)
|
||||||
{
|
{
|
||||||
STREAM* s;
|
STREAM* s;
|
||||||
char* int_str;
|
char* base64_ntlm_token;
|
||||||
int total_length;
|
HttpContext* http_context;
|
||||||
int int_str_length;
|
HttpRequest* http_request;
|
||||||
int command_length;
|
|
||||||
rdpSettings* settings;
|
|
||||||
int tsg_hostname_length;
|
|
||||||
int ntlm_token_base64_length;
|
|
||||||
uint8* ntlm_token_base64_data;
|
|
||||||
|
|
||||||
settings = rpch->settings;
|
base64_ntlm_token = crypto_encode_base64(ntlm_token->pvBuffer, ntlm_token->cbBuffer);
|
||||||
|
|
||||||
command_length = strlen(command);
|
printf("base64_ntlm_token length:%d\n", strlen(base64_ntlm_token));
|
||||||
|
|
||||||
int_str_length = snprintf(NULL, 0, "%d", length);
|
if (strcmp(command, "RPC_IN_DATA") == 0)
|
||||||
tsg_hostname_length = strlen(settings->tsg_hostname);
|
http_context = rpch->http_in->context;
|
||||||
|
else
|
||||||
|
http_context = rpch->http_out->context;
|
||||||
|
|
||||||
int_str = xmalloc(int_str_length + 1);
|
http_request = http_request_new();
|
||||||
snprintf(int_str, int_str_length + 1, "%d", length);
|
|
||||||
|
|
||||||
crypto_base64_encode(ntlm_token->pvBuffer, ntlm_token->cbBuffer, &ntlm_token_base64_data, &ntlm_token_base64_length);
|
http_request->ContentLength = length;
|
||||||
|
|
||||||
total_length = 55 + 24 + 24 + 23 + 16 + int_str_length + 1 + 18 + 6 +
|
http_request_set_method(http_request, http_context->Method);
|
||||||
tsg_hostname_length + 1 + 110 + 20 + ntlm_token_base64_length + 2;
|
http_request_set_uri(http_request, http_context->URI);
|
||||||
|
|
||||||
s = stream_new(total_length);
|
http_request_set_auth_scheme(http_request, "NTLM");
|
||||||
|
http_request_set_auth_param(http_request, base64_ntlm_token);
|
||||||
|
|
||||||
stream_write(s, command, command_length);
|
s = http_request_write(http_context, http_request);
|
||||||
stream_write(s, " /rpc/rpcproxy.dll?localhost:3388 HTTP/1.1\n", 43);
|
|
||||||
stream_write(s, "Accept: application/rpc\n", 24);
|
|
||||||
stream_write(s, "Cache-Control: no-cache\n", 24);
|
|
||||||
stream_write(s, "Connection: Keep-Alive\n", 23);
|
|
||||||
|
|
||||||
stream_write(s, "Content-Length: ", 16);
|
|
||||||
stream_write(s, int_str, int_str_length);
|
|
||||||
stream_write(s, "\n", 1);
|
|
||||||
|
|
||||||
stream_write(s, "User-Agent: MSRPC\n", 18);
|
|
||||||
stream_write(s, "Host: ", 6);
|
|
||||||
stream_write(s, settings->tsg_hostname, tsg_hostname_length);
|
|
||||||
stream_write(s, "\n", 1);
|
|
||||||
stream_write(s, "Pragma: ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, SessionId=33ad20ac-7469-4f63-946d-113eac21a23c\n", 110);
|
|
||||||
stream_write(s, "Authorization: NTLM ", 20);
|
|
||||||
stream_write(s, ntlm_token_base64_data, ntlm_token_base64_length);
|
|
||||||
stream_write(s, "\n\n", 2);
|
|
||||||
stream_seal(s);
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean rpch_out_connect_http(rdpRpch* rpch)
|
boolean rpc_out_connect_http(rdpRpch* rpch)
|
||||||
{
|
{
|
||||||
STREAM* http_stream;
|
STREAM* http_stream;
|
||||||
STREAM* ntlm_stream;
|
STREAM* ntlm_stream;
|
||||||
|
HttpResponse* http_response;
|
||||||
int decoded_ntlm_http_length;
|
int decoded_ntlm_http_length;
|
||||||
int encoded_ntlm_http_length;
|
int encoded_ntlm_http_length;
|
||||||
uint8* decoded_ntlm_http_data = NULL;
|
uint8* decoded_ntlm_http_data = NULL;
|
||||||
@ -236,13 +216,13 @@ boolean rpch_out_connect_http(rdpRpch* rpch)
|
|||||||
|
|
||||||
ntlm_stream = stream_new(0);
|
ntlm_stream = stream_new(0);
|
||||||
|
|
||||||
printf("rpch_out_connect_http\n");
|
printf("rpc_out_connect_http\n");
|
||||||
|
|
||||||
ntlm_client_init(http_out_ntlm, settings->username, settings->password, settings->domain);
|
ntlm_client_init(http_out_ntlm, settings->username, settings->password, settings->domain);
|
||||||
|
|
||||||
ntlm_authenticate(http_out_ntlm);
|
ntlm_authenticate(http_out_ntlm);
|
||||||
|
|
||||||
http_stream = rpch_ntlm_http_data(rpch, "RPC_OUT_DATA", &http_out_ntlm->outputBuffer, NULL, 0);
|
http_stream = rpc_ntlm_http_data(rpch, "RPC_OUT_DATA", &http_out_ntlm->outputBuffer, NULL, 0);
|
||||||
|
|
||||||
DEBUG_RPCH("\nSend:\n%s\n", http_stream->data);
|
DEBUG_RPCH("\nSend:\n%s\n", http_stream->data);
|
||||||
tls_write(tls_out, http_stream->data, http_stream->size);
|
tls_write(tls_out, http_stream->data, http_stream->size);
|
||||||
@ -256,73 +236,15 @@ boolean rpch_out_connect_http(rdpRpch* rpch)
|
|||||||
uint8 buffer_byte;
|
uint8 buffer_byte;
|
||||||
http_out->contentLength = 0;
|
http_out->contentLength = 0;
|
||||||
|
|
||||||
/* Example for how not to do clear code, sorry for that */
|
http_response = http_response_recv(tls_out);
|
||||||
while (true) /* TODO make proper reading */
|
|
||||||
{
|
|
||||||
tls_read(tls_out, &buffer_byte, 1);
|
|
||||||
stream_write(http_stream, &buffer_byte, 1);
|
|
||||||
|
|
||||||
if (encoded_ntlm_http_length == -1)
|
|
||||||
{
|
|
||||||
uint8* start_of_ntlm_http_data = (uint8*) strstr((char*) http_stream->data, "NTLM ");
|
|
||||||
|
|
||||||
if (start_of_ntlm_http_data != NULL)
|
|
||||||
{
|
|
||||||
start_of_ntlm_http_data += 5;
|
|
||||||
|
|
||||||
for (encoded_ntlm_http_length = 0; ; encoded_ntlm_http_length++)
|
|
||||||
{
|
|
||||||
tls_read(tls_out, &buffer_byte, 1);
|
|
||||||
stream_write(http_stream, &buffer_byte, 1);
|
|
||||||
|
|
||||||
if (start_of_ntlm_http_data[encoded_ntlm_http_length] == '\n')
|
|
||||||
{
|
|
||||||
encoded_ntlm_http_length--; /* \r */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
encoded_ntlm_http_data = xmalloc(encoded_ntlm_http_length);
|
|
||||||
memcpy(encoded_ntlm_http_data, start_of_ntlm_http_data, encoded_ntlm_http_length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (http_out->contentLength == 0)
|
|
||||||
{
|
|
||||||
if (strstr((char*) http_stream->data, "Content-Length: ") != NULL)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (*(http_stream->p-1) != '\n')
|
|
||||||
{
|
|
||||||
tls_read(tls_out, &buffer_byte, 1);
|
|
||||||
stream_write(http_stream, &buffer_byte, 1);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
http_out->contentLength = strtol((char*)(http_stream->p - i), NULL, 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*(http_stream->p - 1) == '\n' && *(http_stream->p - 3) == '\n')
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < http_out->contentLength; i++)
|
|
||||||
{
|
|
||||||
tls_read(tls_out, &buffer_byte, 1);
|
|
||||||
stream_write(http_stream, &buffer_byte, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Example end */
|
|
||||||
|
|
||||||
DEBUG_RPCH("\nRecv:\n%s\n", http_stream->data);
|
DEBUG_RPCH("\nRecv:\n%s\n", http_stream->data);
|
||||||
stream_clear(http_stream);
|
stream_clear(http_stream);
|
||||||
http_stream->p = http_stream->data;
|
http_stream->p = http_stream->data;
|
||||||
|
|
||||||
|
encoded_ntlm_http_data = http_response->AuthParam;
|
||||||
|
encoded_ntlm_http_length = strlen(encoded_ntlm_http_data);
|
||||||
|
|
||||||
if (encoded_ntlm_http_length == 0) /* No NTLM data was found */
|
if (encoded_ntlm_http_length == 0) /* No NTLM data was found */
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -336,7 +258,7 @@ boolean rpch_out_connect_http(rdpRpch* rpch)
|
|||||||
http_out->contentLength = 76;
|
http_out->contentLength = 76;
|
||||||
http_out->remContentLength = 76;
|
http_out->remContentLength = 76;
|
||||||
|
|
||||||
http_stream = rpch_ntlm_http_data(rpch, "RPC_OUT_DATA", &http_out_ntlm->outputBuffer, NULL, http_out->contentLength);
|
http_stream = rpc_ntlm_http_data(rpch, "RPC_OUT_DATA", &http_out_ntlm->outputBuffer, NULL, http_out->contentLength);
|
||||||
|
|
||||||
DEBUG_RPCH("\nSend:\n%s\n", http_stream->data);
|
DEBUG_RPCH("\nSend:\n%s\n", http_stream->data);
|
||||||
tls_write(tls_out, http_stream->data, http_stream->size);
|
tls_write(tls_out, http_stream->data, http_stream->size);
|
||||||
@ -351,10 +273,11 @@ boolean rpch_out_connect_http(rdpRpch* rpch)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean rpch_in_connect_http(rdpRpch* rpch)
|
boolean rpc_in_connect_http(rdpRpch* rpch)
|
||||||
{
|
{
|
||||||
STREAM* ntlm_stream;
|
STREAM* ntlm_stream;
|
||||||
STREAM* http_stream;
|
STREAM* http_stream;
|
||||||
|
HttpResponse* http_response;
|
||||||
int decoded_ntlm_http_length;
|
int decoded_ntlm_http_length;
|
||||||
int encoded_ntlm_http_length;
|
int encoded_ntlm_http_length;
|
||||||
uint8* decoded_ntlm_http_data = NULL;
|
uint8* decoded_ntlm_http_data = NULL;
|
||||||
@ -372,7 +295,7 @@ boolean rpch_in_connect_http(rdpRpch* rpch)
|
|||||||
|
|
||||||
ntlm_authenticate(http_in_ntlm);
|
ntlm_authenticate(http_in_ntlm);
|
||||||
|
|
||||||
http_stream = rpch_ntlm_http_data(rpch, "RPC_IN_DATA", &http_in_ntlm->outputBuffer, NULL, 0);
|
http_stream = rpc_ntlm_http_data(rpch, "RPC_IN_DATA", &http_in_ntlm->outputBuffer, NULL, 0);
|
||||||
|
|
||||||
DEBUG_RPCH("\nSend:\n%s\n", http_stream->data);
|
DEBUG_RPCH("\nSend:\n%s\n", http_stream->data);
|
||||||
tls_write(tls_in, http_stream->data, http_stream->size);
|
tls_write(tls_in, http_stream->data, http_stream->size);
|
||||||
@ -388,73 +311,15 @@ boolean rpch_in_connect_http(rdpRpch* rpch)
|
|||||||
uint8 buffer_byte;
|
uint8 buffer_byte;
|
||||||
http_in->contentLength = 0;
|
http_in->contentLength = 0;
|
||||||
|
|
||||||
/* Example for how not to do clear code, sorry for that */
|
http_response = http_response_recv(tls_in);
|
||||||
while (true) /* TODO make proper reading */
|
|
||||||
{
|
|
||||||
tls_read(tls_in, &buffer_byte, 1);
|
|
||||||
stream_write(http_stream, &buffer_byte, 1);
|
|
||||||
|
|
||||||
if (encoded_ntlm_http_length == -1)
|
|
||||||
{
|
|
||||||
uint8* start_of_ntht_data = (uint8*) strstr((char*) http_stream->data, "NTLM ");
|
|
||||||
|
|
||||||
if (start_of_ntht_data != NULL)
|
|
||||||
{
|
|
||||||
start_of_ntht_data += 5;
|
|
||||||
|
|
||||||
for (encoded_ntlm_http_length=0;;encoded_ntlm_http_length++)
|
|
||||||
{
|
|
||||||
tls_read(tls_in, &buffer_byte, 1);
|
|
||||||
stream_write(http_stream, &buffer_byte, 1);
|
|
||||||
|
|
||||||
if (start_of_ntht_data[encoded_ntlm_http_length]=='\n')
|
|
||||||
{
|
|
||||||
encoded_ntlm_http_length--; /* \r */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
encoded_ntlm_http_data = xmalloc(encoded_ntlm_http_length);
|
|
||||||
memcpy(encoded_ntlm_http_data, start_of_ntht_data, encoded_ntlm_http_length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (http_in->contentLength == 0)
|
|
||||||
{
|
|
||||||
if (strstr((char*) http_stream->data, "Content-Length: ") != NULL)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (*(http_stream->p-1) != '\n')
|
|
||||||
{
|
|
||||||
tls_read(tls_in, &buffer_byte, 1);
|
|
||||||
stream_write(http_stream, &buffer_byte, 1);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
http_in->contentLength = strtol((char*)(http_stream->p-i), NULL, 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*(http_stream->p - 1) == '\n' && *(http_stream->p - 3) == '\n')
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0; i < http_in->contentLength; i++)
|
|
||||||
{
|
|
||||||
tls_read(tls_in, &buffer_byte, 1);
|
|
||||||
stream_write(http_stream, &buffer_byte, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Example end */
|
|
||||||
|
|
||||||
DEBUG_RPCH("\nRecv:\n%s\n", http_stream->data);
|
DEBUG_RPCH("\nRecv:\n%s\n", http_stream->data);
|
||||||
stream_clear(http_stream);
|
stream_clear(http_stream);
|
||||||
http_stream->p = http_stream->data;
|
http_stream->p = http_stream->data;
|
||||||
|
|
||||||
|
encoded_ntlm_http_data = http_response->AuthParam;
|
||||||
|
encoded_ntlm_http_length = strlen(encoded_ntlm_http_data);
|
||||||
|
|
||||||
if (encoded_ntlm_http_length == 0) /* No NTLM data was found */
|
if (encoded_ntlm_http_length == 0) /* No NTLM data was found */
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -468,7 +333,7 @@ boolean rpch_in_connect_http(rdpRpch* rpch)
|
|||||||
http_in->contentLength = 1073741824;
|
http_in->contentLength = 1073741824;
|
||||||
http_in->remContentLength = 1073741824;
|
http_in->remContentLength = 1073741824;
|
||||||
|
|
||||||
http_stream = rpch_ntlm_http_data(rpch, "RPC_IN_DATA", &http_in_ntlm->outputBuffer, NULL, http_in->contentLength);
|
http_stream = rpc_ntlm_http_data(rpch, "RPC_IN_DATA", &http_in_ntlm->outputBuffer, NULL, http_in->contentLength);
|
||||||
|
|
||||||
DEBUG_RPCH("\nSend:\n%s\n", http_stream->data);
|
DEBUG_RPCH("\nSend:\n%s\n", http_stream->data);
|
||||||
|
|
||||||
@ -486,7 +351,7 @@ boolean rpch_in_connect_http(rdpRpch* rpch)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpch_out_write(rdpRpch* rpch, uint8* data, int length)
|
int rpc_out_write(rdpRpch* rpch, uint8* data, int length)
|
||||||
{
|
{
|
||||||
int sent = 0;
|
int sent = 0;
|
||||||
int status = -1;
|
int status = -1;
|
||||||
@ -495,7 +360,7 @@ int rpch_out_write(rdpRpch* rpch, uint8* data, int length)
|
|||||||
|
|
||||||
if (http_out->state == RPCH_HTTP_DISCONNECTED)
|
if (http_out->state == RPCH_HTTP_DISCONNECTED)
|
||||||
{
|
{
|
||||||
if (!rpch_out_connect_http(rpch))
|
if (!rpc_out_connect_http(rpch))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,7 +391,7 @@ int rpch_out_write(rdpRpch* rpch, uint8* data, int length)
|
|||||||
return sent;
|
return sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpch_in_write(rdpRpch* rpch, uint8* data, int length)
|
int rpc_in_write(rdpRpch* rpch, uint8* data, int length)
|
||||||
{
|
{
|
||||||
int sent = 0;
|
int sent = 0;
|
||||||
int status = -1;
|
int status = -1;
|
||||||
@ -535,7 +400,7 @@ int rpch_in_write(rdpRpch* rpch, uint8* data, int length)
|
|||||||
|
|
||||||
if (http_in->state == RPCH_HTTP_DISCONNECTED)
|
if (http_in->state == RPCH_HTTP_DISCONNECTED)
|
||||||
{
|
{
|
||||||
if (!rpch_in_connect_http(rpch))
|
if (!rpc_in_connect_http(rpch))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,14 +432,14 @@ int rpch_in_write(rdpRpch* rpch, uint8* data, int length)
|
|||||||
return sent;
|
return sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8* rpch_create_cookie()
|
uint8* rpc_create_cookie()
|
||||||
{
|
{
|
||||||
uint8* ret = xmalloc(16);
|
uint8* ret = xmalloc(16);
|
||||||
RAND_pseudo_bytes(ret, 16);
|
RAND_pseudo_bytes(ret, 16);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean rpch_out_send_CONN_A1(rdpRpch* rpch)
|
boolean rpc_out_send_CONN_A1(rdpRpch* rpch)
|
||||||
{
|
{
|
||||||
STREAM* pdu = stream_new(76);
|
STREAM* pdu = stream_new(76);
|
||||||
|
|
||||||
@ -597,8 +462,8 @@ boolean rpch_out_send_CONN_A1(rdpRpch* rpch)
|
|||||||
uint32 rwsCommandType = 0x00000000;
|
uint32 rwsCommandType = 0x00000000;
|
||||||
uint32 receiveWindowSize = 0x00010000;
|
uint32 receiveWindowSize = 0x00010000;
|
||||||
|
|
||||||
rpch->virtualConnectionCookie = rpch_create_cookie(); /* 16 bytes */
|
rpch->virtualConnectionCookie = rpc_create_cookie(); /* 16 bytes */
|
||||||
rpch->OUTChannelCookie = rpch_create_cookie(); /* 16 bytes */
|
rpch->OUTChannelCookie = rpc_create_cookie(); /* 16 bytes */
|
||||||
rpch->AwailableWindow = receiveWindowSize;
|
rpch->AwailableWindow = receiveWindowSize;
|
||||||
|
|
||||||
stream_write_uint8(pdu, rpc_vers);
|
stream_write_uint8(pdu, rpc_vers);
|
||||||
@ -620,14 +485,14 @@ boolean rpch_out_send_CONN_A1(rdpRpch* rpch)
|
|||||||
stream_write_uint32(pdu, rwsCommandType);
|
stream_write_uint32(pdu, rwsCommandType);
|
||||||
stream_write_uint32(pdu, receiveWindowSize);
|
stream_write_uint32(pdu, receiveWindowSize);
|
||||||
|
|
||||||
rpch_out_write(rpch, pdu->data, stream_get_length(pdu));
|
rpc_out_write(rpch, pdu->data, stream_get_length(pdu));
|
||||||
|
|
||||||
stream_free(pdu);
|
stream_free(pdu);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean rpch_in_send_CONN_B1(rdpRpch* rpch)
|
boolean rpc_in_send_CONN_B1(rdpRpch* rpch)
|
||||||
{
|
{
|
||||||
STREAM* s = stream_new(104);
|
STREAM* s = stream_new(104);
|
||||||
|
|
||||||
@ -654,8 +519,8 @@ boolean rpch_in_send_CONN_B1(rdpRpch* rpch)
|
|||||||
uint32 agidCommandType = 0x0000000c;
|
uint32 agidCommandType = 0x0000000c;
|
||||||
uint8* AssociationGroupId;
|
uint8* AssociationGroupId;
|
||||||
|
|
||||||
rpch->INChannelCookie = rpch_create_cookie(); /* 16 bytes */
|
rpch->INChannelCookie = rpc_create_cookie(); /* 16 bytes */
|
||||||
AssociationGroupId = rpch_create_cookie(); /* 16 bytes */
|
AssociationGroupId = rpc_create_cookie(); /* 16 bytes */
|
||||||
|
|
||||||
stream_write_uint8(s, rpc_vers);
|
stream_write_uint8(s, rpc_vers);
|
||||||
stream_write_uint8(s, rpc_vers_minor);
|
stream_write_uint8(s, rpc_vers_minor);
|
||||||
@ -681,14 +546,14 @@ boolean rpch_in_send_CONN_B1(rdpRpch* rpch)
|
|||||||
stream_write(s, AssociationGroupId, 16);
|
stream_write(s, AssociationGroupId, 16);
|
||||||
stream_seal(s);
|
stream_seal(s);
|
||||||
|
|
||||||
rpch_in_write(rpch, s->data, s->size);
|
rpc_in_write(rpch, s->data, s->size);
|
||||||
|
|
||||||
stream_free(s);
|
stream_free(s);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean rpch_in_send_keep_alive(rdpRpch* rpch)
|
boolean rpc_in_send_keep_alive(rdpRpch* rpch)
|
||||||
{
|
{
|
||||||
STREAM* s = stream_new(28);
|
STREAM* s = stream_new(28);
|
||||||
|
|
||||||
@ -718,14 +583,14 @@ boolean rpch_in_send_keep_alive(rdpRpch* rpch)
|
|||||||
stream_write_uint32(s, ckCommandType);
|
stream_write_uint32(s, ckCommandType);
|
||||||
stream_write_uint32(s, ClientKeepalive);
|
stream_write_uint32(s, ClientKeepalive);
|
||||||
|
|
||||||
rpch_in_write(rpch, s->data, stream_get_length(s));
|
rpc_in_write(rpch, s->data, stream_get_length(s));
|
||||||
|
|
||||||
stream_free(s);
|
stream_free(s);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean rpch_in_send_bind(rdpRpch* rpch)
|
boolean rpc_in_send_bind(rdpRpch* rpch)
|
||||||
{
|
{
|
||||||
rpcconn_bind_hdr_t* bind_pdu;
|
rpcconn_bind_hdr_t* bind_pdu;
|
||||||
rdpSettings* settings = rpch->settings;
|
rdpSettings* settings = rpch->settings;
|
||||||
@ -844,7 +709,7 @@ boolean rpch_in_send_bind(rdpRpch* rpch)
|
|||||||
stream_write(pdu, &bind_pdu->auth_verifier.auth_type, 8); /* assumed that uint8 pointer is 32bit long (4 bytes) */
|
stream_write(pdu, &bind_pdu->auth_verifier.auth_type, 8); /* assumed that uint8 pointer is 32bit long (4 bytes) */
|
||||||
stream_write(pdu, bind_pdu->auth_verifier.auth_value, bind_pdu->auth_length);
|
stream_write(pdu, bind_pdu->auth_verifier.auth_value, bind_pdu->auth_length);
|
||||||
|
|
||||||
rpch_in_write(rpch, pdu->data, stream_get_length(pdu));
|
rpc_in_write(rpch, pdu->data, stream_get_length(pdu));
|
||||||
|
|
||||||
/* TODO there is some allocated memory */
|
/* TODO there is some allocated memory */
|
||||||
xfree(bind_pdu);
|
xfree(bind_pdu);
|
||||||
@ -852,7 +717,7 @@ boolean rpch_in_send_bind(rdpRpch* rpch)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean rpch_in_send_rpc_auth_3(rdpRpch* rpch)
|
boolean rpc_in_send_rpc_auth_3(rdpRpch* rpch)
|
||||||
{
|
{
|
||||||
rpcconn_rpc_auth_3_hdr_t* rpc_auth_3_pdu;
|
rpcconn_rpc_auth_3_hdr_t* rpc_auth_3_pdu;
|
||||||
STREAM* ntlm_stream = stream_new(0xFFFF);
|
STREAM* ntlm_stream = stream_new(0xFFFF);
|
||||||
@ -896,14 +761,14 @@ boolean rpch_in_send_rpc_auth_3(rdpRpch* rpch)
|
|||||||
stream_write(pdu, &rpc_auth_3_pdu->auth_verifier.auth_type, 8);
|
stream_write(pdu, &rpc_auth_3_pdu->auth_verifier.auth_type, 8);
|
||||||
stream_write(pdu, rpc_auth_3_pdu->auth_verifier.auth_value, rpc_auth_3_pdu->auth_length);
|
stream_write(pdu, rpc_auth_3_pdu->auth_verifier.auth_value, rpc_auth_3_pdu->auth_length);
|
||||||
|
|
||||||
rpch_in_write(rpch, pdu->data, stream_get_length(pdu));
|
rpc_in_write(rpch, pdu->data, stream_get_length(pdu));
|
||||||
|
|
||||||
xfree(rpc_auth_3_pdu);
|
xfree(rpc_auth_3_pdu);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean rpch_in_send_flow_control(rdpRpch* rpch)
|
boolean rpc_in_send_flow_control(rdpRpch* rpch)
|
||||||
{
|
{
|
||||||
STREAM* s = stream_new(56);
|
STREAM* s = stream_new(56);
|
||||||
|
|
||||||
@ -944,14 +809,14 @@ boolean rpch_in_send_flow_control(rdpRpch* rpch)
|
|||||||
stream_write_uint32(s, aaa);
|
stream_write_uint32(s, aaa);
|
||||||
stream_write(s, b, 16);
|
stream_write(s, b, 16);
|
||||||
|
|
||||||
rpch_in_write(rpch, s->data, stream_get_length(s));
|
rpc_in_write(rpch, s->data, stream_get_length(s));
|
||||||
|
|
||||||
stream_free(s);
|
stream_free(s);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean rpch_in_send_ping(rdpRpch* rpch)
|
boolean rpc_in_send_ping(rdpRpch* rpch)
|
||||||
{
|
{
|
||||||
STREAM* s = stream_new(20);
|
STREAM* s = stream_new(20);
|
||||||
|
|
||||||
@ -977,14 +842,14 @@ boolean rpch_in_send_ping(rdpRpch* rpch)
|
|||||||
stream_write_uint16(s, flags);
|
stream_write_uint16(s, flags);
|
||||||
stream_write_uint16(s, num_commands);
|
stream_write_uint16(s, num_commands);
|
||||||
|
|
||||||
rpch_in_write(rpch, s->data, stream_get_length(s));
|
rpc_in_write(rpch, s->data, stream_get_length(s));
|
||||||
|
|
||||||
stream_free(s);
|
stream_free(s);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpch_out_read_http_header(rdpRpch* rpch)
|
int rpc_out_read_http_header(rdpRpch* rpch)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
STREAM* http_stream;
|
STREAM* http_stream;
|
||||||
@ -1040,7 +905,7 @@ int rpch_out_read_http_header(rdpRpch* rpch)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpch_proceed_RTS(rdpRpch* rpch, uint8* pdu, int length)
|
int rpc_rts_recv(rdpRpch* rpch, uint8* pdu, int length)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint32 CommandType;
|
uint32 CommandType;
|
||||||
@ -1050,7 +915,7 @@ int rpch_proceed_RTS(rdpRpch* rpch, uint8* pdu, int length)
|
|||||||
|
|
||||||
if (flags & RTS_FLAG_PING)
|
if (flags & RTS_FLAG_PING)
|
||||||
{
|
{
|
||||||
rpch_in_send_keep_alive(rpch);
|
rpc_in_send_keep_alive(rpch);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1128,7 +993,7 @@ int rpch_proceed_RTS(rdpRpch* rpch, uint8* pdu, int length)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpch_out_read(rdpRpch* rpch, uint8* data, int length)
|
int rpc_out_read(rdpRpch* rpch, uint8* data, int length)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
uint8* pdu;
|
uint8* pdu;
|
||||||
@ -1138,11 +1003,11 @@ int rpch_out_read(rdpRpch* rpch, uint8* data, int length)
|
|||||||
rdpRpchHTTP* http_out = rpch->http_out;
|
rdpRpchHTTP* http_out = rpch->http_out;
|
||||||
|
|
||||||
if (rpch->AwailableWindow < 0x00008FFF) /* Just a simple workaround */
|
if (rpch->AwailableWindow < 0x00008FFF) /* Just a simple workaround */
|
||||||
rpch_in_send_flow_control(rpch); /* Send FlowControlAck every time AW reaches the half */
|
rpc_in_send_flow_control(rpch); /* Send FlowControlAck every time AW reaches the half */
|
||||||
|
|
||||||
if (http_out->remContentLength <= 0xFFFF) /* TODO make ChannelRecycling */
|
if (http_out->remContentLength <= 0xFFFF) /* TODO make ChannelRecycling */
|
||||||
{
|
{
|
||||||
if (rpch_out_read_http_header(rpch) < 0)
|
if (rpc_out_read_http_header(rpch) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1169,7 +1034,7 @@ int rpch_out_read(rdpRpch* rpch, uint8* data, int length)
|
|||||||
|
|
||||||
if (ptype == 0x14) /* RTS PDU */
|
if (ptype == 0x14) /* RTS PDU */
|
||||||
{
|
{
|
||||||
rpch_proceed_RTS(rpch, pdu, frag_length);
|
rpc_rts_recv(rpch, pdu, frag_length);
|
||||||
xfree(pdu);
|
xfree(pdu);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1201,14 +1066,14 @@ int rpch_out_read(rdpRpch* rpch, uint8* data, int length)
|
|||||||
return frag_length;
|
return frag_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpch_out_recv_bind_ack(rdpRpch* rpch)
|
int rpc_out_recv_bind_ack(rdpRpch* rpch)
|
||||||
{
|
{
|
||||||
uint16 frag_length;
|
uint16 frag_length;
|
||||||
uint16 auth_length;
|
uint16 auth_length;
|
||||||
STREAM* ntlmssp_stream;
|
STREAM* ntlmssp_stream;
|
||||||
int pdu_length = 0x8FFF; /* 32KB buffer */
|
int pdu_length = 0x8FFF; /* 32KB buffer */
|
||||||
uint8* pdu = xmalloc(pdu_length);
|
uint8* pdu = xmalloc(pdu_length);
|
||||||
int status = rpch_out_read(rpch, pdu, pdu_length);
|
int status = rpc_out_read(rpch, pdu, pdu_length);
|
||||||
|
|
||||||
DEBUG_RPCH("TODO: complete NTLM integration");
|
DEBUG_RPCH("TODO: complete NTLM integration");
|
||||||
|
|
||||||
@ -1230,7 +1095,7 @@ int rpch_out_recv_bind_ack(rdpRpch* rpch)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpch_write(rdpRpch* rpch, uint8* data, int length, uint16 opnum)
|
int rpc_write(rdpRpch* rpch, uint8* data, int length, uint16 opnum)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int status = -1;
|
int status = -1;
|
||||||
@ -1297,7 +1162,7 @@ int rpch_write(rdpRpch* rpch, uint8* data, int length, uint16 opnum)
|
|||||||
|
|
||||||
stream_write(pdu, request_pdu->auth_verifier.auth_value, request_pdu->auth_length);
|
stream_write(pdu, request_pdu->auth_verifier.auth_value, request_pdu->auth_length);
|
||||||
|
|
||||||
status = rpch_in_write(rpch, pdu->data, pdu->p - pdu->data);
|
status = rpc_in_write(rpch, pdu->data, pdu->p - pdu->data);
|
||||||
|
|
||||||
xfree(request_pdu->auth_verifier.auth_value);
|
xfree(request_pdu->auth_verifier.auth_value);
|
||||||
xfree(request_pdu->auth_verifier.auth_pad);
|
xfree(request_pdu->auth_verifier.auth_pad);
|
||||||
@ -1341,7 +1206,7 @@ int rpch_read(rdpRpch* rpch, uint8* data, int length)
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
status = rpch_out_read(rpch, rpch_data, rpch_length);
|
status = rpc_out_read(rpch, rpch_data, rpch_length);
|
||||||
|
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
{
|
{
|
||||||
@ -1400,7 +1265,7 @@ boolean rpch_connect(rdpRpch* rpch)
|
|||||||
uint8* pdu;
|
uint8* pdu;
|
||||||
int pdu_length;
|
int pdu_length;
|
||||||
|
|
||||||
if (!rpch_out_send_CONN_A1(rpch))
|
if (!rpc_out_send_CONN_A1(rpch))
|
||||||
{
|
{
|
||||||
printf("rpch_out_send_CONN_A1 fault!\n");
|
printf("rpch_out_send_CONN_A1 fault!\n");
|
||||||
return false;
|
return false;
|
||||||
@ -1409,32 +1274,32 @@ boolean rpch_connect(rdpRpch* rpch)
|
|||||||
pdu_length = 0xFFFF;
|
pdu_length = 0xFFFF;
|
||||||
pdu = xmalloc(pdu_length);
|
pdu = xmalloc(pdu_length);
|
||||||
|
|
||||||
status = rpch_out_read(rpch, pdu, pdu_length);
|
status = rpc_out_read(rpch, pdu, pdu_length);
|
||||||
|
|
||||||
if (!rpch_in_send_CONN_B1(rpch))
|
if (!rpc_in_send_CONN_B1(rpch))
|
||||||
{
|
{
|
||||||
printf("rpch_out_send_CONN_A1 fault!\n");
|
printf("rpch_out_send_CONN_A1 fault!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = rpch_out_read(rpch, pdu, pdu_length);
|
status = rpc_out_read(rpch, pdu, pdu_length);
|
||||||
|
|
||||||
/* [MS-RPCH] 3.2.1.5.3.1 Connection Establishment
|
/* [MS-RPCH] 3.2.1.5.3.1 Connection Establishment
|
||||||
* at this point VirtualChannel is created
|
* at this point VirtualChannel is created
|
||||||
*/
|
*/
|
||||||
if (!rpch_in_send_bind(rpch))
|
if (!rpc_in_send_bind(rpch))
|
||||||
{
|
{
|
||||||
printf("rpch_out_send_bind fault!\n");
|
printf("rpch_out_send_bind fault!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rpch_out_recv_bind_ack(rpch))
|
if (!rpc_out_recv_bind_ack(rpch))
|
||||||
{
|
{
|
||||||
printf("rpch_out_recv_bind_ack fault!\n");
|
printf("rpch_out_recv_bind_ack fault!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rpch_in_send_rpc_auth_3(rpch))
|
if (!rpc_in_send_rpc_auth_3(rpch))
|
||||||
{
|
{
|
||||||
printf("rpch_out_send_rpc_auth_3 fault!\n");
|
printf("rpch_out_send_rpc_auth_3 fault!\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -25,6 +25,7 @@ typedef struct rdp_rpch rdpRpch;
|
|||||||
typedef struct rdp_rpch_http rdpRpchHTTP;
|
typedef struct rdp_rpch_http rdpRpchHTTP;
|
||||||
|
|
||||||
#include "tcp.h"
|
#include "tcp.h"
|
||||||
|
#include "http.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <freerdp/types.h>
|
#include <freerdp/types.h>
|
||||||
@ -640,7 +641,7 @@ void ntlm_free(rdpNtlm* ntlm);
|
|||||||
boolean rpch_attach(rdpRpch* rpch, rdpTcp* tcp_in, rdpTcp* tcp_out, rdpTls* tls_in, rdpTls* tls_out);
|
boolean rpch_attach(rdpRpch* rpch, rdpTcp* tcp_in, rdpTcp* tcp_out, rdpTls* tls_in, rdpTls* tls_out);
|
||||||
boolean rpch_connect(rdpRpch* rpch);
|
boolean rpch_connect(rdpRpch* rpch);
|
||||||
|
|
||||||
int rpch_write(rdpRpch* rpch, uint8* data, int length, uint16 opnum);
|
int rpc_write(rdpRpch* rpch, uint8* data, int length, uint16 opnum);
|
||||||
int rpch_read(rdpRpch* rpch, uint8* data, int length);
|
int rpch_read(rdpRpch* rpch, uint8* data, int length);
|
||||||
|
|
||||||
rdpRpch* rpch_new(rdpSettings* settings);
|
rdpRpch* rpch_new(rdpSettings* settings);
|
||||||
|
@ -229,7 +229,7 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUG_TSG("TsProxyCreateTunnel");
|
DEBUG_TSG("TsProxyCreateTunnel");
|
||||||
status = rpch_write(rpch, tsg_packet1, sizeof(tsg_packet1), 1);
|
status = rpc_write(rpch, tsg_packet1, sizeof(tsg_packet1), 1);
|
||||||
|
|
||||||
if (status <= 0)
|
if (status <= 0)
|
||||||
{
|
{
|
||||||
@ -270,7 +270,7 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUG_TSG("TsProxyAuthorizeTunnel");
|
DEBUG_TSG("TsProxyAuthorizeTunnel");
|
||||||
status = rpch_write(rpch, tsg_packet2, sizeof(tsg_packet2), 2);
|
status = rpc_write(rpch, tsg_packet2, sizeof(tsg_packet2), 2);
|
||||||
|
|
||||||
if (status <= 0)
|
if (status <= 0)
|
||||||
{
|
{
|
||||||
@ -300,7 +300,7 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUG_TSG("TsProxyMakeTunnelCall");
|
DEBUG_TSG("TsProxyMakeTunnelCall");
|
||||||
status = rpch_write(rpch, tsg_packet3, sizeof(tsg_packet3), 3);
|
status = rpc_write(rpch, tsg_packet3, sizeof(tsg_packet3), 3);
|
||||||
|
|
||||||
if (status <= 0)
|
if (status <= 0)
|
||||||
{
|
{
|
||||||
@ -337,7 +337,7 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUG_TSG("TsProxyCreateChannel");
|
DEBUG_TSG("TsProxyCreateChannel");
|
||||||
status = rpch_write(rpch, s_p4->data, s_p4->size, 4);
|
status = rpc_write(rpch, s_p4->data, s_p4->size, 4);
|
||||||
|
|
||||||
if (status <= 0)
|
if (status <= 0)
|
||||||
{
|
{
|
||||||
@ -374,7 +374,7 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUG_TSG("TsProxySetupReceivePipe");
|
DEBUG_TSG("TsProxySetupReceivePipe");
|
||||||
status = rpch_write(rpch, tsg_packet5, sizeof(tsg_packet5), 8);
|
status = rpc_write(rpch, tsg_packet5, sizeof(tsg_packet5), 8);
|
||||||
|
|
||||||
if (status <= 0)
|
if (status <= 0)
|
||||||
{
|
{
|
||||||
@ -411,7 +411,7 @@ int tsg_write(rdpTsg* tsg, uint8* data, uint32 length)
|
|||||||
|
|
||||||
memcpy(tsg_pkg + 32 + length, pp, 8);
|
memcpy(tsg_pkg + 32 + length, pp, 8);
|
||||||
|
|
||||||
status = rpch_write(tsg->rpch, tsg_pkg, tsg_length, opnum);
|
status = rpc_write(tsg->rpch, tsg_pkg, tsg_length, opnum);
|
||||||
|
|
||||||
xfree(tsg_pkg);
|
xfree(tsg_pkg);
|
||||||
stream_free(s);
|
stream_free(s);
|
||||||
|
@ -531,6 +531,30 @@ void crypto_base64_encode(uint8* data, int length, uint8** enc_data, int* res_le
|
|||||||
BIO_free_all(b64);
|
BIO_free_all(b64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* crypto_encode_base64(uint8* data, int length)
|
||||||
|
{
|
||||||
|
BIO* bmem;
|
||||||
|
BIO* b64;
|
||||||
|
BUF_MEM *bptr;
|
||||||
|
char* base64_string;
|
||||||
|
|
||||||
|
b64 = BIO_new(BIO_f_base64());
|
||||||
|
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
||||||
|
bmem = BIO_new(BIO_s_mem());
|
||||||
|
b64 = BIO_push(b64, bmem);
|
||||||
|
BIO_write(b64, data, length);
|
||||||
|
BIO_flush(b64);
|
||||||
|
BIO_get_mem_ptr(b64, &bptr);
|
||||||
|
|
||||||
|
base64_string = xmalloc(bptr->length);
|
||||||
|
memcpy(base64_string, bptr->data, bptr->length - 1);
|
||||||
|
base64_string[bptr->length] = '\0';
|
||||||
|
|
||||||
|
BIO_free_all(b64);
|
||||||
|
|
||||||
|
return base64_string;
|
||||||
|
}
|
||||||
|
|
||||||
void crypto_base64_decode(uint8* enc_data, int length, uint8** dec_data, int* res_length)
|
void crypto_base64_decode(uint8* enc_data, int length, uint8** dec_data, int* res_length)
|
||||||
{
|
{
|
||||||
BIO *b64, *bmem;
|
BIO *b64, *bmem;
|
||||||
|
Loading…
Reference in New Issue
Block a user