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