Rework Samba4 to use the new common libcli/auth code
[ira/wip.git] / source4 / torture / rpc / samlogon.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    test suite for netlogon SamLogon operations
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
8    Copyright (C) Tim Potter      2003
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 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 netlogon_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                 netlogon_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                     !netlogon_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                 netlogon_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                 netlogon_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                 netlogon_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                     !netlogon_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                 netlogon_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, 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->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         smb_ucs2_t *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                               &unicodepw, samlogon_state->password, NULL)) {
1166                 DEBUG(0, ("push_ucs2_allocate failed!\n"));
1167                 exit(1);
1168         }
1169
1170         nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, strlen_m(samlogon_state->password)*2);
1171
1172         password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password);
1173
1174         if (!convert_string_talloc_convenience(samlogon_state->mem_ctx, 
1175                                    samlogon_state->iconv_convenience,
1176                                    CH_UNIX, CH_DOS, 
1177                                    password, strlen(password)+1, 
1178                                    (void**)&dospw, NULL, false)) {
1179                 DEBUG(0, ("convert_string_talloc failed!\n"));
1180                 exit(1);
1181         }
1182
1183         lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
1184
1185         nt_status = check_samlogon(samlogon_state,
1186                                    break_which,
1187                                    samlogon_state->parameter_control | MSV1_0_CLEARTEXT_PASSWORD_ALLOWED,
1188                                    &chall,
1189                                    &lm_response,
1190                                    &nt_response,
1191                                    lm_key, 
1192                                    user_session_key,
1193                                    error_string);
1194         
1195         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1196                 /* for 'old' passwords, we allow the server to be OK or wrong password */
1197                 if (samlogon_state->old_password) {
1198                         return true;
1199                 }
1200                 /* for 'long' passwords, the LM password is invalid */
1201                 if (break_which == NO_NT && !lm_good) {
1202                         return true;
1203                 }
1204                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
1205         } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
1206                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
1207         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1208                 SAFE_FREE(*error_string);
1209                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1210                 return false;
1211         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1212                 return true;
1213         } else if (!NT_STATUS_IS_OK(nt_status)) {
1214                 return false;
1215         }
1216
1217         if (break_which == NO_NT && !lm_good) {
1218                 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
1219                 return false;
1220         }
1221
1222         return true;
1223 }
1224
1225 static bool test_plaintext_none_broken(struct samlogon_state *samlogon_state, 
1226                                        char **error_string) {
1227         return test_plaintext(samlogon_state, BREAK_NONE, error_string);
1228 }
1229
1230 static bool test_plaintext_lm_broken(struct samlogon_state *samlogon_state, 
1231                                      char **error_string) {
1232         return test_plaintext(samlogon_state, BREAK_LM, error_string);
1233 }
1234
1235 static bool test_plaintext_nt_broken(struct samlogon_state *samlogon_state, 
1236                                      char **error_string) {
1237         return test_plaintext(samlogon_state, BREAK_NT, error_string);
1238 }
1239
1240 static bool test_plaintext_nt_only(struct samlogon_state *samlogon_state, 
1241                                    char **error_string) {
1242         return test_plaintext(samlogon_state, NO_LM, error_string);
1243 }
1244
1245 static bool test_plaintext_lm_only(struct samlogon_state *samlogon_state, 
1246                                    char **error_string) {
1247         return test_plaintext(samlogon_state, NO_NT, error_string);
1248 }
1249
1250 /* 
1251    Tests:
1252    
1253    - LM only
1254    - NT and LM             
1255    - NT
1256    - NT in LM field
1257    - NT in both fields
1258    - NTLMv2
1259    - NTLMv2 and LMv2
1260    - LMv2
1261    - plaintext tests (in challenge-response fields)
1262   
1263    check we get the correct session key in each case
1264    check what values we get for the LM session key
1265    
1266 */
1267
1268 static const struct ntlm_tests {
1269         bool (*fn)(struct samlogon_state *, char **);
1270         const char *name;
1271         bool expect_fail;
1272 } test_table[] = {
1273         {test_lmv2_ntlmv2, "NTLMv2 and LMv2", false},
1274 #if 0
1275         {test_lmv2_ntlmv2_no_dom, "NTLMv2 and LMv2 (no domain)", false},
1276 #endif
1277         {test_lm, "LM", false},
1278         {test_lm_ntlm, "LM and NTLM", false},
1279         {test_lm_ntlm_both_broken, "LM and NTLM, both broken", false},
1280         {test_ntlm, "NTLM", false},
1281         {test_ntlm_in_lm, "NTLM in LM", false},
1282         {test_ntlm_in_both, "NTLM in both", false},
1283         {test_ntlmv2, "NTLMv2", false},
1284         {test_ntlmv2_no_dom, "NTLMv2 (no domain)", false},
1285         {test_lmv2, "LMv2", false},
1286         {test_lmv2_no_dom, "LMv2 (no domain)", false},
1287         {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", false},
1288         {test_ntlmv2_lmv2_broken_no_dom, "NTLMv2 and LMv2, LMv2 broken (no domain)", false},
1289         {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", false},
1290 #if 0
1291         {test_ntlmv2_ntlmv2_broken_no_dom, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", false},
1292 #endif
1293         {test_ntlmv2_both_broken, "NTLMv2 and LMv2, both broken", false},
1294         {test_ntlmv2_both_broken_no_dom, "NTLMv2 and LMv2, both broken (no domain)", false},
1295         {test_ntlm_lm_broken, "NTLM and LM, LM broken", false},
1296         {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", false},
1297         {test_ntlm2, "NTLM2 (NTLMv2 session security)", false},
1298         {test_lmv2_ntlm_both_broken, "LMv2 and NTLM, both broken", false},
1299         {test_lmv2_ntlm_both_broken_no_dom, "LMv2 and NTLM, both broken (no domain)", false},
1300         {test_lmv2_ntlm_break_ntlm, "LMv2 and NTLM, NTLM broken", false},
1301         {test_lmv2_ntlm_break_ntlm_no_dom, "LMv2 and NTLM, NTLM broken (no domain)", false},
1302         {test_lmv2_ntlm_break_lm, "LMv2 and NTLM, LMv2 broken", false},
1303         {test_lmv2_ntlm_break_lm_no_dom, "LMv2 and NTLM, LMv2 broken (no domain)", false},
1304         {test_plaintext_none_broken, "Plaintext", false},
1305         {test_plaintext_lm_broken, "Plaintext LM broken", false},
1306         {test_plaintext_nt_broken, "Plaintext NT broken", false},
1307         {test_plaintext_nt_only, "Plaintext NT only", false},
1308         {test_plaintext_lm_only, "Plaintext LM only", false},
1309         {NULL, NULL}
1310 };
1311
1312 /*
1313   try a netlogon SamLogon
1314 */
1315 static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1316                           struct torture_context *tctx,
1317                           struct netlogon_creds_CredentialState *creds, 
1318                           const char *comment,
1319                           const char *account_domain, const char *account_name, 
1320                           const char *plain_pass, uint32_t parameter_control,
1321                           NTSTATUS expected_error, bool old_password,
1322                           int n_subtests)
1323 {
1324         TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_SamLogon function-level context");
1325         int i, v, l, f;
1326         bool ret = true;
1327         int validation_levels[] = {2,3,6};
1328         int logon_levels[] = { 2, 6 };
1329         int function_levels[] = { 
1330                 NDR_NETR_LOGONSAMLOGON,
1331                 NDR_NETR_LOGONSAMLOGONEX,
1332                 NDR_NETR_LOGONSAMLOGONWITHFLAGS };
1333         struct samlogon_state samlogon_state;
1334
1335         union netr_LogonLevel logon;
1336         union netr_Validation validation;
1337         uint8_t authoritative = 0;
1338         uint32_t flags = 0;
1339
1340         ZERO_STRUCT(logon);
1341
1342         d_printf("testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
1343         
1344         samlogon_state.comment = comment;
1345         samlogon_state.account_name = account_name;
1346         samlogon_state.account_domain = account_domain;
1347         samlogon_state.password = plain_pass;
1348         samlogon_state.workgroup = lp_workgroup(tctx->lp_ctx);
1349         samlogon_state.netbios_name = lp_netbios_name(tctx->lp_ctx);
1350         samlogon_state.p = p;
1351         samlogon_state.creds = creds;
1352         samlogon_state.expected_error = expected_error;
1353         samlogon_state.chall = data_blob_talloc(fn_ctx, NULL, 8);
1354         samlogon_state.parameter_control = parameter_control;
1355         samlogon_state.old_password = old_password;
1356         samlogon_state.iconv_convenience = lp_iconv_convenience(tctx->lp_ctx);
1357
1358         generate_random_buffer(samlogon_state.chall.data, 8);
1359         samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1360         samlogon_state.r_flags.in.computer_name = TEST_MACHINE_NAME;
1361         samlogon_state.r_flags.in.credential = &samlogon_state.auth;
1362         samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2;
1363         samlogon_state.r_flags.in.flags = &flags;
1364         samlogon_state.r_flags.in.logon = &logon;
1365         samlogon_state.r_flags.out.validation = &validation;
1366         samlogon_state.r_flags.out.authoritative = &authoritative;
1367         samlogon_state.r_flags.out.flags = &flags;
1368
1369         samlogon_state.r_ex.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1370         samlogon_state.r_ex.in.computer_name = TEST_MACHINE_NAME;
1371         samlogon_state.r_ex.in.flags = &flags;
1372         samlogon_state.r_ex.in.logon = &logon;
1373         samlogon_state.r_ex.out.validation = &validation;
1374         samlogon_state.r_ex.out.authoritative = &authoritative;
1375         samlogon_state.r_ex.out.flags = &flags;
1376
1377         samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1378         samlogon_state.r.in.computer_name = TEST_MACHINE_NAME;
1379         samlogon_state.r.in.credential = &samlogon_state.auth;
1380         samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
1381         samlogon_state.r.in.logon = &logon;
1382         samlogon_state.r.out.validation = &validation;
1383         samlogon_state.r.out.authoritative = &authoritative;
1384
1385
1386         for (f=0;f<ARRAY_SIZE(function_levels);f++) {
1387                 for (i=0; test_table[i].fn; i++) {
1388                         if (n_subtests && (i > n_subtests)) {
1389                                 continue;
1390                         }
1391                         for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
1392                                 for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
1393                                         char *error_string = NULL;
1394                                         TALLOC_CTX *tmp_ctx = talloc_named(fn_ctx, 0, "test_SamLogon inner loop");
1395                                         samlogon_state.mem_ctx = tmp_ctx;
1396                                         samlogon_state.function_level = function_levels[f];
1397                                         samlogon_state.r.in.validation_level = validation_levels[v];
1398                                         samlogon_state.r.in.logon_level = logon_levels[l];
1399                                         samlogon_state.r_ex.in.validation_level = validation_levels[v];
1400                                         samlogon_state.r_ex.in.logon_level = logon_levels[l];
1401                                         samlogon_state.r_flags.in.validation_level = validation_levels[v];
1402                                         samlogon_state.r_flags.in.logon_level = logon_levels[l];
1403                                         if (!test_table[i].fn(&samlogon_state, &error_string)) {
1404                                                 d_printf("Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n",
1405                                                        samlogon_state.comment,
1406                                                        samlogon_state.account_domain,
1407                                                        samlogon_state.account_name,
1408                                                        test_table[i].name, validation_levels[v], 
1409                                                        logon_levels[l], function_levels[f]);
1410                                                 
1411                                                 if (test_table[i].expect_fail) {
1412                                                         d_printf(" failed (expected, test incomplete): %s\n", error_string);
1413                                                 } else {
1414                                                         d_printf(" failed: %s\n", error_string);
1415                                                         ret = false;
1416                                                 }
1417                                                 SAFE_FREE(error_string);
1418                                         }
1419                                         talloc_free(tmp_ctx);
1420                                 }
1421                         }
1422                 }
1423         }
1424         talloc_free(fn_ctx);
1425         return ret;
1426 }
1427
1428 /*
1429   test an ADS style interactive domain logon
1430 */
1431 bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1432                            struct netlogon_creds_CredentialState *creds, 
1433                            const char *comment,
1434                            const char *workstation_name,
1435                            const char *account_domain, const char *account_name,
1436                            const char *plain_pass, uint32_t parameter_control, 
1437                            NTSTATUS expected_error)
1438 {
1439         NTSTATUS status;
1440         TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context");
1441         struct netr_LogonSamLogonWithFlags r;
1442         struct netr_Authenticator a, ra;
1443         struct netr_PasswordInfo pinfo;
1444         uint32_t flags = 0;
1445
1446         union netr_LogonLevel logon;
1447         union netr_Validation validation;
1448         uint8_t authoritative = 0;
1449
1450         ZERO_STRUCT(a);
1451         ZERO_STRUCT(r);
1452         ZERO_STRUCT(ra);
1453
1454         ZERO_STRUCT(logon);
1455         ZERO_STRUCT(validation);
1456
1457         netlogon_creds_client_authenticator(creds, &a);
1458
1459         logon.password = &pinfo;
1460
1461         r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1462         r.in.computer_name = TEST_MACHINE_NAME;
1463         r.in.credential = &a;
1464         r.in.return_authenticator = &ra;
1465         r.in.logon_level = 5;
1466         r.in.logon = &logon;
1467         r.in.validation_level = 6;
1468         r.in.flags = &flags;
1469         r.out.validation = &validation;
1470         r.out.authoritative = &authoritative;
1471         r.out.flags = &flags;
1472
1473         pinfo.identity_info.domain_name.string = account_domain;
1474         pinfo.identity_info.parameter_control = parameter_control;
1475         pinfo.identity_info.logon_id_low = 0;
1476         pinfo.identity_info.logon_id_high = 0;
1477         pinfo.identity_info.account_name.string = account_name;
1478         pinfo.identity_info.workstation.string = workstation_name;
1479
1480         if (!E_deshash(plain_pass, pinfo.lmpassword.hash)) {
1481                 ZERO_STRUCT(pinfo.lmpassword.hash);
1482         }
1483         E_md4hash(plain_pass, pinfo.ntpassword.hash);
1484
1485         if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1486                 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
1487                 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
1488         } else {
1489                 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
1490                 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
1491         }
1492
1493         d_printf("Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment);
1494
1495         status = dcerpc_netr_LogonSamLogonWithFlags(p, fn_ctx, &r);
1496         if (!r.out.return_authenticator 
1497             || !netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) {
1498                 d_printf("Credential chaining failed\n");
1499                 talloc_free(fn_ctx);
1500                 return false;
1501         }
1502
1503         talloc_free(fn_ctx);
1504
1505         if (!NT_STATUS_EQUAL(expected_error, status)) {
1506                 d_printf("[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n", 
1507                        account_domain, account_name, nt_errstr(expected_error), nt_errstr(status));
1508                 return false;
1509         }
1510
1511         return true;
1512 }
1513
1514
1515
1516 bool torture_rpc_samlogon(struct torture_context *torture)
1517 {
1518         NTSTATUS status;
1519         struct dcerpc_pipe *p;
1520         struct dcerpc_binding *b;
1521         struct cli_credentials *machine_credentials;
1522         TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_netlogon");
1523         bool ret = true;
1524         struct test_join *join_ctx = NULL;
1525         struct test_join *user_ctx = NULL, *user_ctx_wrong_wks = NULL, *user_ctx_wrong_time = NULL;
1526         char *user_password, *user_password_wrong_wks, *user_password_wrong_time;
1527         const char *old_user_password;
1528         char *test_machine_account;
1529         const char *userdomain;
1530         struct samr_SetUserInfo s;
1531         union samr_UserInfo u;
1532         int i;
1533         int ci;
1534
1535         unsigned int credential_flags[] = {
1536                 NETLOGON_NEG_AUTH2_FLAGS,
1537                 NETLOGON_NEG_ARCFOUR,
1538                 NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,
1539                 NETLOGON_NEG_AUTH2_ADS_FLAGS, 
1540                 0 /* yes, this is a valid flag, causes the use of DES */ 
1541         };
1542
1543         struct netlogon_creds_CredentialState *creds;
1544
1545         test_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
1546         /* We only need to join as a workstation here, and in future,
1547          * if we wish to test against trusted domains, we must be a
1548          * workstation here */
1549         join_ctx = torture_join_domain(torture, TEST_MACHINE_NAME, ACB_WSTRUST, 
1550                                        &machine_credentials);
1551         if (!join_ctx) {
1552                 d_printf("Failed to join as Workstation\n");
1553                 return false;
1554         }
1555
1556         userdomain = torture_setting_string(torture, "userdomain", lp_workgroup(torture->lp_ctx));
1557
1558         user_ctx = torture_create_testuser(torture,
1559                                            TEST_USER_NAME,
1560                                            userdomain,
1561                                            ACB_NORMAL, 
1562                                            (const char **)&user_password);
1563         if (!user_ctx) {
1564                 d_printf("Failed to create a test user\n");
1565                 return false;
1566         }
1567
1568         old_user_password = user_password;
1569
1570         test_ChangePasswordUser3(torture_join_samr_pipe(user_ctx), torture,
1571                                  TEST_USER_NAME, 16 /* > 14 */, &user_password, 
1572                                  NULL, 0, false);
1573
1574         user_ctx_wrong_wks = torture_create_testuser(torture,
1575                                                      TEST_USER_NAME_WRONG_WKS,
1576                                            userdomain,
1577                                            ACB_NORMAL, 
1578                                            (const char **)&user_password_wrong_wks);
1579         if (!user_ctx_wrong_wks) {
1580                 d_printf("Failed to create a test user (wrong workstation test)\n");
1581                 return false;
1582         }
1583
1584         ZERO_STRUCT(u);
1585         s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_wks);
1586         s.in.info = &u;
1587         s.in.level = 21;
1588
1589         u.info21.fields_present = SAMR_FIELD_WORKSTATIONS;
1590         u.info21.workstations.string = "not" TEST_MACHINE_NAME;
1591
1592         status = dcerpc_samr_SetUserInfo(torture_join_samr_pipe(user_ctx_wrong_wks), mem_ctx, &s);
1593         if (!NT_STATUS_IS_OK(status)) {
1594                 printf("SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status));
1595                 ret = false;
1596                 goto failed;
1597         }
1598
1599         user_ctx_wrong_time
1600                 = torture_create_testuser(torture, TEST_USER_NAME_WRONG_TIME,
1601                                            userdomain,
1602                                            ACB_NORMAL, 
1603                                            (const char **)&user_password_wrong_time);
1604         if (!user_ctx_wrong_time) {
1605                 d_printf("Failed to create a test user (wrong workstation test)\n");
1606                 return false;
1607         }
1608
1609         ZERO_STRUCT(u);
1610         s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_time);
1611         s.in.info = &u;
1612         s.in.level = 21;
1613
1614         u.info21.fields_present = SAMR_FIELD_WORKSTATIONS | SAMR_FIELD_LOGON_HOURS;
1615         u.info21.workstations.string = TEST_MACHINE_NAME;
1616         u.info21.logon_hours.units_per_week = 168;
1617         u.info21.logon_hours.bits = talloc_zero_array(mem_ctx, uint8_t, 168);
1618
1619         status = dcerpc_samr_SetUserInfo(torture_join_samr_pipe(user_ctx_wrong_time), mem_ctx, &s);
1620         if (!NT_STATUS_IS_OK(status)) {
1621                 printf("SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status));
1622                 ret = false;
1623                 goto failed;
1624         }
1625
1626         status = torture_rpc_binding(torture, &b);
1627         if (!NT_STATUS_IS_OK(status)) {
1628                 ret = false;
1629                 goto failed;
1630         }
1631
1632         /* We have to use schannel, otherwise the SamLogonEx fails
1633          * with INTERNAL_ERROR */
1634
1635         b->flags &= ~DCERPC_AUTH_OPTIONS;
1636         b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
1637
1638         status = dcerpc_pipe_connect_b(mem_ctx, &p, b, 
1639                                        &ndr_table_netlogon,
1640                                        machine_credentials, torture->ev, torture->lp_ctx);
1641
1642         if (!NT_STATUS_IS_OK(status)) {
1643                 d_printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
1644                 ret = false;
1645                 goto failed;
1646         }
1647
1648         status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds);
1649         if (!NT_STATUS_IS_OK(status)) {
1650                 ret = false;
1651                 goto failed;
1652         }
1653
1654         {
1655                 
1656                 struct {
1657                         const char *comment;
1658                         const char *domain;
1659                         const char *username;
1660                         const char *password;
1661                         bool network_login;
1662                         NTSTATUS expected_interactive_error;
1663                         NTSTATUS expected_network_error;
1664                         uint32_t parameter_control;
1665                         bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
1666                 } usercreds[] = {
1667                         {
1668                                 .comment       = "domain\\user",
1669                                 .domain        = cli_credentials_get_domain(cmdline_credentials),
1670                                 .username      = cli_credentials_get_username(cmdline_credentials),
1671                                 .password      = cli_credentials_get_password(cmdline_credentials),
1672                                 .network_login = true,
1673                                 .expected_interactive_error = NT_STATUS_OK,
1674                                 .expected_network_error     = NT_STATUS_OK
1675                         },
1676                         {
1677                                 .comment       = "realm\\user",
1678                                 .domain        = cli_credentials_get_realm(cmdline_credentials),
1679                                 .username      = cli_credentials_get_username(cmdline_credentials),
1680                                 .password      = cli_credentials_get_password(cmdline_credentials),
1681                                 .network_login = true,
1682                                 .expected_interactive_error = NT_STATUS_OK,
1683                                 .expected_network_error     = NT_STATUS_OK
1684                         },
1685                         {
1686                                 .comment       = "user@domain",
1687                                 .domain        = NULL,
1688                                 .username      = talloc_asprintf(mem_ctx, 
1689                                                 "%s@%s", 
1690                                                 cli_credentials_get_username(cmdline_credentials),
1691                                                 cli_credentials_get_domain(cmdline_credentials)
1692                                         ),
1693                                 .password      = cli_credentials_get_password(cmdline_credentials),
1694                                 .network_login = false, /* works for some things, but not NTLMv2.  Odd */
1695                                 .expected_interactive_error = NT_STATUS_OK,
1696                                 .expected_network_error     = NT_STATUS_OK
1697                         },
1698                         {
1699                                 .comment       = "user@realm",
1700                                 .domain        = NULL,
1701                                 .username      = talloc_asprintf(mem_ctx, 
1702                                                 "%s@%s", 
1703                                                 cli_credentials_get_username(cmdline_credentials),
1704                                                 cli_credentials_get_realm(cmdline_credentials)
1705                                         ),
1706                                 .password      = cli_credentials_get_password(cmdline_credentials),
1707                                 .network_login = true,
1708                                 .expected_interactive_error = NT_STATUS_OK,
1709                                 .expected_network_error     = NT_STATUS_OK
1710                         },
1711                         {
1712                                 .comment      = "machine domain\\user",
1713                                 .domain       = cli_credentials_get_domain(machine_credentials),
1714                                 .username     = cli_credentials_get_username(machine_credentials),
1715                                 .password     = cli_credentials_get_password(machine_credentials),
1716                                 .network_login = true,
1717                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1718                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1719                         },
1720                         {
1721                                 .comment      = "machine domain\\user",
1722                                 .domain       = cli_credentials_get_domain(machine_credentials),
1723                                 .username     = cli_credentials_get_username(machine_credentials),
1724                                 .password     = cli_credentials_get_password(machine_credentials),
1725                                 .network_login = true,
1726                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1727                                 .expected_network_error = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
1728                         },
1729                         {
1730                                 .comment       = "machine realm\\user",
1731                                 .domain        = cli_credentials_get_realm(machine_credentials),
1732                                 .username      = cli_credentials_get_username(machine_credentials),
1733                                 .password      = cli_credentials_get_password(machine_credentials),
1734                                 .network_login = true,
1735                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1736                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1737                         },
1738                         {
1739                                 .comment       = "machine user@domain",
1740                                 .domain        = NULL,
1741                                 .username      = talloc_asprintf(mem_ctx, 
1742                                                                 "%s@%s", 
1743                                                                 cli_credentials_get_username(machine_credentials),
1744                                                                 cli_credentials_get_domain(machine_credentials)
1745                                         ), 
1746                                 .password      = cli_credentials_get_password(machine_credentials),
1747                                 .network_login = false, /* works for some things, but not NTLMv2.  Odd */
1748                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1749                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1750                         },
1751                         {
1752                                 .comment       = "machine user@realm",
1753                                 .domain        = NULL,
1754                                 .username      = talloc_asprintf(mem_ctx, 
1755                                                                 "%s@%s", 
1756                                                                 cli_credentials_get_username(machine_credentials),
1757                                                                 cli_credentials_get_realm(machine_credentials)
1758                                         ),
1759                                 .password      = cli_credentials_get_password(machine_credentials),
1760                                 .network_login = true,
1761                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1762                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1763                         },
1764                         {       
1765                                 .comment       = "test user (long pw): domain\\user",
1766                                 .domain        = userdomain,
1767                                 .username      = TEST_USER_NAME,
1768                                 .password      = user_password,
1769                                 .network_login = true,
1770                                 .expected_interactive_error = NT_STATUS_OK,
1771                                 .expected_network_error     = NT_STATUS_OK
1772                         },
1773                         {
1774                                 .comment       = "test user (long pw): user@realm", 
1775                                 .domain        = NULL,
1776                                 .username      = talloc_asprintf(mem_ctx, 
1777                                                                  "%s@%s", 
1778                                                                  TEST_USER_NAME,
1779                                                                  lp_realm(torture->lp_ctx)),
1780                                 .password      = user_password,
1781                                 .network_login = true,
1782                                 .expected_interactive_error = NT_STATUS_OK,
1783                                 .expected_network_error     = NT_STATUS_OK
1784                         },
1785                         {
1786                                 .comment       = "test user (long pw): user@domain",
1787                                 .domain        = NULL,
1788                                 .username      = talloc_asprintf(mem_ctx, 
1789                                                                  "%s@%s", 
1790                                                                  TEST_USER_NAME,
1791                                                                  userdomain),
1792                                 .password      = user_password,
1793                                 .network_login = false, /* works for some things, but not NTLMv2.  Odd */
1794                                 .expected_interactive_error = NT_STATUS_OK,
1795                                 .expected_network_error     = NT_STATUS_OK
1796                         },
1797                         /* Oddball, can we use the old password ? */
1798                         {       
1799                                 .comment       = "test user: user\\domain OLD PASSWORD",
1800                                 .domain        = userdomain,
1801                                 .username      = TEST_USER_NAME,
1802                                 .password      = old_user_password,
1803                                 .network_login = true,
1804                                 .expected_interactive_error = NT_STATUS_WRONG_PASSWORD,
1805                                 .expected_network_error     = NT_STATUS_OK,
1806                                 .old_password  = true
1807                         },
1808                         {       
1809                                 .comment       = "test user (wong workstation): domain\\user",
1810                                 .domain        = userdomain,
1811                                 .username      = TEST_USER_NAME_WRONG_WKS,
1812                                 .password      = user_password_wrong_wks,
1813                                 .network_login = true,
1814                                 .expected_interactive_error = NT_STATUS_INVALID_WORKSTATION,
1815                                 .expected_network_error     = NT_STATUS_INVALID_WORKSTATION
1816                         }
1817                 };
1818                 
1819                 /* Try all the tests for different username forms */
1820                 for (ci = 0; ci < ARRAY_SIZE(usercreds); ci++) {
1821                 
1822                         if (!test_InteractiveLogon(p, mem_ctx, creds,
1823                                                    usercreds[ci].comment,
1824                                                    TEST_MACHINE_NAME,
1825                                                    usercreds[ci].domain,
1826                                                    usercreds[ci].username,
1827                                                    usercreds[ci].password,
1828                                                    usercreds[ci].parameter_control,
1829                                                    usercreds[ci].expected_interactive_error)) {
1830                                 ret = false;
1831                         }
1832                 
1833                         if (usercreds[ci].network_login) {
1834                                 if (!test_SamLogon(p, mem_ctx, torture, creds, 
1835                                                    usercreds[ci].comment,
1836                                                    usercreds[ci].domain,
1837                                                    usercreds[ci].username,
1838                                                    usercreds[ci].password,
1839                                                    usercreds[ci].parameter_control,
1840                                                    usercreds[ci].expected_network_error,
1841                                                    usercreds[ci].old_password,
1842                                                    0)) {
1843                                         ret = false;
1844                                 }
1845                         }
1846                 }
1847
1848                 /* Using the first username form, try the different
1849                  * credentials flag setups, on only one of the tests (checks
1850                  * session key encryption) */
1851
1852                 for (i=0; i < ARRAY_SIZE(credential_flags); i++) {
1853                         /* TODO:  Somehow we lost setting up the different credential flags here! */
1854
1855                         if (!test_InteractiveLogon(p, mem_ctx, creds,
1856                                                    usercreds[0].comment,
1857                                                    TEST_MACHINE_NAME,
1858                                                    usercreds[0].domain,
1859                                                    usercreds[0].username,
1860                                                    usercreds[0].password,
1861                                                    usercreds[0].parameter_control,
1862                                                    usercreds[0].expected_interactive_error)) {
1863                                 ret = false;
1864                         }
1865                 
1866                         if (usercreds[0].network_login) {
1867                                 if (!test_SamLogon(p, mem_ctx, torture, creds,
1868                                                    usercreds[0].comment,
1869                                                    usercreds[0].domain,
1870                                                    usercreds[0].username,
1871                                                    usercreds[0].password,
1872                                                    usercreds[0].parameter_control,
1873                                                    usercreds[0].expected_network_error,
1874                                                    usercreds[0].old_password,
1875                                                    1)) {
1876                                         ret = false;
1877                                 }
1878                         }
1879                 }
1880
1881         }
1882 failed:
1883         talloc_free(mem_ctx);
1884
1885         torture_leave_domain(torture, join_ctx);
1886         torture_leave_domain(torture, user_ctx);
1887         torture_leave_domain(torture, user_ctx_wrong_wks);
1888         torture_leave_domain(torture, user_ctx_wrong_time);
1889         return ret;
1890 }