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