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