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