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