release 0.92.3
[cntlm.git] / ntlm.c
blobdd04864d596df1f83f37183bd3c7e5a6d0c1ca70
1 /*
2 * These are NTLM authentication routines for the main module of CNTLM
4 * CNTLM is free software; you can redistribute it and/or modify it under the
5 * terms of the GNU General Public License as published by the Free Software
6 * Foundation; either version 2 of the License, or (at your option) any later
7 * version.
9 * CNTLM is distributed in the hope that it will be useful, but WITHOUT ANY
10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
16 * St, Fifth Floor, Boston, MA 02110-1301, USA.
18 * Copyright (c) 2007 David Kubicek
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stdint.h>
27 #include "ntlm.h"
28 #include "swap.h"
29 #include "xcrypt.h"
30 #include "utils.h"
31 #include "auth.h"
33 extern int debug;
35 static void ntlm_set_key(unsigned char *src, gl_des_ctx *context) {
36 char key[8];
38 key[0] = src[0];
39 key[1] = ((src[0] << 7) & 0xff) | (src[1] >> 1);
40 key[2] = ((src[1] << 6) & 0xff) | (src[2] >> 2);
41 key[3] = ((src[2] << 5) & 0xff) | (src[3] >> 3);
42 key[4] = ((src[3] << 4) & 0xff) | (src[4] >> 4);
43 key[5] = ((src[4] << 3) & 0xff) | (src[5] >> 5);
44 key[6] = ((src[5] << 2) & 0xff) | (src[6] >> 6);
45 key[7] = (src[6] << 1) & 0xff;
47 gl_des_setkey(context, key);
50 static int ntlm_calc_resp(char **dst, char *keys, char *challenge) {
51 gl_des_ctx context;
53 *dst = new(24 + 1);
55 ntlm_set_key(MEM(keys, unsigned char, 0), &context);
56 gl_des_ecb_encrypt(&context, challenge, *dst);
58 ntlm_set_key(MEM(keys, unsigned char, 7), &context);
59 gl_des_ecb_encrypt(&context, challenge, *dst+8);
61 ntlm_set_key(MEM(keys, unsigned char, 14), &context);
62 gl_des_ecb_encrypt(&context, challenge, *dst+16);
64 return 24;
67 static void ntlm2_calc_resp(char **nthash, int *ntlen, char **lmhash, int *lmlen,
68 char *passnt2, char *challenge, int tbofs, int tblen) {
69 char *tmp, *blob, *nonce, *buf;
70 int64_t tw;
71 int blen;
73 nonce = new(8 + 1);
74 VAL(nonce, uint64_t, 0) = ((uint64_t)random() << 32) | random();
75 tw = ((uint64_t)time(NULL) + 11644473600LLU) * 10000000LLU;
77 if (debug) {
78 tmp = printmem(nonce, 8, 7);
79 #ifdef PRId64
80 printf("NTLMv2:\n\t Nonce: %s\n\tTimestamp: %"PRId64"\n", tmp, tw);
81 #else
82 printf("NTLMv2:\n\t Nonce: %s\n\tTimestamp: %ld\n", tmp, tw);
83 #endif
84 free(tmp);
87 blob = new(4+4+8+8+4+tblen+4 + 1);
88 VAL(blob, uint32_t, 0) = U32LE(0x00000101);
89 VAL(blob, uint32_t, 4) = U32LE(0);
90 VAL(blob, uint64_t, 8) = U64LE(tw);
91 VAL(blob, uint64_t, 16) = U64LE(VAL(nonce, uint64_t, 0));
92 VAL(blob, uint32_t, 24) = U32LE(0);
93 memcpy(blob+28, MEM(challenge, char, tbofs), tblen);
94 VAL(blob, uint32_t, 28+tblen) = U32LE(0);
95 blen = 28+tblen+4;
97 if (0 && debug) {
98 tmp = printmem(blob, blen, 7);
99 printf("\t Blob: %s (%d)\n", tmp, blen);
100 free(tmp);
103 *ntlen = 16+blen;
104 *nthash = new(*ntlen + 1);
105 buf = new(8+blen + 1);
106 memcpy(buf, MEM(challenge, char, 24), 8);
107 memcpy(buf+8, blob, blen);
108 hmac_md5(passnt2, 16, buf, 8+blen, *nthash);
109 memcpy(*nthash+16, blob, blen);
110 free(buf);
112 *lmlen = 24;
113 *lmhash = new(*lmlen + 1);
114 buf = new(16 + 1);
115 memcpy(buf, MEM(challenge, char, 24), 8);
116 memcpy(buf+8, nonce, 8);
117 hmac_md5(passnt2, 16, buf, 16, *lmhash);
118 memcpy(*lmhash+16, nonce, 8);
119 free(buf);
121 free(blob);
122 free(nonce);
123 return;
126 static void ntlm2sr_calc_rest(char **nthash, int *ntlen, char **lmhash, int *lmlen, char *passnt, char *challenge) {
127 char *sess, *nonce, *buf;
129 nonce = new(8 + 1);
130 VAL(nonce, uint64_t, 0) = ((uint64_t)random() << 32) | random();
132 *lmlen = 24;
133 *lmhash = new(*lmlen + 1);
134 memcpy(*lmhash, nonce, 8);
135 memset(*lmhash+8, 0, 16);
137 buf = new(16 + 1);
138 sess = new(16 + 1);
139 memcpy(buf, MEM(challenge, char, 24), 8);
140 memcpy(buf+8, nonce, 8);
141 md5_buffer(buf, 16, sess);
142 free(buf);
144 *ntlen = 24;
145 ntlm_calc_resp(nthash, passnt, sess);
147 free(sess);
148 free(nonce);
149 return;
152 char *ntlm_hash_lm_password(char *password) {
153 char magic[8] = {0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
154 gl_des_ctx context;
155 char *keys, *pass;
157 keys = new(21 + 1);
158 pass = new(14 + 1);
159 uppercase(strncpy(pass, password, MIN(14, strlen(password))));
161 ntlm_set_key(MEM(pass, unsigned char, 0), &context);
162 gl_des_ecb_encrypt(&context, magic, keys);
164 ntlm_set_key(MEM(pass, unsigned char, 7), &context);
165 gl_des_ecb_encrypt(&context, magic, keys+8);
167 memset(keys+16, 0, 5);
168 memset(pass, 0, 14);
169 free(pass);
171 return keys;
174 char *ntlm_hash_nt_password(char *password) {
175 char *u16, *keys;
176 int len;
178 keys = new(21 + 1);
179 len = unicode(&u16, password);
180 md4_buffer(u16, len, keys);
182 memset(keys+16, 0, 5);
183 memset(u16, 0, len);
184 free(u16);
186 return keys;
189 char *ntlm2_hash_password(char *username, char *domain, char *password) {
190 char *tmp, *buf, *passnt, *passnt2;
191 int len;
193 passnt = ntlm_hash_nt_password(password);
195 buf = new(strlen(username)+strlen(domain) + 1);
196 strcat(buf, username);
197 strcat(buf, domain);
198 uppercase(buf);
199 len = unicode(&tmp, buf);
201 passnt2 = new(16 + 1);
202 hmac_md5(passnt, 16, tmp, len, passnt2);
204 free(passnt);
205 free(tmp);
206 free(buf);
208 return passnt2;
211 int ntlm_request(char **dst, struct auth_s *creds) {
212 char *buf, *tmp;
213 int dlen, hlen;
214 uint32_t flags = 0xb206;
216 *dst = NULL;
217 dlen = strlen(creds->domain);
218 hlen = strlen(creds->workstation);
220 if (!creds->flags) {
221 if (creds->hashntlm2)
222 flags = 0xa208b205;
223 else if (creds->hashnt == 2)
224 flags = 0xa208b207;
225 else if (creds->hashnt && creds->hashlm)
226 flags = 0xb207;
227 else if (creds->hashnt)
228 flags = 0xb205;
229 else if (creds->hashlm)
230 flags = 0xb206;
231 else {
232 if (debug) {
233 printf("You're requesting with empty auth_s?!\n");
234 dump_auth(creds);
236 return 0;
238 } else
239 flags = creds->flags;
241 if (debug) {
242 printf("NTLM Request:\n");
243 printf("\t Domain: %s\n", creds->domain);
244 printf("\t Hostname: %s\n", creds->workstation);
245 printf("\t Flags: 0x%X\n", (int)flags);
248 buf = new(NTLM_BUFSIZE);
249 memcpy(buf, "NTLMSSP\0", 8);
250 VAL(buf, uint32_t, 8) = U32LE(1);
251 VAL(buf, uint32_t, 12) = U32LE(flags);
252 VAL(buf, uint16_t, 16) = U16LE(dlen);
253 VAL(buf, uint16_t, 18) = U16LE(dlen);
254 VAL(buf, uint32_t, 20) = U32LE(32 + hlen);
255 VAL(buf, uint16_t, 24) = U16LE(hlen);
256 VAL(buf, uint16_t, 26) = U16LE(hlen);
257 VAL(buf, uint32_t, 28) = U32LE(32);
259 tmp = uppercase(strdup(creds->workstation));
260 memcpy(buf+32, tmp, hlen);
261 free(tmp);
263 tmp = uppercase(strdup(creds->domain));
264 memcpy(buf+32+hlen, tmp, dlen);
265 free(tmp);
267 *dst = buf;
268 return 32+dlen+hlen;
271 static char *printuc(char *src, int len) {
272 char *tmp;
273 int i;
275 tmp = new((len+1)/2 + 1);
276 for (i = 0; i < len/2; ++i) {
277 tmp[i] = src[i*2];
280 return tmp;
284 void dump(char *src, int len) {
285 int i, j;
286 char *tmp;
288 tmp = new(len*3+4);
289 for (i = 0; i < len; ++i) {
290 snprintf(tmp+i*3, 4, "%0hhX ", src[i]);
291 printf("%c ", src[i]);
293 printf("\n%s\n", tmp);
294 free(tmp);
298 int ntlm_response(char **dst, char *challenge, int challen, struct auth_s *creds) {
299 char *buf, *udomain, *uuser, *uhost, *tmp;
300 int dlen, ulen, hlen;
301 uint16_t tpos, tlen, ttype = -1, tbofs = 0, tblen = 0;
302 char *lmhash = NULL, *nthash = NULL;
303 int lmlen = 0, ntlen = 0;
305 if (debug) {
306 printf("NTLM Challenge:\n");
307 tmp = printmem(MEM(challenge, char, 24), 8, 7);
308 printf("\tChallenge: %s (len: %d)\n", tmp, challen);
309 free(tmp);
310 printf("\t Flags: 0x%X\n", U32LE(VAL(challenge, uint32_t, 20)));
313 if (challen > 48) {
314 tbofs = tpos = U16LE(VAL(challenge, uint16_t, 44));
315 while (tpos+4 <= challen && (ttype = U16LE(VAL(challenge, uint16_t, tpos)))) {
316 tlen = U16LE(VAL(challenge, uint16_t, tpos+2));
317 if (tpos+4+tlen > challen)
318 break;
320 if (debug) {
321 switch (ttype) {
322 case 0x1:
323 printf("\t Server: ");
324 break;
325 case 0x2:
326 printf("\tNT domain: ");
327 break;
328 case 0x3:
329 printf("\t FQDN: ");
330 break;
331 case 0x4:
332 printf("\t Domain: ");
333 break;
334 case 0x5:
335 printf("\t TLD: ");
336 break;
337 default:
338 printf("\t %3d: ", ttype);
339 break;
341 tmp = printuc(MEM(challenge, char, tpos+4), tlen);
342 printf("%s\n", tmp);
343 free(tmp);
346 tpos += 4+tlen;
347 tblen += 4+tlen;
350 if (tblen && ttype == 0)
351 tblen += 4;
353 if (debug) {
354 printf("\t TBofs: %d\n\t TBlen: %d\n\t ttype: %d\n", tbofs, tblen, ttype);
358 if (creds->hashntlm2 && !tblen) {
359 return 0;
362 if (creds->hashntlm2) {
363 ntlm2_calc_resp(&nthash, &ntlen, &lmhash, &lmlen, creds->passntlm2, challenge, tbofs, tblen);
366 if (creds->hashnt == 2) {
367 ntlm2sr_calc_rest(&nthash, &ntlen, &lmhash, &lmlen, creds->passnt, challenge);
370 if (creds->hashnt == 1) {
371 ntlen = ntlm_calc_resp(&nthash, creds->passnt, MEM(challenge, char, 24));
374 if (creds->hashlm) {
375 lmlen = ntlm_calc_resp(&lmhash, creds->passlm, MEM(challenge, char, 24));
378 if (creds->hashnt || creds->hashntlm2) {
379 tmp = uppercase(strdup(creds->domain));
380 dlen = unicode(&udomain, tmp);
381 free(tmp);
382 ulen = unicode(&uuser, creds->user);
383 tmp = uppercase(strdup(creds->workstation));
384 hlen = unicode(&uhost, tmp);
385 free(tmp);
386 } else {
387 udomain = uppercase(strdup(creds->domain));
388 uuser = uppercase(strdup(creds->user));
389 uhost = uppercase(strdup(creds->workstation));
391 dlen = strlen(creds->domain);
392 ulen = strlen(creds->user);
393 hlen = strlen(creds->workstation);
396 if (debug) {
397 printf("NTLM Response:\n");
398 printf("\t Hostname: '%s'\n", creds->workstation);
399 printf("\t Domain: '%s'\n", creds->domain);
400 printf("\t Username: '%s'\n", creds->user);
401 if (ntlen) {
402 tmp = printmem(nthash, ntlen, 7);
403 printf("\t Response: '%s' (%d)\n", tmp, ntlen);
404 free(tmp);
406 if (lmlen) {
407 tmp = printmem(lmhash, lmlen, 7);
408 printf("\t Response: '%s' (%d)\n", tmp, lmlen);
409 free(tmp);
413 buf = new(NTLM_BUFSIZE);
414 memcpy(buf, "NTLMSSP\0", 8);
415 VAL(buf, uint32_t, 8) = U32LE(3);
417 /* LM */
418 VAL(buf, uint16_t, 12) = U16LE(lmlen);
419 VAL(buf, uint16_t, 14) = U16LE(lmlen);
420 VAL(buf, uint32_t, 16) = U32LE(64+dlen+ulen+hlen);
422 /* NT */
423 VAL(buf, uint16_t, 20) = U16LE(ntlen);
424 VAL(buf, uint16_t, 22) = U16LE(ntlen);
425 VAL(buf, uint32_t, 24) = U32LE(64+dlen+ulen+hlen+lmlen);
427 /* Domain */
428 VAL(buf, uint16_t, 28) = U16LE(dlen);
429 VAL(buf, uint16_t, 30) = U16LE(dlen);
430 VAL(buf, uint32_t, 32) = U32LE(64);
432 /* Username */
433 VAL(buf, uint16_t, 36) = U16LE(ulen);
434 VAL(buf, uint16_t, 38) = U16LE(ulen);
435 VAL(buf, uint32_t, 40) = U32LE(64+dlen);
437 /* Hostname */
438 VAL(buf, uint16_t, 44) = U16LE(hlen);
439 VAL(buf, uint16_t, 46) = U16LE(hlen);
440 VAL(buf, uint32_t, 48) = U32LE(64+dlen+ulen);
442 /* Session */
443 VAL(buf, uint16_t, 52) = U16LE(0);
444 VAL(buf, uint16_t, 54) = U16LE(0);
445 VAL(buf, uint16_t, 56) = U16LE(64+dlen+ulen+hlen+lmlen+ntlen);
447 /* Flags */
448 VAL(buf, uint32_t, 60) = VAL(challenge, uint32_t, 20);
450 memcpy(MEM(buf, char, 64), udomain, dlen);
451 memcpy(MEM(buf, char, 64+dlen), uuser, ulen);
452 memcpy(MEM(buf, char, 64+dlen+ulen), uhost, hlen);
453 memcpy(MEM(buf, char, 64+dlen+ulen+hlen), lmhash, lmlen);
454 memcpy(MEM(buf, char, 64+dlen+ulen+hlen+24), nthash, ntlen);
456 if (nthash)
457 free(nthash);
458 if (lmhash)
459 free(lmhash);
461 free(uhost);
462 free(uuser);
463 free(udomain);
465 *dst = buf;
466 return 64+dlen+ulen+hlen+lmlen+ntlen;