3 * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de>
5 * hashing done according to description of NTLM on
6 * http://www.innovation.ch/java/ntlm.html
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
29 #include "ciphers/descipher.h"
30 #include "ciphers/md4hash.h"
34 #define NTLM_NEGOTIATE_NTLM2_KEY 0x00080000
36 struct type1_message
{
37 guint8 protocol
[8]; /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0' */
38 guint32 type
; /* 0x00000001 */
39 guint32 flags
; /* 0x0000b203 */
41 guint16 dom_len1
; /* domain string length */
42 guint16 dom_len2
; /* domain string length */
43 guint32 dom_off
; /* domain string offset */
45 guint16 host_len1
; /* host string length */
46 guint16 host_len2
; /* host string length */
47 guint32 host_off
; /* host string offset (always 0x00000020) */
50 guint8 host
[*]; /* host string (ASCII) */
51 guint8 dom
[*]; /* domain string (ASCII) */
55 struct type2_message
{
56 guint8 protocol
[8]; /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'*/
57 guint32 type
; /* 0x00000002 */
60 guint16 msg_len1
; /* target name length */
61 guint16 msg_len2
; /* target name length */
63 guint32 flags
; /* 0x00008201 */
65 guint8 nonce
[8]; /* nonce */
69 struct type3_message
{
70 guint8 protocol
[8]; /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'*/
71 guint32 type
; /* 0x00000003 */
73 guint16 lm_resp_len1
; /* LanManager response length (always 0x18)*/
74 guint16 lm_resp_len2
; /* LanManager response length (always 0x18)*/
75 guint32 lm_resp_off
; /* LanManager response offset */
77 guint16 nt_resp_len1
; /* NT response length (always 0x18) */
78 guint16 nt_resp_len2
; /* NT response length (always 0x18) */
79 guint32 nt_resp_off
; /* NT response offset */
81 guint16 dom_len1
; /* domain string length */
82 guint16 dom_len2
; /* domain string length */
83 guint32 dom_off
; /* domain string offset (always 0x00000040) */
85 guint16 user_len1
; /* username string length */
86 guint16 user_len2
; /* username string length */
87 guint32 user_off
; /* username string offset */
89 guint16 host_len1
; /* host string length */
90 guint16 host_len2
; /* host string length */
91 guint32 host_off
; /* host string offset */
95 guint32 sess_off
; /* message length */
97 guint32 flags
; /* 0x00008201 */
98 /* guint32 flags2; */ /* unknown, used in windows messenger */
102 guint8 dom
[*]; /* domain string (unicode UTF-16LE) */
103 guint8 user
[*]; /* username string (unicode UTF-16LE) */
104 guint8 host
[*]; /* host string (unicode UTF-16LE) */
105 guint8 lm_resp
[*]; /* LanManager response */
106 guint8 nt_resp
[*]; /* NT response */
111 purple_ntlm_gen_type1(const gchar
*hostname
, const gchar
*domain
)
113 int hostnamelen
,host_off
;
114 int domainlen
,dom_off
;
116 struct type1_message
*tmsg
;
119 hostnamelen
= strlen(hostname
);
120 domainlen
= strlen(domain
);
121 host_off
= sizeof(struct type1_message
);
122 dom_off
= sizeof(struct type1_message
) + hostnamelen
;
123 msg
= g_malloc0(sizeof(struct type1_message
) + hostnamelen
+ domainlen
);
124 tmsg
= (struct type1_message
*)(gpointer
)msg
;
125 tmsg
->protocol
[0] = 'N';
126 tmsg
->protocol
[1] = 'T';
127 tmsg
->protocol
[2] = 'L';
128 tmsg
->protocol
[3] = 'M';
129 tmsg
->protocol
[4] = 'S';
130 tmsg
->protocol
[5] = 'S';
131 tmsg
->protocol
[6] = 'P';
132 tmsg
->protocol
[7] = '\0';
133 tmsg
->type
= GUINT32_TO_LE(0x00000001);
134 tmsg
->flags
= GUINT32_TO_LE(0x0000b203);
135 tmsg
->dom_len1
= tmsg
->dom_len2
= GUINT16_TO_LE(domainlen
);
136 tmsg
->dom_off
= GUINT32_TO_LE(dom_off
);
137 tmsg
->host_len1
= tmsg
->host_len2
= GUINT16_TO_LE(hostnamelen
);
138 tmsg
->host_off
= GUINT32_TO_LE(host_off
);
139 memcpy(msg
+ host_off
, hostname
, hostnamelen
);
140 memcpy(msg
+ dom_off
, domain
, domainlen
);
142 tmp
= purple_base64_encode(msg
, sizeof(struct type1_message
) + hostnamelen
+ domainlen
);
149 purple_ntlm_parse_type2(const gchar
*type2
, guint32
*flags
)
153 struct type2_message tmsg
;
154 static guint8 nonce
[8];
156 buff
= purple_base64_decode(type2
, &retlen
);
158 if (buff
!= NULL
&& retlen
>= (sizeof(struct type2_message
) - 1)) {
159 memcpy(&tmsg
, buff
, MIN(retlen
, sizeof(tmsg
)));
160 memcpy(nonce
, tmsg
.nonce
, 8);
162 *flags
= GUINT16_FROM_LE(tmsg
.flags
);
164 purple_debug_error("ntlm", "Unable to parse type2 message - returning empty nonce.\n");
173 * Create a 64bit DES key by taking a 56bit key and adding
174 * a parity bit after every 7th bit.
177 setup_des_key(const guint8 key_56
[], guint8
*key
)
180 key
[1] = ((key_56
[0] << 7) & 0xFF) | (key_56
[1] >> 1);
181 key
[2] = ((key_56
[1] << 6) & 0xFF) | (key_56
[2] >> 2);
182 key
[3] = ((key_56
[2] << 5) & 0xFF) | (key_56
[3] >> 3);
183 key
[4] = ((key_56
[3] << 4) & 0xFF) | (key_56
[4] >> 4);
184 key
[5] = ((key_56
[4] << 3) & 0xFF) | (key_56
[5] >> 5);
185 key
[6] = ((key_56
[5] << 2) & 0xFF) | (key_56
[6] >> 6);
186 key
[7] = (key_56
[6] << 1) & 0xFF;
190 * helper function for purple cipher.c
193 des_ecb_encrypt(const guint8
*plaintext
, guint8
*result
, const guint8
*key
)
195 PurpleCipher
*cipher
;
198 cipher
= purple_des_cipher_new();
199 purple_cipher_set_key(cipher
, key
, 8);
200 encsiz
= purple_cipher_encrypt(cipher
, plaintext
, 8, result
, 8);
201 g_warn_if_fail(encsiz
== 8);
202 g_object_unref(cipher
);
206 * takes a 21 byte array and treats it as 3 56-bit DES keys. The
207 * 8 byte plaintext is encrypted with each key and the resulting 24
208 * bytes are stored in the results array.
211 calc_resp(guint8
*keys
, const guint8
*plaintext
, unsigned char *results
)
214 setup_des_key(keys
, key
);
215 des_ecb_encrypt(plaintext
, results
, key
);
217 setup_des_key(keys
+ 7, key
);
218 des_ecb_encrypt(plaintext
, results
+ 8, key
);
220 setup_des_key(keys
+ 14, key
);
221 des_ecb_encrypt(plaintext
, results
+ 16, key
);
225 * TODO: We think we should be using cryptographically secure random numbers
226 * here. We think the rand() function is probably bad. We think
227 * /dev/urandom is a step up, but using a random function from an SSL
228 * library would probably be best. In Windows we could possibly also
229 * use CryptGenRandom.
232 gensesskey(char *buffer
)
238 fd
= open("/dev/urandom", O_RDONLY
);
240 red
= read(fd
, buffer
, 16);
242 purple_debug_warning("ntlm", "Error reading from /dev/urandom: %s."
243 " Falling back to inferior method.\n", g_strerror(errno
));
245 } else if (red
< 16) {
246 purple_debug_warning("ntlm", "Tried reading 16 bytes from "
247 "/dev/urandom but only got %"
248 G_GSSIZE_FORMAT
". Falling back to "
249 "inferior method\n", (gssize
)red
);
253 purple_debug_warning("ntlm", "Error opening /dev/urandom: %s."
254 " Falling back to inferior method.\n", g_strerror(errno
));
257 for (i
= red
; i
< 16; i
++) {
258 buffer
[i
] = (char)(rand() & 0xff);
263 purple_ntlm_gen_type3(const gchar
*username
, const gchar
*passw
, const gchar
*hostname
, const gchar
*domain
, const guint8
*nonce
, guint32
*flags
)
266 unsigned char lm_hpw
[21];
273 struct type3_message
*tmsg
;
275 unsigned char lm_resp
[24], nt_resp
[24];
276 unsigned char magic
[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
277 unsigned char nt_hpw
[21];
284 domainlen
= strlen(domain
) * 2;
285 usernamelen
= strlen(username
) * 2;
286 hostnamelen
= strlen(hostname
) * 2;
287 msglen
= sizeof(struct type3_message
) + domainlen
+
288 usernamelen
+ hostnamelen
+ 0x18 + 0x18 + ((flags
) ? 0x10 : 0);
289 tmsg
= g_malloc0(msglen
);
290 passwlen
= strlen(passw
);
292 /* type3 message initialization */
293 tmsg
->protocol
[0] = 'N';
294 tmsg
->protocol
[1] = 'T';
295 tmsg
->protocol
[2] = 'L';
296 tmsg
->protocol
[3] = 'M';
297 tmsg
->protocol
[4] = 'S';
298 tmsg
->protocol
[5] = 'S';
299 tmsg
->protocol
[6] = 'P';
300 tmsg
->type
= GUINT32_TO_LE(0x00000003);
301 tmsg
->lm_resp_len1
= tmsg
->lm_resp_len2
= GUINT16_TO_LE(0x18);
302 tmsg
->lm_resp_off
= GUINT32_TO_LE(sizeof(struct type3_message
) + domainlen
+ usernamelen
+ hostnamelen
);
303 tmsg
->nt_resp_len1
= tmsg
->nt_resp_len2
= GUINT16_TO_LE(0x18);
304 tmsg
->nt_resp_off
= GUINT32_TO_LE(sizeof(struct type3_message
) + domainlen
+ usernamelen
+ hostnamelen
+ 0x18);
306 tmsg
->dom_len1
= tmsg
->dom_len2
= GUINT16_TO_LE(domainlen
);
307 tmsg
->dom_off
= GUINT32_TO_LE(sizeof(struct type3_message
));
309 tmsg
->user_len1
= tmsg
->user_len2
= GUINT16_TO_LE(usernamelen
);
310 tmsg
->user_off
= GUINT32_TO_LE(sizeof(struct type3_message
) + domainlen
);
312 tmsg
->host_len1
= tmsg
->host_len2
= GUINT16_TO_LE(hostnamelen
);
313 tmsg
->host_off
= GUINT32_TO_LE(sizeof(struct type3_message
) + domainlen
+ usernamelen
);
316 tmsg
->sess_off
= GUINT32_TO_LE(sizeof(struct type3_message
) + domainlen
+ usernamelen
+ hostnamelen
+ 0x18 + 0x18);
317 tmsg
->sess_len1
= tmsg
->sess_len2
= GUINT16_TO_LE(0x0010);
320 tmsg
->flags
= GUINT32_TO_LE(0x00008201);
322 tmp
= (char *)tmsg
+ sizeof(struct type3_message
);
324 ucs2le
= g_convert(domain
, -1, "UTF-16LE", "UTF-8", NULL
, NULL
, NULL
);
325 if (ucs2le
!= NULL
) {
326 memcpy(tmp
, ucs2le
, domainlen
);
330 purple_debug_info("ntlm", "Unable to encode domain in UTF-16LE.\n");
333 ucs2le
= g_convert(username
, -1, "UTF-16LE", "UTF-8", NULL
, NULL
, NULL
);
334 if (ucs2le
!= NULL
) {
335 memcpy(tmp
, ucs2le
, usernamelen
);
339 purple_debug_info("ntlm", "Unable to encode username in UTF-16LE.\n");
342 ucs2le
= g_convert(hostname
, -1, "UTF-16LE", "UTF-8", NULL
, NULL
, NULL
);
343 if (ucs2le
!= NULL
) {
344 memcpy(tmp
, ucs2le
, hostnamelen
);
348 purple_debug_info("ntlm", "Unable to encode hostname in UTF-16LE.\n");
355 for (idx
= 0; idx
< passwlen
; idx
++)
356 lm_pw
[idx
] = g_ascii_toupper(passw
[idx
]);
357 for (; idx
< 14; idx
++)
360 setup_des_key((unsigned char*)lm_pw
, key
);
361 des_ecb_encrypt(magic
, lm_hpw
, key
);
363 setup_des_key((unsigned char*)(lm_pw
+ 7), key
);
364 des_ecb_encrypt(magic
, lm_hpw
+ 8, key
);
366 memset(lm_hpw
+ 16, 0, 5);
367 calc_resp(lm_hpw
, nonce
, lm_resp
);
368 memcpy(tmp
, lm_resp
, 0x18);
372 /* Convert the password to UTF-16LE */
373 lennt
= strlen(passw
);
374 for (idx
= 0; idx
< lennt
; idx
++)
376 nt_pw
[2 * idx
] = passw
[idx
];
377 nt_pw
[2 * idx
+ 1] = 0;
380 hash
= purple_md4_hash_new();
381 purple_hash_append(hash
, (guint8
*)nt_pw
, 2 * lennt
);
382 purple_hash_digest(hash
, nt_hpw
, sizeof(nt_hpw
));
383 g_object_unref(hash
);
385 memset(nt_hpw
+ 16, 0, 5);
386 calc_resp(nt_hpw
, nonce
, nt_resp
);
387 memcpy(tmp
, nt_resp
, 0x18);
392 tmsg
->flags
= GUINT32_TO_LE(0x409082d4);
394 memcpy(tmp
, sesskey
, 0x10);
397 /*tmsg->flags2 = 0x0a280105;
398 tmsg->flags3 = 0x0f000000;*/
400 tmp
= purple_base64_encode((guchar
*)tmsg
, msglen
);