r13903: Don't generate prototypes for modules and binaries in include/proto.h by
[gd/samba-autobuild/.git] / source4 / torture / rpc / samlogon.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    test suite for netlogon SamLogon operations
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
8    Copyright (C) Tim Potter      2003
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "librpc/gen_ndr/ndr_netlogon.h"
27 #include "auth/auth.h"
28 #include "lib/crypto/crypto.h"
29 #include "lib/cmdline/popt_common.h"
30 #include "torture/rpc/proto.h"
31 #include "auth/gensec/schannel_proto.h"
32
33 #define TEST_MACHINE_NAME "samlogontest"
34 #define TEST_USER_NAME "samlogontestuser"
35
36 enum ntlm_break {
37         BREAK_BOTH,
38         BREAK_NONE,
39         BREAK_LM,
40         BREAK_NT,
41         NO_LM,
42         NO_NT
43 };
44
45 struct samlogon_state {
46         TALLOC_CTX *mem_ctx;
47         const char *comment;
48         const char *account_name;
49         const char *account_domain;
50         const char *password;
51         struct dcerpc_pipe *p;
52         int function_level;
53         uint32_t parameter_control;
54         struct netr_LogonSamLogon r;
55         struct netr_LogonSamLogonEx r_ex;
56         struct netr_LogonSamLogonWithFlags r_flags;
57         struct netr_Authenticator auth, auth2;
58         struct creds_CredentialState *creds;
59         NTSTATUS expected_error;
60         BOOL old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
61         DATA_BLOB chall;
62 };
63
64 /* 
65    Authenticate a user with a challenge/response, checking session key
66    and valid authentication types
67 */
68 static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, 
69                                enum ntlm_break break_which,
70                                uint32_t parameter_control,
71                                DATA_BLOB *chall, 
72                                DATA_BLOB *lm_response, 
73                                DATA_BLOB *nt_response, 
74                                uint8_t lm_key[8], 
75                                uint8_t user_session_key[16], 
76                                char **error_string)
77 {
78         NTSTATUS status;
79         struct netr_LogonSamLogon *r = &samlogon_state->r;
80         struct netr_LogonSamLogonEx *r_ex = &samlogon_state->r_ex;
81         struct netr_LogonSamLogonWithFlags *r_flags = &samlogon_state->r_flags;
82         struct netr_NetworkInfo ninfo;
83         struct netr_SamBaseInfo *base = NULL;
84         uint16_t validation_level = 0;
85         
86         samlogon_state->r.in.logon.network = &ninfo;
87         samlogon_state->r_ex.in.logon.network = &ninfo;
88         samlogon_state->r_flags.in.logon.network = &ninfo;
89         
90         ninfo.identity_info.domain_name.string = samlogon_state->account_domain;
91         ninfo.identity_info.parameter_control = parameter_control;
92         ninfo.identity_info.logon_id_low = 0;
93         ninfo.identity_info.logon_id_high = 0;
94         ninfo.identity_info.account_name.string = samlogon_state->account_name;
95         ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
96                 
97         memcpy(ninfo.challenge, chall->data, 8);
98                 
99         switch (break_which) {
100         case BREAK_NONE:
101                 break;
102         case BREAK_LM:
103                 if (lm_response && lm_response->data) {
104                         lm_response->data[0]++;
105                 }
106                 break;
107         case BREAK_NT:
108                 if (nt_response && nt_response->data) {
109                         nt_response->data[0]++;
110                 }
111                 break;
112         case BREAK_BOTH:
113                 if (lm_response && lm_response->data) {
114                         lm_response->data[0]++;
115                 }
116                 if (nt_response && nt_response->data) {
117                         nt_response->data[0]++;
118                 }
119                 break;
120         case NO_LM:
121                 data_blob_free(lm_response);
122                 break;
123         case NO_NT:
124                 data_blob_free(nt_response);
125                 break;
126         }
127                 
128         if (nt_response) {
129                 ninfo.nt.data = nt_response->data;
130                 ninfo.nt.length = nt_response->length;
131         } else {
132                 ninfo.nt.data = NULL;
133                 ninfo.nt.length = 0;
134         }
135                 
136         if (lm_response) {
137                 ninfo.lm.data = lm_response->data;
138                 ninfo.lm.length = lm_response->length;
139         } else {
140                 ninfo.lm.data = NULL;
141                 ninfo.lm.length = 0;
142         }
143         
144         switch (samlogon_state->function_level) {
145         case DCERPC_NETR_LOGONSAMLOGON: 
146                 ZERO_STRUCT(samlogon_state->auth2);
147                 creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
148
149                 r->out.return_authenticator = NULL;
150                 status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
151                 if (!r->out.return_authenticator || 
152                     !creds_client_check(samlogon_state->creds, &r->out.return_authenticator->cred)) {
153                         printf("Credential chaining failed\n");
154                 }
155                 if (!NT_STATUS_IS_OK(status)) {
156                         if (error_string) {
157                                 *error_string = strdup(nt_errstr(status));
158                         }
159                         return status;
160                 }
161
162                 validation_level = r->in.validation_level;
163
164                 creds_decrypt_samlogon(samlogon_state->creds, validation_level, &r->out.validation);
165
166                 switch (validation_level) {
167                 case 2:
168                         base = &r->out.validation.sam2->base;
169                         break;
170                 case 3:
171                         base = &r->out.validation.sam3->base;
172                         break;
173                 case 6:
174                         base = &r->out.validation.sam6->base;
175                         break;
176                 }
177                 break;
178         case DCERPC_NETR_LOGONSAMLOGONEX: 
179                 status = dcerpc_netr_LogonSamLogonEx(samlogon_state->p, samlogon_state->mem_ctx, r_ex);
180                 if (!NT_STATUS_IS_OK(status)) {
181                         if (error_string) {
182                                 *error_string = strdup(nt_errstr(status));
183                         }
184                         return status;
185                 }
186
187                 validation_level = r_ex->in.validation_level;
188
189                 creds_decrypt_samlogon(samlogon_state->creds, validation_level, &r_ex->out.validation);
190
191                 switch (validation_level) {
192                 case 2:
193                         base = &r_ex->out.validation.sam2->base;
194                         break;
195                 case 3:
196                         base = &r_ex->out.validation.sam3->base;
197                         break;
198                 case 6:
199                         base = &r_ex->out.validation.sam6->base;
200                         break;
201                 }
202                 break;
203         case DCERPC_NETR_LOGONSAMLOGONWITHFLAGS: 
204                 ZERO_STRUCT(samlogon_state->auth2);
205                 creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
206
207                 r_flags->out.return_authenticator = NULL;
208                 status = dcerpc_netr_LogonSamLogonWithFlags(samlogon_state->p, samlogon_state->mem_ctx, r_flags);
209                 if (!r_flags->out.return_authenticator || 
210                     !creds_client_check(samlogon_state->creds, &r_flags->out.return_authenticator->cred)) {
211                         printf("Credential chaining failed\n");
212                 }
213                 if (!NT_STATUS_IS_OK(status)) {
214                         if (error_string) {
215                                 *error_string = strdup(nt_errstr(status));
216                         }
217                         return status;
218                 }
219                 
220                 validation_level = r_flags->in.validation_level;
221
222                 creds_decrypt_samlogon(samlogon_state->creds, validation_level, &r_flags->out.validation);
223
224                 switch (validation_level) {
225                 case 2:
226                         base = &r_flags->out.validation.sam2->base;
227                         break;
228                 case 3:
229                         base = &r_flags->out.validation.sam3->base;
230                         break;
231                 case 6:
232                         base = &r_flags->out.validation.sam6->base;
233                         break;
234                 }
235                 break;
236         default:
237                 /* can't happen */
238                 return NT_STATUS_INVALID_PARAMETER;
239         }
240                 
241         if (!base) {
242                 printf("No user info returned from 'successful' SamLogon*() call!\n");
243                 return NT_STATUS_INVALID_PARAMETER;
244         }
245
246         if (user_session_key) {
247                 memcpy(user_session_key, base->key.key, 16);
248         }
249         if (lm_key) {
250                 memcpy(lm_key, base->LMSessKey.key, 8);
251         }
252                         
253         return status;
254
255
256
257 /* 
258  * Test the normal 'LM and NTLM' combination
259  */
260
261 static BOOL test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) 
262 {
263         BOOL pass = True;
264         BOOL lm_good;
265         NTSTATUS nt_status;
266         DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
267         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
268         DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
269
270         uint8_t lm_key[8];
271         uint8_t user_session_key[16];
272         uint8_t lm_hash[16];
273         uint8_t nt_hash[16];
274         
275         ZERO_STRUCT(lm_key);
276         ZERO_STRUCT(user_session_key);
277
278         lm_good = SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
279         if (!lm_good) {
280                 ZERO_STRUCT(lm_hash);
281         } else {
282                 E_deshash(samlogon_state->password, lm_hash); 
283         }
284                 
285         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
286
287         E_md4hash(samlogon_state->password, nt_hash);
288         SMBsesskeygen_ntv1(nt_hash, session_key.data);
289
290         nt_status = check_samlogon(samlogon_state,
291                                    break_which,
292                                    samlogon_state->parameter_control,
293                                    &samlogon_state->chall,
294                                    &lm_response,
295                                    &nt_response,
296                                    lm_key, 
297                                    user_session_key,
298                                    error_string);
299         
300         data_blob_free(&lm_response);
301
302         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
303                 /* for 'long' passwords, the LM password is invalid */
304                 if (break_which == NO_NT && !lm_good) {
305                         return True;
306                 }
307                 /* for 'old' passwords, we allow the server to be OK or wrong password */
308                 if (samlogon_state->old_password) {
309                         return True;
310                 }
311                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
312         } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
313                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
314         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
315                 SAFE_FREE(*error_string);
316                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
317                 return False;
318         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
319                 return True;
320         } else if (!NT_STATUS_IS_OK(nt_status)) {
321                 return False;
322         }
323
324         if (break_which == NO_NT && !lm_good) {
325                 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
326                 return False;
327         }
328
329         if (memcmp(lm_hash, lm_key, 
330                    sizeof(lm_key)) != 0) {
331                 printf("LM Key does not match expectations!\n");
332                 printf("lm_key:\n");
333                 dump_data(1, lm_key, 8);
334                 printf("expected:\n");
335                 dump_data(1, lm_hash, 8);
336                 pass = False;
337         }
338
339         switch (break_which) {
340         case NO_NT:
341         {
342                 uint8_t lm_key_expected[16];
343                 memcpy(lm_key_expected, lm_hash, 8);
344                 memset(lm_key_expected+8, '\0', 8);
345                 if (memcmp(lm_key_expected, user_session_key, 
346                            16) != 0) {
347                         *error_string = strdup("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
348                         printf("user_session_key:\n");
349                         dump_data(1, user_session_key, sizeof(user_session_key));
350                         printf("expected:\n");
351                         dump_data(1, lm_key_expected, sizeof(lm_key_expected));
352                         pass = False;
353                 }
354                 break;
355         }
356         default:
357                 if (memcmp(session_key.data, user_session_key, 
358                            sizeof(user_session_key)) != 0) {
359                         *error_string = strdup("NT Session Key does not match expectations!\n");
360                         printf("user_session_key:\n");
361                         dump_data(1, user_session_key, 16);
362                         printf("expected:\n");
363                         dump_data(1, session_key.data, session_key.length);
364                         pass = False;
365                 }
366         }
367         return pass;
368 }
369
370 /* 
371  * Test LM authentication, no NT response supplied
372  */
373
374 static BOOL test_lm(struct samlogon_state *samlogon_state, char **error_string) 
375 {
376
377         return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
378 }
379
380 /* 
381  * Test the NTLM response only, no LM.
382  */
383
384 static BOOL test_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
385 {
386         return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
387 }
388
389 /* 
390  * Test the NTLM response only, but in the LM field.
391  */
392
393 static BOOL test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string) 
394 {
395         BOOL lm_good;
396         BOOL pass = True;
397         NTSTATUS nt_status;
398         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
399         DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
400
401         uint8_t lm_key[8];
402         uint8_t lm_hash[16];
403         uint8_t user_session_key[16];
404         uint8_t nt_hash[16];
405         
406         ZERO_STRUCT(lm_key);
407         ZERO_STRUCT(user_session_key);
408
409         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, 
410                      nt_response.data);
411         E_md4hash(samlogon_state->password, nt_hash);
412         SMBsesskeygen_ntv1(nt_hash, 
413                            session_key.data);
414
415         lm_good = E_deshash(samlogon_state->password, lm_hash); 
416         if (!lm_good) {
417                 ZERO_STRUCT(lm_hash);
418         }
419         nt_status = check_samlogon(samlogon_state,
420                                    BREAK_NONE,
421                                    samlogon_state->parameter_control,
422                                    &samlogon_state->chall,
423                                    &nt_response,
424                                    NULL,
425                                    lm_key, 
426                                    user_session_key,
427                                    error_string);
428         
429         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
430                 /* for 'old' passwords, we allow the server to be OK or wrong password */
431                 if (samlogon_state->old_password) {
432                         return True;
433                 }
434                 return False;
435         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
436                 SAFE_FREE(*error_string);
437                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
438                 return False;
439         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
440                 return True;
441         } else if (!NT_STATUS_IS_OK(nt_status)) {
442                 return False;
443         }
444
445         if (lm_good) {
446                 if (memcmp(lm_hash, lm_key, 
447                            sizeof(lm_key)) != 0) {
448                         printf("LM Key does not match expectations!\n");
449                         printf("lm_key:\n");
450                         dump_data(1, lm_key, 8);
451                         printf("expected:\n");
452                         dump_data(1, lm_hash, 8);
453                         pass = False;
454                 }
455 #if 0
456         } else {
457                 if (memcmp(session_key.data, lm_key, 
458                            sizeof(lm_key)) != 0) {
459                         printf("LM Key does not match expectations (first 8 session key)!\n");
460                         printf("lm_key:\n");
461                         dump_data(1, lm_key, 8);
462                         printf("expected:\n");
463                         dump_data(1, session_key.data, 8);
464                         pass = False;
465                 }
466 #endif
467         }
468         if (lm_good && memcmp(lm_hash, user_session_key, 8) != 0) {
469                 uint8_t lm_key_expected[16];
470                 memcpy(lm_key_expected, lm_hash, 8);
471                 memset(lm_key_expected+8, '\0', 8);
472                 if (memcmp(lm_key_expected, user_session_key, 
473                            16) != 0) {
474                         printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
475                         printf("user_session_key:\n");
476                         dump_data(1, user_session_key, sizeof(user_session_key));
477                         printf("expected:\n");
478                         dump_data(1, lm_key_expected, sizeof(lm_key_expected));
479                         pass = False;
480                 }
481         }
482         return pass;
483 }
484
485 /* 
486  * Test the NTLM response only, but in the both the NT and LM fields.
487  */
488
489 static BOOL test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string) 
490 {
491         BOOL pass = True;
492         BOOL lm_good;
493         NTSTATUS nt_status;
494         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
495         DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
496
497         uint8_t lm_key[8];
498         uint8_t lm_hash[16];
499         uint8_t user_session_key[16];
500         uint8_t nt_hash[16];
501         
502         ZERO_STRUCT(lm_key);
503         ZERO_STRUCT(user_session_key);
504
505         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, 
506                      nt_response.data);
507         E_md4hash(samlogon_state->password, nt_hash);
508         SMBsesskeygen_ntv1(nt_hash, 
509                            session_key.data);
510
511         lm_good = E_deshash(samlogon_state->password, lm_hash); 
512         if (!lm_good) {
513                 ZERO_STRUCT(lm_hash);
514         }
515
516         nt_status = check_samlogon(samlogon_state,
517                                    BREAK_NONE,
518                                    samlogon_state->parameter_control,
519                                    &samlogon_state->chall,
520                                    NULL, 
521                                    &nt_response,
522                                    lm_key, 
523                                    user_session_key,
524                                    error_string);
525         
526         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
527                 /* for 'old' passwords, we allow the server to be OK or wrong password */
528                 if (samlogon_state->old_password) {
529                         return True;
530                 }
531                 return False;
532         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
533                 SAFE_FREE(*error_string);
534                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
535                 return False;
536         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
537                 return True;
538         } else if (!NT_STATUS_IS_OK(nt_status)) {
539                 return False;
540         }
541
542         if (!NT_STATUS_IS_OK(nt_status)) {
543                 return False;
544         }
545
546         if (memcmp(lm_hash, lm_key, 
547                    sizeof(lm_key)) != 0) {
548                 printf("LM Key does not match expectations!\n");
549                 printf("lm_key:\n");
550                 dump_data(1, lm_key, 8);
551                 printf("expected:\n");
552                 dump_data(1, lm_hash, 8);
553                 pass = False;
554         }
555         if (memcmp(session_key.data, user_session_key, 
556                    sizeof(user_session_key)) != 0) {
557                 printf("NT Session Key does not match expectations!\n");
558                 printf("user_session_key:\n");
559                 dump_data(1, user_session_key, 16);
560                 printf("expected:\n");
561                 dump_data(1, session_key.data, session_key.length);
562                 pass = False;
563         }
564
565
566         return pass;
567 }
568
569 /* 
570  * Test the NTLMv2 and LMv2 responses
571  */
572
573 enum ntlmv2_domain {
574         UPPER_DOMAIN,
575         NO_DOMAIN
576 };
577
578 static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, 
579                                     enum ntlm_break break_which, 
580                                     enum ntlmv2_domain ntlmv2_domain, 
581                                     char **error_string) 
582 {
583         BOOL pass = True;
584         NTSTATUS nt_status;
585         DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
586         DATA_BLOB lmv2_response = data_blob(NULL, 0);
587         DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
588         DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
589         DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, TEST_MACHINE_NAME, lp_workgroup());
590
591         uint8_t lm_session_key[8];
592         uint8_t user_session_key[16];
593
594         ZERO_STRUCT(lm_session_key);
595         ZERO_STRUCT(user_session_key);
596         
597         switch (ntlmv2_domain) {
598         case UPPER_DOMAIN:
599                 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 
600                                       samlogon_state->account_name, samlogon_state->account_domain, 
601                                       samlogon_state->password, &samlogon_state->chall,
602                                       &names_blob,
603                                       &lmv2_response, &ntlmv2_response, 
604                                       &lmv2_session_key, &ntlmv2_session_key)) {
605                         data_blob_free(&names_blob);
606                         return False;
607                 }
608                 break;
609         case NO_DOMAIN:
610                 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 
611                                       samlogon_state->account_name, "",
612                                       samlogon_state->password, &samlogon_state->chall,
613                                       &names_blob,
614                                       &lmv2_response, &ntlmv2_response, 
615                                       &lmv2_session_key, &ntlmv2_session_key)) {
616                         data_blob_free(&names_blob);
617                         return False;
618                 }
619                 break;
620         }
621         data_blob_free(&names_blob);
622
623         nt_status = check_samlogon(samlogon_state,
624                                    break_which,
625                                    samlogon_state->parameter_control,
626                                    &samlogon_state->chall,
627                                    &lmv2_response,
628                                    &ntlmv2_response,
629                                    lm_session_key, 
630                                    user_session_key,
631                                    error_string);
632         
633         data_blob_free(&lmv2_response);
634         data_blob_free(&ntlmv2_response);
635
636
637         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
638                 /* for 'old' passwords, we allow the server to be OK or wrong password */
639                 if (samlogon_state->old_password) {
640                         return True;
641                 }
642                 return break_which == BREAK_BOTH;
643         } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
644                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
645         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
646                 SAFE_FREE(*error_string);
647                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
648                 return False;
649         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
650                 return True;
651         } else if (!NT_STATUS_IS_OK(nt_status)) {
652                 return False;
653         }
654
655
656         switch (break_which) {
657         case NO_NT:
658                 if (memcmp(lmv2_session_key.data, user_session_key,
659                            sizeof(user_session_key)) != 0) {
660                         printf("USER (LMv2) Session Key does not match expectations!\n");
661                         printf("user_session_key:\n");
662                         dump_data(1, user_session_key, 16);
663                         printf("expected:\n");
664                         dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
665                         pass = False;
666                 }
667                 if (memcmp(lmv2_session_key.data, lm_session_key, 
668                                    sizeof(lm_session_key)) != 0) {
669                         printf("LM (LMv2) Session Key does not match expectations!\n");
670                         printf("lm_session_key:\n");
671                         dump_data(1, lm_session_key, 8);
672                         printf("expected:\n");
673                         dump_data(1, lmv2_session_key.data, 8);
674                         pass = False;
675                 }
676                 break;
677         default:
678                 if (memcmp(ntlmv2_session_key.data, user_session_key, 
679                            sizeof(user_session_key)) != 0) {
680                         if (memcmp(lmv2_session_key.data, user_session_key,
681                                    sizeof(user_session_key)) == 0) {
682                                 printf("USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
683                                 printf("user_session_key:\n");
684                                 dump_data(1, user_session_key, 16);
685                                 printf("expected:\n");
686                                 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
687                                 pass = False;
688                                 
689                         } else {
690                                 printf("USER (NTLMv2) Session Key does not match expectations!\n");
691                                 printf("user_session_key:\n");
692                                 dump_data(1, user_session_key, 16);
693                                 printf("expected:\n");
694                                 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
695                                 pass = False;
696                         }
697                 }
698                 if (memcmp(ntlmv2_session_key.data, lm_session_key, 
699                            sizeof(lm_session_key)) != 0) {
700                         if (memcmp(lmv2_session_key.data, lm_session_key,
701                                    sizeof(lm_session_key)) == 0) {
702                                 printf("LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
703                                 printf("user_session_key:\n");
704                                 dump_data(1, lm_session_key, 8);
705                                 printf("expected:\n");
706                                 dump_data(1, ntlmv2_session_key.data, 8);
707                                 pass = False;
708                         } else {
709                                 printf("LM (NTLMv2) Session Key does not match expectations!\n");
710                                 printf("lm_session_key:\n");
711                                 dump_data(1, lm_session_key, 8);
712                                 printf("expected:\n");
713                                 dump_data(1, ntlmv2_session_key.data, 8);
714                                 pass = False;
715                         }
716                 }
717         }
718
719         return pass;
720 }
721
722 /* 
723  * Test the NTLM and LMv2 responses
724  */
725
726 static BOOL test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, 
727                                   enum ntlm_break break_which, 
728                                   enum ntlmv2_domain ntlmv2_domain, 
729                                   char **error_string) 
730 {
731         BOOL pass = True;
732         NTSTATUS nt_status;
733         DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
734         DATA_BLOB lmv2_response = data_blob(NULL, 0);
735         DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
736         DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
737         DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, lp_netbios_name(), lp_workgroup());
738
739         DATA_BLOB ntlm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
740         DATA_BLOB ntlm_session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
741
742         BOOL lm_good;
743         uint8_t lm_hash[16];
744         uint8_t lm_session_key[8];
745         uint8_t user_session_key[16];
746         uint8_t nt_hash[16];
747
748         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, 
749                      ntlm_response.data);
750         E_md4hash(samlogon_state->password, nt_hash);
751         SMBsesskeygen_ntv1(nt_hash, 
752                            ntlm_session_key.data);
753
754         lm_good = E_deshash(samlogon_state->password, lm_hash); 
755         if (!lm_good) {
756                 ZERO_STRUCT(lm_hash);
757         }
758
759         ZERO_STRUCT(lm_session_key);
760         ZERO_STRUCT(user_session_key);
761
762         switch (ntlmv2_domain) {
763         case UPPER_DOMAIN:
764                 /* TODO - test with various domain cases, and without domain */
765                 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 
766                                       samlogon_state->account_name, samlogon_state->account_domain, 
767                                       samlogon_state->password, &samlogon_state->chall,
768                                       &names_blob,
769                                       &lmv2_response, &ntlmv2_response, 
770                                       &lmv2_session_key, &ntlmv2_session_key)) {
771                         data_blob_free(&names_blob);
772                         return False;
773                 }
774                 break;
775         case NO_DOMAIN:
776                 /* TODO - test with various domain cases, and without domain */
777                 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 
778                                       samlogon_state->account_name, "",
779                                       samlogon_state->password, &samlogon_state->chall,
780                                       &names_blob,
781                                       &lmv2_response, &ntlmv2_response, 
782                                       &lmv2_session_key, &ntlmv2_session_key)) {
783                         data_blob_free(&names_blob);
784                         return False;
785                 }
786                 break;
787         }
788
789         data_blob_free(&names_blob);
790
791         nt_status = check_samlogon(samlogon_state,
792                                    break_which,
793                                    samlogon_state->parameter_control,
794                                    &samlogon_state->chall,
795                                    &lmv2_response,
796                                    &ntlm_response,
797                                    lm_session_key, 
798                                    user_session_key,
799                                    error_string);
800         
801         data_blob_free(&lmv2_response);
802         data_blob_free(&ntlmv2_response);
803
804
805         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
806                 /* for 'old' passwords, we allow the server to be OK or wrong password */
807                 if (samlogon_state->old_password) {
808                         return True;
809                 }
810                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
811         } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
812                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
813         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
814                 SAFE_FREE(*error_string);
815                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
816                 return False;
817         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
818                 return True;
819         } else if (!NT_STATUS_IS_OK(nt_status)) {
820                 return False;
821         }
822
823         switch (break_which) {
824         case NO_NT:
825                 if (memcmp(lmv2_session_key.data, user_session_key, 
826                            sizeof(user_session_key)) != 0) {
827                         printf("USER (LMv2) Session Key does not match expectations!\n");
828                         printf("user_session_key:\n");
829                         dump_data(1, user_session_key, 16);
830                         printf("expected:\n");
831                         dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
832                         pass = False;
833                 }
834                 if (memcmp(lmv2_session_key.data, lm_session_key, 
835                            sizeof(lm_session_key)) != 0) {
836                         printf("LM (LMv2) Session Key does not match expectations!\n");
837                         printf("lm_session_key:\n");
838                         dump_data(1, lm_session_key, 8);
839                         printf("expected:\n");
840                         dump_data(1, lmv2_session_key.data, 8);
841                         pass = False;
842                 }
843                 break;
844         case BREAK_LM:
845                 if (memcmp(ntlm_session_key.data, user_session_key, 
846                            sizeof(user_session_key)) != 0) {
847                         printf("USER (NTLMv2) Session Key does not match expectations!\n");
848                         printf("user_session_key:\n");
849                         dump_data(1, user_session_key, 16);
850                         printf("expected:\n");
851                         dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
852                         pass = False;
853                 }
854                 if (lm_good) {
855                         if (memcmp(lm_hash, lm_session_key, 
856                                    sizeof(lm_session_key)) != 0) {
857                                 printf("LM Session Key does not match expectations!\n");
858                                 printf("lm_session_key:\n");
859                                 dump_data(1, lm_session_key, 8);
860                                 printf("expected:\n");
861                                 dump_data(1, lm_hash, 8);
862                                 pass = False;
863                         }
864                 } else {
865                         static const uint8_t zeros[8];
866                         if (memcmp(zeros, lm_session_key, 
867                                    sizeof(lm_session_key)) != 0) {
868                                 printf("LM Session Key does not match expectations (zeros)!\n");
869                                 printf("lm_session_key:\n");
870                                 dump_data(1, lm_session_key, 8);
871                                 printf("expected:\n");
872                                 dump_data(1, zeros, 8);
873                                 pass = False;
874                         }
875                 }
876                 break;
877         default:
878                 if (memcmp(ntlm_session_key.data, user_session_key, 
879                            sizeof(user_session_key)) != 0) {
880                         printf("USER (NTLMv2) Session Key does not match expectations!\n");
881                         printf("user_session_key:\n");
882                         dump_data(1, user_session_key, 16);
883                         printf("expected:\n");
884                         dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
885                         pass = False;
886                 }
887                 if (memcmp(ntlm_session_key.data, lm_session_key, 
888                            sizeof(lm_session_key)) != 0) {
889                         printf("LM (NTLMv2) Session Key does not match expectations!\n");
890                         printf("lm_session_key:\n");
891                         dump_data(1, lm_session_key, 8);
892                         printf("expected:\n");
893                         dump_data(1, ntlm_session_key.data, 8);
894                         pass = False;
895                 }
896         }
897
898         return pass;
899 }
900
901 /* 
902  * Test the NTLMv2 and LMv2 responses
903  */
904
905 static BOOL test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 
906 {
907         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, UPPER_DOMAIN, error_string);
908 }
909
910 #if 0
911 static BOOL test_lmv2_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
912 {
913         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, NO_DOMAIN, error_string);
914 }
915 #endif
916
917 /* 
918  * Test the LMv2 response only
919  */
920
921 static BOOL test_lmv2(struct samlogon_state *samlogon_state, char **error_string) 
922 {
923         return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, UPPER_DOMAIN, error_string);
924 }
925
926 static BOOL test_lmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
927 {
928         return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, NO_DOMAIN, error_string);
929 }
930
931 /* 
932  * Test the NTLMv2 response only
933  */
934
935 static BOOL test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 
936 {
937         return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, UPPER_DOMAIN, error_string);
938 }
939
940 static BOOL test_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
941 {
942         return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, NO_DOMAIN, error_string);
943 }
944
945 static BOOL test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
946 {
947         return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
948 }
949
950 static BOOL test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string) 
951 {
952         return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
953 }
954
955 static BOOL test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string) 
956 {
957         return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
958 }
959
960 static BOOL test_lm_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string) 
961 {
962         return test_lm_ntlm_broken(samlogon_state, BREAK_BOTH, error_string);
963 }
964 static BOOL test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 
965 {
966         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
967 }
968
969 static BOOL test_ntlmv2_lmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
970 {
971         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
972 }
973
974 static BOOL test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 
975 {
976         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
977 }
978
979 #if 0
980 static BOOL test_ntlmv2_ntlmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
981 {
982         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
983 }
984 #endif
985
986 static BOOL test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char **error_string) 
987 {
988         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
989 }
990
991 static BOOL test_ntlmv2_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
992 {
993         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
994 }
995
996 static BOOL test_lmv2_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string) 
997 {
998         return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
999 }
1000
1001 static BOOL test_lmv2_ntlm_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
1002 {
1003         return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
1004 }
1005
1006 static BOOL test_lmv2_ntlm_break_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
1007 {
1008         return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
1009 }
1010
1011 static BOOL test_lmv2_ntlm_break_ntlm_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
1012 {
1013         return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
1014 }
1015
1016 static BOOL test_lmv2_ntlm_break_lm(struct samlogon_state *samlogon_state, char **error_string) 
1017 {
1018         return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
1019 }
1020
1021 static BOOL test_lmv2_ntlm_break_lm_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
1022 {
1023         return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
1024 }
1025
1026 /* 
1027  * Test the NTLM2 response (extra challenge in LM feild)
1028  *
1029  * This test is the same as the 'break LM' test, but checks that the
1030  * server implements NTLM2 session security in the right place
1031  * (NETLOGON is the wrong place).
1032  */
1033
1034 static BOOL test_ntlm2(struct samlogon_state *samlogon_state, char **error_string) 
1035 {
1036         BOOL pass = True;
1037         NTSTATUS nt_status;
1038         DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1039         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1040
1041         BOOL lm_good;
1042         uint8_t lm_key[8];
1043         uint8_t nt_hash[16];
1044         uint8_t lm_hash[16];
1045         uint8_t nt_key[16];
1046         uint8_t user_session_key[16];
1047         uint8_t expected_user_session_key[16];
1048         uint8_t session_nonce_hash[16];
1049         uint8_t client_chall[8];
1050         
1051         struct MD5Context md5_session_nonce_ctx;
1052         HMACMD5Context hmac_ctx;
1053                         
1054         ZERO_STRUCT(user_session_key);
1055         ZERO_STRUCT(lm_key);
1056         generate_random_buffer(client_chall, 8);
1057         
1058         MD5Init(&md5_session_nonce_ctx);
1059         MD5Update(&md5_session_nonce_ctx, samlogon_state->chall.data, 8);
1060         MD5Update(&md5_session_nonce_ctx, client_chall, 8);
1061         MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
1062         
1063         E_md4hash(samlogon_state->password, (uint8_t *)nt_hash);
1064         lm_good = E_deshash(samlogon_state->password, (uint8_t *)lm_hash);
1065         SMBsesskeygen_ntv1((const uint8_t *)nt_hash, 
1066                            nt_key);
1067
1068         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
1069
1070         memcpy(lm_response.data, session_nonce_hash, 8);
1071         memset(lm_response.data + 8, 0, 16);
1072
1073         hmac_md5_init_rfc2104(nt_key, 16, &hmac_ctx);
1074         hmac_md5_update(samlogon_state->chall.data, 8, &hmac_ctx);
1075         hmac_md5_update(client_chall, 8, &hmac_ctx);
1076         hmac_md5_final(expected_user_session_key, &hmac_ctx);
1077
1078         nt_status = check_samlogon(samlogon_state,
1079                                    BREAK_NONE,
1080                                    samlogon_state->parameter_control,
1081                                    &samlogon_state->chall,
1082                                    &lm_response,
1083                                    &nt_response,
1084                                    lm_key, 
1085                                    user_session_key,
1086                                    error_string);
1087         
1088         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1089                 /* for 'old' passwords, we allow the server to be OK or wrong password */
1090                 if (samlogon_state->old_password) {
1091                         return True;
1092                 }
1093                 return False;
1094         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1095                 SAFE_FREE(*error_string);
1096                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1097                 return False;
1098         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1099                 return True;
1100         } else if (!NT_STATUS_IS_OK(nt_status)) {
1101                 return False;
1102         }
1103
1104         if (lm_good) {
1105                 if (memcmp(lm_hash, lm_key, 
1106                            sizeof(lm_key)) != 0) {
1107                         printf("LM Key does not match expectations!\n");
1108                         printf("lm_key:\n");
1109                         dump_data(1, lm_key, 8);
1110                         printf("expected:\n");
1111                         dump_data(1, lm_hash, 8);
1112                         pass = False;
1113                 }
1114         } else {
1115                 static const uint8_t zeros[8];
1116                 if (memcmp(zeros, lm_key, 
1117                            sizeof(lm_key)) != 0) {
1118                         printf("LM Session Key does not match expectations (zeros)!\n");
1119                         printf("lm_key:\n");
1120                         dump_data(1, lm_key, 8);
1121                         printf("expected:\n");
1122                         dump_data(1, zeros, 8);
1123                         pass = False;
1124                 }
1125         }
1126         if (memcmp(nt_key, user_session_key, 16) != 0) {
1127                 printf("NT Session Key does not match expectations (should be NT Key)!\n");
1128                 printf("user_session_key:\n");
1129                 dump_data(1, user_session_key, sizeof(user_session_key));
1130                 printf("expected:\n");
1131                 dump_data(1, nt_key, sizeof(nt_key));
1132                 pass = False;
1133         }
1134         return pass;
1135 }
1136
1137 static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
1138 {
1139         NTSTATUS nt_status;
1140         DATA_BLOB nt_response = data_blob(NULL, 0);
1141         DATA_BLOB lm_response = data_blob(NULL, 0);
1142         char *password;
1143         char *dospw;
1144         void *unicodepw;
1145
1146         uint8_t user_session_key[16];
1147         uint8_t lm_key[16];
1148         uint8_t lm_hash[16];
1149         static const uint8_t zeros[8];
1150         DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
1151         BOOL lm_good = E_deshash(samlogon_state->password, lm_hash); 
1152
1153         ZERO_STRUCT(user_session_key);
1154         
1155         if ((push_ucs2_talloc(samlogon_state->mem_ctx, &unicodepw, 
1156                               samlogon_state->password)) == -1) {
1157                 DEBUG(0, ("push_ucs2_allocate failed!\n"));
1158                 exit(1);
1159         }
1160
1161         nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, strlen_m(samlogon_state->password)*2);
1162
1163         password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password);
1164
1165         if ((convert_string_talloc(samlogon_state->mem_ctx, CH_UNIX, 
1166                                    CH_DOS, password,
1167                                    strlen(password)+1, 
1168                                    (void**)&dospw)) == -1) {
1169                 DEBUG(0, ("convert_string_talloc failed!\n"));
1170                 exit(1);
1171         }
1172
1173         lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
1174
1175         nt_status = check_samlogon(samlogon_state,
1176                                    break_which,
1177                                    samlogon_state->parameter_control | MSV1_0_CLEARTEXT_PASSWORD_ALLOWED,
1178                                    &chall,
1179                                    &lm_response,
1180                                    &nt_response,
1181                                    lm_key, 
1182                                    user_session_key,
1183                                    error_string);
1184         
1185         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1186                 /* for 'old' passwords, we allow the server to be OK or wrong password */
1187                 if (samlogon_state->old_password) {
1188                         return True;
1189                 }
1190                 /* for 'long' passwords, the LM password is invalid */
1191                 if (break_which == NO_NT && !lm_good) {
1192                         return True;
1193                 }
1194                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
1195         } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
1196                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
1197         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1198                 SAFE_FREE(*error_string);
1199                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1200                 return False;
1201         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1202                 return True;
1203         } else if (!NT_STATUS_IS_OK(nt_status)) {
1204                 return False;
1205         }
1206
1207         if (break_which == NO_NT && !lm_good) {
1208                 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
1209                 return False;
1210         }
1211
1212         return True;
1213 }
1214
1215 static BOOL test_plaintext_none_broken(struct samlogon_state *samlogon_state, 
1216                                        char **error_string) {
1217         return test_plaintext(samlogon_state, BREAK_NONE, error_string);
1218 }
1219
1220 static BOOL test_plaintext_lm_broken(struct samlogon_state *samlogon_state, 
1221                                      char **error_string) {
1222         return test_plaintext(samlogon_state, BREAK_LM, error_string);
1223 }
1224
1225 static BOOL test_plaintext_nt_broken(struct samlogon_state *samlogon_state, 
1226                                      char **error_string) {
1227         return test_plaintext(samlogon_state, BREAK_NT, error_string);
1228 }
1229
1230 static BOOL test_plaintext_nt_only(struct samlogon_state *samlogon_state, 
1231                                    char **error_string) {
1232         return test_plaintext(samlogon_state, NO_LM, error_string);
1233 }
1234
1235 static BOOL test_plaintext_lm_only(struct samlogon_state *samlogon_state, 
1236                                    char **error_string) {
1237         return test_plaintext(samlogon_state, NO_NT, error_string);
1238 }
1239
1240 /* 
1241    Tests:
1242    
1243    - LM only
1244    - NT and LM             
1245    - NT
1246    - NT in LM field
1247    - NT in both fields
1248    - NTLMv2
1249    - NTLMv2 and LMv2
1250    - LMv2
1251    - plaintext tests (in challenge-response fields)
1252   
1253    check we get the correct session key in each case
1254    check what values we get for the LM session key
1255    
1256 */
1257
1258 static const struct ntlm_tests {
1259         BOOL (*fn)(struct samlogon_state *, char **);
1260         const char *name;
1261         BOOL expect_fail;
1262 } test_table[] = {
1263         {test_lmv2_ntlmv2, "NTLMv2 and LMv2", False},
1264 #if 0
1265         {test_lmv2_ntlmv2_no_dom, "NTLMv2 and LMv2 (no domain)", False},
1266 #endif
1267         {test_lm, "LM", False},
1268         {test_lm_ntlm, "LM and NTLM", False},
1269         {test_lm_ntlm_both_broken, "LM and NTLM, both broken", False},
1270         {test_ntlm, "NTLM", False},
1271         {test_ntlm_in_lm, "NTLM in LM", False},
1272         {test_ntlm_in_both, "NTLM in both", False},
1273         {test_ntlmv2, "NTLMv2", False},
1274         {test_ntlmv2_no_dom, "NTLMv2 (no domain)", False},
1275         {test_lmv2, "LMv2", False},
1276         {test_lmv2_no_dom, "LMv2 (no domain)", False},
1277         {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False},
1278         {test_ntlmv2_lmv2_broken_no_dom, "NTLMv2 and LMv2, LMv2 broken (no domain)", False},
1279         {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False},
1280 #if 0
1281         {test_ntlmv2_ntlmv2_broken_no_dom, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", False},
1282 #endif
1283         {test_ntlmv2_both_broken, "NTLMv2 and LMv2, both broken", False},
1284         {test_ntlmv2_both_broken_no_dom, "NTLMv2 and LMv2, both broken (no domain)", False},
1285         {test_ntlm_lm_broken, "NTLM and LM, LM broken", False},
1286         {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False},
1287         {test_ntlm2, "NTLM2 (NTLMv2 session security)", False},
1288         {test_lmv2_ntlm_both_broken, "LMv2 and NTLM, both broken", False},
1289         {test_lmv2_ntlm_both_broken_no_dom, "LMv2 and NTLM, both broken (no domain)", False},
1290         {test_lmv2_ntlm_break_ntlm, "LMv2 and NTLM, NTLM broken", False},
1291         {test_lmv2_ntlm_break_ntlm_no_dom, "LMv2 and NTLM, NTLM broken (no domain)", False},
1292         {test_lmv2_ntlm_break_lm, "LMv2 and NTLM, LMv2 broken", False},
1293         {test_lmv2_ntlm_break_lm_no_dom, "LMv2 and NTLM, LMv2 broken (no domain)", False},
1294         {test_plaintext_none_broken, "Plaintext", False},
1295         {test_plaintext_lm_broken, "Plaintext LM broken", False},
1296         {test_plaintext_nt_broken, "Plaintext NT broken", False},
1297         {test_plaintext_nt_only, "Plaintext NT only", False},
1298         {test_plaintext_lm_only, "Plaintext LM only", False},
1299         {NULL, NULL}
1300 };
1301
1302 /*
1303   try a netlogon SamLogon
1304 */
1305 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1306                           struct creds_CredentialState *creds, 
1307                           const char *comment,
1308                           const char *account_domain, const char *account_name, 
1309                           const char *plain_pass, uint32_t parameter_control,
1310                           NTSTATUS expected_error, BOOL old_password,
1311                           int n_subtests)
1312 {
1313         TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_SamLogon function-level context");
1314         int i, v, l, f;
1315         BOOL ret = True;
1316         int validation_levels[] = {2,3,6};
1317         int logon_levels[] = { 2, 6 };
1318         int function_levels[] = { 
1319                 DCERPC_NETR_LOGONSAMLOGON,
1320                 DCERPC_NETR_LOGONSAMLOGONEX,
1321                 DCERPC_NETR_LOGONSAMLOGONWITHFLAGS };
1322         struct samlogon_state samlogon_state;
1323         
1324         printf("testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
1325         
1326         samlogon_state.comment = comment;
1327         samlogon_state.account_name = account_name;
1328         samlogon_state.account_domain = account_domain;
1329         samlogon_state.password = plain_pass;
1330         samlogon_state.p = p;
1331         samlogon_state.creds = creds;
1332         samlogon_state.expected_error = expected_error;
1333         samlogon_state.chall = data_blob_talloc(fn_ctx, NULL, 8);
1334         samlogon_state.parameter_control = parameter_control;
1335         samlogon_state.old_password = old_password;
1336
1337         generate_random_buffer(samlogon_state.chall.data, 8);
1338         samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1339         samlogon_state.r_flags.in.computer_name = TEST_MACHINE_NAME;
1340         samlogon_state.r_flags.in.credential = &samlogon_state.auth;
1341         samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2;
1342         samlogon_state.r_flags.in.flags = 0;
1343
1344         samlogon_state.r_ex.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1345         samlogon_state.r_ex.in.computer_name = TEST_MACHINE_NAME;
1346         samlogon_state.r_ex.in.flags = 0;
1347
1348         samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1349         samlogon_state.r.in.computer_name = TEST_MACHINE_NAME;
1350         samlogon_state.r.in.credential = &samlogon_state.auth;
1351         samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
1352
1353         for (f=0;f<ARRAY_SIZE(function_levels);f++) {
1354                 for (i=0; test_table[i].fn; i++) {
1355                         if (n_subtests && (i > n_subtests)) {
1356                                 continue;
1357                         }
1358                         for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
1359                                 for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
1360                                         char *error_string = NULL;
1361                                         TALLOC_CTX *tmp_ctx = talloc_named(fn_ctx, 0, "test_SamLogon inner loop");
1362                                         samlogon_state.mem_ctx = tmp_ctx;
1363                                         samlogon_state.function_level = function_levels[f];
1364                                         samlogon_state.r.in.validation_level = validation_levels[v];
1365                                         samlogon_state.r.in.logon_level = logon_levels[l];
1366                                         samlogon_state.r_ex.in.validation_level = validation_levels[v];
1367                                         samlogon_state.r_ex.in.logon_level = logon_levels[l];
1368                                         samlogon_state.r_flags.in.validation_level = validation_levels[v];
1369                                         samlogon_state.r_flags.in.logon_level = logon_levels[l];
1370                                         if (!test_table[i].fn(&samlogon_state, &error_string)) {
1371                                                 printf("Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n",
1372                                                        samlogon_state.comment,
1373                                                        samlogon_state.account_domain,
1374                                                        samlogon_state.account_name,
1375                                                        test_table[i].name, validation_levels[v], 
1376                                                        logon_levels[l], function_levels[f]);
1377                                                 
1378                                                 if (test_table[i].expect_fail) {
1379                                                         printf(" failed (expected, test incomplete): %s\n", error_string);
1380                                                 } else {
1381                                                         printf(" failed: %s\n", error_string);
1382                                                         ret = False;
1383                                                 }
1384                                                 SAFE_FREE(error_string);
1385                                         }
1386                                         talloc_free(tmp_ctx);
1387                                 }
1388                         }
1389                 }
1390         }
1391         talloc_free(fn_ctx);
1392         return ret;
1393 }
1394
1395 /*
1396   test an ADS style interactive domain logon
1397 */
1398 BOOL test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1399                            struct creds_CredentialState *creds, 
1400                            const char *comment,
1401                            const char *workstation_name,
1402                            const char *account_domain, const char *account_name,
1403                            const char *plain_pass, uint32_t parameter_control, 
1404                            NTSTATUS expected_error)
1405 {
1406         NTSTATUS status;
1407         TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context");
1408         struct netr_LogonSamLogonWithFlags r;
1409         struct netr_Authenticator a, ra;
1410         struct netr_PasswordInfo pinfo;
1411
1412         ZERO_STRUCT(a);
1413         ZERO_STRUCT(r);
1414         ZERO_STRUCT(ra);
1415
1416         creds_client_authenticator(creds, &a);
1417
1418         r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1419         r.in.computer_name = TEST_MACHINE_NAME;
1420         r.in.credential = &a;
1421         r.in.return_authenticator = &ra;
1422         r.in.logon_level = 5;
1423         r.in.logon.password = &pinfo;
1424         r.in.validation_level = 6;
1425         r.in.flags = 0;
1426
1427         pinfo.identity_info.domain_name.string = account_domain;
1428         pinfo.identity_info.parameter_control = parameter_control;
1429         pinfo.identity_info.logon_id_low = 0;
1430         pinfo.identity_info.logon_id_high = 0;
1431         pinfo.identity_info.account_name.string = account_name;
1432         pinfo.identity_info.workstation.string = workstation_name;
1433
1434         if (!E_deshash(plain_pass, pinfo.lmpassword.hash)) {
1435                 ZERO_STRUCT(pinfo.lmpassword.hash);
1436         }
1437         E_md4hash(plain_pass, pinfo.ntpassword.hash);
1438
1439         if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1440                 creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
1441                 creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
1442         } else {
1443                 creds_des_encrypt(creds, &pinfo.lmpassword);
1444                 creds_des_encrypt(creds, &pinfo.ntpassword);
1445         }
1446
1447         printf("Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment);
1448
1449         status = dcerpc_netr_LogonSamLogonWithFlags(p, fn_ctx, &r);
1450         if (!r.out.return_authenticator 
1451             || !creds_client_check(creds, &r.out.return_authenticator->cred)) {
1452                 printf("Credential chaining failed\n");
1453                 talloc_free(fn_ctx);
1454                 return False;
1455         }
1456
1457         talloc_free(fn_ctx);
1458
1459         if (!NT_STATUS_EQUAL(expected_error, status)) {
1460                 printf("[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n", 
1461                        account_domain, account_name, nt_errstr(expected_error), nt_errstr(status));
1462                 return False;
1463         }
1464
1465         return True;
1466 }
1467
1468
1469
1470 BOOL torture_rpc_samlogon(void)
1471 {
1472         NTSTATUS status;
1473         struct dcerpc_pipe *p;
1474         struct dcerpc_binding *b;
1475         struct cli_credentials *machine_credentials;
1476         TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_netlogon");
1477         BOOL ret = True;
1478         struct test_join *join_ctx;
1479         struct test_join *user_ctx;
1480         char *user_password;
1481         const char *old_user_password;
1482         char *test_machine_account;
1483         const char *binding = lp_parm_string(-1, "torture", "binding");
1484         const char *userdomain;
1485         int i;
1486         int ci;
1487
1488         unsigned int credential_flags[] = {
1489                 NETLOGON_NEG_AUTH2_FLAGS,
1490                 NETLOGON_NEG_ARCFOUR,
1491                 NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,
1492                 NETLOGON_NEG_AUTH2_ADS_FLAGS, 
1493                 0 /* yes, this is a valid flag, causes the use of DES */ 
1494         };
1495
1496         struct creds_CredentialState *creds;
1497
1498         test_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
1499         /* We only need to join as a workstation here, and in future,
1500          * if we wish to test against trusted domains, we must be a
1501          * workstation here */
1502         join_ctx = torture_join_domain(TEST_MACHINE_NAME, ACB_WSTRUST, 
1503                                        &machine_credentials);
1504         if (!join_ctx) {
1505                 printf("Failed to join as Workstation\n");
1506                 return False;
1507         }
1508
1509         userdomain = lp_parm_string(-1, "torture", "userdomain");
1510         if (!userdomain) {
1511                 userdomain = lp_workgroup();
1512         }
1513
1514         user_ctx = torture_create_testuser(TEST_USER_NAME,
1515                                            userdomain,
1516                                            ACB_NORMAL, 
1517                                            (const char **)&user_password);
1518         if (!user_ctx) {
1519                 printf("Failed to join as Workstation\n");
1520                 return False;
1521         }
1522
1523         old_user_password = user_password;
1524
1525         test_ChangePasswordUser3(torture_join_samr_pipe(user_ctx), mem_ctx,
1526                                  TEST_USER_NAME, 16 /* > 14 */, &user_password);
1527
1528         status = dcerpc_parse_binding(mem_ctx, binding, &b);
1529         if (!NT_STATUS_IS_OK(status)) {
1530                 printf("Bad binding string %s\n", binding);
1531                 ret = False;
1532                 goto failed;
1533         }
1534
1535         /* We have to use schannel, otherwise the SamLogonEx fails
1536          * with INTERNAL_ERROR */
1537
1538         b->flags &= ~DCERPC_AUTH_OPTIONS;
1539         b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
1540
1541         status = dcerpc_pipe_connect_b(mem_ctx, &p, b, 
1542                                                                    &dcerpc_table_netlogon,
1543                                        machine_credentials, NULL);
1544
1545         if (!NT_STATUS_IS_OK(status)) {
1546                 printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
1547                 ret = False;
1548                 goto failed;
1549         }
1550
1551         status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds);
1552         if (!NT_STATUS_IS_OK(status)) {
1553                 ret = False;
1554                 goto failed;
1555         }
1556
1557         {
1558                 
1559                 struct {
1560                         const char *comment;
1561                         const char *domain;
1562                         const char *username;
1563                         const char *password;
1564                         BOOL network_login;
1565                         NTSTATUS expected_interactive_error;
1566                         NTSTATUS expected_network_error;
1567                         uint32_t parameter_control;
1568                         BOOL old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
1569                 } usercreds[] = {
1570                         {
1571                                 .comment       = "domain\\user",
1572                                 .domain        = cli_credentials_get_domain(cmdline_credentials),
1573                                 .username      = cli_credentials_get_username(cmdline_credentials),
1574                                 .password      = cli_credentials_get_password(cmdline_credentials),
1575                                 .network_login = True,
1576                                 .expected_interactive_error = NT_STATUS_OK,
1577                                 .expected_network_error     = NT_STATUS_OK
1578                         },
1579                         {
1580                                 .comment       = "realm\\user",
1581                                 .domain        = cli_credentials_get_realm(cmdline_credentials),
1582                                 .username      = cli_credentials_get_username(cmdline_credentials),
1583                                 .password      = cli_credentials_get_password(cmdline_credentials),
1584                                 .network_login = True,
1585                                 .expected_interactive_error = NT_STATUS_OK,
1586                                 .expected_network_error     = NT_STATUS_OK
1587                         },
1588                         {
1589                                 .comment       = "user@domain",
1590                                 .domain        = NULL,
1591                                 .username      = talloc_asprintf(mem_ctx, 
1592                                                 "%s@%s", 
1593                                                 cli_credentials_get_username(cmdline_credentials),
1594                                                 cli_credentials_get_domain(cmdline_credentials)
1595                                         ),
1596                                 .password      = cli_credentials_get_password(cmdline_credentials),
1597                                 .network_login = False, /* works for some things, but not NTLMv2.  Odd */
1598                                 .expected_interactive_error = NT_STATUS_OK,
1599                                 .expected_network_error     = NT_STATUS_OK
1600                         },
1601                         {
1602                                 .comment       = "user@realm",
1603                                 .domain        = NULL,
1604                                 .username      = talloc_asprintf(mem_ctx, 
1605                                                 "%s@%s", 
1606                                                 cli_credentials_get_username(cmdline_credentials),
1607                                                 cli_credentials_get_realm(cmdline_credentials)
1608                                         ),
1609                                 .password      = cli_credentials_get_password(cmdline_credentials),
1610                                 .network_login = True,
1611                                 .expected_interactive_error = NT_STATUS_OK,
1612                                 .expected_network_error     = NT_STATUS_OK
1613                         },
1614                         {
1615                                 .comment      = "machine domain\\user",
1616                                 .domain       = cli_credentials_get_domain(machine_credentials),
1617                                 .username     = cli_credentials_get_username(machine_credentials),
1618                                 .password     = cli_credentials_get_password(machine_credentials),
1619                                 .network_login = True,
1620                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1621                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1622                         },
1623                         {
1624                                 .comment      = "machine domain\\user",
1625                                 .domain       = cli_credentials_get_domain(machine_credentials),
1626                                 .username     = cli_credentials_get_username(machine_credentials),
1627                                 .password     = cli_credentials_get_password(machine_credentials),
1628                                 .network_login = True,
1629                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1630                                 .expected_network_error = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
1631                         },
1632                         {
1633                                 .comment       = "machine realm\\user",
1634                                 .domain        = cli_credentials_get_realm(machine_credentials),
1635                                 .username      = cli_credentials_get_username(machine_credentials),
1636                                 .password      = cli_credentials_get_password(machine_credentials),
1637                                 .network_login = True,
1638                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1639                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1640                         },
1641                         {
1642                                 .comment       = "machine user@domain",
1643                                 .domain        = NULL,
1644                                 .username      = talloc_asprintf(mem_ctx, 
1645                                                                 "%s@%s", 
1646                                                                 cli_credentials_get_username(machine_credentials),
1647                                                                 cli_credentials_get_domain(machine_credentials)
1648                                         ), 
1649                                 .password      = cli_credentials_get_password(machine_credentials),
1650                                 .network_login = False, /* works for some things, but not NTLMv2.  Odd */
1651                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1652                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1653                         },
1654                         {
1655                                 .comment       = "machine user@realm",
1656                                 .domain        = NULL,
1657                                 .username      = talloc_asprintf(mem_ctx, 
1658                                                                 "%s@%s", 
1659                                                                 cli_credentials_get_username(machine_credentials),
1660                                                                 cli_credentials_get_realm(machine_credentials)
1661                                         ),
1662                                 .password      = cli_credentials_get_password(machine_credentials),
1663                                 .network_login = True,
1664                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1665                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1666                         },
1667                         {       
1668                                 .comment       = "test user (long pw): domain\\user",
1669                                 .domain        = userdomain,
1670                                 .username      = TEST_USER_NAME,
1671                                 .password      = user_password,
1672                                 .network_login = True,
1673                                 .expected_interactive_error = NT_STATUS_OK,
1674                                 .expected_network_error     = NT_STATUS_OK
1675                         },
1676                         {
1677                                 .comment       = "test user (long pw): user@realm", 
1678                                 .domain        = NULL,
1679                                 .username      = talloc_asprintf(mem_ctx, 
1680                                                                  "%s@%s", 
1681                                                                  TEST_USER_NAME,
1682                                                                  lp_realm()),
1683                                 .password      = user_password,
1684                                 .network_login = True,
1685                                 .expected_interactive_error = NT_STATUS_OK,
1686                                 .expected_network_error     = NT_STATUS_OK
1687                         },
1688                         {
1689                                 .comment       = "test user (long pw): user@domain",
1690                                 .domain        = NULL,
1691                                 .username      = talloc_asprintf(mem_ctx, 
1692                                                                  "%s@%s", 
1693                                                                  TEST_USER_NAME,
1694                                                                  userdomain),
1695                                 .password      = user_password,
1696                                 .network_login = False, /* works for some things, but not NTLMv2.  Odd */
1697                                 .expected_interactive_error = NT_STATUS_OK,
1698                                 .expected_network_error     = NT_STATUS_OK
1699                         },
1700                         /* Oddball, can we use the old password ? */
1701                         {       
1702                                 .comment       = "test user: user\\domain OLD PASSWORD",
1703                                 .domain        = userdomain,
1704                                 .username      = TEST_USER_NAME,
1705                                 .password      = old_user_password,
1706                                 .network_login = True,
1707                                 .expected_interactive_error = NT_STATUS_WRONG_PASSWORD,
1708                                 .expected_network_error     = NT_STATUS_OK,
1709                                 .old_password  = True
1710                         }
1711                 };
1712                 
1713                 /* Try all the tests for different username forms */
1714                 for (ci = 0; ci < ARRAY_SIZE(usercreds); ci++) {
1715                 
1716                         if (!test_InteractiveLogon(p, mem_ctx, creds,
1717                                                    usercreds[ci].comment,
1718                                                    TEST_MACHINE_NAME,
1719                                                    usercreds[ci].domain,
1720                                                    usercreds[ci].username,
1721                                                    usercreds[ci].password,
1722                                                    usercreds[ci].parameter_control,
1723                                                    usercreds[ci].expected_interactive_error)) {
1724                                 ret = False;
1725                         }
1726                 
1727                         if (usercreds[ci].network_login) {
1728                                 if (!test_SamLogon(p, mem_ctx, creds, 
1729                                                    usercreds[ci].comment,
1730                                                    usercreds[ci].domain,
1731                                                    usercreds[ci].username,
1732                                                    usercreds[ci].password,
1733                                                    usercreds[ci].parameter_control,
1734                                                    usercreds[ci].expected_network_error,
1735                                                    usercreds[ci].old_password,
1736                                                    0)) {
1737                                         ret = False;
1738                                 }
1739                         }
1740                 }
1741
1742                 /* Using the first username form, try the different
1743                  * credentials flag setups, on only one of the tests (checks
1744                  * session key encryption) */
1745
1746                 for (i=0; i < ARRAY_SIZE(credential_flags); i++) {
1747                         /* TODO:  Somehow we lost setting up the different credential flags here! */
1748
1749                         if (!test_InteractiveLogon(p, mem_ctx, creds,
1750                                                    usercreds[0].comment,
1751                                                    TEST_MACHINE_NAME,
1752                                                    usercreds[0].domain,
1753                                                    usercreds[0].username,
1754                                                    usercreds[0].password,
1755                                                    usercreds[0].parameter_control,
1756                                                    usercreds[0].expected_interactive_error)) {
1757                                 ret = False;
1758                         }
1759                 
1760                         if (usercreds[0].network_login) {
1761                                 if (!test_SamLogon(p, mem_ctx, creds,
1762                                                    usercreds[0].comment,
1763                                                    usercreds[0].domain,
1764                                                    usercreds[0].username,
1765                                                    usercreds[0].password,
1766                                                    usercreds[0].parameter_control,
1767                                                    usercreds[0].expected_network_error,
1768                                                    usercreds[0].old_password,
1769                                                    1)) {
1770                                         ret = False;
1771                                 }
1772                         }
1773                 }
1774
1775         }
1776 failed:
1777         talloc_free(mem_ctx);
1778
1779         torture_leave_domain(join_ctx);
1780         torture_leave_domain(user_ctx);
1781         return ret;
1782 }