tests: more intermediate asserts
[siplcs.git] / src / core / tests.c
blobc0358bc62e80f5bb6e5713c2c796fc8f773894d2
1 /**
2 * @file tests.c
4 * pidgin-sipe
6 * Copyright (C) 2010 pier11 <pier11@operamail.com>
7 * Copyright (C) 2008 Novell, Inc.
9 * Implemented with reference to the follow documentation:
10 * - http://davenport.sourceforge.net/ntlm.html
11 * - MS-NLMP: http://msdn.microsoft.com/en-us/library/cc207842.aspx
12 * - MS-SIP : http://msdn.microsoft.com/en-us/library/cc246115.aspx
14 * Build and run with (adjust as needed to your build platform!)
16 * $ gcc -I /usr/include/libpurple \
17 * -I /usr/include/dbus-1.0 -I /usr/lib/dbus-1.0/include \
18 * -I /usr/include/glib-2.0 -I /usr/lib/glib-2.0/include \
19 * -o tests tests.c sipe-sign.c sipmsg.c sip-sec.c uuid.c -lpurple
20 * ./tests
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 #include <glib.h>
38 #include <stdlib.h>
40 #include "sipe-sign.h"
41 #define _SIPE_COMPILING_TESTS
42 #include "sip-sec-ntlm.c"
44 #ifndef _WIN32
45 #include "dbus-server.h"
46 #endif
48 #include "uuid.h"
50 static int successes = 0;
51 static int failures = 0;
53 static size_t
54 hex_str_to_buff(const char *hex_str, guint8 **bytes)
56 guint8 *buff;
57 char two_digits[3];
58 size_t i;
60 if (!bytes) return 0;
62 gsize length = strlen(hex_str)/2;
63 buff = (guint8 *)g_malloc(length);
64 for (i = 0; i < length; i++) {
65 two_digits[0] = hex_str[i * 2];
66 two_digits[1] = hex_str[i * 2 + 1];
67 two_digits[2] = '\0';
68 buff[i] = (guint8)strtoul(two_digits, NULL, 16);
71 *bytes = buff;
72 return length;
75 static void assert_equal(const char * expected, const guchar * got, int len, gboolean stringify)
77 const gchar * res = (gchar *) got;
78 gchar to_str[len*2];
80 if (stringify) {
81 int i, j;
82 for (i = 0, j = 0; i < len; i++, j+=2) {
83 g_sprintf(&to_str[j], "%02X", (got[i]&0xff));
85 len *= 2;
86 res = to_str;
89 printf("expected: %s\n", expected);
90 printf("received: %s\n", res);
92 if (g_ascii_strncasecmp(expected, res, len) == 0) {
93 successes++;
94 printf("PASSED\n");
95 } else {
96 failures++;
97 printf("FAILED\n");
101 int main()
103 printf ("Starting Tests\n");
105 // Initialization that Pidgin would normally do
106 #ifndef _WIN32
107 g_type_init();
108 #endif
109 purple_signals_init();
110 purple_util_init();
111 purple_debug_init();
112 #ifndef _WIN32
113 purple_dbus_init();
114 #endif
115 purple_ciphers_init();
116 purple_debug_set_enabled(TRUE);
118 /* These tests are from the MS-SIPE document */
120 const char * password = "Password";
121 const char * user = "User";
122 const char * domain = "Domain";
123 const guchar client_challenge [] = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
124 /* server challenge */
125 const guchar nonce [] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
126 /* 16 bytes */
127 const guchar exported_session_key[] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
128 const guchar text [] = {0x50, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x00}; //P·l·a·i·n·t·e·x·t·
131 ////// internal Cyphers tests ///////
132 printf ("\nTesting MD4()\n");
133 guchar md4 [16];
134 MD4 ((const unsigned char *)"message digest", 14, md4);
135 assert_equal("D9130A8164549FE818874806E1C7014B", md4, 16, TRUE);
137 printf ("\nTesting MD5()\n");
138 guchar md5 [16];
139 MD5 ((const unsigned char *)"message digest", 14, md5);
140 assert_equal("F96B697D7CB7938D525A2F31AAF161D0", md5, 16, TRUE);
142 printf ("\nTesting HMAC_MD5()\n");
143 guchar hmac_md5 [16];
144 HMAC_MD5 ((const unsigned char *)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 16, (const unsigned char *)"Hi There", 8, hmac_md5);
145 assert_equal("9294727A3638BB1C13F48EF8158BFC9D", hmac_md5, 16, TRUE);
148 ////// NTLMv1 (without Extended Session Security) ///////
149 use_ntlm_v2 = FALSE;
150 guint32 flags = 0
151 | NTLMSSP_NEGOTIATE_KEY_EXCH
152 | NTLMSSP_NEGOTIATE_56
153 | NTLMSSP_NEGOTIATE_128
154 | NTLMSSP_NEGOTIATE_VERSION
155 | NTLMSSP_TARGET_TYPE_SERVER
156 | NTLMSSP_NEGOTIATE_ALWAYS_SIGN
157 | NTLMSSP_NEGOTIATE_NTLM
158 | NTLMSSP_NEGOTIATE_SEAL
159 | NTLMSSP_NEGOTIATE_SIGN
160 | NTLMSSP_NEGOTIATE_OEM
161 | NTLMSSP_NEGOTIATE_UNICODE;
163 printf ("\n\nTesting Negotiation Flags\n");
164 assert_equal("338202E2", (guchar*)(&flags), 4, TRUE);
166 printf ("\n\nTesting LMOWFv1()\n");
167 guchar response_key_lm [16];
168 LMOWFv1 (password, user, domain, response_key_lm);
169 assert_equal("E52CAC67419A9A224A3B108F3FA6CB6D", response_key_lm, 16, TRUE);
171 printf ("\n\nTesting NTOWFv1()\n");
172 guchar response_key_nt [16];
173 NTOWFv1 (password, user, domain, response_key_nt);
174 assert_equal("A4F49C406510BDCAB6824EE7C30FD852", response_key_nt, 16, TRUE);
176 printf ("\n\nTesting LM Response Generation\n");
177 printf ("Testing NT Response Generation\n");
178 printf ("Testing Session Base Key\n");
179 guchar nt_challenge_response [24];
180 guchar lm_challenge_response [24];
181 guchar session_base_key [16];
183 compute_response(flags,
184 response_key_nt,
185 response_key_lm,
186 nonce,
187 client_challenge,
189 NULL, /* target_info */
190 0, /* target_info_len */
191 lm_challenge_response, /* out */
192 nt_challenge_response, /* out */
193 session_base_key); /* out */
195 assert_equal("98DEF7B87F88AA5DAFE2DF779688A172DEF11C7D5CCDEF13", lm_challenge_response, 24, TRUE);
196 assert_equal("67C43011F30298A2AD35ECE64F16331C44BDBED927841F94", nt_challenge_response, 24, TRUE);
197 assert_equal("D87262B0CDE4B1CB7499BECCCDF10784", session_base_key, 16, TRUE);
199 printf ("\n\nTesting Key Exchange Key\n");
200 guchar key_exchange_key [16];
201 KXKEY(flags, session_base_key, lm_challenge_response, nonce, key_exchange_key);
202 assert_equal("D87262B0CDE4B1CB7499BECCCDF10784", key_exchange_key, 16, TRUE);
204 printf ("\n\nTesting Encrypted Session Key Generation\n");
205 guchar encrypted_random_session_key [16];
206 RC4K (key_exchange_key, 16, exported_session_key, 16, encrypted_random_session_key);
207 assert_equal("518822B1B3F350C8958682ECBB3E3CB7", encrypted_random_session_key, 16, TRUE);
209 printf ("\n\nTesting CRC32\n");
210 guint32 crc = CRC32((char*)text, 18);
211 assert_equal("7D84AA93", (guchar *)&crc, 4, TRUE);
213 printf ("\n\nTesting Encryption\n");
214 guchar client_seal_key [16];
215 //SEALKEY (flags, exported_session_key, TRUE, client_seal_key);
216 guchar buff [18 + 12];
217 memcpy(buff, text, 18);
218 guchar text_enc [18 + 12];
219 guint32 to_enc [3];
220 to_enc[0] = GUINT32_TO_LE(0); // random pad
221 to_enc[1] = GUINT32_TO_LE(crc);
222 to_enc[2] = GUINT32_TO_LE(0); // zero
223 memcpy(buff+18, (gchar *)to_enc, 12);
224 RC4K (exported_session_key, 16, buff, 18 + 12, text_enc);
225 //The point is to not reinitialize rc4 cypher
226 // 0 crc 0 (zero)
227 assert_equal("56FE04D861F9319AF0D7238A2E3B4D457FB8" "45C844E5" "09DCD1DF" "2E459D36", text_enc, 18 + 12, TRUE);
229 printf ("\n\nTesting MAC\n");
230 // won't work in the case with sealing because RC4 is re-initialized inside.
231 //gchar *mac = MAC (flags, (gchar*)text, 18, (guchar*)exported_session_key, 16, (guchar*)exported_session_key,16, 0x00000000, 0);
232 guint32 enc [3];
233 memcpy((gchar *)enc, text_enc+18, 12);
234 guint32 mac2 [4];
235 mac2 [0] = GUINT32_TO_LE(1); // version
236 mac2 [1] = enc [0];
237 mac2 [2] = enc [1];
238 mac2 [3] = enc [2] ^ (GUINT32_TO_LE(0)); // ^ seq
239 assert_equal("0100000045C844E509DCD1DF2E459D36", (guchar*)mac2, 16, TRUE);
242 ////// EXTENDED_SESSIONSECURITY ///////
243 use_ntlm_v2 = FALSE;
244 flags = 0
245 | NTLMSSP_NEGOTIATE_56
246 | NTLMSSP_NEGOTIATE_VERSION
247 | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
248 | NTLMSSP_TARGET_TYPE_SERVER
249 | NTLMSSP_NEGOTIATE_ALWAYS_SIGN
250 | NTLMSSP_NEGOTIATE_NTLM
251 | NTLMSSP_NEGOTIATE_SEAL
252 | NTLMSSP_NEGOTIATE_SIGN
253 | NTLMSSP_NEGOTIATE_OEM
254 | NTLMSSP_NEGOTIATE_UNICODE;
256 printf ("\n\n(Extended session security) Testing Negotiation Flags\n");
257 assert_equal("33820A82", (guchar*)(&flags), 4, TRUE);
259 /* NTOWFv1() is not different from the above test for the same */
261 printf ("\n\n(Extended session security) Testing LM Response\n");
262 printf ("(Extended session security) Testing NT Response\n");
263 printf ("(Extended session security) Testing Session Base Key\n");
264 compute_response(flags,
265 response_key_nt,
266 response_key_lm,
267 nonce,
268 client_challenge,
270 NULL, /* target_info */
271 0, /* target_info_len */
272 lm_challenge_response, /* out */
273 nt_challenge_response, /* out */
274 session_base_key); /* out */
276 assert_equal("AAAAAAAAAAAAAAAA00000000000000000000000000000000", lm_challenge_response, 24, TRUE);
277 assert_equal("7537F803AE367128CA458204BDE7CAF81E97ED2683267232", nt_challenge_response, 24, TRUE);
278 assert_equal("D87262B0CDE4B1CB7499BECCCDF10784", session_base_key, 16, TRUE);
280 printf ("\n\n(Extended session security) Testing Key Exchange Key\n");
281 KXKEY(flags, session_base_key, lm_challenge_response, nonce, key_exchange_key);
282 assert_equal("EB93429A8BD952F8B89C55B87F475EDC", key_exchange_key, 16, TRUE);
284 printf ("\n\n(Extended session security) SIGNKEY\n");
285 guchar client_sign_key [16];
286 SIGNKEY (key_exchange_key, TRUE, client_sign_key);
287 assert_equal("60E799BE5C72FC92922AE8EBE961FB8D", client_sign_key, 16, TRUE);
289 printf ("\n\n(Extended session security) SEALKEY\n");
290 SEALKEY (flags, key_exchange_key, TRUE, client_seal_key);
291 assert_equal("04DD7F014D8504D265A25CC86A3A7C06", client_seal_key, 16, TRUE);
293 printf ("\n\n(Extended session security) Testing Encryption\n");
294 RC4K (client_seal_key, 16, text, 18, text_enc);
295 assert_equal("A02372F6530273F3AA1EB90190CE5200C99D", text_enc, 18, TRUE);
297 printf ("\n\n(Extended session security) Testing MAC\n");
298 gchar *mac = MAC (flags, (gchar*)text,18, client_sign_key,16, client_seal_key,16, 0, 0);
299 assert_equal("01000000FF2AEB52F681793A00000000", (guchar*)mac, 32, FALSE);
300 g_free(mac);
303 ////// NTLMv2 ///////
304 use_ntlm_v2 = TRUE;
305 flags = 0
306 | NTLMSSP_NEGOTIATE_KEY_EXCH
307 | NTLMSSP_NEGOTIATE_56
308 | NTLMSSP_NEGOTIATE_128
309 | NTLMSSP_NEGOTIATE_VERSION
310 | NTLMSSP_NEGOTIATE_TARGET_INFO
311 | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
312 | NTLMSSP_TARGET_TYPE_SERVER
313 | NTLMSSP_NEGOTIATE_ALWAYS_SIGN
314 | NTLMSSP_NEGOTIATE_NTLM
315 | NTLMSSP_NEGOTIATE_SEAL
316 | NTLMSSP_NEGOTIATE_SIGN
317 | NTLMSSP_NEGOTIATE_OEM
318 | NTLMSSP_NEGOTIATE_UNICODE;
320 printf ("\n\nTesting (NTLMv2) Negotiation Flags\n");
321 assert_equal("33828AE2", (guchar*)(&flags), 4, TRUE);
323 printf ("\n\nTesting NTOWFv2()\n");
324 NTOWFv2 (password, user, domain, response_key_nt);
325 NTOWFv2 (password, user, domain, response_key_lm);
326 assert_equal("0C868A403BFD7A93A3001EF22EF02E3F", response_key_nt, 16, TRUE);
329 printf ("\n\nTesting (NTLMv2) LM Response Generation\n");
330 printf ("Testing (NTLMv2) NT Response Generation and Session Base Key\n");
332 Challenge:
333 4e544c4d53535000020000000c000c003800000033828ae20123456789abcdef00000000000000002400240044000000060070170000000f53006500720076006500720002000c0044006f006d00610069006e0001000c0053006500720076006500720000000000
335 NTLMSSP_NEGOTIATE_UNICODE
336 NTLMSSP_NEGOTIATE_OEM
337 NTLMSSP_NEGOTIATE_SIGN
338 NTLMSSP_NEGOTIATE_SEAL
339 NTLMSSP_NEGOTIATE_NTLM
340 NTLMSSP_NEGOTIATE_ALWAYS_SIGN
341 NTLMSSP_TARGET_TYPE_SERVER
342 NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
343 NTLMSSP_NEGOTIATE_TARGET_INFO
344 NTLMSSP_NEGOTIATE_VERSION
345 NTLMSSP_NEGOTIATE_128
346 NTLMSSP_NEGOTIATE_KEY_EXCH
347 NTLMSSP_NEGOTIATE_56
348 target_name.len : 12
349 target_name.maxlen: 12
350 target_name.offset: 56
351 target_info.len : 36
352 target_info.maxlen: 36
353 target_info.offset: 68
354 product: 6.0.6000 (Windows Vista, Windows Server 2008, Windows 7 or Windows Server 2008 R2)
355 ntlm_revision_current: 0x0F (NTLMSSP_REVISION_W2K3)
356 target_name: Server
357 MsvAvNbDomainName: Domain
358 MsvAvNbComputerName: Server
360 target_name:
361 530065007200760065007200
362 target_info:
363 02000c0044006f006d00610069006e0001000c0053006500720076006500720000000000
365 Response:
366 4e544c4d5353500003000000180018006c00000054005400840000000c000c00480000000800080054000000100010005c00000010001000d8000000358288e20501280a0000000f44006f006d00610069006e00550073006500720043004f004d005000550054004500520086c35097ac9cec102554764a57cccc19aaaaaaaaaaaaaaaa68cd0ab851e51c96aabc927bebef6a1c01010000000000000000000000000000aaaaaaaaaaaaaaaa0000000002000c0044006f006d00610069006e0001000c005300650072007600650072000000000000000000c5dad2544fc9799094ce1ce90bc9d03e
370 const guint64 time_val = 0;
371 const guint8 target_info [] = {
372 0x02, 0x00, 0x0C, 0x00, //NetBIOS Domain name, 4 bytes
373 0x44, 0x00, 0x6F, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6E, 0x00, //D.o.m.a.i.n. 12bytes
374 0x01, 0x00, 0x0C, 0x00, //NetBIOS Server name, 4 bytes
375 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, //S.e.r.v.e.r. 12bytes
376 0x00, 0x00, 0x00, 0x00, //Av End, 4 bytes
378 const int target_info_len = 32+4;
379 int ntlmssp_nt_resp_len = (16 + (32+target_info_len));
380 guchar nt_challenge_response_v2 [ntlmssp_nt_resp_len];
382 compute_response(flags,
383 response_key_nt,
384 response_key_lm,
385 nonce,
386 client_challenge,
387 time_val,
388 target_info, /* target_info */
389 target_info_len, /* target_info_len */
390 lm_challenge_response, /* out */
391 nt_challenge_response_v2, /* out */
392 session_base_key); /* out */
394 assert_equal("86C35097AC9CEC102554764A57CCCC19AAAAAAAAAAAAAAAA", lm_challenge_response, 24, TRUE);
395 assert_equal("68CD0AB851E51C96AABC927BEBEF6A1C", nt_challenge_response_v2, 16, TRUE);
396 /* the ref string is taken from binary dump of AUTHENTICATE_MESSAGE */
397 assert_equal("68CD0AB851E51C96AABC927BEBEF6A1C01010000000000000000000000000000AAAAAAAAAAAAAAAA0000000002000C0044006F006D00610069006E0001000C005300650072007600650072000000000000000000", nt_challenge_response_v2, ntlmssp_nt_resp_len, TRUE);
398 assert_equal("8DE40CCADBC14A82F15CB0AD0DE95CA3", session_base_key, 16, TRUE);
400 printf ("\n\nTesting (NTLMv2) Encrypted Session Key\n");
401 // key_exchange_key = session_base_key for NTLMv2
402 KXKEY(flags, session_base_key, lm_challenge_response, nonce, key_exchange_key);
403 //RC4 encryption of the RandomSessionKey with the KeyExchangeKey:
404 RC4K (key_exchange_key, 16, exported_session_key, 16, encrypted_random_session_key);
405 assert_equal("C5DAD2544FC9799094CE1CE90BC9D03E", encrypted_random_session_key, 16, TRUE);
407 printf ("\n\nTesting (NTLMv2) SIGNKEY\n");
408 SIGNKEY (exported_session_key, TRUE, client_sign_key);
409 assert_equal("4788DC861B4782F35D43FD98FE1A2D39", client_sign_key, 16, TRUE);
411 printf ("\n\nTesting (NTLMv2) SEALKEY\n");
412 SEALKEY (flags, exported_session_key, TRUE, client_seal_key);
413 assert_equal("59F600973CC4960A25480A7C196E4C58", client_seal_key, 16, TRUE);
415 printf ("\n\nTesting (NTLMv2) Encryption\n");
416 RC4K (client_seal_key, 16, text, 18, text_enc);
417 assert_equal("54E50165BF1936DC996020C1811B0F06FB5F", text_enc, 18, TRUE);
419 // printf ("\n\nTesting (NTLMv2) Encryption\n");
420 //const guchar text2 [] = {0x50, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x00
421 // , 0x70, 0x35, 0x28, 0x51, 0xf2, 0x56, 0x43, 0x09}; //P·l·a·i·n·t·e·x·t·
422 //guchar text_enc2 [18+8];
423 // RC4K (client_seal_key, 16, text2, 18+8, text_enc2);
424 // assert_equal("54E50165BF1936DC996020C1811B0F06FB5F", text_enc2, 18+8, TRUE);
426 printf ("\n\nTesting (NTLMv2) MAC (without RC4, as we don't keep its handle yet)\n");
427 mac = MAC (flags & ~NTLMSSP_NEGOTIATE_KEY_EXCH, (gchar*)text,18, client_sign_key,16, client_seal_key,16, 0, 0);
428 assert_equal("0100000070352851F256430900000000", (guchar*)mac, 32, FALSE);
429 g_free(mac);
432 /* End tests from the MS-SIPE document */
435 ////// davenport tests ///////
436 // Test from http://davenport.sourceforge.net/ntlm.html#ntlm1Signing
437 const gchar *text_j = "jCIFS";
438 printf ("\n\n(davenport) Testing Signature Algorithm\n");
439 guchar sk [] = {0x01, 0x02, 0x03, 0x04, 0x05, 0xe5, 0x38, 0xb0};
440 assert_equal (
441 "0100000078010900397420FE0E5A0F89",
442 (guchar *) MAC(NEGOTIATE_FLAGS & ~NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY, text_j, strlen(text_j), sk, 8, sk,8, 0x00090178, 0),
443 32, FALSE
446 // Tests from http://davenport.sourceforge.net/ntlm.html#ntlm2Signing
447 printf ("\n\n(davenport) SIGNKEY\n");
448 const guchar master_key [] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00};
449 SIGNKEY (master_key, TRUE, client_sign_key);
450 assert_equal("F7F97A82EC390F9C903DAC4F6ACEB132", client_sign_key, 16, TRUE);
452 printf ("\n\n(davenport) Testing MAC - no Key Exchange flag\n");
453 mac = MAC (flags & ~NTLMSSP_NEGOTIATE_KEY_EXCH, text_j, strlen(text_j), client_sign_key, 16, client_sign_key,16, 0, 0);
454 assert_equal("010000000A003602317A759A00000000", (guchar*)mac, 32, FALSE);
455 g_free(mac);
458 ////// SIPE internal tests ///////
459 // Verify signature of SIPE message received from OCS 2007 after authenticating with pidgin-sipe
460 printf ("\n\nTesting MS-SIPE Example Message Signing\n");
461 char * msg1 = "<NTLM><0878F41B><1><SIP Communications Service><ocs1.ocs.provo.novell.com><8592g5DCBa1694i5887m0D0Bt2247b3F38xAE9Fx><3><REGISTER><sip:gabriel@ocs.provo.novell.com><2947328781><B816D65C2300A32CFA6D371F2AF537FD><900><200>";
462 guchar exported_session_key2 [] = { 0x5F, 0x02, 0x91, 0x53, 0xBC, 0x02, 0x50, 0x58, 0x96, 0x95, 0x48, 0x61, 0x5E, 0x70, 0x99, 0xBA };
463 assert_equal (
464 "0100000000000000BF2E52667DDF6DED",
465 (guchar *) MAC(NEGOTIATE_FLAGS & ~NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY, msg1, strlen(msg1), exported_session_key2, 16, exported_session_key2,16, 0, 100),
466 32, FALSE
469 // Verify parsing of message and signature verification
470 printf ("\n\nTesting MS-SIPE Example Message Parsing, Signing, and Verification\n(Authentication Protocol Version 2)\n");
471 char * msg2 = "SIP/2.0 200 OK\r\nms-keep-alive: UAS; tcp=no; hop-hop=yes; end-end=no; timeout=300\r\nAuthentication-Info: NTLM rspauth=\"0100000000000000BF2E52667DDF6DED\", srand=\"0878F41B\", snum=\"1\", opaque=\"4452DFB0\", qop=\"auth\", targetname=\"ocs1.ocs.provo.novell.com\", realm=\"SIP Communications Service\"\r\nFrom: \"Gabriel Burt\"<sip:gabriel@ocs.provo.novell.com>;tag=2947328781;epid=1234567890\r\nTo: <sip:gabriel@ocs.provo.novell.com>;tag=B816D65C2300A32CFA6D371F2AF537FD\r\nCall-ID: 8592g5DCBa1694i5887m0D0Bt2247b3F38xAE9Fx\r\nCSeq: 3 REGISTER\r\nVia: SIP/2.0/TLS 164.99.194.49:10409;branch=z9hG4bKE0E37DBAF252C3255BAD;received=164.99.195.20;ms-received-port=10409;ms-received-cid=1E00\r\nContact: <sip:164.99.195.20:10409;transport=tls;ms-received-cid=1E00>;expires=900\r\nExpires: 900\r\nAllow-Events: vnd-microsoft-provisioning,vnd-microsoft-roaming-contacts,vnd-microsoft-roaming-ACL,presence,presence.wpending,vnd-microsoft-roaming-self,vnd-microsoft-provisioning-v2\r\nSupported: adhoclist\r\nServer: RTC/3.0\r\nSupported: com.microsoft.msrtc.presence\r\nContent-Length: 0\r\n\r\n";
472 struct sipmsg * msg = sipmsg_parse_msg(msg2);
473 struct sipmsg_breakdown msgbd;
474 msgbd.msg = msg;
475 sipmsg_breakdown_parse(&msgbd, "SIP Communications Service", "ocs1.ocs.provo.novell.com");
476 gchar * msg_str = sipmsg_breakdown_get_string(2, &msgbd);
477 gchar * sig = sip_sec_ntlm_sipe_signature_make (NEGOTIATE_FLAGS & ~NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY, msg_str, 0, exported_session_key2, exported_session_key2);
478 sipmsg_breakdown_free(&msgbd);
479 assert_equal ("0100000000000000BF2E52667DDF6DED", (guchar *) sig, 32, FALSE);
480 printf("purple_ntlm_verify_signature result = %i\n", sip_sec_ntlm_verify_signature (sig, "0100000000000000BF2E52667DDF6DED"));
483 ////// real Communicator 2007 R2 tests //////
484 ////// Recreated/verifyed real authentication communication between
485 ////// Communicator 2007 R2 and Office Communications Server 2007 R2
486 ////// with SIPE NTLMv2 implementation.
488 const char *password2 = "Pa$$word";
489 const char *user2 = "User";
490 const char *domain2 = "COSMO";
492 //Challenge:
493 //TlRMTVNTUAACAAAAAAAAADgAAADzgpji3Ruq9OfiGNEAAAAAAAAAAJYAlgA4AAAABQLODgAAAA8CAAoAQwBPAFMATQBPAAEAGABDAE8AUwBNAE8ALQBPAEMAUwAtAFIAMgAEABYAYwBvAHMAbQBvAC4AbABvAGMAYQBsAAMAMABjAG8AcwBtAG8ALQBvAGMAcwAtAHIAMgAuAGMAbwBzAG0AbwAuAGwAbwBjAGEAbAAFABYAYwBvAHMAbQBvAC4AbABvAGMAYQBsAAAAAAA=
495 Message (length 206):
496 NTLMSSP_NEGOTIATE_UNICODE
497 NTLMSSP_NEGOTIATE_OEM
498 NTLMSSP_NEGOTIATE_SIGN
499 NTLMSSP_NEGOTIATE_SEAL
500 NTLMSSP_NEGOTIATE_DATAGRAM
501 NTLMSSP_NEGOTIATE_LM_KEY
502 NTLMSSP_NEGOTIATE_NTLM
503 NTLMSSP_NEGOTIATE_ALWAYS_SIGN
504 NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
505 NTLMSSP_NEGOTIATE_IDENTIFY
506 NTLMSSP_NEGOTIATE_TARGET_INFO
507 NTLMSSP_NEGOTIATE_VERSION
508 NTLMSSP_NEGOTIATE_128
509 NTLMSSP_NEGOTIATE_KEY_EXCH
510 NTLMSSP_NEGOTIATE_56
511 server_challenge: DD1BAAF4E7E218D1
512 target_name.len : 0
513 target_name.maxlen: 0
514 target_name.offset: 56
515 target_info.len : 150
516 target_info.maxlen: 150
517 target_info.offset: 56
518 product: 5.2.3790 (Windows Server 2003)
519 ntlm_revision_current: 0x0F (NTLMSSP_REVISION_W2K3)
520 target_info raw: 02000A0043004F0053004D004F000100180043004F0053004D004F002D004F00430053002D00520032000400160063006F0073006D006F002E006C006F00630061006C000300300063006F0073006D006F002D006F00630073002D00720032002E0063006F0073006D006F002E006C006F00630061006C000500160063006F0073006D006F002E006C006F00630061006C0000000000
521 MsvAvNbDomainName: COSMO
522 MsvAvNbComputerName: COSMO-OCS-R2
523 MsvAvDnsDomainName: cosmo.local
524 MsvAvDnsComputerName: cosmo-ocs-r2.cosmo.local
525 MsvAvDnsTreeName: cosmo.local
529 //Response:
530 //TlRMTVNTUAADAAAAGAAYAHIAAADGAMYAigAAAAoACgBIAAAACAAIAFIAAAAYABgAWgAAABAAEABQAQAAVYKYYgUCzg4AAAAPQwBPAFMATQBPAFUAcwBlAHIAQwBPAFMATQBPAC0ATwBDAFMALQBSADIAoeku/k4Hi/fFwASazGFmwtauh1yw/apBjcDIAK527KYG0rn769BHMQEBAAAAAAAAWVGaFye5ygHWrodcsP2qQQAAAAACAAoAQwBPAFMATQBPAAEAGABDAE8AUwBNAE8ALQBPAEMAUwAtAFIAMgAEABYAYwBvAHMAbQBvAC4AbABvAGMAYQBsAAMAMABjAG8AcwBtAG8ALQBvAGMAcwAtAHIAMgAuAGMAbwBzAG0AbwAuAGwAbwBjAGEAbAAFABYAYwBvAHMAbQBvAC4AbABvAGMAYQBsAAAAAAAAAAAAMctznhyoCkmFkeiueXEV5A==
532 Message (length 352):
533 NTLMSSP_NEGOTIATE_UNICODE
534 NTLMSSP_REQUEST_TARGET
535 NTLMSSP_NEGOTIATE_SIGN
536 NTLMSSP_NEGOTIATE_DATAGRAM
537 NTLMSSP_NEGOTIATE_NTLM
538 NTLMSSP_NEGOTIATE_ALWAYS_SIGN
539 NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
540 NTLMSSP_NEGOTIATE_IDENTIFY
541 NTLMSSP_NEGOTIATE_TARGET_INFO
542 NTLMSSP_NEGOTIATE_VERSION
543 NTLMSSP_NEGOTIATE_128
544 NTLMSSP_NEGOTIATE_KEY_EXCH
545 lm_resp.len : 24
546 lm_resp.maxlen: 24
547 lm_resp.offset: 114
548 nt_resp.len : 198
549 nt_resp.maxlen: 198
550 nt_resp.offset: 138
551 domain.len : 10
552 domain.maxlen: 10
553 domain.offset: 72
554 user.len : 8
555 user.maxlen: 8
556 user.offset: 82
557 host.len : 24
558 host.maxlen: 24
559 host.offset: 90
560 session_key.len : 16
561 session_key.maxlen: 16
562 session_key.offset: 336
563 product: 5.2.3790 (Windows Server 2003)
564 ntlm_revision_current: 0x0F (NTLMSSP_REVISION_W2K3)
565 lm_resp: A1E92EFE4E078BF7C5C0049ACC6166C2D6AE875CB0FDAA41
566 nt_resp raw: 8DC0C800AE76ECA606D2B9FBEBD04731010100000000000059519A1727B9CA01D6AE875CB0FDAA410000000002000A0043004F0053004D004F000100180043004F0053004D004F002D004F00430053002D00520032000400160063006F0073006D006F002E006C006F00630061006C000300300063006F0073006D006F002D006F00630073002D00720032002E0063006F0073006D006F002E006C006F00630061006C000500160063006F0073006D006F002E006C006F00630061006C000000000000000000
567 nt_resp: 8DC0C800AE76ECA606D2B9FBEBD04731
568 target_info raw: 02000A0043004F0053004D004F000100180043004F0053004D004F002D004F00430053002D00520032000400160063006F0073006D006F002E006C006F00630061006C000300300063006F0073006D006F002D006F00630073002D00720032002E0063006F0073006D006F002E006C006F00630061006C000500160063006F0073006D006F002E006C006F00630061006C0000000000
569 response_version: 1
570 hi_response_version: 1
571 time: 59519A1727B9CA01 - Mon Mar 01 10:08:08 2010
572 client_challenge: D6AE875CB0FDAA41
573 MsvAvNbDomainName: COSMO
574 MsvAvNbComputerName: COSMO-OCS-R2
575 MsvAvDnsDomainName: cosmo.local
576 MsvAvDnsComputerName: cosmo-ocs-r2.cosmo.local
577 MsvAvDnsTreeName: cosmo.local
578 ----------- end of nt_resp v2 -----------
579 domain: COSMO
580 user: User
581 host: COSMO-OCS-R2
582 session_key: 31CB739E1CA80A498591E8AE797115E4
585 const char *request =
586 "REGISTER sip:cosmo.local SIP/2.0\r\n"
587 "Via: SIP/2.0/TLS 192.168.172.6:12723\r\n"
588 "Max-Forwards: 70\r\n"
589 "From: <sip:user@cosmo.local>;tag=3e49177a52;epid=c8ca638a15\r\n"
590 "To: <sip:user@cosmo.local>\r\n"
591 "Call-ID: 4037df9284354df39065195bd57a4b14\r\n"
592 "CSeq: 3 REGISTER\r\n"
593 "Contact: <sip:192.168.172.6:12723;transport=tls;ms-opaque=fad3dfab32>;methods=\"INVITE, MESSAGE, INFO, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER, BENOTIFY\";proxy=replace;+sip.instance=\"<urn:uuid:34D859DB-6585-5F91-A3B4-DE853C15347D>\"\r\n"
594 "User-Agent: UCCAPI/3.5.6907.0 OC/3.5.6907.0 (Microsoft Office Communicator 2007 R2)\r\n"
595 "Supported: gruu-10, adhoclist, msrtc-event-categories\r\n"
596 "Supported: ms-forking\r\n"
597 "ms-keep-alive: UAC;hop-hop=yes\r\n"
598 "Event: registration\r\n"
599 "Proxy-Authorization: NTLM qop=\"auth\", realm=\"SIP Communications Service\", opaque=\"2BDBAC9D\", targetname=\"cosmo-ocs-r2.cosmo.local\", version=4, gssapi-data=\"TlRMTVNTUAADAAAAGAAYAHIAAADGAMYAigAAAAoACgBIAAAACAAIAFIAAAAYABgAWgAAABAAEABQAQAAVYKYYgUCzg4AAAAPQwBPAFMATQBPAFUAcwBlAHIAQwBPAFMATQBPAC0ATwBDAFMALQBSADIAoeku/k4Hi/fFwASazGFmwtauh1yw/apBjcDIAK527KYG0rn769BHMQEBAAAAAAAAWVGaFye5ygHWrodcsP2qQQAAAAACAAoAQwBPAFMATQBPAAEAGABDAE8AUwBNAE8ALQBPAEMAUwAtAFIAMgAEABYAYwBvAHMAbQBvAC4AbABvAGMAYQBsAAMAMABjAG8AcwBtAG8ALQBvAGMAcwAtAHIAMgAuAGMAbwBzAG0AbwAuAGwAbwBjAGEAbAAFABYAYwBvAHMAbQBvAC4AbABvAGMAYQBsAAAAAAAAAAAAMctznhyoCkmFkeiueXEV5A==\", crand=\"13317733\", cnum=\"1\", response=\"0100000029618e9651b65a7764000000\"\r\n"
600 "Content-Length: 0\r\n"
601 "\r\n";
603 const guchar *request_sig = "<NTLM><13317733><1><SIP Communications Service><cosmo-ocs-r2.cosmo.local><4037df9284354df39065195bd57a4b14><3><REGISTER><sip:user@cosmo.local><3e49177a52><sip:user@cosmo.local><><><><>";
604 //Signature:
605 //0100000029618e9651b65a7764000000
607 const char *response =
608 "SIP/2.0 200 OK\r\n"
609 "ms-keep-alive: UAS; tcp=no; hop-hop=yes; end-end=no; timeout=300\r\n"
610 "Authentication-Info: NTLM rspauth=\"01000000E615438A917661BE64000000\", srand=\"9616454F\", snum=\"1\", opaque=\"2BDBAC9D\", qop=\"auth\", targetname=\"cosmo-ocs-r2.cosmo.local\", realm=\"SIP Communications Service\"\r\n"
611 "From: \"User\"<sip:user@cosmo.local>;tag=3e49177a52;epid=c8ca638a15\r\n"
612 "To: <sip:user@cosmo.local>;tag=5E61CCD925D17E043D9A74835A88F664\r\n"
613 "Call-ID: 4037df9284354df39065195bd57a4b14\r\n"
614 "CSeq: 3 REGISTER\r\n"
615 "Via: SIP/2.0/TLS 192.168.172.6:12723;ms-received-port=12723;ms-received-cid=2600\r\n"
616 "Contact: <sip:192.168.172.6:12723;transport=tls;ms-opaque=fad3dfab32;ms-received-cid=2600>;expires=7200;+sip.instance=\"<urn:uuid:34d859db-6585-5f91-a3b4-de853c15347d>\";gruu=\"sip:user@cosmo.local;opaque=user:epid:21nYNIVlkV-jtN6FPBU0fQAA;gruu\"\r\n"
617 "Expires: 7200\r\n"
618 "presence-state: register-action=\"added\"\r\n"
619 "Allow-Events: vnd-microsoft-provisioning,vnd-microsoft-roaming-contacts,vnd-microsoft-roaming-ACL,presence,presence.wpending,vnd-microsoft-roaming-self,vnd-microsoft-provisioning-v2\r\n"
620 "Supported: adhoclist\r\n"
621 "Server: RTC/3.5\r\n"
622 "Supported: msrtc-event-categories\r\n"
623 "Content-Length: 0\r\n"
624 "\r\n";
626 const guchar *response_sig = "<NTLM><9616454F><1><SIP Communications Service><cosmo-ocs-r2.cosmo.local><4037df9284354df39065195bd57a4b14><3><REGISTER><sip:user@cosmo.local><3e49177a52><sip:user@cosmo.local><5E61CCD925D17E043D9A74835A88F664><><><7200><200>";
627 //Signature:
628 //01000000E615438A917661BE64000000
630 use_ntlm_v2 = TRUE;
631 flags = 0
632 | NTLMSSP_NEGOTIATE_UNICODE
633 | NTLMSSP_REQUEST_TARGET
634 | NTLMSSP_NEGOTIATE_SIGN
635 | NTLMSSP_NEGOTIATE_DATAGRAM
636 | NTLMSSP_NEGOTIATE_NTLM
637 | NTLMSSP_NEGOTIATE_ALWAYS_SIGN
638 | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
639 | NTLMSSP_NEGOTIATE_IDENTIFY
640 | NTLMSSP_NEGOTIATE_TARGET_INFO
641 | NTLMSSP_NEGOTIATE_VERSION
642 | NTLMSSP_NEGOTIATE_128
643 | NTLMSSP_NEGOTIATE_KEY_EXCH;
645 NTOWFv2 (password2, user2, domain2, response_key_nt);
646 NTOWFv2 (password2, user2, domain2, response_key_lm);
648 guint8 *buff2;
649 hex_str_to_buff("59519A1727B9CA01", &buff2);
650 const guint64 time_val2 = GUINT64_FROM_LE(*((guint64 *)buff2));
651 g_free(buff2);
653 guint8 *target_info2;
654 const int target_info2_len = hex_str_to_buff("02000A0043004F0053004D004F000100180043004F0053004D004F002D004F00430053002D00520032000400160063006F0073006D006F002E006C006F00630061006C000300300063006F0073006D006F002D006F00630073002D00720032002E0063006F0073006D006F002E006C006F00630061006C000500160063006F0073006D006F002E006C006F00630061006C0000000000", &target_info2);
656 guint8 *nonce2;
657 hex_str_to_buff("DD1BAAF4E7E218D1", &nonce2);
659 guint8 *client_challenge2;
660 hex_str_to_buff("D6AE875CB0FDAA41", &client_challenge2);
662 ntlmssp_nt_resp_len = (16 + (32+target_info2_len));
663 guchar nt_challenge_response_v2_2 [ntlmssp_nt_resp_len];
665 printf ("\n\nTesting (NTLMv2 / OC 2007 R2) LM Response Generation\n");
666 printf ( "Testing (NTLMv2 / OC 2007 R2) NT Response Generation\n");
667 compute_response(flags,
668 response_key_nt,
669 response_key_lm,
670 nonce2,
671 client_challenge2,
672 time_val2,
673 target_info2, /* target_info */
674 target_info2_len, /* target_info_len */
675 lm_challenge_response, /* out */
676 nt_challenge_response_v2_2, /* out */
677 session_base_key); /* out */
678 g_free(client_challenge2);
679 g_free(nonce2);
680 g_free(target_info2);
682 assert_equal("A1E92EFE4E078BF7C5C0049ACC6166C2D6AE875CB0FDAA41", lm_challenge_response, 24, TRUE);
683 assert_equal("8DC0C800AE76ECA606D2B9FBEBD04731", nt_challenge_response_v2_2, 16, TRUE);
684 /* the ref string is taken from binary dump of AUTHENTICATE_MESSAGE */
685 assert_equal("8DC0C800AE76ECA606D2B9FBEBD04731010100000000000059519A1727B9CA01D6AE875CB0FDAA410000000002000A0043004F0053004D004F000100180043004F0053004D004F002D004F00430053002D00520032000400160063006F0073006D006F002E006C006F00630061006C000300300063006F0073006D006F002D006F00630073002D00720032002E0063006F0073006D006F002E006C006F00630061006C000500160063006F0073006D006F002E006C006F00630061006C000000000000000000", nt_challenge_response_v2_2, ntlmssp_nt_resp_len, TRUE);
687 KXKEY(flags, session_base_key, lm_challenge_response, nonce2, key_exchange_key);
688 //as in the Type3 message
689 guint8 *encrypted_random_session_key2;
690 hex_str_to_buff("31CB739E1CA80A498591E8AE797115E4", &encrypted_random_session_key2);
691 guchar exported_session_key3[16];
692 //decoding exported_session_key
693 RC4K (key_exchange_key, 16, encrypted_random_session_key2, 16, exported_session_key3);
694 g_free(encrypted_random_session_key2);
696 guchar server_sign_key [16];
697 guchar server_seal_key [16];
698 SIGNKEY (exported_session_key3, TRUE, client_sign_key);
699 SEALKEY (flags, exported_session_key3, TRUE, client_seal_key);
700 SIGNKEY (exported_session_key3, FALSE, server_sign_key);
701 SEALKEY (flags, exported_session_key3, FALSE, server_seal_key);
703 printf ("\n\nTesting (NTLMv2 / OC 2007 R2) Message Parsing, Signing, and Verification\nClient request\n(Authentication Protocol version 4)\n");
704 msg = sipmsg_parse_msg(request);
705 msgbd.msg = msg;
706 sipmsg_breakdown_parse(&msgbd, "SIP Communications Service", "cosmo-ocs-r2.cosmo.local");
707 msg_str = sipmsg_breakdown_get_string(4, &msgbd);
708 assert_equal (request_sig, msg_str, strlen(request_sig), FALSE);
709 sig = sip_sec_ntlm_sipe_signature_make (flags, msg_str, 0, client_sign_key, client_seal_key);
710 sipmsg_breakdown_free(&msgbd);
711 assert_equal ("0100000029618e9651b65a7764000000", (guchar *) sig,32, FALSE);
712 printf("purple_ntlm_verify_signature result = %i\n", sip_sec_ntlm_verify_signature (sig, "0100000029618e9651b65a7764000000"));
714 printf ("\n\nTesting (NTLMv2 / OC 2007 R2) Message Parsing, Signing, and Verification\nServer response\n(Authentication Protocol version 4)\n");
715 msg = sipmsg_parse_msg(response);
716 msgbd.msg = msg;
717 sipmsg_breakdown_parse(&msgbd, "SIP Communications Service", "cosmo-ocs-r2.cosmo.local");
718 msg_str = sipmsg_breakdown_get_string(4, &msgbd);
719 assert_equal (response_sig, msg_str, strlen(response_sig), FALSE);
720 // server keys here
721 sig = sip_sec_ntlm_sipe_signature_make (flags, msg_str, 0, server_sign_key, server_seal_key);
722 sipmsg_breakdown_free(&msgbd);
723 assert_equal ("01000000E615438A917661BE64000000", (guchar *) sig,32, FALSE);
724 printf("purple_ntlm_verify_signature result = %i\n", sip_sec_ntlm_verify_signature (sig, "01000000E615438A917661BE64000000"));
726 printf ("\n\nTesting (NTLMv2 / OC 2007 R2) MAC - client signing\n");
727 mac = MAC (flags, (gchar*)request_sig,strlen(request_sig), client_sign_key,16, client_seal_key,16, 0, 100);
728 assert_equal("0100000029618e9651b65a7764000000", (guchar*)mac, 32, FALSE);
729 g_free(mac);
731 printf ("\n\nTesting (NTLMv2 / OC 2007 R2) MAC - server's verifying\n");
732 mac = MAC (flags, (gchar*)response_sig,strlen(response_sig), server_sign_key,16, server_seal_key,16, 0, 100);
733 assert_equal("01000000E615438A917661BE64000000", (guchar*)mac, 32, FALSE);
734 g_free(mac);
737 ////// UUID tests ///////
738 /* begin tests from MS-SIPRE */
740 const char *testEpid = "01010101";
741 const char *expectedUUID = "4b1682a8-f968-5701-83fc-7c6741dc6697";
742 gchar *calcUUID = generateUUIDfromEPID(testEpid);
744 printf("\n\nTesting MS-SIPRE UUID derivation\n");
746 assert_equal(expectedUUID, (guchar *) calcUUID, strlen(expectedUUID), FALSE);
747 g_free(calcUUID);
749 guchar addr[6];
750 gchar nmac[6];
752 int i,j;
753 for (i = 0,j=0; i < 6; i++,j+=2) {
754 g_sprintf(&nmac[j], "%02X", addr[i]);
757 printf("Mac: %s\n", g_strdup(nmac));
759 /* end tests from MS-SIPRE */
761 printf ("\nFinished With Tests; %d successs %d failures\n", successes, failures);
763 return(0);
767 Local Variables:
768 mode: c
769 c-file-style: "bsd"
770 indent-tabs-mode: t
771 tab-width: 8
772 End: