Skip to content

Commit 36b3a26

Browse files
committed
Use UCS16LE instead of UCS-2LE
MS-NLMP in 2.2 indicates that UTF-16 little endian w/o BOM is used. Make sure we do the same as now some chracters maybe used in usernames and passwords that use code points outside of the range that can be handled by UCS-2LE. Signed-off-by: Simo Sorce <[email protected]>
1 parent 0279a3e commit 36b3a26

File tree

3 files changed

+53
-29
lines changed

3 files changed

+53
-29
lines changed

src/ntlm.c

+27-27
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,12 @@ int ntlm_init_ctx(struct ntlm_ctx **ctx)
100100
_ctx = calloc(1, sizeof(struct ntlm_ctx));
101101
if (!_ctx) return ENOMEM;
102102

103-
_ctx->from_oem = iconv_open("UCS-2LE", "UTF-8");
103+
_ctx->from_oem = iconv_open("UTF16LE", "UTF-8");
104104
if (_ctx->from_oem == (iconv_t) -1) {
105105
ret = errno;
106106
}
107107

108-
_ctx->to_oem = iconv_open("UTF-8", "UCS-2LE");
108+
_ctx->to_oem = iconv_open("UTF-8", "UTF16LE");
109109
if (_ctx->to_oem == (iconv_t) -1) {
110110
iconv_close(_ctx->from_oem);
111111
ret = errno;
@@ -189,7 +189,7 @@ bool ntlm_casecmp(const char *s1, const char *s2)
189189

190190
/**
191191
* @brief Converts a string using the provided iconv context.
192-
* This function is ok only to convert utf8<->ucs2
192+
* This function is ok only to convert utf8<->utf16le
193193
*
194194
* @param cd The iconv context
195195
* @param in Input buffer
@@ -290,7 +290,7 @@ static int ntlm_decode_oem_str(struct wire_field_hdr *str_hdr,
290290
return 0;
291291
}
292292

293-
static int ntlm_encode_ucs2_str_hdr(struct ntlm_ctx *ctx,
293+
static int ntlm_encode_u16l_str_hdr(struct ntlm_ctx *ctx,
294294
struct wire_field_hdr *hdr,
295295
struct ntlm_buffer *buffer,
296296
size_t *data_offs,
@@ -313,7 +313,7 @@ static int ntlm_encode_ucs2_str_hdr(struct ntlm_ctx *ctx,
313313
return 0;
314314
}
315315

316-
static int ntlm_decode_ucs2_str_hdr(struct ntlm_ctx *ctx,
316+
static int ntlm_decode_u16l_str_hdr(struct ntlm_ctx *ctx,
317317
struct wire_field_hdr *str_hdr,
318318
struct ntlm_buffer *buffer,
319319
size_t payload_offs, char **str)
@@ -431,7 +431,7 @@ static int ntlm_decode_field(struct wire_field_hdr *hdr,
431431
return 0;
432432
}
433433

434-
static int ntlm_encode_av_pair_ucs2_str(struct ntlm_ctx *ctx,
434+
static int ntlm_encode_av_pair_u16l_str(struct ntlm_ctx *ctx,
435435
struct ntlm_buffer *buffer,
436436
size_t *data_offs,
437437
enum msv_av_ids av_id,
@@ -459,7 +459,7 @@ static int ntlm_encode_av_pair_ucs2_str(struct ntlm_ctx *ctx,
459459
return 0;
460460
}
461461

462-
static int ntlm_decode_av_pair_ucs2_str(struct ntlm_ctx *ctx,
462+
static int ntlm_decode_av_pair_u16l_str(struct ntlm_ctx *ctx,
463463
struct wire_av_pair *av_pair,
464464
char **str)
465465
{
@@ -570,35 +570,35 @@ int ntlm_encode_target_info(struct ntlm_ctx *ctx, char *nb_computer_name,
570570
if (!buffer.data) return ENOMEM;
571571

572572
if (nb_computer_name) {
573-
ret = ntlm_encode_av_pair_ucs2_str(ctx, &buffer, &data_offs,
573+
ret = ntlm_encode_av_pair_u16l_str(ctx, &buffer, &data_offs,
574574
MSV_AV_NB_COMPUTER_NAME,
575575
nb_computer_name,
576576
nb_computer_name_len);
577577
if (ret) goto done;
578578
}
579579
if (nb_domain_name) {
580-
ret = ntlm_encode_av_pair_ucs2_str(ctx, &buffer, &data_offs,
580+
ret = ntlm_encode_av_pair_u16l_str(ctx, &buffer, &data_offs,
581581
MSV_AV_NB_DOMAIN_NAME,
582582
nb_domain_name,
583583
nb_domain_name_len);
584584
if (ret) goto done;
585585
}
586586
if (dns_computer_name) {
587-
ret = ntlm_encode_av_pair_ucs2_str(ctx, &buffer, &data_offs,
587+
ret = ntlm_encode_av_pair_u16l_str(ctx, &buffer, &data_offs,
588588
MSV_AV_DNS_COMPUTER_NAME,
589589
dns_computer_name,
590590
dns_computer_name_len);
591591
if (ret) goto done;
592592
}
593593
if (dns_domain_name) {
594-
ret = ntlm_encode_av_pair_ucs2_str(ctx, &buffer, &data_offs,
594+
ret = ntlm_encode_av_pair_u16l_str(ctx, &buffer, &data_offs,
595595
MSV_AV_DNS_DOMAIN_NAME,
596596
dns_domain_name,
597597
dns_domain_name_len);
598598
if (ret) goto done;
599599
}
600600
if (dns_tree_name) {
601-
ret = ntlm_encode_av_pair_ucs2_str(ctx, &buffer, &data_offs,
601+
ret = ntlm_encode_av_pair_u16l_str(ctx, &buffer, &data_offs,
602602
MSV_AV_DNS_TREE_NAME,
603603
dns_tree_name,
604604
dns_tree_name_len);
@@ -626,7 +626,7 @@ int ntlm_encode_target_info(struct ntlm_ctx *ctx, char *nb_computer_name,
626626
if (ret) goto done;
627627
}
628628
if (av_target_name) {
629-
ret = ntlm_encode_av_pair_ucs2_str(ctx, &buffer, &data_offs,
629+
ret = ntlm_encode_av_pair_u16l_str(ctx, &buffer, &data_offs,
630630
MSV_AV_TARGET_NAME,
631631
av_target_name,
632632
av_target_name_len);
@@ -695,7 +695,7 @@ int ntlm_decode_target_info(struct ntlm_ctx *ctx, struct ntlm_buffer *buffer,
695695
break;
696696
case MSV_AV_TARGET_NAME:
697697
if (!av_target_name) continue;
698-
ret = ntlm_decode_av_pair_ucs2_str(ctx, av_pair, &av_target);
698+
ret = ntlm_decode_av_pair_u16l_str(ctx, av_pair, &av_target);
699699
if (ret) goto done;
700700
break;
701701
case MSV_AV_SINGLE_HOST:
@@ -715,27 +715,27 @@ int ntlm_decode_target_info(struct ntlm_ctx *ctx, struct ntlm_buffer *buffer,
715715
break;
716716
case MSV_AV_DNS_TREE_NAME:
717717
if (!dns_tree_name) continue;
718-
ret = ntlm_decode_av_pair_ucs2_str(ctx, av_pair, &dns_tree);
718+
ret = ntlm_decode_av_pair_u16l_str(ctx, av_pair, &dns_tree);
719719
if (ret) goto done;
720720
break;
721721
case MSV_AV_DNS_DOMAIN_NAME:
722722
if (!dns_domain_name) continue;
723-
ret = ntlm_decode_av_pair_ucs2_str(ctx, av_pair, &dns_domain);
723+
ret = ntlm_decode_av_pair_u16l_str(ctx, av_pair, &dns_domain);
724724
if (ret) goto done;
725725
break;
726726
case MSV_AV_DNS_COMPUTER_NAME:
727727
if (!dns_computer_name) continue;
728-
ret = ntlm_decode_av_pair_ucs2_str(ctx, av_pair, &dns_computer);
728+
ret = ntlm_decode_av_pair_u16l_str(ctx, av_pair, &dns_computer);
729729
if (ret) goto done;
730730
break;
731731
case MSV_AV_NB_DOMAIN_NAME:
732732
if (!nb_domain_name) continue;
733-
ret = ntlm_decode_av_pair_ucs2_str(ctx, av_pair, &nb_domain);
733+
ret = ntlm_decode_av_pair_u16l_str(ctx, av_pair, &nb_domain);
734734
if (ret) goto done;
735735
break;
736736
case MSV_AV_NB_COMPUTER_NAME:
737737
if (!nb_computer_name) continue;
738-
ret = ntlm_decode_av_pair_ucs2_str(ctx, av_pair, &nb_computer);
738+
ret = ntlm_decode_av_pair_u16l_str(ctx, av_pair, &nb_computer);
739739
if (ret) goto done;
740740
break;
741741
default:
@@ -1063,7 +1063,7 @@ int ntlm_encode_chal_msg(struct ntlm_ctx *ctx,
10631063
if ((flags & NTLMSSP_TARGET_TYPE_SERVER)
10641064
|| (flags & NTLMSSP_TARGET_TYPE_DOMAIN)) {
10651065
if (flags & NTLMSSP_NEGOTIATE_UNICODE) {
1066-
ret = ntlm_encode_ucs2_str_hdr(ctx, &msg->target_name, &buffer,
1066+
ret = ntlm_encode_u16l_str_hdr(ctx, &msg->target_name, &buffer,
10671067
&data_offs, target_name, target_len);
10681068
} else {
10691069
ret = ntlm_encode_oem_str(&msg->target_name, &buffer,
@@ -1114,7 +1114,7 @@ int ntlm_decode_chal_msg(struct ntlm_ctx *ctx,
11141114
if ((flags & NTLMSSP_TARGET_TYPE_SERVER)
11151115
|| (flags & NTLMSSP_TARGET_TYPE_DOMAIN)) {
11161116
if (flags & NTLMSSP_NEGOTIATE_UNICODE) {
1117-
ret = ntlm_decode_ucs2_str_hdr(ctx, &msg->target_name, buffer,
1117+
ret = ntlm_decode_u16l_str_hdr(ctx, &msg->target_name, buffer,
11181118
payload_offs, &trg);
11191119
} else {
11201120
ret = ntlm_decode_oem_str(&msg->target_name, buffer,
@@ -1251,7 +1251,7 @@ int ntlm_encode_auth_msg(struct ntlm_ctx *ctx,
12511251

12521252
if (domain_name_len) {
12531253
if (flags & NTLMSSP_NEGOTIATE_UNICODE) {
1254-
ret = ntlm_encode_ucs2_str_hdr(ctx, &msg->domain_name,
1254+
ret = ntlm_encode_u16l_str_hdr(ctx, &msg->domain_name,
12551255
&buffer, &data_offs,
12561256
domain_name, domain_name_len);
12571257
} else {
@@ -1263,7 +1263,7 @@ int ntlm_encode_auth_msg(struct ntlm_ctx *ctx,
12631263
}
12641264
if (user_name_len) {
12651265
if (flags & NTLMSSP_NEGOTIATE_UNICODE) {
1266-
ret = ntlm_encode_ucs2_str_hdr(ctx, &msg->user_name,
1266+
ret = ntlm_encode_u16l_str_hdr(ctx, &msg->user_name,
12671267
&buffer, &data_offs,
12681268
user_name, user_name_len);
12691269
} else {
@@ -1275,7 +1275,7 @@ int ntlm_encode_auth_msg(struct ntlm_ctx *ctx,
12751275
}
12761276
if (workstation_len) {
12771277
if (flags & NTLMSSP_NEGOTIATE_UNICODE) {
1278-
ret = ntlm_encode_ucs2_str_hdr(ctx, &msg->workstation,
1278+
ret = ntlm_encode_u16l_str_hdr(ctx, &msg->workstation,
12791279
&buffer, &data_offs,
12801280
workstation, workstation_len);
12811281
} else {
@@ -1381,7 +1381,7 @@ int ntlm_decode_auth_msg(struct ntlm_ctx *ctx,
13811381
}
13821382
if (msg->domain_name.len != 0 && domain_name) {
13831383
if (flags & NTLMSSP_NEGOTIATE_UNICODE) {
1384-
ret = ntlm_decode_ucs2_str_hdr(ctx, &msg->domain_name, buffer,
1384+
ret = ntlm_decode_u16l_str_hdr(ctx, &msg->domain_name, buffer,
13851385
payload_offs, &dom);
13861386
} else {
13871387
ret = ntlm_decode_oem_str(&msg->domain_name, buffer,
@@ -1391,7 +1391,7 @@ int ntlm_decode_auth_msg(struct ntlm_ctx *ctx,
13911391
}
13921392
if (msg->user_name.len != 0 && user_name) {
13931393
if (flags & NTLMSSP_NEGOTIATE_UNICODE) {
1394-
ret = ntlm_decode_ucs2_str_hdr(ctx, &msg->user_name, buffer,
1394+
ret = ntlm_decode_u16l_str_hdr(ctx, &msg->user_name, buffer,
13951395
payload_offs, &usr);
13961396
} else {
13971397
ret = ntlm_decode_oem_str(&msg->user_name, buffer,
@@ -1401,7 +1401,7 @@ int ntlm_decode_auth_msg(struct ntlm_ctx *ctx,
14011401
}
14021402
if (msg->workstation.len != 0 && workstation) {
14031403
if (flags & NTLMSSP_NEGOTIATE_UNICODE) {
1404-
ret = ntlm_decode_ucs2_str_hdr(ctx, &msg->workstation, buffer,
1404+
ret = ntlm_decode_u16l_str_hdr(ctx, &msg->workstation, buffer,
14051405
payload_offs, &wks);
14061406
} else {
14071407
ret = ntlm_decode_oem_str(&msg->workstation, buffer,

src/ntlm_crypto.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ int NTOWFv1(const char *password, struct ntlm_key *result)
6666
int ret;
6767

6868
len = strlen(password);
69-
retstr = u8_conv_to_encoding("UCS-2LE", iconveh_error,
69+
retstr = u8_conv_to_encoding("UTF16LE", iconveh_error,
7070
(const uint8_t *)password, len,
7171
NULL, NULL, &out);
7272
if (!retstr) return ERR_CRYPTO;
@@ -267,7 +267,7 @@ int NTOWFv2(struct ntlm_ctx *ctx, struct ntlm_key *nt_hash,
267267
offs += len;
268268
}
269269

270-
retstr = (uint8_t *)u8_conv_to_encoding("UCS-2LE", iconveh_error,
270+
retstr = (uint8_t *)u8_conv_to_encoding("UTF16LE", iconveh_error,
271271
upcased, offs, NULL, NULL, &out);
272272
if (!retstr) return ERR_CRYPTO;
273273

tests/ntlmssptest.c

+24
Original file line numberDiff line numberDiff line change
@@ -2289,6 +2289,25 @@ int test_ZERO_LMKEY(struct ntlm_ctx *ctx)
22892289
return test_keys("results", &MS_SessionKey, &result);
22902290
}
22912291

2292+
int test_NTOWF_UTF16(struct ntlm_ctx *ctx)
2293+
{
2294+
const char *passwd = "Pass\xF0\x9D\x84\x9E";
2295+
struct ntlm_key expected = {
2296+
.data = {
2297+
0x0d, 0x72, 0xdd, 0xde, 0xdd, 0xba, 0xe5, 0xff,
2298+
0x24, 0x48, 0x20, 0xe0, 0x72, 0x41, 0x3b, 0x90
2299+
},
2300+
.length = 16
2301+
};
2302+
struct ntlm_key result = { .length = 16 };
2303+
int ret;
2304+
2305+
ret = NTOWFv1(passwd, &result);
2306+
if (ret) return ret;
2307+
2308+
return test_keys("results", &expected, &result);
2309+
}
2310+
22922311
int main(int argc, const char *argv[])
22932312
{
22942313
struct ntlm_ctx *ctx;
@@ -2507,6 +2526,11 @@ int main(int argc, const char *argv[])
25072526
fprintf(stderr, "Test: %s\n", (ret ? "FAIL":"SUCCESS"));
25082527
if (ret) gret++;
25092528

2529+
fprintf(stderr, "Test NTOWF iwith UTF16\n");
2530+
ret = test_NTOWF_UTF16(ctx);
2531+
fprintf(stderr, "Test: %s\n", (ret ? "FAIL":"SUCCESS"));
2532+
if (ret) gret++;
2533+
25102534
done:
25112535
ntlm_free_ctx(&ctx);
25122536
return gret;

0 commit comments

Comments
 (0)