1/*
2   Unix SMB/CIFS implementation.
3   Password and authentication handling
4   Copyright (C) Andrew Tridgell              1992-2000
5   Copyright (C) Luke Kenneth Casson Leighton 1996-2000
6   Copyright (C) Andrew Bartlett              2001-2003
7   Copyright (C) Gerald Carter                2003
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24#include "includes.h"
25
26#undef DBGC_CLASS
27#define DBGC_CLASS DBGC_AUTH
28
29/****************************************************************************
30 Core of smb password checking routine.
31****************************************************************************/
32
33static BOOL smb_pwd_check_ntlmv1(const DATA_BLOB *nt_response,
34				 const uchar *part_passwd,
35				 const DATA_BLOB *sec_blob,
36				 DATA_BLOB *user_sess_key)
37{
38	/* Finish the encryption of part_passwd. */
39	uchar p24[24];
40
41	if (part_passwd == NULL) {
42		DEBUG(10,("No password set - DISALLOWING access\n"));
43		/* No password set - always false ! */
44		return False;
45	}
46
47	if (sec_blob->length != 8) {
48		DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challenge size (%lu)\n",
49			  (unsigned long)sec_blob->length));
50		return False;
51	}
52
53	if (nt_response->length != 24) {
54		DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%lu)\n",
55			  (unsigned long)nt_response->length));
56		return False;
57	}
58
59	SMBOWFencrypt(part_passwd, sec_blob->data, p24);
60	if (user_sess_key != NULL) {
61		*user_sess_key = data_blob(NULL, 16);
62		SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key->data);
63	}
64
65
66#ifdef DEBUG_PASSWORD
67	DEBUG(100,("Part password (P16) was |\n"));
68	dump_data(100, (const char *)part_passwd, 16);
69	DEBUGADD(100,("Password from client was |\n"));
70	dump_data(100, (const char *)nt_response->data, nt_response->length);
71	DEBUGADD(100,("Given challenge was |\n"));
72	dump_data(100, (const char *)sec_blob->data, sec_blob->length);
73	DEBUGADD(100,("Value from encryption was |\n"));
74	dump_data(100, (const char *)p24, 24);
75#endif
76	return (memcmp(p24, nt_response->data, 24) == 0);
77}
78
79/****************************************************************************
80 Core of smb password checking routine. (NTLMv2, LMv2)
81 Note:  The same code works with both NTLMv2 and LMv2.
82****************************************************************************/
83
84static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB *ntv2_response,
85				 const uchar *part_passwd,
86				 const DATA_BLOB *sec_blob,
87				 const char *user, const char *domain,
88				 BOOL upper_case_domain, /* should the domain be transformed into upper case? */
89				 DATA_BLOB *user_sess_key)
90{
91	/* Finish the encryption of part_passwd. */
92	uchar kr[16];
93	uchar value_from_encryption[16];
94	uchar client_response[16];
95	DATA_BLOB client_key_data;
96	BOOL res;
97
98	if (part_passwd == NULL) {
99		DEBUG(10,("No password set - DISALLOWING access\n"));
100		/* No password set - always False */
101		return False;
102	}
103
104	if (sec_blob->length != 8) {
105		DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect challenge size (%lu)\n",
106			  (unsigned long)sec_blob->length));
107		return False;
108	}
109
110	if (ntv2_response->length < 24) {
111		/* We MUST have more than 16 bytes, or the stuff below will go
112		   crazy.  No known implementation sends less than the 24 bytes
113		   for LMv2, let alone NTLMv2. */
114		DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%lu)\n",
115			  (unsigned long)ntv2_response->length));
116		return False;
117	}
118
119	client_key_data = data_blob(ntv2_response->data+16, ntv2_response->length-16);
120	/*
121	   todo:  should we be checking this for anything?  We can't for LMv2,
122	   but for NTLMv2 it is meant to contain the current time etc.
123	*/
124
125	memcpy(client_response, ntv2_response->data, sizeof(client_response));
126
127	if (!ntv2_owf_gen(part_passwd, user, domain, upper_case_domain, kr)) {
128		return False;
129	}
130
131	SMBOWFencrypt_ntv2(kr, sec_blob, &client_key_data, value_from_encryption);
132	if (user_sess_key != NULL) {
133		*user_sess_key = data_blob(NULL, 16);
134		SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key->data);
135	}
136
137#if DEBUG_PASSWORD
138	DEBUG(100,("Part password (P16) was |\n"));
139	dump_data(100, (const char *)part_passwd, 16);
140	DEBUGADD(100,("Password from client was |\n"));
141	dump_data(100, (const char *)ntv2_response->data, ntv2_response->length);
142	DEBUGADD(100,("Variable data from client was |\n"));
143	dump_data(100, (const char *)client_key_data.data, client_key_data.length);
144	DEBUGADD(100,("Given challenge was |\n"));
145	dump_data(100, (const char *)sec_blob->data, sec_blob->length);
146	DEBUGADD(100,("Value from encryption was |\n"));
147	dump_data(100, (const char *)value_from_encryption, 16);
148#endif
149	data_blob_clear_free(&client_key_data);
150	res = (memcmp(value_from_encryption, client_response, 16) == 0);
151	if ((!res) && (user_sess_key != NULL))
152		data_blob_clear_free(user_sess_key);
153	return res;
154}
155
156/**
157 * Check a challenge-response password against the value of the NT or
158 * LM password hash.
159 *
160 * @param mem_ctx talloc context
161 * @param challenge 8-byte challenge.  If all zero, forces plaintext comparison
162 * @param nt_response 'unicode' NT response to the challenge, or unicode password
163 * @param lm_response ASCII or LANMAN response to the challenge, or password in DOS code page
164 * @param username internal Samba username, for log messages
165 * @param client_username username the client used
166 * @param client_domain domain name the client used (may be mapped)
167 * @param nt_pw MD4 unicode password from our passdb or similar
168 * @param lm_pw LANMAN ASCII password from our passdb or similar
169 * @param user_sess_key User session key
170 * @param lm_sess_key LM session key (first 8 bytes of the LM hash)
171 */
172
173NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
174			     const DATA_BLOB *challenge,
175			     const DATA_BLOB *lm_response,
176			     const DATA_BLOB *nt_response,
177			     const DATA_BLOB *lm_interactive_pwd,
178			     const DATA_BLOB *nt_interactive_pwd,
179			     const char *username,
180			     const char *client_username,
181			     const char *client_domain,
182			     const uint8 *lm_pw, const uint8 *nt_pw,
183			     DATA_BLOB *user_sess_key,
184			     DATA_BLOB *lm_sess_key)
185{
186	static const unsigned char zeros[8] = { 0, };
187	FILE* fp = NULL;//water, If all shared folders are 'All - no password', then no need to login for "HTTP", "FTP" or samba.
188    int no_password = 0;    // Foxconn added pling 11/30/2009 */
189	if (nt_pw == NULL) {
190		DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n",
191			 username));
192	}
193
194	if (nt_interactive_pwd && nt_interactive_pwd->length && nt_pw) {
195		if (nt_interactive_pwd->length != 16) {
196			DEBUG(3,("ntlm_password_check: Interactive logon: Invalid NT password length (%d) supplied for user %s\n", (int)nt_interactive_pwd->length,
197				 username));
198			return NT_STATUS_WRONG_PASSWORD;
199		}
200
201		if (memcmp(nt_interactive_pwd->data, nt_pw, 16) == 0) {
202			if (user_sess_key) {
203				*user_sess_key = data_blob(NULL, 16);
204				SMBsesskeygen_ntv1(nt_pw, NULL, user_sess_key->data);
205			}
206			return NT_STATUS_OK;
207		} else {
208			DEBUG(3,("ntlm_password_check: Interactive logon: NT password check failed for user %s\n",
209				 username));
210			return NT_STATUS_WRONG_PASSWORD;
211		}
212
213	} else if (lm_interactive_pwd && lm_interactive_pwd->length && lm_pw) {
214		if (lm_interactive_pwd->length != 16) {
215			DEBUG(3,("ntlm_password_check: Interactive logon: Invalid LANMAN password length (%d) supplied for user %s\n", (int)lm_interactive_pwd->length,
216				 username));
217			return NT_STATUS_WRONG_PASSWORD;
218		}
219
220		if (!lp_lanman_auth()) {
221			DEBUG(3,("ntlm_password_check: Interactive logon: only LANMAN password supplied for user %s, and LM passwords are disabled!\n",
222				 username));
223			return NT_STATUS_WRONG_PASSWORD;
224		}
225
226		if (memcmp(lm_interactive_pwd->data, lm_pw, 16) == 0) {
227			return NT_STATUS_OK;
228		} else {
229			DEBUG(3,("ntlm_password_check: Interactive logon: LANMAN password check failed for user %s\n",
230				 username));
231			return NT_STATUS_WRONG_PASSWORD;
232		}
233	}
234
235	/* Check for cleartext netlogon. Used by Exchange 5.5. */
236	if (challenge->length == sizeof(zeros) &&
237	    (memcmp(challenge->data, zeros, challenge->length) == 0 )) {
238
239		DEBUG(4,("ntlm_password_check: checking plaintext passwords for user %s\n",
240			 username));
241		if (nt_pw && nt_response->length) {
242			unsigned char pwhash[16];
243			mdfour(pwhash, nt_response->data, nt_response->length);
244			if (memcmp(pwhash, nt_pw, sizeof(pwhash)) == 0) {
245				return NT_STATUS_OK;
246			} else {
247				DEBUG(3,("ntlm_password_check: NT (Unicode) plaintext password check failed for user %s\n",
248					 username));
249				return NT_STATUS_WRONG_PASSWORD;
250			}
251
252		} else if (!lp_lanman_auth()) {
253			DEBUG(3,("ntlm_password_check: (plaintext password check) LANMAN passwords NOT PERMITTED for user %s\n",
254				 username));
255
256		} else if (lm_pw && lm_response->length) {
257			uchar dospwd[14];
258			uchar p16[16];
259			ZERO_STRUCT(dospwd);
260
261			memcpy(dospwd, lm_response->data, MIN(lm_response->length, sizeof(dospwd)));
262			/* Only the fisrt 14 chars are considered, password need not be null terminated. */
263
264			/* we *might* need to upper-case the string here */
265			E_P16((const unsigned char *)dospwd, p16);
266
267			if (memcmp(p16, lm_pw, sizeof(p16)) == 0) {
268				return NT_STATUS_OK;
269			} else {
270				DEBUG(3,("ntlm_password_check: LANMAN (ASCII) plaintext password check failed for user %s\n",
271					 username));
272				return NT_STATUS_WRONG_PASSWORD;
273			}
274		} else {
275			DEBUG(3, ("Plaintext authentication for user %s attempted, but neither NT nor LM passwords available\n", username));
276			return NT_STATUS_WRONG_PASSWORD;
277		}
278	}
279
280	if (nt_response->length != 0 && nt_response->length < 24) {
281		DEBUG(2,("ntlm_password_check: invalid NT password length (%lu) for user %s\n",
282			 (unsigned long)nt_response->length, username));
283	}
284
285	if (nt_response->length >= 24 && nt_pw) {
286		if (nt_response->length > 24) {
287			/* We have the NT MD4 hash challenge available - see if we can
288			   use it
289			*/
290			DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n", client_domain));
291			if (smb_pwd_check_ntlmv2( nt_response,
292						  nt_pw, challenge,
293						  client_username,
294						  client_domain,
295						  False,
296						  user_sess_key)) {
297				return NT_STATUS_OK;
298			}
299
300			DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n", client_domain));
301			if (smb_pwd_check_ntlmv2( nt_response,
302						  nt_pw, challenge,
303						  client_username,
304						  client_domain,
305						  True,
306						  user_sess_key)) {
307				return NT_STATUS_OK;
308			}
309
310			DEBUG(0,("ntlm_password_check: Checking NTLMv2 password without a domain\n"));
311
312			/*foxconn add start, water, 06/08/2009*/
313			/*If all shared folders are 'All - no password',
314			 then no need to login for "HTTP", "FTP" or samba.*/
315			fp = fopen("/tmp/all_no_password","r");
316			if (fp != NULL)
317			{
318			    fclose(fp);
319			    DEBUG(0, ("all_no_password, ntlm_check.c\n"));
320    			return NT_STATUS_OK;
321			}
322			/*foxconn add end, water, 06/08/2009*/
323
324			/*foxconn add start, water, 11/17/2008*/
325			/*when username=guest, user can access the shared folder with any password*/
326			if (0 == strcmp("guest", client_username))
327    		{
328    			DEBUG(0, ("guest, ntlm_check.c\n"));
329    			return NT_STATUS_OK;
330    		}
331			//return NT_STATUS_OK;
332			/*foxconn add end, water, 11/17/2008*/
333			if (smb_pwd_check_ntlmv2( nt_response,
334						  nt_pw, challenge,
335						  client_username,
336						  "",
337						  False,
338						  user_sess_key)) {
339				return NT_STATUS_OK;
340			} else {
341				DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n"));
342				return NT_STATUS_WRONG_PASSWORD;
343			}
344		}
345
346		if (lp_ntlm_auth()) {
347			/* We have the NT MD4 hash challenge available - see if we can
348			   use it (ie. does it exist in the smbpasswd file).
349			*/
350			DEBUG(0,("ntlm_password_check: Checking NT MD4 password\n"));
351
352			/*foxconn add start, water, 06/08/2009*/
353			/*If all shared folders are 'All - no password',
354			 then no need to login for "HTTP", "FTP" or samba.*/
355			fp = fopen("/tmp/all_no_password","r");
356			if (fp != NULL)
357			{
358			    fclose(fp);
359			    DEBUG(0, ("all_no_password, ntlm_check.c\n"));
360    			return NT_STATUS_OK;
361			}
362			/*foxconn add end, water, 06/08/2009*/
363
364			/*foxconn add start, water, 11/17/2008*/
365			/*when username=guest, user can access the shared folder with any password*/
366			if (0 == strcmp("guest", username))
367    		{
368    			DEBUG(0, ("water, guest, ntlm_check.c\n"));
369    			return NT_STATUS_OK;
370    		}
371			//return NT_STATUS_OK;
372			/*foxconn add end, water, 11/17/2008*/
373			if (smb_pwd_check_ntlmv1(nt_response,
374						 nt_pw, challenge,
375						 user_sess_key)) {
376				/* The LM session key for this response is not very secure,
377				   so use it only if we otherwise allow LM authentication */
378
379				if (lp_lanman_auth() && lm_pw) {
380					uint8 first_8_lm_hash[16];
381					memcpy(first_8_lm_hash, lm_pw, 8);
382					memset(first_8_lm_hash + 8, '\0', 8);
383					if (lm_sess_key) {
384						*lm_sess_key = data_blob(first_8_lm_hash, 16);
385					}
386				}
387				return NT_STATUS_OK;
388			} else {
389				DEBUG(3,("ntlm_password_check: NT MD4 password check failed for user %s\n",
390					 username));
391				return NT_STATUS_WRONG_PASSWORD;
392			}
393		} else {
394			DEBUG(2,("ntlm_password_check: NTLMv1 passwords NOT PERMITTED for user %s\n",
395				 username));
396			/* no return, becouse we might pick up LMv2 in the LM field */
397		}
398	}
399
400	/* Foxconn add end pling 11/30/2009 */
401	/* If all shared folders are 'All - no password',
402	 * then no need to login for "HTTP", "FTP" or samba.
403     */
404	fp = fopen("/tmp/all_no_password","r");
405	if (fp != NULL) {
406	    fclose(fp);
407        no_password = 1;
408	}
409	/* Foxconn add end pling 11/30/2009 */
410
411	if (lm_response->length == 0) {
412        /* Foxconn added start pling 11/30/2009 */
413        if (no_password)
414    		return NT_STATUS_OK;
415        /* Foxconn added end pling 11/30/2009 */
416		DEBUG(3,("ntlm_password_check: NEITHER LanMan nor NT password supplied for user %s\n",
417			 username));
418		return NT_STATUS_WRONG_PASSWORD;
419	}
420
421	if (lm_response->length < 24) {
422        /* Foxconn added start pling 11/30/2009 */
423        if (no_password)
424    		return NT_STATUS_OK;
425        /* Foxconn added end pling 11/30/2009 */
426		DEBUG(2,("ntlm_password_check: invalid LanMan password length (%lu) for user %s\n",
427			 (unsigned long)nt_response->length, username));
428		return NT_STATUS_WRONG_PASSWORD;
429	}
430
431	if (!lp_lanman_auth()) {
432		DEBUG(3,("ntlm_password_check: Lanman passwords NOT PERMITTED for user %s\n",
433			 username));
434	} else if (!lm_pw) {
435		DEBUG(3,("ntlm_password_check: NO LanMan password set for user %s (and no NT password supplied)\n",
436			 username));
437	} else {
438		DEBUG(4,("ntlm_password_check: Checking LM password\n"));
439		if (smb_pwd_check_ntlmv1(lm_response,
440					 lm_pw, challenge,
441					 NULL)) {
442			uint8 first_8_lm_hash[16];
443			memcpy(first_8_lm_hash, lm_pw, 8);
444			memset(first_8_lm_hash + 8, '\0', 8);
445			if (user_sess_key) {
446				*user_sess_key = data_blob(first_8_lm_hash, 16);
447			}
448
449			if (lm_sess_key) {
450				*lm_sess_key = data_blob(first_8_lm_hash, 16);
451			}
452			return NT_STATUS_OK;
453		}
454	}
455
456	if (!nt_pw) {
457		DEBUG(4,("ntlm_password_check: LM password check failed for user, no NT password %s\n",username));
458		return NT_STATUS_WRONG_PASSWORD;
459	}
460
461	/* This is for 'LMv2' authentication.  almost NTLMv2 but limited to 24 bytes.
462	   - related to Win9X, legacy NAS pass-though authentication
463	*/
464	DEBUG(4,("ntlm_password_check: Checking LMv2 password with domain %s\n", client_domain));
465	if (smb_pwd_check_ntlmv2( lm_response,
466				  nt_pw, challenge,
467				  client_username,
468				  client_domain,
469				  False,
470				  NULL)) {
471		return NT_STATUS_OK;
472	}
473
474	DEBUG(4,("ntlm_password_check: Checking LMv2 password with upper-cased version of domain %s\n", client_domain));
475	if (smb_pwd_check_ntlmv2( lm_response,
476				  nt_pw, challenge,
477				  client_username,
478				  client_domain,
479				  True,
480				  NULL)) {
481		return NT_STATUS_OK;
482	}
483
484	DEBUG(4,("ntlm_password_check: Checking LMv2 password without a domain\n"));
485	if (smb_pwd_check_ntlmv2( lm_response,
486				  nt_pw, challenge,
487				  client_username,
488				  "",
489				  False,
490				  NULL)) {
491		return NT_STATUS_OK;
492	}
493
494	/* Apparently NT accepts NT responses in the LM field
495	   - I think this is related to Win9X pass-though authentication
496	*/
497	DEBUG(4,("ntlm_password_check: Checking NT MD4 password in LM field\n"));
498	if (lp_ntlm_auth()) {
499		if (smb_pwd_check_ntlmv1(lm_response,
500					 nt_pw, challenge,
501					 NULL)) {
502			/* The session key for this response is still very odd.
503			   It not very secure, so use it only if we otherwise
504			   allow LM authentication */
505
506			if (lp_lanman_auth() && lm_pw) {
507				uint8 first_8_lm_hash[16];
508				memcpy(first_8_lm_hash, lm_pw, 8);
509				memset(first_8_lm_hash + 8, '\0', 8);
510				if (user_sess_key) {
511					*user_sess_key = data_blob(first_8_lm_hash, 16);
512				}
513
514				if (lm_sess_key) {
515					*lm_sess_key = data_blob(first_8_lm_hash, 16);
516				}
517			}
518			return NT_STATUS_OK;
519		}
520		DEBUG(3,("ntlm_password_check: LM password, NT MD4 password in LM field and LMv2 failed for user %s\n",username));
521	} else {
522		DEBUG(3,("ntlm_password_check: LM password and LMv2 failed for user %s, and NT MD4 password in LM field not permitted\n",username));
523	}
524	return NT_STATUS_WRONG_PASSWORD;
525}
526
527