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