1 /* Proxytunnel - (C) 2001-2008 Jos Visser / Mark Janssen    */
2 /* Contact:                  josv@osp.nl / maniac@maniac.nl */
3 
4 /*
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */
19 
20 /* ntlm.c -- Code for handling NTLM authentication */
21 /* NTLM Code from Paul Solomon <psolomon@tpg.com.au> */
22 
23 #include "ntlm.h"
24 #include "global.h"
25 #include "base64.h"
26 #include <stdlib.h>
27 #include <string.h>
28 #include "proxytunnel.h"
29 #include <ctype.h>
30 #include <sys/time.h>
31 #include <openssl/md4.h>
32 #include <openssl/md5.h>
33 
34 #define TYPE1_DATA_SEG 8
35 #define TYPE2_BUF_SIZE 2048
36 #define DOMAIN_BUFLEN 256
37 #define LM2_DIGEST_LEN 24
38 
39 int ntlm_challenge = 0;
40 void message( char *s, ... );
41 int unicode = 0;
42 
43 unsigned char challenge[8];
44 char domain[DOMAIN_BUFLEN];
45 char workstation[] = "WORKSTATION";
46 
47 unsigned char unipasswd[DOMAIN_BUFLEN * 2];
48 
49 unsigned char t2_buf[TYPE2_BUF_SIZE];
50 
51 unsigned char *pblob = NULL;
52 int bloblen;
53 
54 unsigned char *t_info;
55 int t_info_len;
56 
57 unsigned long flags;
58 
59 unsigned char lm2digest[LM2_DIGEST_LEN];
60 
build_type1()61 void build_type1() {
62 	ntlm_type1 *type1;
63 	int len = sizeof(ntlm_type1) + sizeof(unsigned char) * TYPE1_DATA_SEG;
64 
65 	type1 = (ntlm_type1 *)malloc(len);
66 	if (!type1) {
67 		message("Fatal Error in build type1, Malloc failed\n");
68 		exit(-1);
69 	}
70 
71 	memset(type1, 0, len);
72 	type1->signature[0] = 'N';
73 	type1->signature[1] = 'T';
74 	type1->signature[2] = 'L';
75 	type1->signature[3] = 'M';
76 	type1->signature[4] = 'S';
77 	type1->signature[5] = 'S';
78 	type1->signature[6] = 'P';
79 	type1->signature[7] = '\0';
80 
81 	type1->message_type = NTLM_TYPE_1;
82 	type1->flags = NEG_UNICODE | NEG_OEM | REQ_TARGET | NEG_NTLM | NEG_ASIGN | NEG_NTLM2 | NEG_128 | NEG_56 | IE_SETSTHIS;
83 
84 	base64((unsigned char *)ntlm_type1_buf, (unsigned char *)type1, len);
85 
86 	free(type1);
87 	return;
88 }
89 
90 
parse_type2(unsigned char * buf)91 int parse_type2(unsigned char *buf) {
92 	int len = unbase64(t2_buf, buf, TYPE2_BUF_SIZE);
93 	ntlm_type2 *t2 = (ntlm_type2 *)t2_buf;
94 	int i;
95 
96 	if (len <= 0) {
97 		message("parse_type2: failed to decode the message\n");
98 		return -1;
99 	}
100 
101 	if (strcmp((const char *)t2->signature, "NTLMSSP") != 0) {
102 		message("parse_type2: Signature did not match\n");
103 		return -1;
104 	}
105 
106 	if( args_info.verbose_flag )
107 		message("parse_type2: Signature matched\n");
108 
109 	if (t2->message_type != NTLM_TYPE_2) {
110 		message("parse_type2: Incorrect message type sent\n");
111 		return -1;
112 	}
113 
114 	if (t2->target_name.length > 0 && t2->target_name.length < DOMAIN_BUFLEN && (t2->target_name.length + t2->target_name.offset < len)) {
115 		int sp = 1;
116 		if (t2->flags & NEG_UNICODE)
117 			sp = 2;
118 		for (i = 0; i < t2->target_name.length / sp; i++)
119 			domain[i] = t2_buf[t2->target_name.offset + i * sp];
120 		domain[i] = 0;
121 	} else {
122 		domain[0] = 0;
123 	}
124 
125 	for (i = 0; i < 8; i++)
126 		challenge[i] = t2->challenge[i];
127 
128 	if( args_info.verbose_flag )
129 		message("NTLM Got Domain: %s\n", domain);
130 
131 	if( args_info.domain_given ) {
132 		if( ! args_info.quiet_flag )
133 			message( "NTLM Overriding domain: %s\n", args_info.domain_arg );
134 		for( i = 0; i < strlen(args_info.domain_arg); i++ ) {
135 			domain[i] = args_info.domain_arg[i];
136 		}
137 		domain[i] = 0;
138 	}
139 
140 	if( args_info.verbose_flag ) {
141 		message("NTLM Domain: %s\n", domain);
142 		message("NTLM Got Challenge: ");
143 
144 		for (i = 0; i < 8; i++)
145 			message("%02X", challenge[i]);
146 		message("\n");
147 	}
148 
149 	if (!(t2->flags & NEG_NTLM && t2->flags & NEG_NTLM2)) {
150 		message("parse_type2: Sorry, only NTLMv2 is supported at this time\n");
151 		return -1;
152 	}
153 
154 	if (t2->flags & NEG_UNICODE)
155 		unicode = 1;
156 	else
157 		unicode = 0;
158 
159 	t_info = &t2_buf[t2->target_info.offset];
160 	t_info_len = t2->target_info.length;
161 
162 	flags = t2->flags;
163 
164 	ntlm_challenge = 1;
165 
166 	build_ntlm2_response();
167 
168 	return 0;
169 }
170 
171 
build_type3_response()172 void build_type3_response() {
173 	unsigned char *t3;
174 	ntlm_type3 *type3;
175 	int len;
176 	int sp = 1;
177 	int i;
178 
179 	if (unicode)
180 		sp = 2;
181 
182 	len = sizeof(ntlm_type3) + sizeof(unsigned char) * (LM2_DIGEST_LEN + bloblen + (strlen(domain) + strlen(args_info.user_arg) + strlen(workstation)) * sp);
183 
184 	type3 = (ntlm_type3 *)malloc(len);
185 	if (!type3) {
186 		message("Fatal Error in build type3, Malloc failed\n");
187 		exit(-1);
188 	}
189 	t3 = (unsigned char *) type3;
190 
191 	memset(type3, 0, len);
192 	type3->signature[0] = 'N';
193 	type3->signature[1] = 'T';
194 	type3->signature[2] = 'L';
195 	type3->signature[3] = 'M';
196 	type3->signature[4] = 'S';
197 	type3->signature[5] = 'S';
198 	type3->signature[6] = 'P';
199 	type3->signature[7] = '\0';
200 
201 	type3->message_type = NTLM_TYPE_3;
202 	type3->flags = flags & ~TAR_DOMAIN & ~NEG_TARINFO;
203 
204 	type3->LM_response.length = LM2_DIGEST_LEN;
205 	type3->LM_response.space = LM2_DIGEST_LEN;
206 	type3->LM_response.offset = sizeof(ntlm_type3);
207 	memcpy(&t3[type3->LM_response.offset], lm2digest, LM2_DIGEST_LEN);
208 
209 	type3->NTLM_response.length = bloblen;
210 	type3->NTLM_response.space = bloblen;
211 	type3->NTLM_response.offset = type3->LM_response.offset + type3->LM_response.space;
212 	memcpy(&t3[type3->NTLM_response.offset], pblob, bloblen);
213 
214 	type3->domain.length = strlen(domain) * sp;
215 	type3->domain.space = strlen(domain) * sp;
216 	type3->domain.offset = type3->NTLM_response.offset + type3->NTLM_response.space;
217 	for (i = 0; i < strlen(domain); i++)
218 		t3[type3->domain.offset + i * sp] = domain[i];
219 
220 	type3->user.length = strlen(args_info.user_arg) * sp;
221 	type3->user.space = strlen(args_info.user_arg) * sp;
222 	type3->user.offset = type3->domain.offset + type3->domain.space;
223 	for (i = 0; i < strlen(args_info.user_arg); i++)
224 		t3[type3->user.offset + i * sp] = args_info.user_arg[i];
225 
226 	type3->workstation.length = strlen(workstation) * sp;
227 	type3->workstation.space = strlen(workstation) * sp;
228 	type3->workstation.offset = type3->user.offset + type3->user.space;
229 	for (i = 0; i < strlen(workstation); i++)
230 		t3[type3->workstation.offset + i * sp] = workstation[i];
231 
232 	base64((unsigned char *)ntlm_type3_buf, (unsigned char *)type3, len);
233 
234 	free(type3);
235 	return;
236 }
237 
238 /*
239 ** Function: hmac_md5
240 */
241 
242 void
hmac_md5(text,text_len,key,key_len,digest)243 hmac_md5(text, text_len, key, key_len, digest)
244 unsigned char* text; /* pointer to data stream */
245 int text_len; /* length of data stream */
246 unsigned char* key; /* pointer to authentication key */
247 int key_len; /* length of authentication key */
248 unsigned char digest[16]; /* caller digest to be filled in */
249 {
250 	MD5_CTX context;
251 	unsigned char k_ipad[65];    /* inner padding - key XORd with ipad */
252 	unsigned char k_opad[65];    /* outer padding - key XORd with opad */
253 	unsigned char tk[16];
254 	int i;
255 
256 	/* if key is longer than 64 bytes reset it to key=MD5(key) */
257 	if (key_len > 64) {
258 		MD5_CTX tctx;
259 		MD5_Init( &tctx );
260 		MD5_Update( &tctx, key, key_len );
261 		MD5_Final( tk, &tctx );
262 		key = tk;
263 		key_len = 16;
264 	}
265 
266 	/*
267 	 * the HMAC_MD5 transform looks like:
268 	 *
269 	 * MD5(K XOR opad, MD5(K XOR ipad, text))
270 	 *
271 	 * where K is an n byte key
272 	 * ipad is the byte 0x36 repeated 64 times
273 	 * opad is the byte 0x5c repeated 64 times
274 	 * and text is the data being protected
275 	 */
276 
277 	/* start out by storing key in pads */
278 	bzero( k_ipad, sizeof k_ipad);
279 	bzero( k_opad, sizeof k_opad);
280 	bcopy( key, k_ipad, key_len);
281 	bcopy( key, k_opad, key_len);
282 
283 	/* XOR key with ipad and opad values */
284 	for (i=0; i<64; i++) {
285 		k_ipad[i] ^= 0x36;
286 		k_opad[i] ^= 0x5c;
287 	}
288 
289 	/* perform inner MD5 */
290 	MD5_Init(&context);                   /* init context for 1st pass */
291 	MD5_Update(&context, k_ipad, 64);     /* start with inner pad */
292 	MD5_Update(&context, text, text_len); /* then text of datagram */
293 	MD5_Final(digest, &context);          /* finish up 1st pass */
294 
295 	/* perform outer MD5 */
296 	MD5_Init(&context);                   /* init context for 2nd pass */
297 	MD5_Update(&context, k_opad, 64);     /* start with outer pad */
298 	MD5_Update(&context, digest, 16);     /* then results of 1st hash */
299 	MD5_Final(digest, &context);          /* finish up 2nd pass */
300 }
301 
build_ntlm2_response()302 void build_ntlm2_response() {
303 	int i, j;
304 	int passlen = 0;
305 	MD4_CTX passcontext;
306 	unsigned char passdigest[16];
307 	unsigned char *userdom;
308 	int userdomlen;
309 	unsigned char userdomdigest[16];
310 	blob *b;
311 	struct timeval t;
312 	unsigned char responsedigest[16];
313 	unsigned char lm2data[16];
314 
315 	if (pblob != NULL)
316 		free(pblob);
317 
318 	memset(unipasswd, 0, sizeof(unsigned char) * DOMAIN_BUFLEN * 2);
319 	for (i = 0; i < strlen(args_info.pass_arg); i++) {
320 		if (unicode) {
321 			unipasswd[i * 2] = args_info.pass_arg[i];
322 			passlen++;
323 			passlen++;
324 		} else {
325 			unipasswd[i] = args_info.pass_arg[i];
326 			passlen++;
327 		}
328 	}
329 
330 	MD4_Init (&passcontext);
331 	MD4_Update (&passcontext, unipasswd, passlen);
332 	MD4_Final (passdigest, &passcontext);
333 
334 	if( args_info.verbose_flag ) {
335 		message("NTLM: MD4 of password is: ");
336 		for( i = 0; i < 16; i++)
337 			message("%02X", passdigest[i]);
338 		message("\nDOMAIN: %s\nUSER: %s\n", domain, args_info.user_arg);
339 	}
340 
341 	userdomlen = sizeof(unsigned char) * (strlen(args_info.user_arg) + strlen(domain)) * 2;
342 	userdom = (unsigned char *)malloc(userdomlen);
343 	memset(userdom, 0, userdomlen);
344 	if (!userdom) {
345 		message("Fatal Error in build_ntlm2_response, Malloc failed\n");
346 		exit(-1);
347 	}
348 
349 	userdomlen = 0;
350 	for (i = 0; i < strlen(args_info.user_arg); i++) {
351 		if (unicode) {
352 			userdom[i * 2] = toupper(args_info.user_arg[i]);
353 			userdomlen++;
354 			userdomlen++;
355 		} else {
356 			userdom[i] = toupper(args_info.user_arg[i]);
357 			userdomlen++;
358 		}
359 	}
360 
361 	for (j = 0; j < strlen(domain); j++) {
362 		if (unicode) {
363 			userdom[i * 2 + j * 2] = toupper(domain[j]);
364 			userdomlen++;
365 			userdomlen++;
366 		} else {
367 			userdom[i + j] = toupper(domain[j]);
368 			userdomlen++;
369 		}
370 	}
371 
372 	if( args_info.verbose_flag ) {
373 		message("userdom is: ");
374 		for( i = 0; i < userdomlen; i++)
375 			message("%02X", userdom[i]);
376 		message("\n");
377 	}
378 
379 	hmac_md5(userdom, userdomlen, passdigest, 16, userdomdigest);
380 
381 	free(userdom);
382 
383 	if( args_info.verbose_flag ) {
384 		message("HMAC_MD5 of userdom keyed with MD4 pass is: ");
385 		for( i = 0; i < 16; i++)
386 			message("%02X", userdomdigest[i]);
387 		message("\n");
388 	}
389 
390 	if ((sizeof(long long) != 8)) {
391 		message("We are in trouble here.. long long support is not here!!\n");
392 		exit(-1);
393 	}
394 
395 	bloblen = sizeof(blob) + sizeof(unsigned char) * t_info_len;
396 
397 	pblob = (unsigned char *)malloc(bloblen);
398 	if (!pblob) {
399 		message("Fatal Error in build_ntlm2_response, Malloc failed\n");
400 		exit(-1);
401 	}
402 
403 	memset(pblob, 0, bloblen);
404 
405 	b = (blob *)pblob;
406 
407 	for (i = 0; i < 8; i++)
408 		b->digest[8 + i] = challenge[i];
409 
410 	b->signature = 0x00000101;
411 
412 	/* This is nasty, also not sure all this 64bit arithmetic will
413 	 * work all the time.. basically the spec says you need the
414 	 * number of 10ths of microseconds since jan 1, 1601.
415 	 */
416 
417 	gettimeofday(&t, NULL);
418 	b->timestamp = (long long)t.tv_sec;
419 	b->timestamp += 11644473600LL;
420 	b->timestamp *= 1000000LL;
421 	b->timestamp += (long long)t.tv_usec;
422 	b->timestamp *= 10LL;
423 
424 	// need a ramdom client challenge
425 	for (i = 0; i < 8; i++)
426 		b->client_challenge[i] = (unsigned char) ((256.0 * rand()) / (RAND_MAX + 1.0)) ;
427 
428 	if( args_info.verbose_flag ) {
429 		message("client_challenge is: ");
430 		for( i = 0; i < 8; i++)
431 			message("%02X", b->client_challenge[i]);
432 		message("\n");
433 	}
434 
435 	memcpy(&b->data_start, t_info, t_info_len);
436 
437 	hmac_md5(&pblob[8], bloblen - 8, userdomdigest, 16, responsedigest);
438 
439 	for(i = 0; i < 16; i++)
440 		b->digest[i] = responsedigest[i];
441 
442 	if( args_info.verbose_flag ) {
443 		message("HMAC is: ");
444 		for( i = 0; i < 16; i++)
445 			message("%02X", responsedigest[i]);
446 		message("\n");
447 	}
448 
449 	// LM2 response generation
450 
451 	for (i = 0; i < 8; i++)
452 		lm2data[i] = challenge[i];
453 
454 	for (i = 0; i < 8; i++)
455 		lm2data[8 + i] = b->client_challenge[i];
456 
457 	hmac_md5(lm2data, 16, userdomdigest, 16, lm2digest);
458 
459 	for (i = 0; i < 8; i++)
460 		lm2digest[16 + i] = b->client_challenge[i];
461 }
462 
463 // vim:noexpandtab:ts=4
464