libfreerdp-core: start using HTTP utils for NTLM HTTP authentication

This commit is contained in:
Marc-André Moreau 2012-04-16 16:21:46 -04:00
parent 883b04d51f
commit fa7900d293
7 changed files with 402 additions and 234 deletions

View File

@ -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_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_decode(uint8* enc_data, int length, uint8** dec_data, int* res_length);

View File

@ -97,9 +97,19 @@ void http_request_set_uri(HttpRequest* http_request, char* 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, ...) \
_str = xmalloc(snprintf(NULL, 0, _fmt, ## __VA_ARGS__)); \
snprintf(_str, snprintf(NULL, 0, _fmt, ## __VA_ARGS__), _fmt, ## __VA_ARGS__);
_str = xmalloc(snprintf(NULL, 0, _fmt, ## __VA_ARGS__) + 1); \
snprintf(_str, snprintf(NULL, 0, _fmt, ## __VA_ARGS__) + 1, _fmt, ## __VA_ARGS__);
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;
int length = 0;
http_request->count = 10;
http_request->count = 9;
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[1], "Accept: %s\n", http_context->Accept);
http_encode_line(http_request->lines[2], "Cache-Control: %s\n", http_context->CacheControl);
http_encode_line(http_request->lines[3], "Connection: %s\n", http_context->Connection);
http_encode_line(http_request->lines[4], "Content-Length: %d\n", http_request->ContentLength);
http_encode_line(http_request->lines[5], "User-Agent: %s\n", http_context->UserAgent);
http_encode_line(http_request->lines[6], "Host: %s\n", http_context->Host);
http_encode_line(http_request->lines[7], "Pragma: %s\n", 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");
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[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);
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++)
{
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);
for (i = 0; i < http_request->count; i++)
{
stream_write(s, http_request->lines[i], strlen(http_request->lines[i]));
stream_write(s, "\n", 1);
xfree(http_request->lines[i]);
}
stream_write(s, "\n", 1);
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);
return s;
@ -161,3 +186,228 @@ void http_request_free(HttpRequest* 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);
}
}

View File

@ -20,7 +20,12 @@
#ifndef 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/crypto/tls.h>
#include <freerdp/utils/stream.h>
struct _http_context
@ -34,7 +39,6 @@ struct _http_context
char* Connection;
char* Pragma;
};
typedef struct _http_context HttpContext;
void http_context_set_method(HttpContext* http_context, char* method);
void http_context_set_uri(HttpContext* http_context, char* uri);
@ -55,18 +59,41 @@ struct _http_request
char* Method;
char* URI;
char* AuthScheme;
char* AuthParam;
char* Authorization;
int ContentLength;
char* Content;
};
typedef struct _http_request HttpRequest;
void http_request_set_method(HttpRequest* http_request, char* method);
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);
HttpRequest* http_request_new();
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 */

View File

@ -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;
char* int_str;
int total_length;
int int_str_length;
int command_length;
rdpSettings* settings;
int tsg_hostname_length;
int ntlm_token_base64_length;
uint8* ntlm_token_base64_data;
char* base64_ntlm_token;
HttpContext* http_context;
HttpRequest* http_request;
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);
tsg_hostname_length = strlen(settings->tsg_hostname);
if (strcmp(command, "RPC_IN_DATA") == 0)
http_context = rpch->http_in->context;
else
http_context = rpch->http_out->context;
int_str = xmalloc(int_str_length + 1);
snprintf(int_str, int_str_length + 1, "%d", length);
http_request = http_request_new();
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 +
tsg_hostname_length + 1 + 110 + 20 + ntlm_token_base64_length + 2;
http_request_set_method(http_request, http_context->Method);
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);
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);
s = http_request_write(http_context, http_request);
return s;
}
boolean rpch_out_connect_http(rdpRpch* rpch)
boolean rpc_out_connect_http(rdpRpch* rpch)
{
STREAM* http_stream;
STREAM* ntlm_stream;
HttpResponse* http_response;
int decoded_ntlm_http_length;
int encoded_ntlm_http_length;
uint8* decoded_ntlm_http_data = NULL;
@ -236,13 +216,13 @@ boolean rpch_out_connect_http(rdpRpch* rpch)
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_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);
tls_write(tls_out, http_stream->data, http_stream->size);
@ -256,73 +236,15 @@ boolean rpch_out_connect_http(rdpRpch* rpch)
uint8 buffer_byte;
http_out->contentLength = 0;
/* Example for how not to do clear code, sorry for that */
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 */
http_response = http_response_recv(tls_out);
DEBUG_RPCH("\nRecv:\n%s\n", http_stream->data);
stream_clear(http_stream);
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 */
return false;
@ -336,7 +258,7 @@ boolean rpch_out_connect_http(rdpRpch* rpch)
http_out->contentLength = 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);
tls_write(tls_out, http_stream->data, http_stream->size);
@ -351,10 +273,11 @@ boolean rpch_out_connect_http(rdpRpch* rpch)
return true;
}
boolean rpch_in_connect_http(rdpRpch* rpch)
boolean rpc_in_connect_http(rdpRpch* rpch)
{
STREAM* ntlm_stream;
STREAM* http_stream;
HttpResponse* http_response;
int decoded_ntlm_http_length;
int encoded_ntlm_http_length;
uint8* decoded_ntlm_http_data = NULL;
@ -372,7 +295,7 @@ boolean rpch_in_connect_http(rdpRpch* rpch)
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);
tls_write(tls_in, http_stream->data, http_stream->size);
@ -388,73 +311,15 @@ boolean rpch_in_connect_http(rdpRpch* rpch)
uint8 buffer_byte;
http_in->contentLength = 0;
/* Example for how not to do clear code, sorry for that */
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 */
http_response = http_response_recv(tls_in);
DEBUG_RPCH("\nRecv:\n%s\n", http_stream->data);
stream_clear(http_stream);
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 */
return false;
@ -468,7 +333,7 @@ boolean rpch_in_connect_http(rdpRpch* rpch)
http_in->contentLength = 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);
@ -486,7 +351,7 @@ boolean rpch_in_connect_http(rdpRpch* rpch)
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 status = -1;
@ -495,7 +360,7 @@ int rpch_out_write(rdpRpch* rpch, uint8* data, int length)
if (http_out->state == RPCH_HTTP_DISCONNECTED)
{
if (!rpch_out_connect_http(rpch))
if (!rpc_out_connect_http(rpch))
return false;
}
@ -526,7 +391,7 @@ int rpch_out_write(rdpRpch* rpch, uint8* data, int length)
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 status = -1;
@ -535,7 +400,7 @@ int rpch_in_write(rdpRpch* rpch, uint8* data, int length)
if (http_in->state == RPCH_HTTP_DISCONNECTED)
{
if (!rpch_in_connect_http(rpch))
if (!rpc_in_connect_http(rpch))
return -1;
}
@ -567,14 +432,14 @@ int rpch_in_write(rdpRpch* rpch, uint8* data, int length)
return sent;
}
uint8* rpch_create_cookie()
uint8* rpc_create_cookie()
{
uint8* ret = xmalloc(16);
RAND_pseudo_bytes(ret, 16);
return ret;
}
boolean rpch_out_send_CONN_A1(rdpRpch* rpch)
boolean rpc_out_send_CONN_A1(rdpRpch* rpch)
{
STREAM* pdu = stream_new(76);
@ -597,8 +462,8 @@ boolean rpch_out_send_CONN_A1(rdpRpch* rpch)
uint32 rwsCommandType = 0x00000000;
uint32 receiveWindowSize = 0x00010000;
rpch->virtualConnectionCookie = rpch_create_cookie(); /* 16 bytes */
rpch->OUTChannelCookie = rpch_create_cookie(); /* 16 bytes */
rpch->virtualConnectionCookie = rpc_create_cookie(); /* 16 bytes */
rpch->OUTChannelCookie = rpc_create_cookie(); /* 16 bytes */
rpch->AwailableWindow = receiveWindowSize;
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, receiveWindowSize);
rpch_out_write(rpch, pdu->data, stream_get_length(pdu));
rpc_out_write(rpch, pdu->data, stream_get_length(pdu));
stream_free(pdu);
return true;
}
boolean rpch_in_send_CONN_B1(rdpRpch* rpch)
boolean rpc_in_send_CONN_B1(rdpRpch* rpch)
{
STREAM* s = stream_new(104);
@ -654,8 +519,8 @@ boolean rpch_in_send_CONN_B1(rdpRpch* rpch)
uint32 agidCommandType = 0x0000000c;
uint8* AssociationGroupId;
rpch->INChannelCookie = rpch_create_cookie(); /* 16 bytes */
AssociationGroupId = rpch_create_cookie(); /* 16 bytes */
rpch->INChannelCookie = rpc_create_cookie(); /* 16 bytes */
AssociationGroupId = rpc_create_cookie(); /* 16 bytes */
stream_write_uint8(s, rpc_vers);
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_seal(s);
rpch_in_write(rpch, s->data, s->size);
rpc_in_write(rpch, s->data, s->size);
stream_free(s);
return true;
}
boolean rpch_in_send_keep_alive(rdpRpch* rpch)
boolean rpc_in_send_keep_alive(rdpRpch* rpch)
{
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, ClientKeepalive);
rpch_in_write(rpch, s->data, stream_get_length(s));
rpc_in_write(rpch, s->data, stream_get_length(s));
stream_free(s);
return true;
}
boolean rpch_in_send_bind(rdpRpch* rpch)
boolean rpc_in_send_bind(rdpRpch* rpch)
{
rpcconn_bind_hdr_t* bind_pdu;
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_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 */
xfree(bind_pdu);
@ -852,7 +717,7 @@ boolean rpch_in_send_bind(rdpRpch* rpch)
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;
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_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);
return true;
}
boolean rpch_in_send_flow_control(rdpRpch* rpch)
boolean rpc_in_send_flow_control(rdpRpch* rpch)
{
STREAM* s = stream_new(56);
@ -944,14 +809,14 @@ boolean rpch_in_send_flow_control(rdpRpch* rpch)
stream_write_uint32(s, aaa);
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);
return true;
}
boolean rpch_in_send_ping(rdpRpch* rpch)
boolean rpc_in_send_ping(rdpRpch* rpch)
{
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, 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);
return true;
}
int rpch_out_read_http_header(rdpRpch* rpch)
int rpc_out_read_http_header(rdpRpch* rpch)
{
int status;
STREAM* http_stream;
@ -1040,7 +905,7 @@ int rpch_out_read_http_header(rdpRpch* rpch)
return status;
}
int rpch_proceed_RTS(rdpRpch* rpch, uint8* pdu, int length)
int rpc_rts_recv(rdpRpch* rpch, uint8* pdu, int length)
{
int i;
uint32 CommandType;
@ -1050,7 +915,7 @@ int rpch_proceed_RTS(rdpRpch* rpch, uint8* pdu, int length)
if (flags & RTS_FLAG_PING)
{
rpch_in_send_keep_alive(rpch);
rpc_in_send_keep_alive(rpch);
return 0;
}
@ -1128,7 +993,7 @@ int rpch_proceed_RTS(rdpRpch* rpch, uint8* pdu, int length)
return 0;
}
int rpch_out_read(rdpRpch* rpch, uint8* data, int length)
int rpc_out_read(rdpRpch* rpch, uint8* data, int length)
{
int status;
uint8* pdu;
@ -1138,11 +1003,11 @@ int rpch_out_read(rdpRpch* rpch, uint8* data, int length)
rdpRpchHTTP* http_out = rpch->http_out;
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 (rpch_out_read_http_header(rpch) < 0)
if (rpc_out_read_http_header(rpch) < 0)
return -1;
}
@ -1169,7 +1034,7 @@ int rpch_out_read(rdpRpch* rpch, uint8* data, int length)
if (ptype == 0x14) /* RTS PDU */
{
rpch_proceed_RTS(rpch, pdu, frag_length);
rpc_rts_recv(rpch, pdu, frag_length);
xfree(pdu);
return 0;
}
@ -1201,14 +1066,14 @@ int rpch_out_read(rdpRpch* rpch, uint8* data, int length)
return frag_length;
}
int rpch_out_recv_bind_ack(rdpRpch* rpch)
int rpc_out_recv_bind_ack(rdpRpch* rpch)
{
uint16 frag_length;
uint16 auth_length;
STREAM* ntlmssp_stream;
int pdu_length = 0x8FFF; /* 32KB buffer */
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");
@ -1230,7 +1095,7 @@ int rpch_out_recv_bind_ack(rdpRpch* rpch)
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 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);
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_pad);
@ -1341,7 +1206,7 @@ int rpch_read(rdpRpch* rpch, uint8* data, int length)
while (true)
{
status = rpch_out_read(rpch, rpch_data, rpch_length);
status = rpc_out_read(rpch, rpch_data, rpch_length);
if (status == 0)
{
@ -1400,7 +1265,7 @@ boolean rpch_connect(rdpRpch* rpch)
uint8* pdu;
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");
return false;
@ -1409,32 +1274,32 @@ boolean rpch_connect(rdpRpch* rpch)
pdu_length = 0xFFFF;
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");
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
* 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");
return false;
}
if (!rpch_out_recv_bind_ack(rpch))
if (!rpc_out_recv_bind_ack(rpch))
{
printf("rpch_out_recv_bind_ack fault!\n");
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");
return false;

View File

@ -25,6 +25,7 @@ typedef struct rdp_rpch rdpRpch;
typedef struct rdp_rpch_http rdpRpchHTTP;
#include "tcp.h"
#include "http.h"
#include <time.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_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);
rdpRpch* rpch_new(rdpSettings* settings);

View File

@ -229,7 +229,7 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
*/
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)
{
@ -270,7 +270,7 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
*/
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)
{
@ -300,7 +300,7 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
*/
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)
{
@ -337,7 +337,7 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
*/
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)
{
@ -374,7 +374,7 @@ boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port)
*/
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)
{
@ -411,7 +411,7 @@ int tsg_write(rdpTsg* tsg, uint8* data, uint32 length)
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);
stream_free(s);

View File

@ -531,6 +531,30 @@ void crypto_base64_encode(uint8* data, int length, uint8** enc_data, int* res_le
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)
{
BIO *b64, *bmem;