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