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