From 72d2c7c1d8a5966bf07daf004cea4c725fe37ec5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 18 Jun 2012 15:56:40 -0400 Subject: [PATCH] libfreerdp-core: use DER for parts of TSRequest encoding, just like mstsc --- include/freerdp/crypto/der.h | 42 +++----------- include/freerdp/crypto/nla.h | 1 + libfreerdp-core/connection.c | 3 + libfreerdp-crypto/der.c | 135 +++++++++++++------------------------------ libfreerdp-crypto/nla.c | 68 ++++++++++++++-------- 5 files changed, 95 insertions(+), 154 deletions(-) diff --git a/include/freerdp/crypto/der.h b/include/freerdp/crypto/der.h index 82dca49..e692823 100644 --- a/include/freerdp/crypto/der.h +++ b/include/freerdp/crypto/der.h @@ -23,41 +23,13 @@ #include #include -#define der_read_length er_read_length -#define _der_skip_length _er_skip_length -#define der_get_content_length er_get_content_length -#define der_read_universal_tag er_read_universal_tag -#define der_write_universal_tag er_write_universal_tag -#define der_read_application_tag er_read_application_tag -#define der_read_enumerated er_read_enumerated -#define der_read_contextual_tag er_read_contextual_tag -#define der_skip_contextual_tag er_skip_contextual_tag -#define der_read_sequence_tag er_read_sequence_tag -#define der_skip_sequence er_skip_sequence -#define der_skip_sequence_tag er_skip_sequence_tag -#define der_read_bit_string er_read_bit_string -#define der_read_octet_string er_read_octet_string -#define der_skip_octet_string er_skip_octet_string -#define der_read_boolean er_read_boolean -#define der_write_boolean er_write_boolean -#define der_read_integer er_read_integer -#define der_write_integer er_write_integer -#define der_read_integer_length er_read_integer_length -#define der_skip_integer er_skip_integer -#define der_write_sequence_tag(_a, _b) er_write_sequence_tag(_a, _b, true) -#define der_write_octet_string_tag(_a, _b) er_write_octet_string_tag(_a, _b, true) -#define der_write_octet_string(_a, _b, _c) er_write_octet_string(_a, _b, _c, true) -#define der_write_bit_string_tag(_a, _b, _c) er_write_bit_string_tag(_a, _b, _c, true); -#define der_write_contextual_tag(_a, _b, _c, _d) er_write_contextual_tag(_a, _b, _c, _d, true); -#define der_write_enumerated(_a, _b, _c) er_write_enumerated(_a, _b, _c, true) -#define der_write_application_tag(_a, _b, _c) er_write_application_tag(_a, _b, _c, true) - +FREERDP_API int _der_skip_length(int length); FREERDP_API int der_write_length(STREAM* s, int length); -FREERDP_API boolean der_write_bit_string(STREAM* s, uint32 length, uint8 padding); -FREERDP_API boolean der_write_general_string(STREAM* s, char* str); -FREERDP_API char* der_read_general_string(STREAM* s, int *length); -FREERDP_API int der_write_principal_name(STREAM* s, uint8 ntype, char** name); -FREERDP_API int der_write_generalized_time(STREAM* s, char* tstr); -FREERDP_API boolean der_read_generalized_time(STREAM* s, char** tstr); +FREERDP_API int der_get_content_length(int length); +FREERDP_API int der_skip_octet_string(int length); +FREERDP_API int der_skip_sequence_tag(int length); +FREERDP_API int der_write_sequence_tag(STREAM* s, int length); +FREERDP_API int der_skip_contextual_tag(int length); +FREERDP_API void der_write_octet_string(STREAM* s, uint8* oct_str, int length); #endif /* FREERDP_CRYPTO_DER_H */ diff --git a/include/freerdp/crypto/nla.h b/include/freerdp/crypto/nla.h index 5975382..520d904 100644 --- a/include/freerdp/crypto/nla.h +++ b/include/freerdp/crypto/nla.h @@ -30,6 +30,7 @@ typedef struct rdp_credssp rdpCredssp; #include #include +#include #include struct rdp_credssp diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 46fc2c4..a59a478 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -533,6 +533,7 @@ boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s) rdp->nego->selected_protocol = 0; printf("Requested protocols:"); + if ((rdp->nego->requested_protocols & PROTOCOL_TLS)) { printf(" TLS"); @@ -544,6 +545,7 @@ boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s) else printf("(n)"); } + if ((rdp->nego->requested_protocols & PROTOCOL_NLA)) { printf(" NLA"); @@ -555,6 +557,7 @@ boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s) else printf("(n)"); } + printf(" RDP"); if (rdp->settings->rdp_security && rdp->nego->selected_protocol == 0) { diff --git a/libfreerdp-crypto/der.c b/libfreerdp-crypto/der.c index a547a0c..8c12713 100644 --- a/libfreerdp-crypto/der.c +++ b/libfreerdp-crypto/der.c @@ -19,6 +19,16 @@ #include +int _der_skip_length(int length) +{ + if (length > 0x7F && length <= 0xFF) + return 2; + else if (length > 0xFF) + return 3; + else + return 1; +} + int der_write_length(STREAM* s, int length) { if (length > 0x7F && length <= 0xFF) @@ -40,114 +50,51 @@ int der_write_length(STREAM* s, int length) } } -boolean der_write_general_string(STREAM* s, char* str) +int der_get_content_length(int length) { - STREAM* tmp_s; - - tmp_s = stream_new(0); - stream_attach(tmp_s, (uint8*)str, strlen(str)); - - der_write_universal_tag(s, ER_TAG_GENERAL_STRING, false); - der_write_length(s, strlen(str)); - - stream_copy(s, tmp_s, strlen(str)); - stream_detach(tmp_s); - stream_free(tmp_s) ; - - return true; + if (length > 0x7F && length <= 0xFF) + return length - 3; + else if (length > 0xFF) + return length - 4; + else + return length - 2; } -char* der_read_general_string(STREAM* s, int *length) +int der_write_contextual_tag(STREAM* s, uint8 tag, int length, boolean pc) { - char* str; - int len; - - if(der_read_universal_tag(s, ER_TAG_GENERAL_STRING, false)) - { - der_read_length(s, &len); - str = (char*)xzalloc((len + 1) * sizeof(char)); - memcpy(str, s->p, len); - stream_seek(s, len); - *length = len + 2; - return str; - } - - stream_rewind(s, 1); - *length = 0; - - return NULL; + stream_write_uint8(s, (ER_CLASS_CTXT | ER_PC(pc)) | (ER_TAG_MASK & tag)); + return der_write_length(s, length) + 1; } -int der_write_principal_name(STREAM* s, uint8 ntype, char** name) +void der_write_universal_tag(STREAM* s, uint8 tag, boolean pc) { - uint8 len; - char** p; - - len = 0; - p = name; - - while (*p != NULL) - { - len += strlen(*p) + 2; - p++; - } - - p = name; - der_write_sequence_tag(s, len+9); - der_write_contextual_tag(s, 0, 3, true); - der_write_integer(s, ntype); - der_write_contextual_tag(s, 1, len + 2, true); - der_write_sequence_tag(s, len); - - while (*p != NULL) - { - der_write_general_string(s, *p); - p++; - } - - return len + 11; + stream_write_uint8(s, (ER_CLASS_UNIV | ER_PC(pc)) | (ER_TAG_MASK & tag)); } -int der_write_generalized_time(STREAM* s, char* tstr) +int der_skip_octet_string(int length) { - uint8 len; - STREAM* tmp_s; - - len = strlen(tstr); - tmp_s = stream_new(0); - - stream_attach(tmp_s, (uint8*) tstr, strlen(tstr)); - der_write_universal_tag(s, ER_TAG_GENERALIZED_TIME, false); - der_write_length(s, len); - - stream_copy(s, tmp_s, len); - stream_detach(tmp_s); - stream_free(tmp_s) ; - - return len + 2; + return 1 + _der_skip_length(length) + length; } -boolean der_read_generalized_time(STREAM* s, char** tstr) +void der_write_octet_string(STREAM* s, uint8* oct_str, int length) { - int length; - uint8* bm; - stream_get_mark(s, bm); - - if (!der_read_universal_tag(s, ER_TAG_GENERALIZED_TIME, false)) - goto err; - - der_read_length(s, &length); - - if (length != 15) - goto err; - - *tstr = xzalloc(length + 1); - stream_read(s, *tstr, length); + der_write_universal_tag(s, ER_TAG_OCTET_STRING, false); + der_write_length(s, length); + stream_write(s, oct_str, length); +} - return true; +int der_skip_sequence_tag(int length) +{ + return 1 + _der_skip_length(length); +} - err: - stream_set_mark(s, bm); - return false; +int der_write_sequence_tag(STREAM* s, int length) +{ + stream_write_uint8(s, (ER_CLASS_UNIV | ER_CONSTRUCT) | (ER_TAG_MASK & ER_TAG_SEQUENCE)); + return der_write_length(s, length) + 1; } +int der_skip_contextual_tag(int length) +{ + return _der_skip_length(length) + 1; +} diff --git a/libfreerdp-crypto/nla.c b/libfreerdp-crypto/nla.c index 1508c15..fe882d9 100644 --- a/libfreerdp-crypto/nla.c +++ b/libfreerdp-crypto/nla.c @@ -440,7 +440,18 @@ int credssp_server_authenticate(rdpCredssp* credssp) * ASC_REQ_ALLOCATE_MEMORY */ - fContextReq = ASC_REQ_MUTUAL_AUTH | ASC_REQ_CONFIDENTIALITY; + fContextReq = 0; + fContextReq |= ASC_REQ_MUTUAL_AUTH; + fContextReq |= ASC_REQ_CONFIDENTIALITY; + + fContextReq |= ASC_REQ_CONNECTION; + fContextReq |= ASC_REQ_USE_SESSION_KEY; + fContextReq |= ASC_REQ_CONFIDENTIALITY; + + fContextReq |= ASC_REQ_REPLAY_DETECT; + fContextReq |= ASC_REQ_SEQUENCE_DETECT; + + fContextReq |= ASC_REQ_EXTENDED_ERROR; while (true) { @@ -633,29 +644,35 @@ SECURITY_STATUS credssp_encrypt_public_key_echo(rdpCredssp* credssp) SECURITY_STATUS credssp_decrypt_public_key_echo(rdpCredssp* credssp) { int length; + BYTE* buffer; ULONG pfQOP; BYTE* public_key1; BYTE* public_key2; - BYTE* pub_key_auth; int public_key_length; SecBuffer Buffers[2]; SecBufferDesc Message; SECURITY_STATUS status; + if (credssp->PublicKey.cbBuffer + credssp->ContextSizes.cbMaxSignature != credssp->pubKeyAuth.cbBuffer) + { + printf("credssp_decrypt_public_key_echo: unexpected pubKeyAuth buffer size:%d\n", credssp->pubKeyAuth.cbBuffer); + return SEC_E_INVALID_TOKEN; + } + length = credssp->pubKeyAuth.cbBuffer; - pub_key_auth = (BYTE*) credssp->pubKeyAuth.pvBuffer; + buffer = (BYTE*) malloc(length); + CopyMemory(buffer, credssp->pubKeyAuth.pvBuffer, length); + public_key_length = credssp->PublicKey.cbBuffer; Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted TLS Public Key */ Buffers[0].cbBuffer = credssp->ContextSizes.cbMaxSignature; - Buffers[0].pvBuffer = malloc(Buffers[0].cbBuffer); - CopyMemory(Buffers[0].pvBuffer, pub_key_auth, Buffers[0].cbBuffer); + Buffers[0].pvBuffer = buffer; - Buffers[1].cbBuffer = length - Buffers[0].cbBuffer; - Buffers[1].pvBuffer = malloc(Buffers[1].cbBuffer); - CopyMemory(Buffers[1].pvBuffer, &pub_key_auth[Buffers[0].cbBuffer], Buffers[1].cbBuffer); + Buffers[1].cbBuffer = length - credssp->ContextSizes.cbMaxSignature; + Buffers[1].pvBuffer = buffer + credssp->ContextSizes.cbMaxSignature; Message.cBuffers = 2; Message.ulVersion = SECBUFFER_VERSION; @@ -693,8 +710,7 @@ SECURITY_STATUS credssp_decrypt_public_key_echo(rdpCredssp* credssp) public_key2[0]++; - free(Buffers[0].pvBuffer); - free(Buffers[1].pvBuffer); + free(buffer); return SEC_E_OK; } @@ -956,17 +972,17 @@ SECURITY_STATUS credssp_decrypt_ts_credentials(rdpCredssp* credssp) int credssp_skip_nego_token(int length) { - length = ber_skip_octet_string(length); - length += ber_skip_contextual_tag(length); + length = der_skip_octet_string(length); + length += der_skip_contextual_tag(length); return length; } int credssp_skip_nego_tokens(int length) { length = credssp_skip_nego_token(length); - length += ber_skip_sequence_tag(length); - length += ber_skip_sequence_tag(length); - length += ber_skip_contextual_tag(length); + length += der_skip_sequence_tag(length); + length += der_skip_sequence_tag(length); + length += der_skip_contextual_tag(length); return length; } @@ -988,7 +1004,7 @@ int credssp_skip_ts_request(int length) { length += ber_skip_integer(2); length += ber_skip_contextual_tag(3); - length += ber_skip_sequence_tag(length); + length += der_skip_sequence_tag(length); return length; } @@ -1016,20 +1032,22 @@ void credssp_send(rdpCredssp* credssp) s = stream_new(ts_request_length); /* TSRequest */ - length = ber_get_content_length(ts_request_length); - ber_write_sequence_tag(s, length); /* SEQUENCE */ - ber_write_contextual_tag(s, 0, 3, true); /* [0] version */ + length = der_get_content_length(ts_request_length); + der_write_sequence_tag(s, length); /* SEQUENCE */ + + /* [0] version */ + ber_write_contextual_tag(s, 0, 3, true); ber_write_integer(s, 2); /* INTEGER */ /* [1] negoTokens (NegoData) */ if (nego_tokens_length > 0) { - length = ber_get_content_length(nego_tokens_length); - length -= ber_write_contextual_tag(s, 1, length, true); /* NegoData */ - length -= ber_write_sequence_tag(s, length); /* SEQUENCE OF NegoDataItem */ - length -= ber_write_sequence_tag(s, length); /* NegoDataItem */ - length -= ber_write_contextual_tag(s, 0, length, true); /* [0] negoToken */ - ber_write_octet_string(s, credssp->negoToken.pvBuffer, length); /* OCTET STRING */ + length = der_get_content_length(nego_tokens_length); + length -= der_write_contextual_tag(s, 1, length, true); /* NegoData */ + length -= der_write_sequence_tag(s, length); /* SEQUENCE OF NegoDataItem */ + length -= der_write_sequence_tag(s, length); /* NegoDataItem */ + length -= der_write_contextual_tag(s, 0, length, true); /* [0] negoToken */ + der_write_octet_string(s, (uint8*) credssp->negoToken.pvBuffer, length); /* OCTET STRING */ } /* [2] authInfo (OCTET STRING) */ -- 2.7.4