2 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of KTH nor the names of its contributors may be
18 * used to endorse or promote products derived from this software without
19 * specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 #include <krb5-types.h> /* or <inttypes.h> */
44 static int dumpdata_flag
;
49 const char *user
= "foo",
51 *hostname
= "myhostname",
52 *password
= "digestpassword",
54 struct ntlm_type1 type1
;
55 struct ntlm_type2 type2
;
56 struct ntlm_type3 type3
;
60 memset(&type1
, 0, sizeof(type1
));
62 type1
.flags
= NTLM_NEG_UNICODE
|NTLM_NEG_TARGET
|NTLM_NEG_NTLM
|NTLM_NEG_VERSION
;
63 type1
.domain
= rk_UNCONST(domain
);
64 type1
.hostname
= rk_UNCONST(hostname
);
68 ret
= heim_ntlm_encode_type1(&type1
, &data
);
70 errx(1, "heim_ntlm_encode_type1");
72 memset(&type1
, 0, sizeof(type1
));
75 rk_dumpdata("ntlm-type1", data
.data
, data
.length
);
77 ret
= heim_ntlm_decode_type1(&data
, &type1
);
80 errx(1, "heim_ntlm_encode_type1");
82 if (strcmp(type1
.domain
, domain
) != 0)
83 errx(1, "parser got domain wrong: %s", type1
.domain
);
85 if (strcmp(type1
.hostname
, hostname
) != 0)
86 errx(1, "parser got hostname wrong: %s", type1
.hostname
);
88 heim_ntlm_free_type1(&type1
);
94 memset(&type2
, 0, sizeof(type2
));
96 flags
= NTLM_NEG_UNICODE
| NTLM_NEG_NTLM
| NTLM_TARGET_DOMAIN
;
99 memset(type2
.challenge
, 0x7f, sizeof(type2
.challenge
));
100 type2
.targetname
= rk_UNCONST(target
);
101 type2
.targetinfo
.data
= NULL
;
102 type2
.targetinfo
.length
= 0;
104 ret
= heim_ntlm_encode_type2(&type2
, &data
);
106 errx(1, "heim_ntlm_encode_type2");
108 memset(&type2
, 0, sizeof(type2
));
111 rk_dumpdata("ntlm-type2", data
.data
, data
.length
);
113 ret
= heim_ntlm_decode_type2(&data
, &type2
);
116 errx(1, "heim_ntlm_decode_type2");
118 heim_ntlm_free_type2(&type2
);
124 memset(&type3
, 0, sizeof(type3
));
127 type3
.username
= rk_UNCONST(user
);
128 type3
.targetname
= rk_UNCONST(target
);
129 type3
.ws
= rk_UNCONST("workstation");
133 heim_ntlm_nt_key(password
, &key
);
135 heim_ntlm_calculate_ntlm1(key
.data
, key
.length
,
141 ret
= heim_ntlm_encode_type3(&type3
, &data
, NULL
);
143 errx(1, "heim_ntlm_encode_type3");
145 free(type3
.ntlm
.data
);
147 memset(&type3
, 0, sizeof(type3
));
150 rk_dumpdata("ntlm-type3", data
.data
, data
.length
);
152 ret
= heim_ntlm_decode_type3(&data
, 1, &type3
);
155 errx(1, "heim_ntlm_decode_type3");
157 if (strcmp("workstation", type3
.ws
) != 0)
158 errx(1, "type3 ws wrong");
160 if (strcmp(target
, type3
.targetname
) != 0)
161 errx(1, "type3 targetname wrong");
163 if (strcmp(user
, type3
.username
) != 0)
164 errx(1, "type3 username wrong");
167 heim_ntlm_free_type3(&type3
);
173 memset(&type2
, 0, sizeof(type2
));
175 flags
= NTLM_NEG_UNICODE
| NTLM_NEG_NTLM
| NTLM_TARGET_DOMAIN
;
178 memset(type2
.challenge
, 0x7f, sizeof(type2
.challenge
));
179 type2
.targetname
= rk_UNCONST(target
);
180 type2
.targetinfo
.data
= "\x00\x00";
181 type2
.targetinfo
.length
= 2;
183 ret
= heim_ntlm_encode_type2(&type2
, &data
);
185 errx(1, "heim_ntlm_encode_type2");
187 memset(&type2
, 0, sizeof(type2
));
189 ret
= heim_ntlm_decode_type2(&data
, &type2
);
192 errx(1, "heim_ntlm_decode_type2");
194 heim_ntlm_free_type2(&type2
);
204 *password
= "test1234",
207 serverchallenge
[8] = "\x67\x7f\x1c\x55\x7a\x5e\xe9\x6c";
208 struct ntlm_buf infotarget
, infotarget2
, answer
, key
;
209 unsigned char ntlmv2
[16], ntlmv2_1
[16];
212 infotarget
.length
= 70;
214 "\x02\x00\x0c\x00\x54\x00\x45\x00\x53\x00\x54\x00\x4e\x00\x54\x00"
215 "\x01\x00\x0c\x00\x4d\x00\x45\x00\x4d\x00\x42\x00\x45\x00\x52\x00"
216 "\x03\x00\x1e\x00\x6d\x00\x65\x00\x6d\x00\x62\x00\x65\x00\x72\x00"
217 "\x2e\x00\x74\x00\x65\x00\x73\x00\x74\x00\x2e\x00\x63\x00\x6f"
224 heim_ntlm_nt_key(password
, &key
);
226 ret
= heim_ntlm_calculate_ntlm2(key
.data
,
235 errx(1, "heim_ntlm_calculate_ntlm2");
237 ret
= heim_ntlm_verify_ntlm2(key
.data
,
247 errx(1, "heim_ntlm_verify_ntlm2");
249 if (memcmp(ntlmv2
, ntlmv2_1
, sizeof(ntlmv2
)) != 0)
250 errx(1, "ntlm master key not same");
252 if (infotarget
.length
> infotarget2
.length
)
253 errx(1, "infotarget length");
255 if (memcmp(infotarget
.data
, infotarget2
.data
, infotarget
.length
) != 0)
256 errx(1, "infotarget not the same");
260 free(infotarget2
.data
);
266 test_ntlm2_session_resp(void)
269 struct ntlm_buf lm
, ntlm
;
271 const unsigned char lm_resp
[24] =
272 "\xff\xff\xff\x00\x11\x22\x33\x44"
273 "\x00\x00\x00\x00\x00\x00\x00\x00"
274 "\x00\x00\x00\x00\x00\x00\x00\x00";
275 const unsigned char ntlm2_sess_resp
[24] =
276 "\x10\xd5\x50\x83\x2d\x12\xb2\xcc"
277 "\xb7\x9d\x5a\xd1\xf4\xee\xd3\xdf"
278 "\x82\xac\xa4\xc3\x68\x1d\xd4\x55";
280 const unsigned char client_nonce
[8] =
281 "\xff\xff\xff\x00\x11\x22\x33\x44";
282 const unsigned char server_challenge
[8] =
283 "\x01\x23\x45\x67\x89\xab\xcd\xef";
285 const unsigned char ntlm_hash
[16] =
286 "\xcd\x06\xca\x7c\x7e\x10\xc9\x9b"
287 "\x1d\x33\xb7\x48\x5a\x2e\xd8\x08";
289 ret
= heim_ntlm_calculate_ntlm2_sess(client_nonce
,
295 errx(1, "heim_ntlm_calculate_ntlm2_sess_resp");
297 if (lm
.length
!= 24 || memcmp(lm
.data
, lm_resp
, 24) != 0)
298 errx(1, "lm_resp wrong");
299 if (ntlm
.length
!= 24 || memcmp(ntlm
.data
, ntlm2_sess_resp
, 24) != 0)
300 errx(1, "ntlm2_sess_resp wrong");
312 unsigned char type3
[413] =
313 "\x4e\x54\x4c\x4d\x53\x53\x50\x00\x03\x00\x00\x00\x18\x00\x18\x00"
314 "\x80\x00\x00\x00\x9e\x00\x9e\x00\x98\x00\x00\x00\x14\x00\x14\x00"
315 "\x48\x00\x00\x00\x10\x00\x10\x00\x5c\x00\x00\x00\x14\x00\x14\x00"
316 "\x6c\x00\x00\x00\x00\x00\x00\x00\x36\x01\x00\x00\x05\x82\x88\xa2"
317 "\x05\x01\x28\x0a\x00\x00\x00\x0f\x43\x00\x4f\x00\x4c\x00\x4c\x00"
318 "\x45\x00\x59\x00\x2d\x00\x58\x00\x50\x00\x34\x00\x54\x00\x45\x00"
319 "\x53\x00\x54\x00\x55\x00\x53\x00\x45\x00\x52\x00\x43\x00\x4f\x00"
320 "\x4c\x00\x4c\x00\x45\x00\x59\x00\x2d\x00\x58\x00\x50\x00\x34\x00"
321 "\x2f\x96\xec\x0a\xf7\x9f\x2e\x24\xba\x09\x48\x10\xa5\x22\xd4\xe1"
322 "\x16\x6a\xca\x58\x74\x9a\xc1\x4f\x54\x6f\xee\x40\x96\xce\x43\x6e"
323 "\xdf\x99\x20\x71\x6c\x9a\xda\x2a\x01\x01\x00\x00\x00\x00\x00\x00"
324 "\x8d\xc0\x57\xc9\x79\x5e\xcb\x01\x16\x6a\xca\x58\x74\x9a\xc1\x4f"
325 "\x00\x00\x00\x00\x02\x00\x14\x00\x4e\x00\x55\x00\x54\x00\x43\x00"
326 "\x52\x00\x41\x00\x43\x00\x4b\x00\x45\x00\x52\x00\x01\x00\x14\x00"
327 "\x4e\x00\x55\x00\x54\x00\x43\x00\x52\x00\x41\x00\x43\x00\x4b\x00"
328 "\x45\x00\x52\x00\x04\x00\x12\x00\x61\x00\x70\x00\x70\x00\x6c\x00"
329 "\x65\x00\x2e\x00\x63\x00\x6f\x00\x6d\x00\x03\x00\x20\x00\x68\x00"
330 "\x75\x00\x6d\x00\x6d\x00\x65\x00\x6c\x00\x2e\x00\x61\x00\x70\x00"
331 "\x70\x00\x6c\x00\x65\x00\x2e\x00\x63\x00\x6f\x00\x6d\x00\x00\x00"
332 "\x00\x00\x00\x00\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f"
333 "\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20"
334 "\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x20"
335 "\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x33\x00\x20\x00\x32"
336 "\x00\x36\x00\x30\x00\x30\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64"
337 "\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32"
338 "\x00\x20\x00\x35\x00\x2e\x00\x31\x00\x00\x00\x00\x00";
339 const unsigned char challenge
[8] =
340 "\xe4\x9c\x6a\x12\xe1\xbd\xde\x6a";
341 unsigned char sessionkey
[16];
343 const char key
[16] = "\xD1\x83\x98\x3E\xAE\xA7\xBE\x99\x59\xC8\xF4\xC1\x98\xED\x0E\x68";
345 struct ntlm_buf data
;
346 struct ntlm_type3 t3
;
349 struct ntlm_targetinfo ti
;
351 unsigned char timsg
[114] =
352 "\002\000\024\000N\000U\000T\000C\000R\000A\000C\000K\000E\000R\000\001\000\024\000N\000U\000T\000C\000R\000A\000C\000K\000E\000R\000\004\000\022\000a\000p\000p\000l\000e\000.\000c\000o\000m\000\003\000 \000h\000u\000m\000m\000e\000l\000.\000a\000p\000p\000l\000e\000.\000c\000o\000m\000\000\000\000\000\000\000\000";
356 data
.length
= sizeof(type3
);
358 ret
= heim_ntlm_decode_type3(&data
, 1, &t3
);
360 errx(1, "heim_ntlm_decode_type3");
362 memset(&ti
, 0, sizeof(ti
));
365 data
.length
= sizeof(timsg
);
367 ret
= heim_ntlm_decode_targetinfo(&data
, 1, &ti
);
371 ret
= heim_ntlm_verify_ntlm2(key
, sizeof(key
),
380 errx(1, "verify_ntlmv2");
382 if (sizeof(timsg
) != data
.length
|| memcmp(timsg
, data
.data
, sizeof(timsg
)) != 0)
383 errx(1, "target info wrong: %d != %d",
384 (int)sizeof(timsg
), (int)data
.length
);
386 heim_ntlm_free_type3(&t3
);
387 heim_ntlm_free_targetinfo(&ti
);
393 test_targetinfo(void)
395 struct ntlm_targetinfo ti
;
397 const char *dnsservername
= "dnsservername";
398 const char *targetname
= "targetname";
399 const char z16
[16] = { 0 };
402 memset(&ti
, 0, sizeof(ti
));
404 ti
.dnsservername
= rk_UNCONST(dnsservername
);
406 ti
.targetname
= rk_UNCONST(targetname
);
407 ti
.channel_bindings
.data
= rk_UNCONST(z16
);
408 ti
.channel_bindings
.length
= sizeof(z16
);
410 ret
= heim_ntlm_encode_targetinfo(&ti
, 1, &buf
);
414 memset(&ti
, 0, sizeof(ti
));
416 ret
= heim_ntlm_decode_targetinfo(&buf
, 1, &ti
);
420 if (ti
.dnsservername
== NULL
||
421 strcmp(ti
.dnsservername
, dnsservername
) != 0)
422 errx(1, "ti.dnshostname != %s", dnsservername
);
424 errx(1, "ti.avflags != 1");
425 if (ti
.targetname
== NULL
||
426 strcmp(ti
.targetname
, targetname
) != 0)
427 errx(1, "ti.targetname != %s", targetname
);
429 if (ti
.channel_bindings
.length
!= sizeof(z16
) ||
430 memcmp(ti
.channel_bindings
.data
, z16
, sizeof(z16
)) != 0)
431 errx(1, "ti.channel_bindings != Z(16)");
433 heim_ntlm_free_targetinfo(&ti
);
439 test_string2key(void)
441 const char *pw
= "山田";
444 unsigned char key
[16] = {
445 0xc6, 0x5d, 0xc7, 0x61, 0xa1, 0x34, 0x17, 0xa1,
446 0x17, 0x08, 0x9c, 0x1b, 0xb0, 0x0d, 0x0f, 0x19
449 if (heim_ntlm_nt_key(pw
, &buf
) != 0)
450 errx(1, "heim_ntlmv_nt_key(jp)");
452 if (buf
.length
!= 16 || memcmp(buf
.data
, key
, 16) != 0)
453 errx(1, "compare failed");
455 heim_ntlm_free_buf(&buf
);
464 "\x4e\x54\x4c\x4d\x53\x53\x50\x00\x02\x00\x00\x00\x06\x00\x06\x00"
465 "\x38\x00\x00\x00\x05\x02\x89\x62\x62\x94\xb1\xf3\x56\x80\xb0\xf9"
466 "\x00\x00\x00\x00\x00\x00\x00\x00\x9e\x00\x9e\x00\x3e\x00\x00\x00"
467 "\x06\x01\xb0\x1d\x00\x00\x00\x0f\x43\x00\x4f\x00\x53\x00\x02\x00"
468 "\x06\x00\x43\x00\x4f\x00\x53\x00\x01\x00\x12\x00\x43\x00\x4f\x00"
469 "\x53\x00\x57\x00\x49\x00\x4e\x00\x37\x00\x4a\x00\x50\x00\x04\x00"
470 "\x1a\x00\x63\x00\x6f\x00\x73\x00\x2e\x00\x61\x00\x70\x00\x70\x00"
471 "\x6c\x00\x65\x00\x2e\x00\x63\x00\x6f\x00\x6d\x00\x03\x00\x2e\x00"
472 "\x63\x00\x6f\x00\x73\x00\x77\x00\x69\x00\x6e\x00\x37\x00\x6a\x00"
473 "\x70\x00\x2e\x00\x63\x00\x6f\x00\x73\x00\x2e\x00\x61\x00\x70\x00"
474 "\x70\x00\x6c\x00\x65\x00\x2e\x00\x63\x00\x6f\x00\x6d\x00\x05\x00"
475 "\x1a\x00\x63\x00\x6f\x00\x73\x00\x2e\x00\x61\x00\x70\x00\x70\x00"
476 "\x6c\x00\x65\x00\x2e\x00\x63\x00\x6f\x00\x6d\x00\x07\x00\x08\x00"
477 "\x94\x51\xf0\xbd\xdc\x61\xcb\x01\x00\x00\x00\x00";
480 "\x4e\x54\x4c\x4d\x53\x53\x50\x00\x03\x00\x00\x00\x18\x00\x18\x00"
481 "\x74\x00\x00\x00\xce\x00\xce\x00\x8c\x00\x00\x00\x1a\x00\x1a\x00"
482 "\x40\x00\x00\x00\x04\x00\x04\x00\x5a\x00\x00\x00\x16\x00\x16\x00"
483 "\x5e\x00\x00\x00\x10\x00\x10\x00\x5a\x01\x00\x00\x05\x02\x89\x62"
484 "\x31\x00\x37\x00\x2e\x00\x32\x00\x30\x00\x31\x00\x2e\x00\x35\x00"
485 "\x37\x00\x2e\x00\x31\x00\x32\x00\x31\x00\x71\x5c\x30\x75\x77\x00"
486 "\x6f\x00\x72\x00\x6b\x00\x73\x00\x74\x00\x61\x00\x74\x00\x69\x00"
487 "\x6f\x00\x6e\x00\xab\xad\xeb\x72\x01\xd4\x5f\xdf\x59\x07\x5f\xa9"
488 "\xfd\x54\x98\x2d\xfa\x17\xbb\xf1\x3c\x8f\xf5\x20\xe6\x8f\xd7\x0a"
489 "\xc9\x19\x3e\x94\x61\x31\xdb\x0f\x55\xe8\xe2\x53\x01\x01\x00\x00"
490 "\x00\x00\x00\x00\x00\x06\x3e\x30\xe4\x61\xcb\x01\x71\x98\x10\x6b"
491 "\x4c\x82\xec\xb3\x00\x00\x00\x00\x02\x00\x06\x00\x43\x00\x4f\x00"
492 "\x53\x00\x01\x00\x12\x00\x43\x00\x4f\x00\x53\x00\x57\x00\x49\x00"
493 "\x4e\x00\x37\x00\x4a\x00\x50\x00\x04\x00\x1a\x00\x63\x00\x6f\x00"
494 "\x73\x00\x2e\x00\x61\x00\x70\x00\x70\x00\x6c\x00\x65\x00\x2e\x00"
495 "\x63\x00\x6f\x00\x6d\x00\x03\x00\x2e\x00\x63\x00\x6f\x00\x73\x00"
496 "\x77\x00\x69\x00\x6e\x00\x37\x00\x6a\x00\x70\x00\x2e\x00\x63\x00"
497 "\x6f\x00\x73\x00\x2e\x00\x61\x00\x70\x00\x70\x00\x6c\x00\x65\x00"
498 "\x2e\x00\x63\x00\x6f\x00\x6d\x00\x05\x00\x1a\x00\x63\x00\x6f\x00"
499 "\x73\x00\x2e\x00\x61\x00\x70\x00\x70\x00\x6c\x00\x65\x00\x2e\x00"
500 "\x63\x00\x6f\x00\x6d\x00\x07\x00\x08\x00\xab\xec\xcc\x30\xe4\x61"
501 "\xcb\x01\x00\x00\x00\x00\x00\x00\x00\x00\xbc\x2e\xba\x3f\xd1\xb1"
502 "\xa7\x70\x00\x9d\x55\xa0\x59\x74\x2b\x78";
505 struct ntlm_type2 type2
;
506 struct ntlm_type3 type3
;
507 struct ntlm_buf data
;
510 data
.length
= sizeof(buf2
);
513 memset(&type2
, 0, sizeof(type2
));
515 ret
= heim_ntlm_decode_type2(&data
, &type2
);
517 errx(1, "heim_ntlm_decode_type2(jp): %d", ret
);
522 ret
= heim_ntlm_encode_type2(&type2
, &data
);
524 errx(1, "heim_ntlm_encode_type2(jp): %d", ret
);
526 heim_ntlm_free_type2(&type2
);
527 heim_ntlm_free_buf(&data
);
529 data
.length
= sizeof(buf3
);
532 memset(&type3
, 0, sizeof(type3
));
534 ret
= heim_ntlm_decode_type3(&data
, 1, &type3
);
536 errx(1, "heim_ntlm_decode_type2(jp): %d", ret
);
541 ret
= heim_ntlm_encode_type3(&type3
, &data
, NULL
);
543 errx(1, "heim_ntlm_decode_type2(jp): %d", ret
);
545 heim_ntlm_free_type3(&type3
);
546 heim_ntlm_free_buf(&data
);
552 static int verbose_flag
= 0;
553 static int version_flag
= 0;
554 static int help_flag
= 0;
556 static struct getargs args
[] = {
557 {"verbose", 0, arg_flag
, &verbose_flag
, "verbose printing", NULL
},
558 {"version", 0, arg_flag
, &version_flag
, "print version", NULL
},
559 {"help", 0, arg_flag
, &help_flag
, NULL
, NULL
}
565 arg_printusage (args
, sizeof(args
)/sizeof(*args
),
571 main(int argc
, char **argv
)
573 int ret
= 0, optidx
= 0;
575 setprogname(argv
[0]);
577 if(getarg(args
, sizeof(args
) / sizeof(args
[0]), argc
, argv
, &optidx
))
589 printf("test_parse\n");
593 printf("test_keys\n");
597 printf("test_ntlm2_session_resp\n");
598 ret
|= test_ntlm2_session_resp();
601 printf("test_targetinfo\n");
602 ret
|= test_targetinfo();
605 printf("test_ntlmv2\n");
606 ret
|= test_ntlmv2();
609 printf("test_string2key\n");
610 ret
|= test_string2key();