From ea5acaa7b5d5317ff5697bf1a18015a44c56fd7c Mon Sep 17 00:00:00 2001 From: speidy Date: Wed, 13 Apr 2016 02:18:56 -0400 Subject: core: ber encoder fix --- libfreerdp-core/ber.c | 227 +++++++++++++++++++++++++++++++++------------- libfreerdp-core/ber.h | 19 ++-- libfreerdp-core/credssp.c | 28 +++--- 3 files changed, 190 insertions(+), 84 deletions(-) diff --git a/libfreerdp-core/ber.c b/libfreerdp-core/ber.c index bb81493..fda3c12 100644 --- a/libfreerdp-core/ber.c +++ b/libfreerdp-core/ber.c @@ -19,25 +19,45 @@ #include "ber.h" -void ber_read_length(STREAM* s, int* length) +int ber_read_length(STREAM* s, int* length) { uint8 byte; + if (stream_get_left(s) < 1) + { + return 0; + } stream_read_uint8(s, byte); if (byte & 0x80) { byte &= ~(0x80); + if (stream_get_left(s) < byte) + { + return 0; + } + if (byte == 1) + { stream_read_uint8(s, *length); + } + if (byte == 2) + { stream_read_uint16_be(s, *length); + } + else + { + return 0; + } } else { *length = byte; } + + return 1; } /** @@ -48,25 +68,29 @@ void ber_read_length(STREAM* s, int* length) int ber_write_length(STREAM* s, int length) { - if (length > 0x7F) + if (length > 0xFF) { - stream_write_uint8(s, 0x82); + stream_write_uint8(s, 0x80 ^ 2); stream_write_uint16_be(s, length); return 3; } - else + if (length > 0x7F) { - stream_write_uint8(s, length); - return 1; + stream_write_uint8(s, 0x80 ^ 1); + stream_write_uint16_be(s, length); + return 2; } + stream_write_uint8(s, length); + return 1; } -int _ber_skip_length(int length) +int _ber_sizeof_length(int length) { - if (length > 0x7F) + if (length > 0xFF) return 3; - else - return 1; + if (length > 0x7F) + return 2; + return 1; } int ber_get_content_length(int length) @@ -84,12 +108,17 @@ int ber_get_content_length(int length) * @return */ -tbool ber_read_universal_tag(STREAM* s, uint8 tag, tbool pc) +int ber_read_universal_tag(STREAM* s, uint8 tag, tbool pc) { uint8 byte; + if (stream_get_left(s) < 1) + { + return 0; + } stream_read_uint8(s, byte); + if (byte != (BER_CLASS_UNIV | BER_PC(pc) | (BER_TAG_MASK & tag))) return false; @@ -103,9 +132,10 @@ tbool ber_read_universal_tag(STREAM* s, uint8 tag, tbool pc) * @param pc primitive (false) or constructed (true) */ -void ber_write_universal_tag(STREAM* s, uint8 tag, tbool pc) +int ber_write_universal_tag(STREAM* s, uint8 tag, tbool pc) { stream_write_uint8(s, (BER_CLASS_UNIV | BER_PC(pc)) | (BER_TAG_MASK & tag)); + return 1; } /** @@ -121,11 +151,19 @@ tbool ber_read_application_tag(STREAM* s, uint8 tag, int* length) if (tag > 30) { + if (stream_get_left(s) < 1) + { + return 0; + } stream_read_uint8(s, byte); if (byte != ((BER_CLASS_APPL | BER_CONSTRUCT) | BER_TAG_MASK)) return false; + if (stream_get_left(s) < 1) + { + return 0; + } stream_read_uint8(s, byte); if (byte != tag) @@ -135,6 +173,10 @@ tbool ber_read_application_tag(STREAM* s, uint8 tag, int* length) } else { + if (stream_get_left(s) < 1) + { + return 0; + } stream_read_uint8(s, byte); if (byte != ((BER_CLASS_APPL | BER_CONSTRUCT) | (BER_TAG_MASK & tag))) @@ -172,6 +214,10 @@ tbool ber_read_contextual_tag(STREAM* s, uint8 tag, int* length, tbool pc) { uint8 byte; + if (stream_get_left(s) < 1) + { + return 0; + } stream_read_uint8(s, byte); if (byte != ((BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag))) @@ -180,34 +226,34 @@ tbool ber_read_contextual_tag(STREAM* s, uint8 tag, int* length, tbool pc) return false; } - ber_read_length(s, length); - - return true; + return ber_read_length(s, length); } int ber_write_contextual_tag(STREAM* s, uint8 tag, int length, tbool pc) { stream_write_uint8(s, (BER_CLASS_CTXT | BER_PC(pc)) | (BER_TAG_MASK & tag)); - return ber_write_length(s, length) + 1; + return 1 + ber_write_length(s, length); } int ber_skip_contextual_tag(int length) { - return _ber_skip_length(length) + 1; + return 1 + _ber_sizeof_length(length); } tbool ber_read_sequence_tag(STREAM* s, int* length) { uint8 byte; + if (stream_get_left(s) < 1) + { + return 0; + } stream_read_uint8(s, byte); if (byte != ((BER_CLASS_UNIV | BER_CONSTRUCT) | (BER_TAG_SEQUENCE_OF))) return false; - ber_read_length(s, length); - - return true; + return ber_read_length(s, length); } /** @@ -219,30 +265,36 @@ tbool ber_read_sequence_tag(STREAM* s, int* length) int ber_write_sequence_tag(STREAM* s, int length) { stream_write_uint8(s, (BER_CLASS_UNIV | BER_CONSTRUCT) | (BER_TAG_MASK & BER_TAG_SEQUENCE)); - return ber_write_length(s, length) + 1; + return 1 + ber_write_length(s, length); } -int ber_skip_sequence(int length) +int ber_sizeof_sequence(int length) { - return 1 + _ber_skip_length(length) + length; + return 1 + _ber_sizeof_length(length) + length; } -int ber_skip_sequence_tag(int length) +int ber_sizeof_sequence_tag(int length) { - return 1 + _ber_skip_length(length); + return 1 + _ber_sizeof_length(length); } tbool ber_read_enumerated(STREAM* s, uint8* enumerated, uint8 count) { int length; - ber_read_universal_tag(s, BER_TAG_ENUMERATED, false); - ber_read_length(s, &length); + if (!ber_read_universal_tag(s, BER_TAG_ENUMERATED, false) || + !ber_read_length(s, &length)) + { + return false; + } - if (length == 1) - stream_read_uint8(s, *enumerated); - else + + if (length != 1 || stream_get_left(s) < 1) + { return false; + } + + stream_read_uint8(s, *enumerated); /* check that enumerated value falls within expected range */ if (*enumerated + 1 > count) @@ -260,8 +312,17 @@ void ber_write_enumerated(STREAM* s, uint8 enumerated, uint8 count) tbool ber_read_bit_string(STREAM* s, int* length, uint8* padding) { - ber_read_universal_tag(s, BER_TAG_BIT_STRING, false); - ber_read_length(s, length); + if (!ber_read_universal_tag(s, BER_TAG_BIT_STRING, false) || + !ber_read_length(s, length)) + { + return false; + } + + if (stream_get_left(s) < 1) + { + return false; + } + stream_read_uint8(s, *padding); return true; @@ -282,23 +343,38 @@ tbool ber_read_octet_string(STREAM* s, int* length) * @param length string length */ -void ber_write_octet_string(STREAM* s, const uint8* oct_str, int length) +int ber_write_octet_string(STREAM* s, const uint8* oct_str, int length) { - ber_write_universal_tag(s, BER_TAG_OCTET_STRING, false); - ber_write_length(s, length); + int size = 0; + + size += ber_write_universal_tag(s, BER_TAG_OCTET_STRING, false); + size += ber_write_length(s, length); + stream_write(s, oct_str, length); + + size += length; + return size; + } +tbool ber_read_octet_string_tag(STREAM* s, int* length) +{ + return + ber_read_universal_tag(s, BER_TAG_OCTET_STRING, false) && + ber_read_length(s, length); +} + + int ber_write_octet_string_tag(STREAM* s, int length) { ber_write_universal_tag(s, BER_TAG_OCTET_STRING, false); ber_write_length(s, length); - return 1 + _ber_skip_length(length); + return 1 + _ber_sizeof_length(length); } -int ber_skip_octet_string(int length) +int ber_sizeof_octet_string(int length) { - return 1 + _ber_skip_length(length) + length; + return 1 + _ber_sizeof_length(length) + length; } /** @@ -312,13 +388,16 @@ tbool ber_read_boolean(STREAM* s, tbool* value) int length; uint8 v; - if (!ber_read_universal_tag(s, BER_TAG_BOOLEAN, false)) + if (!ber_read_universal_tag(s, BER_TAG_BOOLEAN, false) || + !ber_read_length(s, &length)) return false; - ber_read_length(s, &length); - if (length != 1) + + if (length != 1 || stream_get_left(s) < 1) return false; + stream_read_uint8(s, v); *value = (v ? true : false); + return true; } @@ -339,19 +418,31 @@ tbool ber_read_integer(STREAM* s, uint32* value) { int length; - ber_read_universal_tag(s, BER_TAG_INTEGER, false); - ber_read_length(s, &length); + if (!ber_read_universal_tag(s, BER_TAG_INTEGER, false) || + !ber_read_length(s, &length) || + stream_get_left(s) < length) + { + return false; + } if (value == NULL) { + if (stream_get_left(s) < length) + { + return false; + } stream_seek(s, length); return true; } if (length == 1) + { stream_read_uint8(s, *value); + } else if (length == 2) + { stream_read_uint16_be(s, *value); + } else if (length == 3) { uint8 byte; @@ -360,9 +451,19 @@ tbool ber_read_integer(STREAM* s, uint32* value) *value += (byte << 16); } else if (length == 4) + { stream_read_uint32_be(s, *value); + } + else if (length == 8) + { + fprintf(stderr, "%s: should implement reading an 8 bytes integer\n", __FUNCTION__); + return false; + } else + { + fprintf(stderr, "%s: should implement reading an integer with length=%d\n", __FUNCTION__, length); return false; + } return true; } @@ -377,48 +478,52 @@ int ber_write_integer(STREAM* s, uint32 value) { ber_write_universal_tag(s, BER_TAG_INTEGER, false); - if (value <= 0xFF) + if (value < 0x80) { ber_write_length(s, 1); stream_write_uint8(s, value); - return 2; + return 3; } - else if (value < 0xFF80) + else if (value < 0x8000) { ber_write_length(s, 2); stream_write_uint16_be(s, value); - return 3; + return 4; } - else if (value < 0xFF8000) + else if (value < 0x800000) { ber_write_length(s, 3); stream_write_uint8(s, (value >> 16)); stream_write_uint16_be(s, (value & 0xFFFF)); - return 4; + return 5; } - else if (value <= 0xFFFFFFFF) + else if (value < 0x80000000) { ber_write_length(s, 4); stream_write_uint32_be(s, value); - return 5; + return 6; } return 0; } -int ber_skip_integer(uint32 value) +int ber_sizeof_integer(uint32 value) { - if (value <= 0xFF) + if (value < 0x80) { - return _ber_skip_length(1) + 2; + return 3; } - else if (value <= 0xFFFF) + else if (value < 0x8000) { - return _ber_skip_length(2) + 3; + return 4; } - else if (value <= 0xFFFFFFFF) + else if (value < 0x800000) { - return _ber_skip_length(4) + 5; + return 5; + } + else if (value < 0x80000000) + { + return 6; } return 0; @@ -426,7 +531,7 @@ int ber_skip_integer(uint32 value) tbool ber_read_integer_length(STREAM* s, int* length) { - ber_read_universal_tag(s, BER_TAG_INTEGER, false); - ber_read_length(s, length); - return true; + return + ber_read_universal_tag(s, BER_TAG_INTEGER, false) && + ber_read_length(s, length); } diff --git a/libfreerdp-core/ber.h b/libfreerdp-core/ber.h index b03ce13..a048aa4 100644 --- a/libfreerdp-core/ber.h +++ b/libfreerdp-core/ber.h @@ -50,12 +50,12 @@ #define BER_PC(_pc) (_pc ? BER_CONSTRUCT : BER_PRIMITIVE) -void ber_read_length(STREAM* s, int* length); +int ber_read_length(STREAM* s, int* length); int ber_write_length(STREAM* s, int length); -int _ber_skip_length(int length); +int _ber_sizeof_length(int length); int ber_get_content_length(int length); -tbool ber_read_universal_tag(STREAM* s, uint8 tag, tbool pc); -void ber_write_universal_tag(STREAM* s, uint8 tag, tbool pc); +int ber_read_universal_tag(STREAM* s, uint8 tag, tbool pc); +int ber_write_universal_tag(STREAM* s, uint8 tag, tbool pc); tbool ber_read_application_tag(STREAM* s, uint8 tag, int* length); void ber_write_application_tag(STREAM* s, uint8 tag, int length); tbool ber_read_application_tag(STREAM* s, uint8 tag, int* length); @@ -66,18 +66,19 @@ int ber_write_contextual_tag(STREAM* s, uint8 tag, int length, tbool pc); int ber_skip_contextual_tag(int length); tbool ber_read_sequence_tag(STREAM* s, int* length); int ber_write_sequence_tag(STREAM* s, int length); -int ber_skip_sequence(int length); -int ber_skip_sequence_tag(int length); +int ber_sizeof_sequence(int length); +int ber_sizeof_sequence_tag(int length); tbool ber_read_bit_string(STREAM* s, int* length, uint8* padding); tbool ber_read_octet_string(STREAM* s, int* length); -void ber_write_octet_string(STREAM* s, const uint8* oct_str, int length); +int ber_write_octet_string(STREAM* s, const uint8* oct_str, int length); +tbool ber_read_octet_string_tag(STREAM* s, int* length); int ber_write_octet_string_tag(STREAM* s, int length); -int ber_skip_octet_string(int length); +int ber_sizeof_octet_string(int length); tbool ber_read_boolean(STREAM* s, tbool* value); void ber_write_boolean(STREAM* s, tbool value); tbool ber_read_integer(STREAM* s, uint32* value); int ber_write_integer(STREAM* s, uint32 value); tbool ber_read_integer_length(STREAM* s, int* length); -int ber_skip_integer(uint32 value); +int ber_sizeof_integer(uint32 value); #endif /* __BER_H */ diff --git a/libfreerdp-core/credssp.c b/libfreerdp-core/credssp.c index ad45549..f5e212a 100644 --- a/libfreerdp-core/credssp.c +++ b/libfreerdp-core/credssp.c @@ -329,19 +329,19 @@ int credssp_skip_ts_password_creds(rdpCredssp* credssp) int length; int ts_password_creds_length = 0; - length = ber_skip_octet_string(credssp->ntlmssp->domain.length); + length = ber_sizeof_octet_string(credssp->ntlmssp->domain.length); length += ber_skip_contextual_tag(length); ts_password_creds_length += length; - length = ber_skip_octet_string(credssp->ntlmssp->username.length); + length = ber_sizeof_octet_string(credssp->ntlmssp->username.length); length += ber_skip_contextual_tag(length); ts_password_creds_length += length; - length = ber_skip_octet_string(credssp->ntlmssp->password.length); + length = ber_sizeof_octet_string(credssp->ntlmssp->password.length); length += ber_skip_contextual_tag(length); ts_password_creds_length += length; - length = ber_skip_sequence(ts_password_creds_length); + length = ber_sizeof_sequence(ts_password_creds_length); return length; } @@ -375,16 +375,16 @@ int credssp_skip_ts_credentials(rdpCredssp* credssp) int ts_password_creds_length; int ts_credentials_length = 0; - length = ber_skip_integer(0); + length = ber_sizeof_integer(0); length += ber_skip_contextual_tag(length); ts_credentials_length += length; ts_password_creds_length = credssp_skip_ts_password_creds(credssp); - length = ber_skip_octet_string(ts_password_creds_length); + length = ber_sizeof_octet_string(ts_password_creds_length); length += ber_skip_contextual_tag(length); ts_credentials_length += length; - length = ber_skip_sequence(ts_credentials_length); + length = ber_sizeof_sequence(ts_credentials_length); return length; } @@ -435,7 +435,7 @@ void credssp_encode_ts_credentials(rdpCredssp* credssp) int credssp_skip_nego_token(int length) { - length = ber_skip_octet_string(length); + length = ber_sizeof_octet_string(length); length += ber_skip_contextual_tag(length); return length; } @@ -443,31 +443,31 @@ int credssp_skip_nego_token(int 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_sizeof_sequence_tag(length); + length += ber_sizeof_sequence_tag(length); length += ber_skip_contextual_tag(length); return length; } int credssp_skip_pub_key_auth(int length) { - length = ber_skip_octet_string(length); + length = ber_sizeof_octet_string(length); length += ber_skip_contextual_tag(length); return length; } int credssp_skip_auth_info(int length) { - length = ber_skip_octet_string(length); + length = ber_sizeof_octet_string(length); length += ber_skip_contextual_tag(length); return length; } int credssp_skip_ts_request(int length) { - length += ber_skip_integer(2); + length += ber_sizeof_integer(2); length += ber_skip_contextual_tag(3); - length += ber_skip_sequence_tag(length); + length += ber_sizeof_sequence_tag(length); return length; } -- cgit v1.2.3 From c9759d682d097d886d6f0a9f3ceddf3b490cb0b7 Mon Sep 17 00:00:00 2001 From: speidy Date: Wed, 13 Apr 2016 09:59:14 -0400 Subject: credssp: adjustments for ber encoding issues, long passwords (>128) is working now --- libfreerdp-core/ber.c | 2 +- libfreerdp-core/ber.h | 2 +- libfreerdp-core/credssp.c | 156 ++++++++++++++++++++++------------------------ 3 files changed, 78 insertions(+), 82 deletions(-) diff --git a/libfreerdp-core/ber.c b/libfreerdp-core/ber.c index fda3c12..ea03135 100644 --- a/libfreerdp-core/ber.c +++ b/libfreerdp-core/ber.c @@ -235,7 +235,7 @@ int ber_write_contextual_tag(STREAM* s, uint8 tag, int length, tbool pc) return 1 + ber_write_length(s, length); } -int ber_skip_contextual_tag(int length) +int ber_sizeof_contextual_tag(int length) { return 1 + _ber_sizeof_length(length); } diff --git a/libfreerdp-core/ber.h b/libfreerdp-core/ber.h index a048aa4..292860f 100644 --- a/libfreerdp-core/ber.h +++ b/libfreerdp-core/ber.h @@ -63,7 +63,7 @@ tbool ber_read_enumerated(STREAM* s, uint8* enumerated, uint8 count); void ber_write_enumerated(STREAM* s, uint8 enumerated, uint8 count); tbool ber_read_contextual_tag(STREAM* s, uint8 tag, int* length, tbool pc); int ber_write_contextual_tag(STREAM* s, uint8 tag, int length, tbool pc); -int ber_skip_contextual_tag(int length); +int ber_sizeof_contextual_tag(int length); tbool ber_read_sequence_tag(STREAM* s, int* length); int ber_write_sequence_tag(STREAM* s, int length); int ber_sizeof_sequence(int length); diff --git a/libfreerdp-core/credssp.c b/libfreerdp-core/credssp.c index f5e212a..913c527 100644 --- a/libfreerdp-core/credssp.c +++ b/libfreerdp-core/credssp.c @@ -67,6 +67,12 @@ * */ + +#define ber_sizeof_sequence_octet_string(length) ber_sizeof_contextual_tag(ber_sizeof_octet_string(length)) + ber_sizeof_octet_string(length) +#define ber_write_sequence_octet_string(stream, context, value, length) ber_write_contextual_tag(stream, context, ber_sizeof_octet_string(length), true) + ber_write_octet_string(stream, value, length) + + + /** * Initialize NTLMSSP authentication module. * @param credssp @@ -324,21 +330,21 @@ void credssp_encrypt_ts_credentials(rdpCredssp* credssp, rdpBlob* d) freerdp_blob_free(&encrypted_ts_credentials); } -int credssp_skip_ts_password_creds(rdpCredssp* credssp) +int credssp_sizeof_ts_password_creds(rdpCredssp* credssp) { int length; int ts_password_creds_length = 0; - length = ber_sizeof_octet_string(credssp->ntlmssp->domain.length); - length += ber_skip_contextual_tag(length); + length = ber_sizeof_octet_string(credssp->ntlmssp->domain.length * 2); + length += ber_sizeof_contextual_tag(length); ts_password_creds_length += length; - length = ber_sizeof_octet_string(credssp->ntlmssp->username.length); - length += ber_skip_contextual_tag(length); + length = ber_sizeof_octet_string(credssp->ntlmssp->username.length * 2); + length += ber_sizeof_contextual_tag(length); ts_password_creds_length += length; - length = ber_sizeof_octet_string(credssp->ntlmssp->password.length); - length += ber_skip_contextual_tag(length); + length = ber_sizeof_octet_string(credssp->ntlmssp->password.length * 2); + length += ber_sizeof_contextual_tag(length); ts_password_creds_length += length; length = ber_sizeof_sequence(ts_password_creds_length); @@ -346,71 +352,62 @@ int credssp_skip_ts_password_creds(rdpCredssp* credssp) return length; } -void credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s) +int credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s) { - int length; + int size = 0; + int innerSize = credssp_sizeof_ts_password_creds(credssp); - length = credssp_skip_ts_password_creds(credssp); + if (innerSize > stream_get_left(s)) + { + printf("\033[91m[ ERROR ] Not enough space allocated for ts_password_creds\033[0m"); + } /* TSPasswordCreds (SEQUENCE) */ - length = ber_get_content_length(length); - ber_write_sequence_tag(s, length); + size += ber_write_sequence_tag(s, innerSize); /* [0] domainName (OCTET STRING) */ - ber_write_contextual_tag(s, 0, credssp->ntlmssp->domain.length + 2, true); - ber_write_octet_string(s, credssp->ntlmssp->domain.data, credssp->ntlmssp->domain.length); + size += ber_write_sequence_octet_string(s, 0, credssp->ntlmssp->domain.data, credssp->ntlmssp->domain.length * 2); /* [1] userName (OCTET STRING) */ - ber_write_contextual_tag(s, 1, credssp->ntlmssp->username.length + 2, true); - ber_write_octet_string(s, credssp->ntlmssp->username.data, credssp->ntlmssp->username.length); + size += ber_write_sequence_octet_string(s, 1, credssp->ntlmssp->username.data, credssp->ntlmssp->username.length * 2); /* [2] password (OCTET STRING) */ - ber_write_contextual_tag(s, 2, credssp->ntlmssp->password.length + 2, true); - ber_write_octet_string(s, credssp->ntlmssp->password.data, credssp->ntlmssp->password.length); + size += ber_write_sequence_octet_string(s, 2, credssp->ntlmssp->password.data, credssp->ntlmssp->password.length * 2); + + return size; } -int credssp_skip_ts_credentials(rdpCredssp* credssp) +int credssp_sizeof_ts_credentials(rdpCredssp* credssp) { - int length; - int ts_password_creds_length; - int ts_credentials_length = 0; - - length = ber_sizeof_integer(0); - length += ber_skip_contextual_tag(length); - ts_credentials_length += length; + int size = 0; - ts_password_creds_length = credssp_skip_ts_password_creds(credssp); - length = ber_sizeof_octet_string(ts_password_creds_length); - length += ber_skip_contextual_tag(length); - ts_credentials_length += length; + size += ber_sizeof_integer(1); + size += ber_sizeof_contextual_tag(ber_sizeof_integer(1)); + size += ber_sizeof_octet_string(ber_sizeof_sequence(credssp_sizeof_ts_password_creds(credssp))); - length = ber_sizeof_sequence(ts_credentials_length); - - return length; + return size; } -void credssp_write_ts_credentials(rdpCredssp* credssp, STREAM* s) +int credssp_write_ts_credentials(rdpCredssp* credssp, STREAM* s) { - int length; - int ts_password_creds_length; - - length = credssp_skip_ts_credentials(credssp); - ts_password_creds_length = credssp_skip_ts_password_creds(credssp); + int size = 0; + int innerSize = credssp_sizeof_ts_credentials(credssp); /* TSCredentials (SEQUENCE) */ - length = ber_get_content_length(length); - length -= ber_write_sequence_tag(s, length); + size += ber_write_sequence_tag(s, innerSize); /* [0] credType (INTEGER) */ - length -= ber_write_contextual_tag(s, 0, 3, true); - length -= ber_write_integer(s, 1); + size += ber_write_contextual_tag(s, 0, ber_sizeof_integer(1), true); + size += ber_write_integer(s, 1); /* [1] credentials (OCTET STRING) */ - length -= 1; - length -= ber_write_contextual_tag(s, 1, length, true); - length -= ber_write_octet_string_tag(s, ts_password_creds_length); + int passwordSize = ber_sizeof_sequence(credssp_sizeof_ts_password_creds(credssp)); + + size += ber_write_contextual_tag(s, 1, ber_sizeof_octet_string(passwordSize), true); + size += ber_write_octet_string_tag(s, passwordSize); + size += credssp_write_ts_password_creds(credssp, s); - credssp_write_ts_password_creds(credssp, s); + return size; } /** @@ -424,7 +421,7 @@ void credssp_encode_ts_credentials(rdpCredssp* credssp) int length; s = stream_new(0); - length = credssp_skip_ts_credentials(credssp); + length = ber_sizeof_sequence(credssp_sizeof_ts_credentials(credssp)); freerdp_blob_alloc(&credssp->ts_credentials, length); stream_attach(s, credssp->ts_credentials.data, length); @@ -433,41 +430,40 @@ void credssp_encode_ts_credentials(rdpCredssp* credssp) stream_free(s); } -int credssp_skip_nego_token(int length) +int credssp_sizeof_nego_token(int length) { length = ber_sizeof_octet_string(length); - length += ber_skip_contextual_tag(length); + length += ber_sizeof_contextual_tag(length); return length; } -int credssp_skip_nego_tokens(int length) +int credssp_sizeof_nego_tokens(int length) { - length = credssp_skip_nego_token(length); + length = credssp_sizeof_nego_token(length); length += ber_sizeof_sequence_tag(length); length += ber_sizeof_sequence_tag(length); - length += ber_skip_contextual_tag(length); + length += ber_sizeof_contextual_tag(length); return length; } -int credssp_skip_pub_key_auth(int length) +int credssp_sizeof_pub_key_auth(int length) { length = ber_sizeof_octet_string(length); - length += ber_skip_contextual_tag(length); + length += ber_sizeof_contextual_tag(length); return length; } -int credssp_skip_auth_info(int length) +int credssp_sizeof_auth_info(int length) { length = ber_sizeof_octet_string(length); - length += ber_skip_contextual_tag(length); + length += ber_sizeof_contextual_tag(length); return length; } -int credssp_skip_ts_request(int length) +int credssp_sizeof_ts_request(int length) { length += ber_sizeof_integer(2); - length += ber_skip_contextual_tag(3); - length += ber_sizeof_sequence_tag(length); + length += ber_sizeof_contextual_tag(3); return length; } @@ -488,46 +484,46 @@ void credssp_send(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rd int pub_key_auth_length; int auth_info_length; - nego_tokens_length = (negoToken != NULL) ? credssp_skip_nego_tokens(negoToken->length) : 0; - pub_key_auth_length = (pubKeyAuth != NULL) ? credssp_skip_pub_key_auth(pubKeyAuth->length) : 0; - auth_info_length = (authInfo != NULL) ? credssp_skip_auth_info(authInfo->length) : 0; + nego_tokens_length = (negoToken != NULL) ? credssp_sizeof_nego_tokens(negoToken->length) : 0; + pub_key_auth_length = (pubKeyAuth != NULL) ? credssp_sizeof_pub_key_auth(pubKeyAuth->length) : 0; + auth_info_length = (authInfo != NULL) ? credssp_sizeof_auth_info(authInfo->length) : 0; length = nego_tokens_length + pub_key_auth_length + auth_info_length; - ts_request_length = credssp_skip_ts_request(length); - s = stream_new(ts_request_length); + ts_request_length = credssp_sizeof_ts_request(length); + + s = stream_new(ber_sizeof_sequence(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 */ + ber_write_sequence_tag(s, ts_request_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, negoToken->data, length); /* OCTET STRING */ + length = nego_tokens_length; + + length -= ber_write_contextual_tag(s, 1, ber_sizeof_sequence(ber_sizeof_sequence(ber_sizeof_sequence_octet_string(credssp->negoToken.length))), true); /* NegoData */ + length -= ber_write_sequence_tag(s, ber_sizeof_sequence(ber_sizeof_sequence_octet_string(credssp->negoToken.length))); /* SEQUENCE OF NegoDataItem */ + length -= ber_write_sequence_tag(s, ber_sizeof_sequence_octet_string(credssp->negoToken.length)); /* NegoDataItem */ + length -= ber_write_octet_string(s, negoToken->data, negoToken->length); /* OCTET STRING */ } /* [2] authInfo (OCTET STRING) */ if (auth_info_length > 0) { - length = ber_get_content_length(auth_info_length); - length -= ber_write_contextual_tag(s, 2, length, true); - ber_write_octet_string(s, authInfo->data, authInfo->length); + length = auth_info_length; + length -= ber_write_sequence_octet_string(s, 2, authInfo->data, authInfo->length); } /* [3] pubKeyAuth (OCTET STRING) */ if (pub_key_auth_length > 0) { - length = ber_get_content_length(pub_key_auth_length); - length -= ber_write_contextual_tag(s, 3, length, true); - ber_write_octet_string(s, pubKeyAuth->data, length); + length = pub_key_auth_length; + length -= ber_write_sequence_octet_string(s, 3, pubKeyAuth->data, pubKeyAuth->length); } tls_write(credssp->tls, s->data, stream_get_length(s)); -- cgit v1.2.3 From 575c06297bd8385d323344fe1425daafe7346cf7 Mon Sep 17 00:00:00 2001 From: speidy Date: Wed, 13 Apr 2016 17:35:55 -0400 Subject: credssp: work in progress --- libfreerdp-core/ber.c | 26 +++++++++++++------------- libfreerdp-core/credssp.c | 29 ++++++++++------------------- libfreerdp-core/ntlmssp.c | 4 ++++ 3 files changed, 27 insertions(+), 32 deletions(-) diff --git a/libfreerdp-core/ber.c b/libfreerdp-core/ber.c index ea03135..6b83e6b 100644 --- a/libfreerdp-core/ber.c +++ b/libfreerdp-core/ber.c @@ -42,8 +42,7 @@ int ber_read_length(STREAM* s, int* length) { stream_read_uint8(s, *length); } - - if (byte == 2) + else if (byte == 2) { stream_read_uint16_be(s, *length); } @@ -77,7 +76,7 @@ int ber_write_length(STREAM* s, int length) if (length > 0x7F) { stream_write_uint8(s, 0x80 ^ 1); - stream_write_uint16_be(s, length); + stream_write_uint8(s, length); return 2; } stream_write_uint8(s, length); @@ -93,13 +92,13 @@ int _ber_sizeof_length(int length) return 1; } -int ber_get_content_length(int length) -{ - if (length - 1 > 0x7F) - return length - 4; - else - return length - 2; -} +//int ber_get_content_length(int length) +//{ +// if (length - 1 > 0x7F) +// return length - 4; +// else +// return length - 2; +//} /** * Read BER Universal tag. @@ -349,9 +348,7 @@ int ber_write_octet_string(STREAM* s, const uint8* oct_str, int length) size += ber_write_universal_tag(s, BER_TAG_OCTET_STRING, false); size += ber_write_length(s, length); - stream_write(s, oct_str, length); - size += length; return size; @@ -476,22 +473,24 @@ tbool ber_read_integer(STREAM* s, uint32* value) int ber_write_integer(STREAM* s, uint32 value) { - ber_write_universal_tag(s, BER_TAG_INTEGER, false); if (value < 0x80) { + ber_write_universal_tag(s, BER_TAG_INTEGER, false); ber_write_length(s, 1); stream_write_uint8(s, value); return 3; } else if (value < 0x8000) { + ber_write_universal_tag(s, BER_TAG_INTEGER, false); ber_write_length(s, 2); stream_write_uint16_be(s, value); return 4; } else if (value < 0x800000) { + ber_write_universal_tag(s, BER_TAG_INTEGER, false); ber_write_length(s, 3); stream_write_uint8(s, (value >> 16)); stream_write_uint16_be(s, (value & 0xFFFF)); @@ -499,6 +498,7 @@ int ber_write_integer(STREAM* s, uint32 value) } else if (value < 0x80000000) { + ber_write_universal_tag(s, BER_TAG_INTEGER, false); ber_write_length(s, 4); stream_write_uint32_be(s, value); return 6; diff --git a/libfreerdp-core/credssp.c b/libfreerdp-core/credssp.c index 913c527..d74f3f5 100644 --- a/libfreerdp-core/credssp.c +++ b/libfreerdp-core/credssp.c @@ -332,22 +332,11 @@ void credssp_encrypt_ts_credentials(rdpCredssp* credssp, rdpBlob* d) int credssp_sizeof_ts_password_creds(rdpCredssp* credssp) { - int length; - int ts_password_creds_length = 0; + int length = 0; - length = ber_sizeof_octet_string(credssp->ntlmssp->domain.length * 2); - length += ber_sizeof_contextual_tag(length); - ts_password_creds_length += length; - - length = ber_sizeof_octet_string(credssp->ntlmssp->username.length * 2); - length += ber_sizeof_contextual_tag(length); - ts_password_creds_length += length; - - length = ber_sizeof_octet_string(credssp->ntlmssp->password.length * 2); - length += ber_sizeof_contextual_tag(length); - ts_password_creds_length += length; - - length = ber_sizeof_sequence(ts_password_creds_length); + length += ber_sizeof_sequence_octet_string(credssp->ntlmssp->domain.length * 2); + length += ber_sizeof_sequence_octet_string(credssp->ntlmssp->username.length * 2); + length += ber_sizeof_sequence_octet_string(credssp->ntlmssp->password.length * 2); return length; } @@ -509,7 +498,7 @@ void credssp_send(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rd length -= ber_write_contextual_tag(s, 1, ber_sizeof_sequence(ber_sizeof_sequence(ber_sizeof_sequence_octet_string(credssp->negoToken.length))), true); /* NegoData */ length -= ber_write_sequence_tag(s, ber_sizeof_sequence(ber_sizeof_sequence_octet_string(credssp->negoToken.length))); /* SEQUENCE OF NegoDataItem */ length -= ber_write_sequence_tag(s, ber_sizeof_sequence_octet_string(credssp->negoToken.length)); /* NegoDataItem */ - length -= ber_write_octet_string(s, negoToken->data, negoToken->length); /* OCTET STRING */ + length -= ber_write_sequence_octet_string(s, 0, negoToken->data, negoToken->length); /* OCTET STRING */ } /* [2] authInfo (OCTET STRING) */ @@ -549,6 +538,7 @@ int credssp_recv(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rdp s = stream_new(2048); status = tls_read(credssp->tls, s->data, stream_get_left(s)); + if (status < 0) return -1; @@ -558,12 +548,13 @@ int credssp_recv(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rdp ber_read_integer(s, &version); /* [1] negoTokens (NegoData) */ + if (ber_read_contextual_tag(s, 1, &length, true) != false) { ber_read_sequence_tag(s, &length); /* SEQUENCE OF NegoDataItem */ ber_read_sequence_tag(s, &length); /* NegoDataItem */ ber_read_contextual_tag(s, 0, &length, true); /* [0] negoToken */ - ber_read_octet_string(s, &length); /* OCTET STRING */ + ber_read_octet_string_tag(s, &length); /* OCTET STRING */ freerdp_blob_alloc(negoToken, length); stream_read(s, negoToken->data, length); } @@ -571,7 +562,7 @@ int credssp_recv(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rdp /* [2] authInfo (OCTET STRING) */ if (ber_read_contextual_tag(s, 2, &length, true) != false) { - ber_read_octet_string(s, &length); /* OCTET STRING */ + ber_read_octet_string_tag(s, &length); /* OCTET STRING */ freerdp_blob_alloc(authInfo, length); stream_read(s, authInfo->data, length); } @@ -579,7 +570,7 @@ int credssp_recv(rdpCredssp* credssp, rdpBlob* negoToken, rdpBlob* authInfo, rdp /* [3] pubKeyAuth (OCTET STRING) */ if (ber_read_contextual_tag(s, 3, &length, true) != false) { - ber_read_octet_string(s, &length); /* OCTET STRING */ + ber_read_octet_string_tag(s, &length); /* OCTET STRING */ freerdp_blob_alloc(pubKeyAuth, length); stream_read(s, pubKeyAuth->data, length); } diff --git a/libfreerdp-core/ntlmssp.c b/libfreerdp-core/ntlmssp.c index 0069cb4..8c92913 100644 --- a/libfreerdp-core/ntlmssp.c +++ b/libfreerdp-core/ntlmssp.c @@ -1198,8 +1198,10 @@ void ntlmssp_encrypt_message(NTLMSSP* ntlmssp, rdpBlob* msg, rdpBlob* encrypted_ /* Allocate space for encrypted message */ freerdp_blob_alloc(encrypted_msg, msg->length); + printf("rc4 %d % d %d %d\n", ntlmssp->send_rc4_seal, msg->length, msg->data, encrypted_msg->data); /* Encrypt message using with RC4 */ crypto_rc4(ntlmssp->send_rc4_seal, msg->length, msg->data, encrypted_msg->data); + printf("rc4 done\n"); } /* RC4-encrypt first 8 bytes of digest */ @@ -1816,7 +1818,9 @@ int ntlmssp_recv(NTLMSSP* ntlmssp, STREAM* s) stream_read_uint32(s, messageType); if (messageType == 2 && ntlmssp->state == NTLMSSP_STATE_CHALLENGE) + { ntlmssp_recv_challenge_message(ntlmssp, s); + } return 1; } -- cgit v1.2.3 From e446b33039342daed5d554d3e095d14f7dc8dff0 Mon Sep 17 00:00:00 2001 From: speidy Date: Thu, 14 Apr 2016 00:46:45 -0400 Subject: credssp: long passwords working now --- libfreerdp-core/ber.c | 5 ++--- libfreerdp-core/credssp.c | 2 +- libfreerdp-core/ntlmssp.c | 2 -- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/libfreerdp-core/ber.c b/libfreerdp-core/ber.c index 6b83e6b..22c2af5 100644 --- a/libfreerdp-core/ber.c +++ b/libfreerdp-core/ber.c @@ -168,7 +168,7 @@ tbool ber_read_application_tag(STREAM* s, uint8 tag, int* length) if (byte != tag) return false; - ber_read_length(s, length); + return ber_read_length(s, length); } else { @@ -181,7 +181,7 @@ tbool ber_read_application_tag(STREAM* s, uint8 tag, int* length) if (byte != ((BER_CLASS_APPL | BER_CONSTRUCT) | (BER_TAG_MASK & tag))) return false; - ber_read_length(s, length); + return ber_read_length(s, length); } return true; @@ -345,7 +345,6 @@ tbool ber_read_octet_string(STREAM* s, int* length) int ber_write_octet_string(STREAM* s, const uint8* oct_str, int length) { int size = 0; - size += ber_write_universal_tag(s, BER_TAG_OCTET_STRING, false); size += ber_write_length(s, length); stream_write(s, oct_str, length); diff --git a/libfreerdp-core/credssp.c b/libfreerdp-core/credssp.c index d74f3f5..4402c00 100644 --- a/libfreerdp-core/credssp.c +++ b/libfreerdp-core/credssp.c @@ -372,7 +372,7 @@ int credssp_sizeof_ts_credentials(rdpCredssp* credssp) size += ber_sizeof_integer(1); size += ber_sizeof_contextual_tag(ber_sizeof_integer(1)); - size += ber_sizeof_octet_string(ber_sizeof_sequence(credssp_sizeof_ts_password_creds(credssp))); + size += ber_sizeof_sequence_octet_string(ber_sizeof_sequence(credssp_sizeof_ts_password_creds(credssp))); return size; } diff --git a/libfreerdp-core/ntlmssp.c b/libfreerdp-core/ntlmssp.c index 8c92913..5a175f0 100644 --- a/libfreerdp-core/ntlmssp.c +++ b/libfreerdp-core/ntlmssp.c @@ -1198,10 +1198,8 @@ void ntlmssp_encrypt_message(NTLMSSP* ntlmssp, rdpBlob* msg, rdpBlob* encrypted_ /* Allocate space for encrypted message */ freerdp_blob_alloc(encrypted_msg, msg->length); - printf("rc4 %d % d %d %d\n", ntlmssp->send_rc4_seal, msg->length, msg->data, encrypted_msg->data); /* Encrypt message using with RC4 */ crypto_rc4(ntlmssp->send_rc4_seal, msg->length, msg->data, encrypted_msg->data); - printf("rc4 done\n"); } /* RC4-encrypt first 8 bytes of digest */ -- cgit v1.2.3 From 67ea8cae60cf6b1023f5c475d0f79e1652d93a10 Mon Sep 17 00:00:00 2001 From: speidy Date: Sat, 16 Apr 2016 02:15:01 -0400 Subject: multimon: move up X11 specific config from gcc, validate multimon input --- client/X11/xf_monitor.c | 2 +- libfreerdp-core/gcc.c | 9 +++++---- libfreerdp-utils/args.c | 43 +++++++++++++++++++++++++++++-------------- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/client/X11/xf_monitor.c b/client/X11/xf_monitor.c index 7ede960..b5877a0 100644 --- a/client/X11/xf_monitor.c +++ b/client/X11/xf_monitor.c @@ -56,7 +56,7 @@ tbool xf_detect_monitors(xfInfo* xfi, rdpSettings* settings) if (settings->num_monitors > 0) { - /* already setup */ + /* already setup in args */ return true; } diff --git a/libfreerdp-core/gcc.c b/libfreerdp-core/gcc.c index 6721937..a7fba4f 100644 --- a/libfreerdp-core/gcc.c +++ b/libfreerdp-core/gcc.c @@ -358,9 +358,10 @@ void gcc_write_client_data_blocks(STREAM* s, rdpSettings* settings) gcc_write_client_network_data(s, settings); /* extended client data supported */ - - //if (settings->negotiationFlags) + if (settings->negotiationFlags & EXTENDED_CLIENT_DATA_SUPPORTED) + { gcc_write_client_monitor_data(s, settings); + } } tbool gcc_read_server_data_blocks(STREAM* s, rdpSettings* settings, int length) @@ -1154,8 +1155,8 @@ void gcc_write_client_monitor_data(STREAM* s, rdpSettings* settings) { left = settings->monitors[i].x; top = settings->monitors[i].y; - right = settings->monitors[i].x + settings->monitors[i].width - 1; - bottom = settings->monitors[i].y + settings->monitors[i].height - 1; + right = settings->monitors[i].width; + bottom = settings->monitors[i].height; flags = settings->monitors[i].is_primary ? MONITOR_PRIMARY : 0; stream_write_uint32(s, left); /* left */ diff --git a/libfreerdp-utils/args.c b/libfreerdp-utils/args.c index 7f010eb..7257472 100644 --- a/libfreerdp-utils/args.c +++ b/libfreerdp-utils/args.c @@ -127,8 +127,8 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, " --secure-checksum: use salted checksums with Standard RDP encryption\n" " --version: print version information\n" " --skip-bs: do not keep backing store\n" - " --multimon-set: hard set monitor list num x y width height isprimary x y...\n" - " two screen example --multimon-set 2 0 0 512 768 512 0 512 768\n" + " --multimon-set: hard set monitor list: , ...\n" + " two screen example --multimon-set 2 0 0 512 768 1 512 0 512 768 0\n" "\n", argv[0]); return FREERDP_ARGS_PARSE_HELP; //TODO: What is the correct return } @@ -789,18 +789,33 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, int n; settings->num_monitors = atoi(argv[index + 1]); index++; - for (n = 0; n < settings->num_monitors; n++) - { - settings->monitors[n].x = atoi(argv[index + 1]); - index++; - settings->monitors[n].y = atoi(argv[index + 1]); - index++; - settings->monitors[n].width = atoi(argv[index + 1]); - index++; - settings->monitors[n].height = atoi(argv[index + 1]); - index++; - settings->monitors[n].is_primary = atoi(argv[index + 1]); - index++; + + if ((argc - index) <= (settings->num_monitors * 5)) + { + printf("--multimon-set: error, not enough multimon args to parse\n"); + return FREERDP_ARGS_PARSE_FAILURE; + } + + if (settings->num_monitors > 1 && settings->num_monitors <= 16) + { + for (n = 0; n < settings->num_monitors; n++) + { + settings->monitors[n].x = atoi(argv[index + 1]); + index++; + settings->monitors[n].y = atoi(argv[index + 1]); + index++; + settings->monitors[n].width = settings->monitors[n].x + atoi(argv[index + 1]) - 1; + index++; + settings->monitors[n].height = settings->monitors[n].y + atoi(argv[index + 1]) - 1; + index++; + settings->monitors[n].is_primary = atoi(argv[index + 1]); + index++; + } + } + else + { + printf("--multimon-set: invalid number of monitors (%d), should be between 2 to 16\n", settings->num_monitors); + return FREERDP_ARGS_PARSE_FAILURE; } } else if (argv[index][0] != '-') -- cgit v1.2.3