gensec: split GENSEC into mechanism-dependent and runtime functions
[kamenim/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/torture_rpc.h"
31 #include "auth/gensec/gensec.h"
32 #include "auth/gensec/schannel.h"
33 #include "libcli/auth/libcli_auth.h"
34 #include "param/param.h"
35
36 #define TEST_MACHINE_NAME "samlogontest"
37 #define TEST_USER_NAME "samlogontestuser"
38 #define TEST_USER_NAME_WRONG_WKS "samlogontest2"
39 #define TEST_USER_NAME_WRONG_TIME "samlogontest3"
40
41 enum ntlm_break {
42         BREAK_BOTH,
43         BREAK_NONE,
44         BREAK_LM,
45         BREAK_NT,
46         NO_LM,
47         NO_NT
48 };
49
50 struct samlogon_state {
51         TALLOC_CTX *mem_ctx;
52         const char *comment;
53         const char *account_name;
54         const char *account_domain;
55         const char *netbios_name;
56         const char *password;
57         const char *workgroup;
58         struct dcerpc_pipe *p;
59         int function_level;
60         uint32_t parameter_control;
61         struct netr_LogonSamLogon r;
62         struct netr_LogonSamLogonEx r_ex;
63         struct netr_LogonSamLogonWithFlags r_flags;
64         struct netr_Authenticator auth, auth2;
65         struct netlogon_creds_CredentialState *creds;
66         NTSTATUS expected_error;
67         bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
68         DATA_BLOB chall;
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         size_t converted_size = 0;
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, &converted_size)) {
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(samlogon_state->mem_ctx,
1194                                    CH_UNIX, CH_DOS,
1195                                    password, strlen(password)+1,
1196                                    (void**)&dospw, &converted_size)) {
1197                 DEBUG(0, ("convert_string_talloc failed!\n"));
1198                 exit(1);
1199         }
1200
1201         lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
1202
1203         nt_status = check_samlogon(samlogon_state,
1204                                    break_which,
1205                                    samlogon_state->parameter_control | MSV1_0_CLEARTEXT_PASSWORD_ALLOWED,
1206                                    &chall,
1207                                    &lm_response,
1208                                    &nt_response,
1209                                    lm_key,
1210                                    user_session_key,
1211                                    error_string);
1212
1213         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1214                 /* for 'old' passwords, we allow the server to be OK or wrong password */
1215                 if (samlogon_state->old_password) {
1216                         return true;
1217                 }
1218                 /* for 'long' passwords, the LM password is invalid */
1219                 if (break_which == NO_NT && !lm_good) {
1220                         return true;
1221                 }
1222                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
1223         } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
1224                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
1225         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1226                 SAFE_FREE(*error_string);
1227                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1228                 return false;
1229         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1230                 return true;
1231         } else if (!NT_STATUS_IS_OK(nt_status)) {
1232                 return false;
1233         }
1234
1235         if (break_which == NO_NT && !lm_good) {
1236                 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
1237                 return false;
1238         }
1239
1240         return true;
1241 }
1242
1243 static bool test_plaintext_none_broken(struct samlogon_state *samlogon_state,
1244                                        char **error_string) {
1245         return test_plaintext(samlogon_state, BREAK_NONE, error_string);
1246 }
1247
1248 static bool test_plaintext_lm_broken(struct samlogon_state *samlogon_state,
1249                                      char **error_string) {
1250         return test_plaintext(samlogon_state, BREAK_LM, error_string);
1251 }
1252
1253 static bool test_plaintext_nt_broken(struct samlogon_state *samlogon_state,
1254                                      char **error_string) {
1255         return test_plaintext(samlogon_state, BREAK_NT, error_string);
1256 }
1257
1258 static bool test_plaintext_nt_only(struct samlogon_state *samlogon_state,
1259                                    char **error_string) {
1260         return test_plaintext(samlogon_state, NO_LM, error_string);
1261 }
1262
1263 static bool test_plaintext_lm_only(struct samlogon_state *samlogon_state,
1264                                    char **error_string) {
1265         return test_plaintext(samlogon_state, NO_NT, error_string);
1266 }
1267
1268 /*
1269    Tests:
1270
1271    - LM only
1272    - NT and LM
1273    - NT
1274    - NT in LM field
1275    - NT in both fields
1276    - NTLMv2
1277    - NTLMv2 and LMv2
1278    - LMv2
1279    - plaintext tests (in challenge-response fields)
1280
1281    check we get the correct session key in each case
1282    check what values we get for the LM session key
1283
1284 */
1285
1286 static const struct ntlm_tests {
1287         bool (*fn)(struct samlogon_state *, char **);
1288         const char *name;
1289         bool expect_fail;
1290 } test_table[] = {
1291         {test_lmv2_ntlmv2, "NTLMv2 and LMv2", false},
1292 #if 0
1293         {test_lmv2_ntlmv2_no_dom, "NTLMv2 and LMv2 (no domain)", false},
1294 #endif
1295         {test_lm, "LM", false},
1296         {test_lm_ntlm, "LM and NTLM", false},
1297         {test_lm_ntlm_both_broken, "LM and NTLM, both broken", false},
1298         {test_ntlm, "NTLM", false},
1299         {test_ntlm_in_lm, "NTLM in LM", false},
1300         {test_ntlm_in_both, "NTLM in both", false},
1301         {test_ntlmv2, "NTLMv2", false},
1302         {test_ntlmv2_no_dom, "NTLMv2 (no domain)", false},
1303         {test_lmv2, "LMv2", false},
1304         {test_lmv2_no_dom, "LMv2 (no domain)", false},
1305         {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", false},
1306         {test_ntlmv2_lmv2_broken_no_dom, "NTLMv2 and LMv2, LMv2 broken (no domain)", false},
1307         {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", false},
1308 #if 0
1309         {test_ntlmv2_ntlmv2_broken_no_dom, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", false},
1310 #endif
1311         {test_ntlmv2_both_broken, "NTLMv2 and LMv2, both broken", false},
1312         {test_ntlmv2_both_broken_no_dom, "NTLMv2 and LMv2, both broken (no domain)", false},
1313         {test_ntlm_lm_broken, "NTLM and LM, LM broken", false},
1314         {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", false},
1315         {test_ntlm2, "NTLM2 (NTLMv2 session security)", false},
1316         {test_lmv2_ntlm_both_broken, "LMv2 and NTLM, both broken", false},
1317         {test_lmv2_ntlm_both_broken_no_dom, "LMv2 and NTLM, both broken (no domain)", false},
1318         {test_lmv2_ntlm_break_ntlm, "LMv2 and NTLM, NTLM broken", false},
1319         {test_lmv2_ntlm_break_ntlm_no_dom, "LMv2 and NTLM, NTLM broken (no domain)", false},
1320         {test_lmv2_ntlm_break_lm, "LMv2 and NTLM, LMv2 broken", false},
1321         {test_lmv2_ntlm_break_lm_no_dom, "LMv2 and NTLM, LMv2 broken (no domain)", false},
1322         {test_plaintext_none_broken, "Plaintext", false},
1323         {test_plaintext_lm_broken, "Plaintext LM broken", false},
1324         {test_plaintext_nt_broken, "Plaintext NT broken", false},
1325         {test_plaintext_nt_only, "Plaintext NT only", false},
1326         {test_plaintext_lm_only, "Plaintext LM only", false},
1327         {NULL, NULL}
1328 };
1329
1330 /*
1331   try a netlogon SamLogon
1332 */
1333 static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1334                           struct torture_context *tctx,
1335                           struct netlogon_creds_CredentialState *creds,
1336                           const char *comment,
1337                           const char *account_domain, const char *account_name,
1338                           const char *plain_pass, uint32_t parameter_control,
1339                           NTSTATUS expected_error, bool old_password,
1340                           int n_subtests)
1341 {
1342         TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_SamLogon function-level context");
1343         int i, v, l, f;
1344         bool ret = true;
1345         int validation_levels[] = {2,3,6};
1346         int logon_levels[] = { 2, 6 };
1347         int function_levels[] = {
1348                 NDR_NETR_LOGONSAMLOGON,
1349                 NDR_NETR_LOGONSAMLOGONEX,
1350                 NDR_NETR_LOGONSAMLOGONWITHFLAGS };
1351         struct samlogon_state samlogon_state;
1352
1353         union netr_LogonLevel logon;
1354         union netr_Validation validation;
1355         uint8_t authoritative = 0;
1356         uint32_t flags = 0;
1357
1358         ZERO_STRUCT(logon);
1359
1360         d_printf("Testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
1361
1362         samlogon_state.comment = comment;
1363         samlogon_state.account_name = account_name;
1364         samlogon_state.account_domain = account_domain;
1365         samlogon_state.password = plain_pass;
1366         samlogon_state.workgroup = lpcfg_workgroup(tctx->lp_ctx);
1367         samlogon_state.netbios_name = lpcfg_netbios_name(tctx->lp_ctx);
1368         samlogon_state.p = p;
1369         samlogon_state.creds = creds;
1370         samlogon_state.expected_error = expected_error;
1371         samlogon_state.chall = data_blob_talloc(fn_ctx, NULL, 8);
1372         samlogon_state.parameter_control = parameter_control;
1373         samlogon_state.old_password = old_password;
1374
1375         generate_random_buffer(samlogon_state.chall.data, 8);
1376         samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1377         samlogon_state.r_flags.in.computer_name = TEST_MACHINE_NAME;
1378         samlogon_state.r_flags.in.credential = &samlogon_state.auth;
1379         samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2;
1380         samlogon_state.r_flags.in.flags = &flags;
1381         samlogon_state.r_flags.in.logon = &logon;
1382         samlogon_state.r_flags.out.validation = &validation;
1383         samlogon_state.r_flags.out.authoritative = &authoritative;
1384         samlogon_state.r_flags.out.flags = &flags;
1385
1386         samlogon_state.r_ex.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1387         samlogon_state.r_ex.in.computer_name = TEST_MACHINE_NAME;
1388         samlogon_state.r_ex.in.flags = &flags;
1389         samlogon_state.r_ex.in.logon = &logon;
1390         samlogon_state.r_ex.out.validation = &validation;
1391         samlogon_state.r_ex.out.authoritative = &authoritative;
1392         samlogon_state.r_ex.out.flags = &flags;
1393
1394         samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1395         samlogon_state.r.in.computer_name = TEST_MACHINE_NAME;
1396         samlogon_state.r.in.credential = &samlogon_state.auth;
1397         samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
1398         samlogon_state.r.in.logon = &logon;
1399         samlogon_state.r.out.validation = &validation;
1400         samlogon_state.r.out.authoritative = &authoritative;
1401
1402
1403         for (f=0;f<ARRAY_SIZE(function_levels);f++) {
1404                 for (i=0; test_table[i].fn; i++) {
1405                         if (n_subtests && (i > n_subtests)) {
1406                                 continue;
1407                         }
1408                         for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
1409                                 for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
1410                                         char *error_string = NULL;
1411                                         TALLOC_CTX *tmp_ctx = talloc_named(fn_ctx, 0, "test_SamLogon inner loop");
1412                                         samlogon_state.mem_ctx = tmp_ctx;
1413                                         samlogon_state.function_level = function_levels[f];
1414                                         samlogon_state.r.in.validation_level = validation_levels[v];
1415                                         samlogon_state.r.in.logon_level = logon_levels[l];
1416                                         samlogon_state.r_ex.in.validation_level = validation_levels[v];
1417                                         samlogon_state.r_ex.in.logon_level = logon_levels[l];
1418                                         samlogon_state.r_flags.in.validation_level = validation_levels[v];
1419                                         samlogon_state.r_flags.in.logon_level = logon_levels[l];
1420                                         if (!test_table[i].fn(&samlogon_state, &error_string)) {
1421                                                 d_printf("Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n",
1422                                                        samlogon_state.comment,
1423                                                        samlogon_state.account_domain,
1424                                                        samlogon_state.account_name,
1425                                                        test_table[i].name, validation_levels[v],
1426                                                        logon_levels[l], function_levels[f]);
1427
1428                                                 if (test_table[i].expect_fail) {
1429                                                         d_printf(" failed (expected, test incomplete): %s\n", error_string);
1430                                                 } else {
1431                                                         d_printf(" failed: %s\n", error_string);
1432                                                         ret = false;
1433                                                 }
1434                                                 SAFE_FREE(error_string);
1435                                         }
1436                                         talloc_free(tmp_ctx);
1437                                 }
1438                         }
1439                 }
1440         }
1441         talloc_free(fn_ctx);
1442         return ret;
1443 }
1444
1445 /*
1446   test an ADS style interactive domain logon
1447 */
1448 bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1449                            struct netlogon_creds_CredentialState *creds,
1450                            const char *comment,
1451                            const char *workstation_name,
1452                            const char *account_domain, const char *account_name,
1453                            const char *plain_pass, uint32_t parameter_control,
1454                            NTSTATUS expected_error)
1455 {
1456         NTSTATUS status;
1457         TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context");
1458         struct netr_LogonSamLogonWithFlags r;
1459         struct netr_Authenticator a, ra;
1460         struct netr_PasswordInfo pinfo;
1461         uint32_t flags = 0;
1462
1463         union netr_LogonLevel logon;
1464         union netr_Validation validation;
1465         uint8_t authoritative = 0;
1466         struct dcerpc_binding_handle *b = p->binding_handle;
1467
1468         ZERO_STRUCT(a);
1469         ZERO_STRUCT(r);
1470         ZERO_STRUCT(ra);
1471
1472         ZERO_STRUCT(logon);
1473         ZERO_STRUCT(validation);
1474
1475         netlogon_creds_client_authenticator(creds, &a);
1476
1477         logon.password = &pinfo;
1478
1479         r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1480         r.in.computer_name = TEST_MACHINE_NAME;
1481         r.in.credential = &a;
1482         r.in.return_authenticator = &ra;
1483         r.in.logon_level = 5;
1484         r.in.logon = &logon;
1485         r.in.validation_level = 6;
1486         r.in.flags = &flags;
1487         r.out.validation = &validation;
1488         r.out.authoritative = &authoritative;
1489         r.out.flags = &flags;
1490
1491         pinfo.identity_info.domain_name.string = account_domain;
1492         pinfo.identity_info.parameter_control = parameter_control;
1493         pinfo.identity_info.logon_id_low = 0;
1494         pinfo.identity_info.logon_id_high = 0;
1495         pinfo.identity_info.account_name.string = account_name;
1496         pinfo.identity_info.workstation.string = workstation_name;
1497
1498         if (!E_deshash(plain_pass, pinfo.lmpassword.hash)) {
1499                 ZERO_STRUCT(pinfo.lmpassword.hash);
1500         }
1501         E_md4hash(plain_pass, pinfo.ntpassword.hash);
1502
1503         if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1504                 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
1505                 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
1506         } else {
1507                 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
1508                 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
1509         }
1510
1511         d_printf("Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment);
1512
1513         status = dcerpc_netr_LogonSamLogonWithFlags_r(b, fn_ctx, &r);
1514         if (!NT_STATUS_IS_OK(status)) {
1515                 d_printf("%s: netr_LogonSamLogonWithFlags - %s\n",
1516                          __location__, nt_errstr(status));
1517                 return false;
1518         }
1519         if (!r.out.return_authenticator
1520             || !netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) {
1521                 d_printf("Credential chaining failed\n");
1522                 talloc_free(fn_ctx);
1523                 return false;
1524         }
1525
1526         talloc_free(fn_ctx);
1527
1528         if (!NT_STATUS_EQUAL(expected_error, r.out.result)) {
1529                 d_printf("[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n",
1530                        account_domain, account_name, nt_errstr(expected_error), nt_errstr(r.out.result));
1531                 return false;
1532         }
1533
1534         return true;
1535 }
1536
1537 /* This sets and resets the "minPwdAge" (in order to allow immediate user
1538  * password changes). The behaviour is controlled by the "set" boolean. */
1539 static bool handle_minPwdAge(struct torture_context *torture,
1540                              TALLOC_CTX *mem_ctx, bool set)
1541 {
1542         struct dcerpc_pipe *p;
1543         struct policy_handle connect_handle, domain_handle;
1544         struct samr_Connect c_r;
1545         struct samr_LookupDomain ld_r;
1546         struct samr_OpenDomain od_r;
1547         struct samr_QueryDomainInfo qdi_r;
1548         struct samr_SetDomainInfo sdi_r;
1549         struct samr_Close cl_r;
1550         struct lsa_String domName;
1551         struct dom_sid *domSid = NULL;
1552         union samr_DomainInfo *domInfo = NULL;
1553         static int64_t old_minPwdAge = 0;
1554         NTSTATUS status;
1555
1556         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
1557         if (!NT_STATUS_IS_OK(status)) {
1558                 return false;
1559         }
1560
1561         c_r.in.system_name = 0;
1562         c_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1563         c_r.out.connect_handle = &connect_handle;
1564
1565         torture_assert_ntstatus_ok(torture,
1566                                    dcerpc_samr_Connect_r(p->binding_handle, mem_ctx, &c_r),
1567                                    "Connect failed");
1568         torture_assert_ntstatus_ok(torture, c_r.out.result, "Connect failed");
1569
1570         ld_r.in.connect_handle = &connect_handle;
1571         ld_r.in.domain_name = &domName;
1572         ld_r.in.domain_name->string = lpcfg_workgroup(torture->lp_ctx);
1573         ld_r.out.sid = &domSid;
1574
1575         torture_assert_ntstatus_ok(torture,
1576                                    dcerpc_samr_LookupDomain_r(p->binding_handle, mem_ctx, &ld_r),
1577                                    "LookupDomain failed");
1578         torture_assert_ntstatus_ok(torture, ld_r.out.result,
1579                                    "LookupDomain failed");
1580
1581         od_r.in.connect_handle = &connect_handle;
1582         od_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1583         od_r.in.sid = *ld_r.out.sid;
1584         od_r.out.domain_handle = &domain_handle;
1585
1586         torture_assert_ntstatus_ok(torture,
1587                                    dcerpc_samr_OpenDomain_r(p->binding_handle, mem_ctx, &od_r),
1588                                    "OpenDomain failed");
1589         torture_assert_ntstatus_ok(torture, od_r.out.result,
1590                                    "OpenDomain failed");
1591
1592         qdi_r.in.domain_handle = &domain_handle;
1593         qdi_r.in.level = DomainPasswordInformation;
1594         qdi_r.out.info = &domInfo;
1595
1596         torture_assert_ntstatus_ok(torture,
1597                                    dcerpc_samr_QueryDomainInfo_r(p->binding_handle, mem_ctx, &qdi_r),
1598                                    "QueryDomainInfo failed");
1599         torture_assert_ntstatus_ok(torture, qdi_r.out.result,
1600                                    "QueryDomainInfo failed");
1601
1602         if (set) {
1603                 old_minPwdAge = domInfo->info1.min_password_age;
1604                 domInfo->info1.min_password_age = 0;
1605         } else {
1606                 domInfo->info1.min_password_age = old_minPwdAge;
1607         }
1608
1609         sdi_r.in.domain_handle = &domain_handle;
1610         sdi_r.in.level = DomainPasswordInformation;
1611         sdi_r.in.info = domInfo;
1612
1613         torture_assert_ntstatus_ok(torture,
1614                                    dcerpc_samr_SetDomainInfo_r(p->binding_handle, mem_ctx, &sdi_r),
1615                                    "SetDomainInfo failed");
1616         torture_assert_ntstatus_ok(torture, sdi_r.out.result,
1617                                    "SetDomainInfo failed");
1618
1619         cl_r.in.handle = &connect_handle;
1620         cl_r.out.handle = &connect_handle;
1621
1622         torture_assert_ntstatus_ok(torture,
1623                                    dcerpc_samr_Close_r(p->binding_handle, mem_ctx, &cl_r),
1624                                    "Close failed");
1625         torture_assert_ntstatus_ok(torture, cl_r.out.result, "Close failed");
1626
1627         return true;
1628 }
1629
1630 bool torture_rpc_samlogon(struct torture_context *torture)
1631 {
1632         NTSTATUS status;
1633         struct dcerpc_pipe *p;
1634         struct dcerpc_binding *b;
1635         struct cli_credentials *machine_credentials;
1636         TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_netlogon");
1637         bool ret = true;
1638         struct test_join *join_ctx = NULL;
1639         struct test_join *user_ctx = NULL, *user_ctx_wrong_wks = NULL, *user_ctx_wrong_time = NULL;
1640         char *user_password, *user_password_wrong_wks, *user_password_wrong_time;
1641         const char *old_user_password;
1642         char *test_machine_account;
1643         const char *userdomain;
1644         struct samr_SetUserInfo s;
1645         union samr_UserInfo u;
1646         int i;
1647         int ci;
1648
1649         unsigned int credential_flags[] = {
1650                 NETLOGON_NEG_AUTH2_FLAGS,
1651                 NETLOGON_NEG_ARCFOUR,
1652                 NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,
1653                 NETLOGON_NEG_AUTH2_ADS_FLAGS,
1654                 0 /* yes, this is a valid flag, causes the use of DES */
1655         };
1656
1657         struct netlogon_creds_CredentialState *creds;
1658         struct dcerpc_pipe *tmp_p = NULL;
1659
1660         torture_assert(torture, handle_minPwdAge(torture, mem_ctx, true),
1661                        "handle_minPwdAge error!");
1662
1663         test_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
1664         /* We only need to join as a workstation here, and in future,
1665          * if we wish to test against trusted domains, we must be a
1666          * workstation here */
1667         join_ctx = torture_join_domain(torture, TEST_MACHINE_NAME, ACB_WSTRUST,
1668                                        &machine_credentials);
1669         if (!join_ctx) {
1670                 d_printf("Failed to join as Workstation\n");
1671                 return false;
1672         }
1673
1674         userdomain = torture_setting_string(torture, "userdomain", lpcfg_workgroup(torture->lp_ctx));
1675
1676         user_ctx = torture_create_testuser(torture,
1677                                            TEST_USER_NAME,
1678                                            userdomain,
1679                                            ACB_NORMAL,
1680                                            (const char **)&user_password);
1681         if (!user_ctx) {
1682                 d_printf("Failed to create a test user\n");
1683                 return false;
1684         }
1685
1686         old_user_password = user_password;
1687
1688         tmp_p = torture_join_samr_pipe(user_ctx);
1689         test_ChangePasswordUser3(tmp_p, torture,
1690                                  TEST_USER_NAME, 16 /* > 14 */, &user_password,
1691                                  NULL, 0, false);
1692
1693         user_ctx_wrong_wks = torture_create_testuser(torture,
1694                                                      TEST_USER_NAME_WRONG_WKS,
1695                                            userdomain,
1696                                            ACB_NORMAL,
1697                                            (const char **)&user_password_wrong_wks);
1698         if (!user_ctx_wrong_wks) {
1699                 d_printf("Failed to create a test user (wrong workstation test)\n");
1700                 return false;
1701         }
1702
1703         ZERO_STRUCT(u);
1704         s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_wks);
1705         s.in.info = &u;
1706         s.in.level = 21;
1707
1708         u.info21.fields_present = SAMR_FIELD_WORKSTATIONS;
1709         u.info21.workstations.string = "not" TEST_MACHINE_NAME;
1710
1711         tmp_p = torture_join_samr_pipe(user_ctx_wrong_wks);
1712         status = dcerpc_samr_SetUserInfo_r(tmp_p->binding_handle, mem_ctx, &s);
1713         if (!NT_STATUS_IS_OK(status)) {
1714                 printf("SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status));
1715                 ret = false;
1716                 goto failed;
1717         }
1718         if (!NT_STATUS_IS_OK(s.out.result)) {
1719                 printf("SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s.out.result));
1720                 ret = false;
1721                 goto failed;
1722         }
1723
1724         user_ctx_wrong_time
1725                 = torture_create_testuser(torture, TEST_USER_NAME_WRONG_TIME,
1726                                            userdomain,
1727                                            ACB_NORMAL,
1728                                            (const char **)&user_password_wrong_time);
1729         if (!user_ctx_wrong_time) {
1730                 d_printf("Failed to create a test user (wrong workstation test)\n");
1731                 return false;
1732         }
1733
1734         ZERO_STRUCT(u);
1735         s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_time);
1736         s.in.info = &u;
1737         s.in.level = 21;
1738
1739         u.info21.fields_present = SAMR_FIELD_WORKSTATIONS | SAMR_FIELD_LOGON_HOURS;
1740         u.info21.workstations.string = TEST_MACHINE_NAME;
1741         u.info21.logon_hours.units_per_week = 168;
1742         u.info21.logon_hours.bits = talloc_zero_array(mem_ctx, uint8_t, 168);
1743
1744         tmp_p = torture_join_samr_pipe(user_ctx_wrong_time);
1745         status = dcerpc_samr_SetUserInfo_r(tmp_p->binding_handle, mem_ctx, &s);
1746         if (!NT_STATUS_IS_OK(status)) {
1747                 printf("SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status));
1748                 ret = false;
1749                 goto failed;
1750         }
1751         if (!NT_STATUS_IS_OK(s.out.result)) {
1752                 printf("SetUserInfo (list of workstations) failed - %s\n", nt_errstr(s.out.result));
1753                 ret = false;
1754                 goto failed;
1755         }
1756
1757         status = torture_rpc_binding(torture, &b);
1758         if (!NT_STATUS_IS_OK(status)) {
1759                 ret = false;
1760                 goto failed;
1761         }
1762
1763         /* We have to use schannel, otherwise the SamLogonEx fails
1764          * with INTERNAL_ERROR */
1765
1766         b->flags &= ~DCERPC_AUTH_OPTIONS;
1767         b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
1768
1769         status = dcerpc_pipe_connect_b(mem_ctx, &p, b,
1770                                        &ndr_table_netlogon,
1771                                        machine_credentials, torture->ev, torture->lp_ctx);
1772
1773         if (!NT_STATUS_IS_OK(status)) {
1774                 d_printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
1775                 ret = false;
1776                 goto failed;
1777         }
1778
1779         status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds);
1780         if (!NT_STATUS_IS_OK(status)) {
1781                 ret = false;
1782                 goto failed;
1783         }
1784
1785         {
1786
1787                 struct {
1788                         const char *comment;
1789                         const char *domain;
1790                         const char *username;
1791                         const char *password;
1792                         bool network_login;
1793                         NTSTATUS expected_interactive_error;
1794                         NTSTATUS expected_network_error;
1795                         uint32_t parameter_control;
1796                         bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
1797                 } usercreds[] = {
1798                         {
1799                                 .comment       = "domain\\user",
1800                                 .domain        = cli_credentials_get_domain(cmdline_credentials),
1801                                 .username      = cli_credentials_get_username(cmdline_credentials),
1802                                 .password      = cli_credentials_get_password(cmdline_credentials),
1803                                 .network_login = true,
1804                                 .expected_interactive_error = NT_STATUS_OK,
1805                                 .expected_network_error     = NT_STATUS_OK
1806                         },
1807                         {
1808                                 .comment       = "realm\\user",
1809                                 .domain        = cli_credentials_get_realm(cmdline_credentials),
1810                                 .username      = cli_credentials_get_username(cmdline_credentials),
1811                                 .password      = cli_credentials_get_password(cmdline_credentials),
1812                                 .network_login = true,
1813                                 .expected_interactive_error = NT_STATUS_OK,
1814                                 .expected_network_error     = NT_STATUS_OK
1815                         },
1816                         {
1817                                 .comment       = "user@domain",
1818                                 .domain        = NULL,
1819                                 .username      = talloc_asprintf(mem_ctx,
1820                                                 "%s@%s",
1821                                                 cli_credentials_get_username(cmdline_credentials),
1822                                                 cli_credentials_get_domain(cmdline_credentials)
1823                                         ),
1824                                 .password      = cli_credentials_get_password(cmdline_credentials),
1825                                 .network_login = false, /* works for some things, but not NTLMv2.  Odd */
1826                                 .expected_interactive_error = NT_STATUS_OK,
1827                                 .expected_network_error     = NT_STATUS_OK
1828                         },
1829                         {
1830                                 .comment       = "user@realm",
1831                                 .domain        = NULL,
1832                                 .username      = talloc_asprintf(mem_ctx,
1833                                                 "%s@%s",
1834                                                 cli_credentials_get_username(cmdline_credentials),
1835                                                 cli_credentials_get_realm(cmdline_credentials)
1836                                         ),
1837                                 .password      = cli_credentials_get_password(cmdline_credentials),
1838                                 .network_login = true,
1839                                 .expected_interactive_error = NT_STATUS_OK,
1840                                 .expected_network_error     = NT_STATUS_OK
1841                         },
1842                         {
1843                                 .comment      = "machine domain\\user",
1844                                 .domain       = cli_credentials_get_domain(machine_credentials),
1845                                 .username     = cli_credentials_get_username(machine_credentials),
1846                                 .password     = cli_credentials_get_password(machine_credentials),
1847                                 .network_login = true,
1848                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1849                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1850                         },
1851                         {
1852                                 .comment      = "machine domain\\user",
1853                                 .domain       = cli_credentials_get_domain(machine_credentials),
1854                                 .username     = cli_credentials_get_username(machine_credentials),
1855                                 .password     = cli_credentials_get_password(machine_credentials),
1856                                 .network_login = true,
1857                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1858                                 .expected_network_error = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
1859                         },
1860                         {
1861                                 .comment       = "machine realm\\user",
1862                                 .domain        = cli_credentials_get_realm(machine_credentials),
1863                                 .username      = cli_credentials_get_username(machine_credentials),
1864                                 .password      = cli_credentials_get_password(machine_credentials),
1865                                 .network_login = true,
1866                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1867                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1868                         },
1869                         {
1870                                 .comment       = "machine user@domain",
1871                                 .domain        = NULL,
1872                                 .username      = talloc_asprintf(mem_ctx,
1873                                                                 "%s@%s",
1874                                                                 cli_credentials_get_username(machine_credentials),
1875                                                                 cli_credentials_get_domain(machine_credentials)
1876                                         ),
1877                                 .password      = cli_credentials_get_password(machine_credentials),
1878                                 .network_login = false, /* works for some things, but not NTLMv2.  Odd */
1879                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1880                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1881                         },
1882                         {
1883                                 .comment       = "machine user@realm",
1884                                 .domain        = NULL,
1885                                 .username      = talloc_asprintf(mem_ctx,
1886                                                                 "%s@%s",
1887                                                                 cli_credentials_get_username(machine_credentials),
1888                                                                 cli_credentials_get_realm(machine_credentials)
1889                                         ),
1890                                 .password      = cli_credentials_get_password(machine_credentials),
1891                                 .network_login = true,
1892                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1893                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1894                         },
1895                         {
1896                                 .comment       = "test user (long pw): domain\\user",
1897                                 .domain        = userdomain,
1898                                 .username      = TEST_USER_NAME,
1899                                 .password      = user_password,
1900                                 .network_login = true,
1901                                 .expected_interactive_error = NT_STATUS_OK,
1902                                 .expected_network_error     = NT_STATUS_OK
1903                         },
1904                         {
1905                                 .comment       = "test user (long pw): user@realm",
1906                                 .domain        = NULL,
1907                                 .username      = talloc_asprintf(mem_ctx,
1908                                                                  "%s@%s",
1909                                                                  TEST_USER_NAME,
1910                                                                  lpcfg_realm(torture->lp_ctx)),
1911                                 .password      = user_password,
1912                                 .network_login = true,
1913                                 .expected_interactive_error = NT_STATUS_OK,
1914                                 .expected_network_error     = NT_STATUS_OK
1915                         },
1916                         {
1917                                 .comment       = "test user (long pw): user@domain",
1918                                 .domain        = NULL,
1919                                 .username      = talloc_asprintf(mem_ctx,
1920                                                                  "%s@%s",
1921                                                                  TEST_USER_NAME,
1922                                                                  userdomain),
1923                                 .password      = user_password,
1924                                 .network_login = false, /* works for some things, but not NTLMv2.  Odd */
1925                                 .expected_interactive_error = NT_STATUS_OK,
1926                                 .expected_network_error     = NT_STATUS_OK
1927                         },
1928                         /* Oddball, can we use the old password ? */
1929                         {
1930                                 .comment       = "test user: user\\domain OLD PASSWORD",
1931                                 .domain        = userdomain,
1932                                 .username      = TEST_USER_NAME,
1933                                 .password      = old_user_password,
1934                                 .network_login = true,
1935                                 .expected_interactive_error = NT_STATUS_WRONG_PASSWORD,
1936                                 .expected_network_error     = NT_STATUS_OK,
1937                                 .old_password  = true
1938                         },
1939                         {
1940                                 .comment       = "test user (wong workstation): domain\\user",
1941                                 .domain        = userdomain,
1942                                 .username      = TEST_USER_NAME_WRONG_WKS,
1943                                 .password      = user_password_wrong_wks,
1944                                 .network_login = true,
1945                                 .expected_interactive_error = NT_STATUS_INVALID_WORKSTATION,
1946                                 .expected_network_error     = NT_STATUS_INVALID_WORKSTATION
1947                         }
1948                 };
1949
1950                 /* Try all the tests for different username forms */
1951                 for (ci = 0; ci < ARRAY_SIZE(usercreds); ci++) {
1952
1953                         if (!test_InteractiveLogon(p, mem_ctx, creds,
1954                                                    usercreds[ci].comment,
1955                                                    TEST_MACHINE_NAME,
1956                                                    usercreds[ci].domain,
1957                                                    usercreds[ci].username,
1958                                                    usercreds[ci].password,
1959                                                    usercreds[ci].parameter_control,
1960                                                    usercreds[ci].expected_interactive_error)) {
1961                                 ret = false;
1962                         }
1963
1964                         if (usercreds[ci].network_login) {
1965                                 if (!test_SamLogon(p, mem_ctx, torture, creds,
1966                                                    usercreds[ci].comment,
1967                                                    usercreds[ci].domain,
1968                                                    usercreds[ci].username,
1969                                                    usercreds[ci].password,
1970                                                    usercreds[ci].parameter_control,
1971                                                    usercreds[ci].expected_network_error,
1972                                                    usercreds[ci].old_password,
1973                                                    0)) {
1974                                         ret = false;
1975                                 }
1976                         }
1977                 }
1978
1979                 /* Using the first username form, try the different
1980                  * credentials flag setups, on only one of the tests (checks
1981                  * session key encryption) */
1982
1983                 for (i=0; i < ARRAY_SIZE(credential_flags); i++) {
1984                         /* TODO:  Somehow we lost setting up the different credential flags here! */
1985
1986                         if (!test_InteractiveLogon(p, mem_ctx, creds,
1987                                                    usercreds[0].comment,
1988                                                    TEST_MACHINE_NAME,
1989                                                    usercreds[0].domain,
1990                                                    usercreds[0].username,
1991                                                    usercreds[0].password,
1992                                                    usercreds[0].parameter_control,
1993                                                    usercreds[0].expected_interactive_error)) {
1994                                 ret = false;
1995                         }
1996
1997                         if (usercreds[0].network_login) {
1998                                 if (!test_SamLogon(p, mem_ctx, torture, creds,
1999                                                    usercreds[0].comment,
2000                                                    usercreds[0].domain,
2001                                                    usercreds[0].username,
2002                                                    usercreds[0].password,
2003                                                    usercreds[0].parameter_control,
2004                                                    usercreds[0].expected_network_error,
2005                                                    usercreds[0].old_password,
2006                                                    1)) {
2007                                         ret = false;
2008                                 }
2009                         }
2010                 }
2011
2012         }
2013 failed:
2014         torture_assert(torture, handle_minPwdAge(torture, mem_ctx, false),
2015                        "handle_minPwdAge error!");
2016
2017         talloc_free(mem_ctx);
2018
2019         torture_leave_domain(torture, join_ctx);
2020         torture_leave_domain(torture, user_ctx);
2021         torture_leave_domain(torture, user_ctx_wrong_wks);
2022         torture_leave_domain(torture, user_ctx_wrong_time);
2023         return ret;
2024 }