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