a2388706bcfb71c8b646e500dbf1e2ad93c7473e
[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                              enum ntlm_auth_level ntlm_auth,
263                              const struct samr_Password *client_lanman,
264                              const struct samr_Password *client_nt,
265                              const char *username, 
266                              const struct samr_Password *stored_lanman, 
267                              const struct samr_Password *stored_nt)
268 {
269         if (ntlm_auth == NTLM_AUTH_DISABLED) {
270                 DBG_WARNING("hash_password_check: NTLM authentication not "
271                             "permitted by configuration.\n");
272                 return NT_STATUS_NTLM_BLOCKED;
273         }
274
275         if (stored_nt == NULL) {
276                 DEBUG(3,("hash_password_check: NO NT password stored for user %s.\n",
277                          username));
278         }
279
280         if (client_nt && stored_nt) {
281                 if (mem_equal_const_time(client_nt->hash, stored_nt->hash, sizeof(stored_nt->hash))) {
282                         return NT_STATUS_OK;
283                 } else {
284                         DEBUG(3,("hash_password_check: Interactive logon: NT password check failed for user %s\n",
285                                  username));
286                         return NT_STATUS_WRONG_PASSWORD;
287                 }
288
289         } else if (client_lanman && stored_lanman) {
290                 if (!lanman_auth) {
291                         DEBUG(3,("hash_password_check: Interactive logon: only LANMAN password supplied for user %s, and LM passwords are disabled!\n",
292                                  username));
293                         return NT_STATUS_WRONG_PASSWORD;
294                 }
295                 if (strchr_m(username, '@')) {
296                         return NT_STATUS_NOT_FOUND;
297                 }
298
299                 if (mem_equal_const_time(client_lanman->hash, stored_lanman->hash, sizeof(stored_lanman->hash))) {
300                         return NT_STATUS_OK;
301                 } else {
302                         DEBUG(3,("hash_password_check: Interactive logon: LANMAN password check failed for user %s\n",
303                                  username));
304                         return NT_STATUS_WRONG_PASSWORD;
305                 }
306         }
307         if (strchr_m(username, '@')) {
308                 return NT_STATUS_NOT_FOUND;
309         }
310         return NT_STATUS_WRONG_PASSWORD;
311 }
312
313 /**
314  * Check a challenge-response password against the value of the NT or
315  * LM password hash.
316  *
317  * @param mem_ctx talloc context
318  * @param challenge 8-byte challenge.  If all zero, forces plaintext comparison
319  * @param nt_response 'unicode' NT response to the challenge, or unicode password
320  * @param lm_response ASCII or LANMAN response to the challenge, or password in DOS code page
321  * @param username internal Samba username, for log messages
322  * @param client_username username the client used
323  * @param client_domain domain name the client used (may be mapped)
324  * @param stored_lanman LANMAN ASCII password from our passdb or similar
325  * @param stored_nt MD4 unicode password from our passdb or similar
326  * @param user_sess_key User session key
327  * @param lm_sess_key LM session key (first 8 bytes of the LM hash)
328  */
329
330 NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
331                              bool lanman_auth,
332                              enum ntlm_auth_level ntlm_auth,
333                              uint32_t logon_parameters,
334                              const DATA_BLOB *challenge,
335                              const DATA_BLOB *lm_response,
336                              const DATA_BLOB *nt_response,
337                              const char *username, 
338                              const char *client_username, 
339                              const char *client_domain,
340                              const struct samr_Password *stored_lanman, 
341                              const struct samr_Password *stored_nt, 
342                              DATA_BLOB *user_sess_key, 
343                              DATA_BLOB *lm_sess_key)
344 {
345         DATA_BLOB tmp_sess_key;
346         const char *upper_client_domain = NULL;
347
348         if (ntlm_auth == NTLM_AUTH_DISABLED) {
349                 DBG_WARNING("ntlm_password_check: NTLM authentication not "
350                             "permitted by configuration.\n");
351                 return NT_STATUS_NTLM_BLOCKED;
352         }
353
354         if (client_domain != NULL) {
355                 upper_client_domain = talloc_strdup_upper(mem_ctx, client_domain);
356                 if (upper_client_domain == NULL) {
357                         return NT_STATUS_NO_MEMORY;
358                 }
359         }
360
361         if (stored_nt == NULL) {
362                 DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n", 
363                          username));
364         }
365
366         *lm_sess_key = data_blob(NULL, 0);
367         *user_sess_key = data_blob(NULL, 0);
368
369         /* Check for cleartext netlogon. Used by Exchange 5.5. */
370         if ((logon_parameters & MSV1_0_CLEARTEXT_PASSWORD_ALLOWED)
371             && challenge->length == 8
372             && (all_zero(challenge->data, challenge->length))) {
373                 struct samr_Password client_nt;
374                 struct samr_Password client_lm;
375                 char *unix_pw = NULL;
376                 bool lm_ok;
377                 size_t converted_size = 0;
378
379                 DEBUG(4,("ntlm_password_check: checking plaintext passwords for user %s\n",
380                          username));
381                 mdfour(client_nt.hash, nt_response->data, nt_response->length);
382
383                 if (lm_response->length && 
384                     (convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, 
385                                           lm_response->data, lm_response->length, 
386                                            &unix_pw, &converted_size))) {
387                         if (E_deshash(unix_pw, client_lm.hash)) {
388                                 lm_ok = true;
389                         } else {
390                                 lm_ok = false;
391                         }
392                 } else {
393                         lm_ok = false;
394                 }
395                 return hash_password_check(mem_ctx, 
396                                            lanman_auth,
397                                            ntlm_auth,
398                                            lm_ok ? &client_lm : NULL, 
399                                            nt_response->length ? &client_nt : NULL, 
400                                            username,  
401                                            stored_lanman, stored_nt);
402         }
403
404         if (nt_response->length != 0 && nt_response->length < 24) {
405                 DBG_NOTICE("invalid NT password length (%zu) for user %s\n",
406                            nt_response->length,
407                            username);
408         }
409
410         if (nt_response->length > 24 && stored_nt) {
411                 /* We have the NT MD4 hash challenge available - see if we can
412                    use it 
413                 */
414                 DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n",
415                         client_domain ? client_domain : "<NULL>"));
416                 if (smb_pwd_check_ntlmv2(mem_ctx,
417                                          nt_response, 
418                                          stored_nt->hash, challenge, 
419                                          client_username, 
420                                          client_domain,
421                                          user_sess_key)) {
422                         if (user_sess_key->length) {
423                                 *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length));
424                         }
425                         return NT_STATUS_OK;
426                 }
427
428                 DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n",
429                         upper_client_domain ? upper_client_domain : "<NULL>"));
430                 if (smb_pwd_check_ntlmv2(mem_ctx,
431                                          nt_response, 
432                                          stored_nt->hash, challenge, 
433                                          client_username, 
434                                          upper_client_domain,
435                                          user_sess_key)) {
436                         if (user_sess_key->length) {
437                                 *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length));
438                         }
439                         return NT_STATUS_OK;
440                 }
441
442                 DEBUG(4,("ntlm_password_check: Checking NTLMv2 password without a domain\n"));
443                 if (smb_pwd_check_ntlmv2(mem_ctx,
444                                          nt_response, 
445                                          stored_nt->hash, challenge, 
446                                          client_username, 
447                                          "",
448                                          user_sess_key)) {
449                         if (user_sess_key->length) {
450                                 *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length));
451                         }
452                         return NT_STATUS_OK;
453                 } else {
454                         DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n"));
455                 }
456         } else if (nt_response->length == 24 && stored_nt) {
457                 if (ntlm_auth == NTLM_AUTH_ON
458                     || (ntlm_auth == NTLM_AUTH_MSCHAPv2_NTLMV2_ONLY && (logon_parameters & MSV1_0_ALLOW_MSVCHAPV2))) {
459                         /* We have the NT MD4 hash challenge available - see if we can
460                            use it (ie. does it exist in the smbpasswd file).
461                         */
462                         DEBUG(4,("ntlm_password_check: Checking NT MD4 password\n"));
463                         if (smb_pwd_check_ntlmv1(mem_ctx, 
464                                                  nt_response, 
465                                                  stored_nt->hash, challenge,
466                                                  user_sess_key)) {
467                                 /* The LM session key for this response is not very secure, 
468                                    so use it only if we otherwise allow LM authentication */
469
470                                 if (lanman_auth && stored_lanman) {
471                                         *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, MIN(8, user_sess_key->length));
472                                 }
473                                 return NT_STATUS_OK;
474                         } else {
475                                 DEBUG(3,("ntlm_password_check: NT MD4 password check failed for user %s\n",
476                                          username));
477                                 return NT_STATUS_WRONG_PASSWORD;
478                         }
479                 } else {
480                         DEBUG(2,("ntlm_password_check: NTLMv1 passwords NOT PERMITTED for user %s\n",
481                                  username));                    
482                         /* no return, because we might pick up LMv2 in the LM field */
483                 }
484         }
485
486         if (lm_response->length == 0) {
487                 DEBUG(3,("ntlm_password_check: NEITHER LanMan nor NT password supplied for user %s\n",
488                          username));
489                 return NT_STATUS_WRONG_PASSWORD;
490         }
491
492         if (lm_response->length < 24) {
493                 DBG_NOTICE("invalid LanMan password length (%zu) for "
494                            "user %s\n",
495                            nt_response->length, username);
496                 return NT_STATUS_WRONG_PASSWORD;
497         }
498
499         if (!lanman_auth) {
500                 DEBUG(3,("ntlm_password_check: Lanman passwords NOT PERMITTED for user %s\n",
501                          username));
502         } else if (!stored_lanman) {
503                 DEBUG(3,("ntlm_password_check: NO LanMan password set for user %s (and no NT password supplied)\n",
504                          username));
505         } else if (strchr_m(username, '@')) {
506                 DEBUG(3,("ntlm_password_check: NO LanMan password allowed for username@realm logins (user: %s)\n",
507                          username));
508         } else {
509                 DEBUG(4,("ntlm_password_check: Checking LM password\n"));
510                 if (smb_pwd_check_ntlmv1(mem_ctx,
511                                          lm_response, 
512                                          stored_lanman->hash, challenge,
513                                          NULL)) {
514                         /* The session key for this response is still very odd.  
515                            It not very secure, so use it only if we otherwise 
516                            allow LM authentication */
517
518                         if (lanman_auth && stored_lanman) {
519                                 uint8_t first_8_lm_hash[16];
520                                 memcpy(first_8_lm_hash, stored_lanman->hash, 8);
521                                 memset(first_8_lm_hash + 8, '\0', 8);
522                                 *user_sess_key = data_blob_talloc(mem_ctx, first_8_lm_hash, 16);
523                                 *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, 8);
524                         }
525                         return NT_STATUS_OK;
526                 }
527         }
528
529         if (!stored_nt) {
530                 DEBUG(4,("ntlm_password_check: LM password check failed for user, no NT password %s\n",username));
531                 return NT_STATUS_WRONG_PASSWORD;
532         }
533
534         /* This is for 'LMv2' authentication.  almost NTLMv2 but limited to 24 bytes.
535            - related to Win9X, legacy NAS pass-though authentication
536         */
537         DEBUG(4,("ntlm_password_check: Checking LMv2 password with domain %s\n",
538                 client_domain ? client_domain : "<NULL>"));
539         if (smb_pwd_check_ntlmv2(mem_ctx,
540                                  lm_response, 
541                                  stored_nt->hash, challenge, 
542                                  client_username,
543                                  client_domain,
544                                  &tmp_sess_key)) {
545                 if (nt_response->length > 24) {
546                         /* If NTLMv2 authentication has preceded us
547                          * (even if it failed), then use the session
548                          * key from that.  See the RPC-SAMLOGON
549                          * torture test */
550                         smb_sess_key_ntlmv2(mem_ctx,
551                                             nt_response, 
552                                             stored_nt->hash, challenge, 
553                                             client_username,
554                                             client_domain,
555                                             user_sess_key);
556                 } else {
557                         /* Otherwise, use the LMv2 session key */
558                         *user_sess_key = tmp_sess_key;
559                 }
560                 if (user_sess_key->length) {
561                         *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length));
562                 }
563                 return NT_STATUS_OK;
564         }
565
566         DEBUG(4,("ntlm_password_check: Checking LMv2 password with upper-cased version of domain %s\n",
567                 upper_client_domain ? upper_client_domain : "<NULL>"));
568         if (smb_pwd_check_ntlmv2(mem_ctx,
569                                  lm_response, 
570                                  stored_nt->hash, challenge, 
571                                  client_username,
572                                  upper_client_domain,
573                                  &tmp_sess_key)) {
574                 if (nt_response->length > 24) {
575                         /* If NTLMv2 authentication has preceded us
576                          * (even if it failed), then use the session
577                          * key from that.  See the RPC-SAMLOGON
578                          * torture test */
579                         smb_sess_key_ntlmv2(mem_ctx,
580                                             nt_response, 
581                                             stored_nt->hash, challenge, 
582                                             client_username,
583                                             upper_client_domain,
584                                             user_sess_key);
585                 } else {
586                         /* Otherwise, use the LMv2 session key */
587                         *user_sess_key = tmp_sess_key;
588                 }
589                 if (user_sess_key->length) {
590                         *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length));
591                 }
592                 return NT_STATUS_OK;
593         }
594
595         DEBUG(4,("ntlm_password_check: Checking LMv2 password without a domain\n"));
596         if (smb_pwd_check_ntlmv2(mem_ctx,
597                                  lm_response, 
598                                  stored_nt->hash, challenge, 
599                                  client_username,
600                                  "",
601                                  &tmp_sess_key)) {
602                 if (nt_response->length > 24) {
603                         /* If NTLMv2 authentication has preceded us
604                          * (even if it failed), then use the session
605                          * key from that.  See the RPC-SAMLOGON
606                          * torture test */
607                         smb_sess_key_ntlmv2(mem_ctx,
608                                             nt_response, 
609                                             stored_nt->hash, challenge, 
610                                             client_username,
611                                             "",
612                                             user_sess_key);
613                 } else {
614                         /* Otherwise, use the LMv2 session key */
615                         *user_sess_key = tmp_sess_key;
616                 }
617                 if (user_sess_key->length) {
618                         *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length));
619                 }
620                 return NT_STATUS_OK;
621         }
622
623         /* Apparently NT accepts NT responses in the LM field
624            - I think this is related to Win9X pass-though authentication
625         */
626         DEBUG(4,("ntlm_password_check: Checking NT MD4 password in LM field\n"));
627         if (ntlm_auth == NTLM_AUTH_ON) {
628                 if (smb_pwd_check_ntlmv1(mem_ctx, 
629                                          lm_response, 
630                                          stored_nt->hash, challenge,
631                                          NULL)) {
632                         /* The session key for this response is still very odd.  
633                            It not very secure, so use it only if we otherwise 
634                            allow LM authentication */
635
636                         if (lanman_auth && stored_lanman) {
637                                 uint8_t first_8_lm_hash[16];
638                                 memcpy(first_8_lm_hash, stored_lanman->hash, 8);
639                                 memset(first_8_lm_hash + 8, '\0', 8);
640                                 *user_sess_key = data_blob_talloc(mem_ctx, first_8_lm_hash, 16);
641                                 *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, 8);
642                         }
643                         return NT_STATUS_OK;
644                 }
645                 DEBUG(3,("ntlm_password_check: LM password, NT MD4 password in LM field and LMv2 failed for user %s\n",username));
646         } else {
647                 DEBUG(3,("ntlm_password_check: LM password and LMv2 failed for user %s, and NT MD4 password in LM field not permitted\n",username));
648         }
649
650         /* Try and match error codes */
651         if (strchr_m(username, '@')) {
652                 return NT_STATUS_NOT_FOUND;
653         }
654         return NT_STATUS_WRONG_PASSWORD;
655 }
656