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