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