cb4be7f6507c76dd7581473c56cce4085db23dd3
[samba.git] / libcli / auth / ntlm_check.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Password and authentication handling
4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2004
5    Copyright (C) Gerald Carter                             2003
6    Copyright (C) Luke Kenneth Casson Leighton         1996-2000
7
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 3 of the License, or
11    (at your option) any later version.
12
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.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "lib/crypto/md4.h"
24 #include "librpc/gen_ndr/netlogon.h"
25 #include "libcli/auth/libcli_auth.h"
26
27 /****************************************************************************
28  Core of smb password checking routine.
29 ****************************************************************************/
30
31 static bool smb_pwd_check_ntlmv1(TALLOC_CTX *mem_ctx,
32                                  const DATA_BLOB *nt_response,
33                                  const uint8_t *part_passwd,
34                                  const DATA_BLOB *sec_blob,
35                                  DATA_BLOB *user_sess_key)
36 {
37         /* Finish the encryption of part_passwd. */
38         uint8_t p24[24];
39         int rc;
40         bool ok;
41
42         if (part_passwd == NULL) {
43                 DEBUG(10,("No password set - DISALLOWING access\n"));
44                 /* No password set - always false ! */
45                 return false;
46         }
47
48         if (sec_blob->length != 8) {
49                 DBG_ERR("incorrect challenge size (%zu)\n", sec_blob->length);
50                 return false;
51         }
52
53         if (nt_response->length != 24) {
54                 DBG_ERR("incorrect password length (%zu)\n",
55                         nt_response->length);
56                 return false;
57         }
58
59         rc = SMBOWFencrypt(part_passwd, sec_blob->data, p24);
60         if (rc != 0) {
61                 return false;
62         }
63
64 #if DEBUG_PASSWORD
65         DEBUG(100,("Part password (P16) was |\n"));
66         dump_data(100, part_passwd, 16);
67         DEBUGADD(100,("Password from client was |\n"));
68         dump_data(100, nt_response->data, nt_response->length);
69         DEBUGADD(100,("Given challenge was |\n"));
70         dump_data(100, sec_blob->data, sec_blob->length);
71         DEBUGADD(100,("Value from encryption was |\n"));
72         dump_data(100, p24, 24);
73 #endif
74         ok = mem_equal_const_time(p24, nt_response->data, 24);
75         if (!ok) {
76                 return false;
77         }
78         if (user_sess_key != NULL) {
79                 *user_sess_key = data_blob_talloc(mem_ctx, NULL, 16);
80                 if (user_sess_key->data == NULL) {
81                         DBG_ERR("data_blob_talloc failed\n");
82                         return false;
83                 }
84                 SMBsesskeygen_ntv1(part_passwd, user_sess_key->data);
85         }
86         return true;
87 }
88
89 /****************************************************************************
90  Core of smb password checking routine. (NTLMv2, LMv2)
91  Note:  The same code works with both NTLMv2 and LMv2.
92 ****************************************************************************/
93
94 static bool smb_pwd_check_ntlmv2(TALLOC_CTX *mem_ctx,
95                                  const DATA_BLOB *ntv2_response,
96                                  const uint8_t *part_passwd,
97                                  const DATA_BLOB *sec_blob,
98                                  const char *user, const char *domain,
99                                  DATA_BLOB *user_sess_key)
100 {
101         /* Finish the encryption of part_passwd. */
102         uint8_t kr[16];
103         uint8_t value_from_encryption[16];
104         DATA_BLOB client_key_data;
105         NTSTATUS status;
106         bool ok;
107
108         if (part_passwd == NULL) {
109                 DEBUG(10,("No password set - DISALLOWING access\n"));
110                 /* No password set - always false */
111                 return false;
112         }
113
114         if (sec_blob->length != 8) {
115                 DBG_ERR("incorrect challenge size (%zu)\n", sec_blob->length);
116                 return false;
117         }
118
119         if (ntv2_response->length < 24) {
120                 /* We MUST have more than 16 bytes, or the stuff below will go
121                    crazy.  No known implementation sends less than the 24 bytes
122                    for LMv2, let alone NTLMv2. */
123                 DBG_ERR("incorrect password length (%zu)\n",
124                         ntv2_response->length);
125                 return false;
126         }
127
128         client_key_data = data_blob_talloc(mem_ctx, ntv2_response->data+16, ntv2_response->length-16);
129         /* 
130            todo:  should we be checking this for anything?  We can't for LMv2, 
131            but for NTLMv2 it is meant to contain the current time etc.
132         */
133
134         if (!ntv2_owf_gen(part_passwd, user, domain, kr)) {
135                 return false;
136         }
137
138         status = SMBOWFencrypt_ntv2(kr,
139                                     sec_blob,
140                                     &client_key_data,
141                                     value_from_encryption);
142         if (!NT_STATUS_IS_OK(status)) {
143                 return false;
144         }
145
146 #if DEBUG_PASSWORD
147         DEBUG(100,("Part password (P16) was |\n"));
148         dump_data(100, part_passwd, 16);
149         DEBUGADD(100,("Password from client was |\n"));
150         dump_data(100, ntv2_response->data, ntv2_response->length);
151         DEBUGADD(100,("Variable data from client was |\n"));
152         dump_data(100, client_key_data.data, client_key_data.length);
153         DEBUGADD(100,("Given challenge was |\n"));
154         dump_data(100, sec_blob->data, sec_blob->length);
155         DEBUGADD(100,("Value from encryption was |\n"));
156         dump_data(100, value_from_encryption, 16);
157 #endif
158         data_blob_clear_free(&client_key_data);
159
160         ok = mem_equal_const_time(value_from_encryption, ntv2_response->data, 16);
161         if (!ok) {
162                 return false;
163         }
164         if (user_sess_key != NULL) {
165                 *user_sess_key = data_blob_talloc(mem_ctx, NULL, 16);
166                 if (user_sess_key->data == NULL) {
167                         DBG_ERR("data_blob_talloc failed\n");
168                         return false;
169                 }
170
171                 status = SMBsesskeygen_ntv2(
172                         kr, value_from_encryption, user_sess_key->data);
173                 if (!NT_STATUS_IS_OK(status)) {
174                         return false;
175                 }
176         }
177         return true;
178 }
179
180 /****************************************************************************
181  Core of smb password checking routine. (NTLMv2, LMv2)
182  Note:  The same code works with both NTLMv2 and LMv2.
183 ****************************************************************************/
184
185 static bool smb_sess_key_ntlmv2(TALLOC_CTX *mem_ctx,
186                                 const DATA_BLOB *ntv2_response,
187                                 const uint8_t *part_passwd,
188                                 const DATA_BLOB *sec_blob,
189                                 const char *user, const char *domain,
190                                 DATA_BLOB *user_sess_key)
191 {
192         /* Finish the encryption of part_passwd. */
193         uint8_t kr[16];
194         uint8_t value_from_encryption[16];
195         DATA_BLOB client_key_data;
196         NTSTATUS status;
197
198         if (part_passwd == NULL) {
199                 DEBUG(10,("No password set - DISALLOWING access\n"));
200                 /* No password set - always false */
201                 return false;
202         }
203
204         if (sec_blob->length != 8) {
205                 DBG_ERR("incorrect challenge size (%zu)\n", sec_blob->length);
206                 return false;
207         }
208
209         if (ntv2_response->length < 24) {
210                 /* We MUST have more than 16 bytes, or the stuff below will go
211                    crazy.  No known implementation sends less than the 24 bytes
212                    for LMv2, let alone NTLMv2. */
213                 DBG_ERR("incorrect password length (%zu)\n",
214                         ntv2_response->length);
215                 return false;
216         }
217
218         client_key_data = data_blob_talloc(mem_ctx, ntv2_response->data+16, ntv2_response->length-16);
219
220         if (!ntv2_owf_gen(part_passwd, user, domain, kr)) {
221                 return false;
222         }
223
224         status = SMBOWFencrypt_ntv2(kr,
225                                     sec_blob,
226                                     &client_key_data,
227                                     value_from_encryption);
228         if (!NT_STATUS_IS_OK(status)) {
229                 return false;
230         }
231         *user_sess_key = data_blob_talloc(mem_ctx, NULL, 16);
232         if (user_sess_key->data == NULL) {
233                 DBG_ERR("data_blob_talloc failed\n");
234                 return false;
235         }
236         status = SMBsesskeygen_ntv2(kr,
237                                     value_from_encryption,
238                                     user_sess_key->data);
239         if (!NT_STATUS_IS_OK(status)) {
240                 return false;
241         }
242         return true;
243 }
244
245 /**
246  * Compare password hashes against those from the SAM
247  *
248  * @param mem_ctx talloc context
249  * @param client_lanman LANMAN password hash, as supplied by the client
250  * @param client_nt NT (MD4) password hash, as supplied by the client
251  * @param username internal Samba username, for log messages
252  * @param client_username username the client used
253  * @param client_domain domain name the client used (may be mapped)
254  * @param stored_lanman LANMAN password hash, as stored on the SAM
255  * @param stored_nt NT (MD4) password hash, as stored on the SAM
256  * @param user_sess_key User session key
257  * @param lm_sess_key LM session key (first 8 bytes of the LM hash)
258  */
259
260 NTSTATUS hash_password_check(TALLOC_CTX *mem_ctx,
261                              bool lanman_auth,
262                              const struct samr_Password *client_lanman,
263                              const struct samr_Password *client_nt,
264                              const char *username, 
265                              const struct samr_Password *stored_lanman, 
266                              const struct samr_Password *stored_nt)
267 {
268         if (stored_nt == NULL) {
269                 DEBUG(3,("hash_password_check: NO NT password stored for user %s.\n",
270                          username));
271         }
272
273         if (client_nt && stored_nt) {
274                 if (mem_equal_const_time(client_nt->hash, stored_nt->hash, sizeof(stored_nt->hash))) {
275                         return NT_STATUS_OK;
276                 } else {
277                         DEBUG(3,("hash_password_check: Interactive logon: NT password check failed for user %s\n",
278                                  username));
279                         return NT_STATUS_WRONG_PASSWORD;
280                 }
281
282         } else if (client_lanman && stored_lanman) {
283                 if (!lanman_auth) {
284                         DEBUG(3,("hash_password_check: Interactive logon: only LANMAN password supplied for user %s, and LM passwords are disabled!\n",
285                                  username));
286                         return NT_STATUS_WRONG_PASSWORD;
287                 }
288                 if (strchr_m(username, '@')) {
289                         return NT_STATUS_NOT_FOUND;
290                 }
291
292                 if (mem_equal_const_time(client_lanman->hash, stored_lanman->hash, sizeof(stored_lanman->hash))) {
293                         return NT_STATUS_OK;
294                 } else {
295                         DEBUG(3,("hash_password_check: Interactive logon: LANMAN password check failed for user %s\n",
296                                  username));
297                         return NT_STATUS_WRONG_PASSWORD;
298                 }
299         }
300         if (strchr_m(username, '@')) {
301                 return NT_STATUS_NOT_FOUND;
302         }
303         return NT_STATUS_WRONG_PASSWORD;
304 }
305
306 /**
307  * Check a challenge-response password against the value of the NT or
308  * LM password hash.
309  *
310  * @param mem_ctx talloc context
311  * @param challenge 8-byte challenge.  If all zero, forces plaintext comparison
312  * @param nt_response 'unicode' NT response to the challenge, or unicode password
313  * @param lm_response ASCII or LANMAN response to the challenge, or password in DOS code page
314  * @param username internal Samba username, for log messages
315  * @param client_username username the client used
316  * @param client_domain domain name the client used (may be mapped)
317  * @param stored_lanman LANMAN ASCII password from our passdb or similar
318  * @param stored_nt MD4 unicode password from our passdb or similar
319  * @param user_sess_key User session key
320  * @param lm_sess_key LM session key (first 8 bytes of the LM hash)
321  */
322
323 NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
324                              bool lanman_auth,
325                              enum ntlm_auth_level ntlm_auth,
326                              uint32_t logon_parameters,
327                              const DATA_BLOB *challenge,
328                              const DATA_BLOB *lm_response,
329                              const DATA_BLOB *nt_response,
330                              const char *username, 
331                              const char *client_username, 
332                              const char *client_domain,
333                              const struct samr_Password *stored_lanman, 
334                              const struct samr_Password *stored_nt, 
335                              DATA_BLOB *user_sess_key, 
336                              DATA_BLOB *lm_sess_key)
337 {
338         DATA_BLOB tmp_sess_key;
339         const char *upper_client_domain = NULL;
340
341         if (ntlm_auth == NTLM_AUTH_DISABLED) {
342                 DBG_WARNING("ntlm_password_check: NTLM authentication not "
343                             "permitted by configuration.\n");
344                 return NT_STATUS_NTLM_BLOCKED;
345         }
346
347         if (client_domain != NULL) {
348                 upper_client_domain = talloc_strdup_upper(mem_ctx, client_domain);
349                 if (upper_client_domain == NULL) {
350                         return NT_STATUS_NO_MEMORY;
351                 }
352         }
353
354         if (stored_nt == NULL) {
355                 DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n", 
356                          username));
357         }
358
359         *lm_sess_key = data_blob(NULL, 0);
360         *user_sess_key = data_blob(NULL, 0);
361
362         /* Check for cleartext netlogon. Used by Exchange 5.5. */
363         if ((logon_parameters & MSV1_0_CLEARTEXT_PASSWORD_ALLOWED)
364             && challenge->length == 8
365             && (all_zero(challenge->data, challenge->length))) {
366                 struct samr_Password client_nt;
367                 struct samr_Password client_lm;
368                 char *unix_pw = NULL;
369                 bool lm_ok;
370                 size_t converted_size = 0;
371
372                 DEBUG(4,("ntlm_password_check: checking plaintext passwords for user %s\n",
373                          username));
374                 mdfour(client_nt.hash, nt_response->data, nt_response->length);
375
376                 if (lm_response->length && 
377                     (convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, 
378                                           lm_response->data, lm_response->length, 
379                                            (void *)&unix_pw, &converted_size))) {
380                         if (E_deshash(unix_pw, client_lm.hash)) {
381                                 lm_ok = true;
382                         } else {
383                                 lm_ok = false;
384                         }
385                 } else {
386                         lm_ok = false;
387                 }
388                 return hash_password_check(mem_ctx, 
389                                            lanman_auth,
390                                            lm_ok ? &client_lm : NULL, 
391                                            nt_response->length ? &client_nt : NULL, 
392                                            username,  
393                                            stored_lanman, stored_nt);
394         }
395
396         if (nt_response->length != 0 && nt_response->length < 24) {
397                 DBG_NOTICE("invalid NT password length (%zu) for user %s\n",
398                            nt_response->length,
399                            username);
400         }
401
402         if (nt_response->length > 24 && stored_nt) {
403                 /* We have the NT MD4 hash challenge available - see if we can
404                    use it 
405                 */
406                 DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n",
407                         client_domain ? client_domain : "<NULL>"));
408                 if (smb_pwd_check_ntlmv2(mem_ctx,
409                                          nt_response, 
410                                          stored_nt->hash, challenge, 
411                                          client_username, 
412                                          client_domain,
413                                          user_sess_key)) {
414                         if (user_sess_key->length) {
415                                 *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length));
416                         }
417                         return NT_STATUS_OK;
418                 }
419
420                 DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n",
421                         upper_client_domain ? upper_client_domain : "<NULL>"));
422                 if (smb_pwd_check_ntlmv2(mem_ctx,
423                                          nt_response, 
424                                          stored_nt->hash, challenge, 
425                                          client_username, 
426                                          upper_client_domain,
427                                          user_sess_key)) {
428                         if (user_sess_key->length) {
429                                 *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length));
430                         }
431                         return NT_STATUS_OK;
432                 }
433
434                 DEBUG(4,("ntlm_password_check: Checking NTLMv2 password without a domain\n"));
435                 if (smb_pwd_check_ntlmv2(mem_ctx,
436                                          nt_response, 
437                                          stored_nt->hash, challenge, 
438                                          client_username, 
439                                          "",
440                                          user_sess_key)) {
441                         if (user_sess_key->length) {
442                                 *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length));
443                         }
444                         return NT_STATUS_OK;
445                 } else {
446                         DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n"));
447                 }
448         } else if (nt_response->length == 24 && stored_nt) {
449                 if (ntlm_auth == NTLM_AUTH_ON
450                     || (ntlm_auth == NTLM_AUTH_MSCHAPv2_NTLMV2_ONLY && (logon_parameters & MSV1_0_ALLOW_MSVCHAPV2))) {
451                         /* We have the NT MD4 hash challenge available - see if we can
452                            use it (ie. does it exist in the smbpasswd file).
453                         */
454                         DEBUG(4,("ntlm_password_check: Checking NT MD4 password\n"));
455                         if (smb_pwd_check_ntlmv1(mem_ctx, 
456                                                  nt_response, 
457                                                  stored_nt->hash, challenge,
458                                                  user_sess_key)) {
459                                 /* The LM session key for this response is not very secure, 
460                                    so use it only if we otherwise allow LM authentication */
461
462                                 if (lanman_auth && stored_lanman) {
463                                         *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, MIN(8, user_sess_key->length));
464                                 }
465                                 return NT_STATUS_OK;
466                         } else {
467                                 DEBUG(3,("ntlm_password_check: NT MD4 password check failed for user %s\n",
468                                          username));
469                                 return NT_STATUS_WRONG_PASSWORD;
470                         }
471                 } else {
472                         DEBUG(2,("ntlm_password_check: NTLMv1 passwords NOT PERMITTED for user %s\n",
473                                  username));                    
474                         /* no return, because we might pick up LMv2 in the LM field */
475                 }
476         }
477
478         if (lm_response->length == 0) {
479                 DEBUG(3,("ntlm_password_check: NEITHER LanMan nor NT password supplied for user %s\n",
480                          username));
481                 return NT_STATUS_WRONG_PASSWORD;
482         }
483
484         if (lm_response->length < 24) {
485                 DBG_NOTICE("invalid LanMan password length (%zu) for "
486                            "user %s\n",
487                            nt_response->length, username);
488                 return NT_STATUS_WRONG_PASSWORD;
489         }
490
491         if (!lanman_auth) {
492                 DEBUG(3,("ntlm_password_check: Lanman passwords NOT PERMITTED for user %s\n",
493                          username));
494         } else if (!stored_lanman) {
495                 DEBUG(3,("ntlm_password_check: NO LanMan password set for user %s (and no NT password supplied)\n",
496                          username));
497         } else if (strchr_m(username, '@')) {
498                 DEBUG(3,("ntlm_password_check: NO LanMan password allowed for username@realm logins (user: %s)\n",
499                          username));
500         } else {
501                 DEBUG(4,("ntlm_password_check: Checking LM password\n"));
502                 if (smb_pwd_check_ntlmv1(mem_ctx,
503                                          lm_response, 
504                                          stored_lanman->hash, challenge,
505                                          NULL)) {
506                         /* The session key for this response is still very odd.  
507                            It not very secure, so use it only if we otherwise 
508                            allow LM authentication */
509
510                         if (lanman_auth && stored_lanman) {
511                                 uint8_t first_8_lm_hash[16];
512                                 memcpy(first_8_lm_hash, stored_lanman->hash, 8);
513                                 memset(first_8_lm_hash + 8, '\0', 8);
514                                 *user_sess_key = data_blob_talloc(mem_ctx, first_8_lm_hash, 16);
515                                 *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, 8);
516                         }
517                         return NT_STATUS_OK;
518                 }
519         }
520
521         if (!stored_nt) {
522                 DEBUG(4,("ntlm_password_check: LM password check failed for user, no NT password %s\n",username));
523                 return NT_STATUS_WRONG_PASSWORD;
524         }
525
526         /* This is for 'LMv2' authentication.  almost NTLMv2 but limited to 24 bytes.
527            - related to Win9X, legacy NAS pass-though authentication
528         */
529         DEBUG(4,("ntlm_password_check: Checking LMv2 password with domain %s\n",
530                 client_domain ? client_domain : "<NULL>"));
531         if (smb_pwd_check_ntlmv2(mem_ctx,
532                                  lm_response, 
533                                  stored_nt->hash, challenge, 
534                                  client_username,
535                                  client_domain,
536                                  &tmp_sess_key)) {
537                 if (nt_response->length > 24) {
538                         /* If NTLMv2 authentication has preceded us
539                          * (even if it failed), then use the session
540                          * key from that.  See the RPC-SAMLOGON
541                          * torture test */
542                         smb_sess_key_ntlmv2(mem_ctx,
543                                             nt_response, 
544                                             stored_nt->hash, challenge, 
545                                             client_username,
546                                             client_domain,
547                                             user_sess_key);
548                 } else {
549                         /* Otherwise, use the LMv2 session key */
550                         *user_sess_key = tmp_sess_key;
551                 }
552                 if (user_sess_key->length) {
553                         *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length));
554                 }
555                 return NT_STATUS_OK;
556         }
557
558         DEBUG(4,("ntlm_password_check: Checking LMv2 password with upper-cased version of domain %s\n",
559                 upper_client_domain ? upper_client_domain : "<NULL>"));
560         if (smb_pwd_check_ntlmv2(mem_ctx,
561                                  lm_response, 
562                                  stored_nt->hash, challenge, 
563                                  client_username,
564                                  upper_client_domain,
565                                  &tmp_sess_key)) {
566                 if (nt_response->length > 24) {
567                         /* If NTLMv2 authentication has preceded us
568                          * (even if it failed), then use the session
569                          * key from that.  See the RPC-SAMLOGON
570                          * torture test */
571                         smb_sess_key_ntlmv2(mem_ctx,
572                                             nt_response, 
573                                             stored_nt->hash, challenge, 
574                                             client_username,
575                                             upper_client_domain,
576                                             user_sess_key);
577                 } else {
578                         /* Otherwise, use the LMv2 session key */
579                         *user_sess_key = tmp_sess_key;
580                 }
581                 if (user_sess_key->length) {
582                         *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length));
583                 }
584                 return NT_STATUS_OK;
585         }
586
587         DEBUG(4,("ntlm_password_check: Checking LMv2 password without a domain\n"));
588         if (smb_pwd_check_ntlmv2(mem_ctx,
589                                  lm_response, 
590                                  stored_nt->hash, challenge, 
591                                  client_username,
592                                  "",
593                                  &tmp_sess_key)) {
594                 if (nt_response->length > 24) {
595                         /* If NTLMv2 authentication has preceded us
596                          * (even if it failed), then use the session
597                          * key from that.  See the RPC-SAMLOGON
598                          * torture test */
599                         smb_sess_key_ntlmv2(mem_ctx,
600                                             nt_response, 
601                                             stored_nt->hash, challenge, 
602                                             client_username,
603                                             "",
604                                             user_sess_key);
605                 } else {
606                         /* Otherwise, use the LMv2 session key */
607                         *user_sess_key = tmp_sess_key;
608                 }
609                 if (user_sess_key->length) {
610                         *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length));
611                 }
612                 return NT_STATUS_OK;
613         }
614
615         /* Apparently NT accepts NT responses in the LM field
616            - I think this is related to Win9X pass-though authentication
617         */
618         DEBUG(4,("ntlm_password_check: Checking NT MD4 password in LM field\n"));
619         if (ntlm_auth == NTLM_AUTH_ON) {
620                 if (smb_pwd_check_ntlmv1(mem_ctx, 
621                                          lm_response, 
622                                          stored_nt->hash, challenge,
623                                          NULL)) {
624                         /* The session key for this response is still very odd.  
625                            It not very secure, so use it only if we otherwise 
626                            allow LM authentication */
627
628                         if (lanman_auth && stored_lanman) {
629                                 uint8_t first_8_lm_hash[16];
630                                 memcpy(first_8_lm_hash, stored_lanman->hash, 8);
631                                 memset(first_8_lm_hash + 8, '\0', 8);
632                                 *user_sess_key = data_blob_talloc(mem_ctx, first_8_lm_hash, 16);
633                                 *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, 8);
634                         }
635                         return NT_STATUS_OK;
636                 }
637                 DEBUG(3,("ntlm_password_check: LM password, NT MD4 password in LM field and LMv2 failed for user %s\n",username));
638         } else {
639                 DEBUG(3,("ntlm_password_check: LM password and LMv2 failed for user %s, and NT MD4 password in LM field not permitted\n",username));
640         }
641
642         /* Try and match error codes */
643         if (strchr_m(username, '@')) {
644                 return NT_STATUS_NOT_FOUND;
645         }
646         return NT_STATUS_WRONG_PASSWORD;
647 }
648