Fixed the bug #2786479: Some messages could not be delivered to all users.
[siplcs.git] / src / sip-ntlm.c
blob9bfcbcbc3f1cbfd5bb158338bf3d650a7e370b94
1 /**
2 * @file sip-ntlm.c
4 * pidgin-sipe
6 * Copyright (C) 2008 Novell, Inc.
7 * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de>
8 * Modify 2007, Anibal Avelar <debianmx@gmail.com>
10 * Implemented with reference to the follow documentation:
11 * - http://davenport.sourceforge.net/ntlm.html
12 * - MS-NLMP: http://msdn.microsoft.com/en-us/library/cc207842.aspx
13 * - MS-SIP : http://msdn.microsoft.com/en-us/library/cc246115.aspx
15 * hashing done according to description of NTLM on
16 * http://www.innovation.ch/java/ntlm.html
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include <glib.h>
34 #ifndef _WIN32
35 #include <sys/socket.h>
36 #include <sys/ioctl.h>
37 #include <sys/types.h>
38 #include <netinet/in.h>
39 #include <net/if.h>
40 #else /* _WIN32 */
41 #ifdef _DLL
42 #define _WS2TCPIP_H_
43 #define _WINSOCK2API_
44 #define _LIBC_INTERNAL_
45 #endif /* _DLL */
46 #include "network.h"
47 #include "internal.h"
48 #endif /* _WIN32 */
50 #include <stdlib.h>
51 #include <string.h>
52 #include <iconv.h>
53 #ifdef HAVE_LANGINFO_CODESET
54 #include <langinfo.h>
55 #endif /* HAVE_LANGINFO_CODESET */
57 #include "debug.h"
58 #include "util.h"
59 #include "cipher.h"
60 #include "sip-ntlm.h"
62 #define NTLM_NEGOTIATE_NTLM2_KEY 0x00080000
64 struct challenge_message {
65 guint8 protocol[8]; /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'*/
66 guint8 type; /* 0x02 */
67 guint8 zero1[7];
68 short msg_len; /* 0x28 */
69 guint8 zero2[2];
70 guint32 flags; /* 0x8201 */
72 guint8 nonce[8];
73 guint8 zero[8];
76 struct authenticate_message {
77 guint8 protocol[8]; /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'*/
78 //guint32 type; /* 0x03 */
79 guint8 type; /* 0x03 */
80 guint8 zero1[3];
82 guint16 lm_resp_len1; /* LanManager response length (always 0x18)*/
83 guint16 lm_resp_len2; /* LanManager response length (always 0x18)*/
84 //guint32 lm_resp_off; /* LanManager response offset */
85 guint16 lm_resp_off; /* LanManager response offset */
86 guint8 zero2[2];
88 /* NtChallengeResponseFields */
89 guint16 nt_resp_len1; /* NT response length (always 0x18) */
90 guint16 nt_resp_len2; /* NT response length (always 0x18) */
91 //guint32 nt_resp_off; /* NT response offset */
92 guint16 nt_resp_off; /* NT response offset */
93 guint8 zero3[2];
95 /* DomainNameFields */
96 guint16 dom_len1; /* domain string length */
97 guint16 dom_len2; /* domain string length */
98 //guint32 dom_off; /* domain string offset (always 0x40) */
99 guint16 dom_off; /* domain string offset (always 0x40) */
100 guint8 zero4[2];
102 /* UserNameFields */
103 guint16 user_len1; /* username string length */
104 guint16 user_len2; /* username string length */
105 //guint32 user_off; /* username string offset */
106 guint16 user_off; /* username string offset */
107 guint8 zero5[2];
109 /* WorkstationFields */
110 guint16 host_len1; /* host string length */
111 guint16 host_len2; /* host string length */
112 //guint32 host_off; /* host string offset */
113 guint16 host_off; /* host string offset */
114 guint8 zero6[2];
116 /* EncryptedRandomSessionKeyFields */
117 guint16 sess_len1;
118 guint16 sess_len2;
119 //guint32 sess_off;
120 guint16 sess_off;
121 guint8 zero7[2];
123 guint32 flags;
125 // don't care values
126 // version
127 // mic
129 // payload
130 /* guint32 flags2; unknown, used in windows messenger
131 guint32 flags3; */
133 #if 0
134 guint8 dom[*]; /* domain string (unicode UTF-16LE) */
135 guint8 user[*]; /* username string (unicode UTF-16LE) */
136 guint8 host[*]; /* host string (unicode UTF-16LE) */
137 guint8 lm_resp[*]; /* LanManager response */
138 guint8 nt_resp[*]; /* NT response */
139 #endif
142 /* Private Methods */
144 static void setup_des_key(const unsigned char key_56[], char *key)
146 key[0] = key_56[0];
147 key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
148 key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
149 key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
150 key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
151 key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
152 key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
153 key[7] = (key_56[6] << 1) & 0xFF;
156 static void des_ecb_encrypt(const char *plaintext, char *result, const char *key)
158 PurpleCipher *cipher;
159 PurpleCipherContext *context;
160 gsize outlen;
162 cipher = purple_ciphers_find_cipher("des");
163 context = purple_cipher_context_new(cipher, NULL);
164 purple_cipher_context_set_key(context, (guchar*)key);
165 purple_cipher_context_encrypt(context, (guchar*)plaintext, 8, (guchar*)result, &outlen);
166 purple_cipher_context_destroy(context);
169 static int
170 unicode_strconvcopy(gchar *dest, const gchar *source, int remlen)
172 GIConv fd;
173 gchar *inbuf = (gchar *) source;
174 gchar *outbuf = dest;
175 size_t inbytes = strlen(source);
176 size_t outbytes = remlen;
177 #ifdef HAVE_LANGINFO_CODESET
178 char *sys_cp = nl_langinfo(CODESET);
179 #else
180 char *sys_cp = SIPE_DEFAULT_CODESET;
181 #endif /* HAVE_LANGINFO_CODESET */
183 /* fall back to utf-8 */
184 if (!sys_cp) sys_cp = "UTF-8";
186 fd = g_iconv_open("UTF-16LE", sys_cp);
187 if( fd == (iconv_t)-1 ) {
188 purple_debug_error( "sipe", "iconv_open returned -1, cannot continue\n" );
190 g_iconv(fd, &inbuf, &inbytes, &outbuf, &outbytes);
191 g_iconv_close(fd);
192 return (remlen - outbytes);
195 // (k = 7 byte key, d = 8 byte data) returns 8 bytes in results
196 static void
197 DES (const char *k, const char *d, char * results)
199 char key[8];
200 setup_des_key(k, key);
201 des_ecb_encrypt(d, results, key);
204 // (K = 21 byte key, D = 8 bytes of data) returns 24 bytes in results:
205 static void
206 DESL (char *k, const char *d, char * results)
208 char keys[21];
210 // Copy the first 16 bytes
211 memcpy(keys, k, 16);
213 // Zero out the last 5 bytes of the key
214 memset(keys + 16, 0, 5);
216 DES(keys, d, results);
217 DES(keys + 7, d, results + 8);
218 DES(keys + 14, d, results + 16);
221 static void
222 MD4 (const char * d, int len, char * result)
224 PurpleCipher * cipher = purple_ciphers_find_cipher("md4");
225 PurpleCipherContext * context = purple_cipher_context_new(cipher, NULL);
226 purple_cipher_context_append(context, (guchar*)d, len);
227 purple_cipher_context_digest(context, MD4_DIGEST_LEN, (guchar*)result, NULL);
228 purple_cipher_context_destroy(context);
232 static void
233 NTOWFv1 (const char* password, const char *user, const char *domain, char * result)
235 int len = 2 * strlen(password); // utf16 should not be more
236 char *unicode_password = g_new0(char, len);
238 len = unicode_strconvcopy(unicode_password, password, len);
239 MD4 (unicode_password, len, result);
240 g_free(unicode_password);
243 // static void
244 // MD5 (const char * d, int len, char * result)
245 // {
246 // PurpleCipher * cipher = purple_ciphers_find_cipher("md5");
247 // PurpleCipherContext * context = purple_cipher_context_new(cipher, NULL);
248 // purple_cipher_context_append(context, (guchar*)d, len);
249 // purple_cipher_context_digest(context, len, (guchar*)result, NULL);
250 // purple_cipher_context_destroy(context);
251 // }
253 static void
254 RC4K (const char * k, const char * d, char * result)
256 PurpleCipherContext * context = purple_cipher_context_new_by_name("rc4", NULL);
257 purple_cipher_context_set_option(context, "key_len", (gpointer)16);
258 purple_cipher_context_set_key(context, k);
259 purple_cipher_context_encrypt(context, (const guchar *)d, 16, result, NULL);
260 purple_cipher_context_destroy(context);
263 static void
264 KXKEY (const char * session_base_key, const char * lm_challenge_resonse, char * key_exchange_key)
266 // Assume v1 and NTLMSSP_REQUEST_NON_NT_SESSION_KEY not set
267 memcpy(key_exchange_key, session_base_key, 16);
270 // This method is only used for NTLM v2 session security w/ enhanced security negotiated
271 /*void
272 SIGNKEY (const char * random_session_key, gboolean client, char * result)
274 char * magic = client
275 ? "session key to client-to-server signing key magic constant"
276 : "session key to server-to-client signing key magic constant";
278 int len = strlen(magic);
279 char md5_input [16 + len];
280 memcpy(md5_input, random_session_key, 16);
281 memcpy(md5_input + 16, magic, len);
283 MD5 (md5_input, len + 16, result);
286 static void
287 LMOWFv1 (const char *password, const char *user, const char *domain, char *result)
289 /* "KGS!@#$%" */
290 unsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
291 char uppercase_password[14];
292 int i;
294 int len = strlen(password);
295 if (len > 14) {
296 len = 14;
299 // Uppercase password
300 for (i = 0; i < len; i++) {
301 uppercase_password[i] = g_ascii_toupper(password[i]);
304 // Zero the rest
305 for (; i < 14; i++) {
306 uppercase_password[i] = 0;
309 DES (uppercase_password, magic, result);
310 DES (uppercase_password + 7, magic, result + 8);
313 static void
314 NONCE(char *buffer, int num)
316 int i;
317 for (i = 0; i < num; i++) {
318 buffer[i] = (char)(rand() & 0xff);
322 /* End Private Methods */
324 gchar *purple_ntlm_parse_challenge(gchar *challenge, guint32 *flags) {
325 gsize retlen;
326 static gchar nonce[8];
327 struct challenge_message *tmsg = (struct challenge_message*)purple_base64_decode((char*)challenge, &retlen);
328 memcpy(nonce, tmsg->nonce, 8);
330 purple_debug_info("sipe", "received NTLM NegotiateFlags = %X; OK? %i\n", tmsg->flags, (tmsg->flags & NEGOTIATE_FLAGS) == NEGOTIATE_FLAGS);
332 if (flags) {
333 *flags = tmsg->flags;
335 g_free(tmsg);
336 return nonce;
339 // static void
340 // print_hex_array(char * msg, int num)
341 // {
342 // int k;
343 // for (k = 0; k < num; k++) {
344 // printf("0x%02X, ", msg[k]&0xff);
345 // }
346 // printf("\n");
347 // }
349 // static void
350 // print_hex_array_title(char * title, char * msg, int num)
351 // {
352 // printf("%s:\n", title);
353 // print_hex_array(msg, num);
354 // }
356 /* source copy from gg's common.c */
357 static guint32 crc32_table[256];
358 static int crc32_initialized = 0;
360 static void crc32_make_table()
362 guint32 h = 1;
363 unsigned int i, j;
365 memset(crc32_table, 0, sizeof(crc32_table));
367 for (i = 128; i; i >>= 1) {
368 h = (h >> 1) ^ ((h & 1) ? 0xedb88320L : 0);
370 for (j = 0; j < 256; j += 2 * i)
371 crc32_table[i + j] = crc32_table[j] ^ h;
374 crc32_initialized = 1;
377 static guint32 crc32(guint32 crc, const guint8 *buf, int len)
379 if (!crc32_initialized)
380 crc32_make_table();
382 if (!buf || len < 0)
383 return crc;
385 crc ^= 0xffffffffL;
387 while (len--)
388 crc = (crc >> 8) ^ crc32_table[(crc ^ *buf++) & 0xff];
390 return crc ^ 0xffffffffL;
393 static long
394 CRC32 (char * msg)
396 long crc = 0L;//crc32(0L, Z_NULL, 0);
397 crc = crc32(crc, msg, strlen(msg));
398 //char * ptr = (char*) &crc;
399 //return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | (ptr[3] & 0xff);
400 return crc;
403 gchar *
404 purple_ntlm_gen_signature (char * buf, char * signing_key, guint32 random_pad, long sequence, int key_len)
406 gint32 *res_ptr;
407 gint32 plaintext [] = {0, CRC32(buf), sequence};
409 guchar result [16];
410 gchar signature [32];
411 int i, j;
412 PurpleCipherContext *rc4 = purple_cipher_context_new_by_name("rc4", NULL);
413 purple_cipher_context_set_option(rc4, "key_len", (gpointer)key_len);
414 purple_cipher_context_set_key(rc4, signing_key);
415 purple_cipher_context_encrypt(rc4, (const guchar *)plaintext, 12, result+4, NULL);
416 purple_cipher_context_destroy(rc4);
418 res_ptr = (gint32 *)result;
419 // Highest four bytes are the Version
420 res_ptr[0] = 0x00000001;
422 // Replace the first four bytes of the ciphertext with a counter value
423 // currently set to this hardcoded value
424 res_ptr[1] = random_pad;
426 for (i = 0, j = 0; i < 16; i++, j+=2) {
427 g_sprintf(&signature[j], "%02X", result[i]);
430 //printf("sig: %s\n", signature);
431 return g_strdup(signature);
434 gchar *
435 purple_ntlm_sipe_signature_make (char * msg, char * signing_key)
437 return purple_ntlm_gen_signature(msg, signing_key, 0, 100, 16);
440 gboolean
441 purple_ntlm_verify_signature (char * a, char * b)
443 // Make sure the last 16 bytes match
444 gboolean ret = g_ascii_strncasecmp(a + 16, b + 16, 16) == 0;
445 return ret;
448 gchar *
449 purple_ntlm_gen_authenticate(const gchar **ntlm_key, const gchar *user, const gchar *password, const gchar *hostname, const gchar *domain, const guint8 *nonce, guint32 *flags)
451 int msglen = sizeof(struct authenticate_message) + 2*(strlen(domain)
452 + strlen(user)+ strlen(hostname) + NTLMSSP_NT_OR_LM_KEY_LEN)
453 + NTLMSSP_SESSION_KEY_LEN;
454 struct authenticate_message *tmsg = g_malloc0(msglen);
455 char *tmp;
456 int remlen;
457 char response_key_lm [16];
458 char lm_challenge_response [NTLMSSP_NT_OR_LM_KEY_LEN];
459 char response_key_nt [16];
460 char nt_challenge_response [NTLMSSP_NT_OR_LM_KEY_LEN];
461 char session_base_key [16];
462 char key_exchange_key [16];
463 char exported_session_key[16];
464 char encrypted_random_session_key [16];
466 /* authenticate message initialization */
467 memcpy(tmsg->protocol, "NTLMSSP\0", 8);
468 tmsg->type = 3;
470 /* Set Negotiate Flags */
471 tmsg->flags = NEGOTIATE_FLAGS;
473 /* Domain */
474 tmsg->dom_off = sizeof(struct authenticate_message);
475 tmp = ((char*) tmsg) + tmsg->dom_off;
476 remlen = ((char *)tmsg)+msglen-tmp;
477 tmsg->dom_len1 = tmsg->dom_len2 = unicode_strconvcopy(tmp, domain, remlen);
478 tmp += tmsg->dom_len1;
479 remlen = ((char *)tmsg)+msglen-tmp;
481 /* User */
482 tmsg->user_off = tmsg->dom_off + tmsg->dom_len1;
483 tmsg->user_len1 = tmsg->user_len2 = unicode_strconvcopy(tmp, user, remlen);
484 tmp += tmsg->user_len1;
485 remlen = ((char *)tmsg)+msglen-tmp;
487 /* Host */
488 tmsg->host_off = tmsg->user_off + tmsg->user_len1;
489 tmsg->host_len1 = tmsg->host_len2 = unicode_strconvcopy(tmp, hostname, remlen);
490 tmp += tmsg->host_len1;
492 /* LM */
493 tmsg->lm_resp_len1 = tmsg->lm_resp_len2 = NTLMSSP_NT_OR_LM_KEY_LEN;
494 tmsg->lm_resp_off = tmsg->host_off + tmsg->host_len1;
496 LMOWFv1 (password, user, domain, response_key_lm);
497 DESL (response_key_lm, nonce, lm_challenge_response);
498 memcpy(tmp, lm_challenge_response, NTLMSSP_NT_OR_LM_KEY_LEN);
499 tmp += NTLMSSP_NT_OR_LM_KEY_LEN;
501 /* NT */
502 tmsg->nt_resp_len1 = tmsg->nt_resp_len2 = NTLMSSP_NT_OR_LM_KEY_LEN;
503 tmsg->nt_resp_off = tmsg->lm_resp_off + tmsg->lm_resp_len1;
505 NTOWFv1 (password, user, domain, response_key_nt);
506 DESL (response_key_nt, nonce, nt_challenge_response);
507 memcpy(tmp, nt_challenge_response, NTLMSSP_NT_OR_LM_KEY_LEN);
508 tmp += NTLMSSP_NT_OR_LM_KEY_LEN;
510 /* Session Key */
511 tmsg->sess_len1 = tmsg->sess_len2 = NTLMSSP_SESSION_KEY_LEN;
512 tmsg->sess_off = tmsg->nt_resp_off + tmsg->nt_resp_len1;
514 MD4(response_key_nt, 16, session_base_key);
516 KXKEY(session_base_key, lm_challenge_response, key_exchange_key);
518 NONCE (exported_session_key, 16);
520 *ntlm_key = g_strndup (exported_session_key, 16);
522 RC4K (key_exchange_key, exported_session_key, encrypted_random_session_key);
523 memcpy(tmp, encrypted_random_session_key, 16);
524 tmp += NTLMSSP_SESSION_KEY_LEN;
526 tmp = purple_base64_encode((guchar*) tmsg, msglen);
527 purple_debug_info("sipe", "Generated NTLM AUTHENTICATE message\n");
528 g_free(tmsg);
529 return tmp;