2 Unix SMB/CIFS implementation.
4 test suite for netlogon rpc operations
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
8 Copyright (C) Tim Potter 2003
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 2 of the License, or
13 (at your option) any later version.
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.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #define TEST_MACHINE_NAME "torturetest"
31 struct dcerpc_pipe *p;
32 const char *machine_password;
33 struct policy_handle acct_handle;
37 join the domain as a BDC
39 static BOOL join_domain_bdc(TALLOC_CTX *mem_ctx)
42 struct samr_Connect c;
43 struct samr_CreateUser2 r;
44 struct samr_OpenDomain o;
45 struct samr_LookupDomain l;
46 struct samr_GetUserPwInfo pwp;
47 struct samr_SetUserInfo s;
48 union samr_UserInfo u;
49 struct policy_handle handle;
50 struct policy_handle domain_handle;
51 uint32 access_granted;
54 DATA_BLOB session_key;
55 struct samr_Name name;
56 int policy_min_pw_len = 0;
58 printf("Connecting to SAMR\n");
60 status = torture_rpc_connection(&join.p,
64 if (!NT_STATUS_IS_OK(status)) {
68 c.in.system_name = NULL;
69 c.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
70 c.out.handle = &handle;
72 status = dcerpc_samr_Connect(join.p, mem_ctx, &c);
73 if (!NT_STATUS_IS_OK(status)) {
74 printf("samr_Connect failed - %s\n", nt_errstr(status));
78 printf("Opening domain %s\n", lp_workgroup());
80 name.name = lp_workgroup();
81 l.in.handle = &handle;
84 status = dcerpc_samr_LookupDomain(join.p, mem_ctx, &l);
85 if (!NT_STATUS_IS_OK(status)) {
86 printf("LookupDomain failed - %s\n", nt_errstr(status));
90 o.in.handle = &handle;
91 o.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
93 o.out.domain_handle = &domain_handle;
95 status = dcerpc_samr_OpenDomain(join.p, mem_ctx, &o);
96 if (!NT_STATUS_IS_OK(status)) {
97 printf("OpenDomain failed - %s\n", nt_errstr(status));
101 printf("Creating machine account %s\n", TEST_MACHINE_NAME);
104 name.name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
105 r.in.handle = &domain_handle;
106 r.in.username = &name;
107 r.in.acct_flags = ACB_SVRTRUST;
108 r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
109 r.out.acct_handle = &join.acct_handle;
110 r.out.access_granted = &access_granted;
113 status = dcerpc_samr_CreateUser2(join.p, mem_ctx, &r);
115 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS) &&
116 test_DeleteUser_byname(join.p, mem_ctx, &domain_handle, name.name)) {
120 if (!NT_STATUS_IS_OK(status)) {
121 printf("CreateUser2 failed - %s\n", nt_errstr(status));
125 pwp.in.handle = &join.acct_handle;
127 status = dcerpc_samr_GetUserPwInfo(join.p, mem_ctx, &pwp);
128 if (NT_STATUS_IS_OK(status)) {
129 policy_min_pw_len = pwp.out.info.min_pwd_len;
132 join.machine_password = generate_random_str(mem_ctx, MAX(8, policy_min_pw_len));
134 printf("Setting machine account password '%s'\n", join.machine_password);
136 s.in.handle = &join.acct_handle;
140 encode_pw_buffer(u.info24.password.data, join.machine_password, STR_UNICODE);
141 u.info24.pw_len = strlen(join.machine_password);
143 status = dcerpc_fetch_session_key(join.p, &session_key);
144 if (!NT_STATUS_IS_OK(status)) {
145 printf("SetUserInfo level %u - no session key - %s\n",
146 s.in.level, nt_errstr(status));
150 SamOEMhashBlob(u.info24.password.data, 516, &session_key);
152 status = dcerpc_samr_SetUserInfo(join.p, mem_ctx, &s);
153 if (!NT_STATUS_IS_OK(status)) {
154 printf("SetUserInfo failed - %s\n", nt_errstr(status));
158 s.in.handle = &join.acct_handle;
162 u.info16.acct_flags = ACB_SVRTRUST;
164 printf("Resetting ACB flags\n");
166 status = dcerpc_samr_SetUserInfo(join.p, mem_ctx, &s);
167 if (!NT_STATUS_IS_OK(status)) {
168 printf("SetUserInfo failed - %s\n", nt_errstr(status));
176 leave the domain as a BDC
178 static BOOL leave_domain_bdc(TALLOC_CTX *mem_ctx)
180 struct samr_DeleteUser d;
183 d.in.handle = &join.acct_handle;
184 d.out.handle = &join.acct_handle;
186 status = dcerpc_samr_DeleteUser(join.p, mem_ctx, &d);
187 if (!NT_STATUS_IS_OK(status)) {
188 printf("Delete of machine account failed\n");
195 static BOOL test_LogonUasLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
198 struct netr_LogonUasLogon r;
200 r.in.server_name = NULL;
201 r.in.username = lp_parm_string(-1, "torture", "username");
202 r.in.workstation = TEST_MACHINE_NAME;
204 printf("Testing LogonUasLogon\n");
206 status = dcerpc_netr_LogonUasLogon(p, mem_ctx, &r);
207 if (!NT_STATUS_IS_OK(status)) {
208 printf("LogonUasLogon - %s\n", nt_errstr(status));
216 static BOOL test_LogonUasLogoff(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
219 struct netr_LogonUasLogoff r;
221 r.in.server_name = NULL;
222 r.in.username = lp_parm_string(-1, "torture", "username");
223 r.in.workstation = TEST_MACHINE_NAME;
225 printf("Testing LogonUasLogoff\n");
227 status = dcerpc_netr_LogonUasLogoff(p, mem_ctx, &r);
228 if (!NT_STATUS_IS_OK(status)) {
229 printf("LogonUasLogoff - %s\n", nt_errstr(status));
237 static BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
238 struct creds_CredentialState *creds)
241 struct netr_ServerReqChallenge r;
242 struct netr_ServerAuthenticate a;
243 const char *plain_pass;
246 printf("Testing ServerReqChallenge\n");
248 r.in.server_name = NULL;
249 r.in.computer_name = TEST_MACHINE_NAME;
250 generate_random_buffer(r.in.credentials.data, sizeof(r.in.credentials.data), False);
252 status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
253 if (!NT_STATUS_IS_OK(status)) {
254 printf("ServerReqChallenge - %s\n", nt_errstr(status));
258 plain_pass = join.machine_password;
260 printf("Unable to fetch machine password!\n");
264 E_md4hash(plain_pass, mach_pwd);
266 creds_client_init(creds, &r.in.credentials, &r.out.credentials, mach_pwd,
269 a.in.server_name = NULL;
270 a.in.username = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
271 a.in.secure_channel_type = SEC_CHAN_BDC;
272 a.in.computer_name = TEST_MACHINE_NAME;
274 printf("Testing ServerAuthenticate\n");
276 status = dcerpc_netr_ServerAuthenticate(p, mem_ctx, &a);
277 if (!NT_STATUS_IS_OK(status)) {
278 printf("ServerAuthenticate - %s\n", nt_errstr(status));
282 if (!creds_client_check(creds, &a.out.credentials)) {
283 printf("Credential chaining failed\n");
290 static BOOL test_SetupCredentials2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
291 uint32 negotiate_flags,
292 struct creds_CredentialState *creds)
295 struct netr_ServerReqChallenge r;
296 struct netr_ServerAuthenticate2 a;
297 const char *plain_pass;
300 printf("Testing ServerReqChallenge\n");
302 r.in.server_name = NULL;
303 r.in.computer_name = TEST_MACHINE_NAME;
304 generate_random_buffer(r.in.credentials.data, sizeof(r.in.credentials.data), False);
306 status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
307 if (!NT_STATUS_IS_OK(status)) {
308 printf("ServerReqChallenge - %s\n", nt_errstr(status));
312 plain_pass = join.machine_password;
314 printf("Unable to fetch machine password!\n");
318 E_md4hash(plain_pass, mach_pwd);
320 creds_client_init(creds, &r.in.credentials, &r.out.credentials, mach_pwd,
323 a.in.server_name = NULL;
324 a.in.username = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
325 a.in.secure_channel_type = SEC_CHAN_BDC;
326 a.in.computer_name = TEST_MACHINE_NAME;
327 a.in.negotiate_flags = &negotiate_flags;
328 a.out.negotiate_flags = &negotiate_flags;
330 printf("Testing ServerAuthenticate2\n");
332 status = dcerpc_netr_ServerAuthenticate2(p, mem_ctx, &a);
333 if (!NT_STATUS_IS_OK(status)) {
334 printf("ServerAuthenticate2 - %s\n", nt_errstr(status));
338 if (!creds_client_check(creds, &a.out.credentials)) {
339 printf("Credential chaining failed\n");
343 printf("negotiate_flags=0x%08x\n", negotiate_flags);
356 struct samlogon_state {
358 const char *username;
359 const char *password;
360 struct dcerpc_pipe *p;
361 struct netr_LogonSamLogon r;
362 struct netr_Authenticator auth, auth2;
363 struct creds_CredentialState creds;
368 Authenticate a user with a challenge/response, checking session key
369 and valid authentication types
372 static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
373 enum ntlm_break break_which,
375 DATA_BLOB *lm_response,
376 DATA_BLOB *nt_response,
378 uint8 user_session_key[16],
382 struct netr_LogonSamLogon *r = &samlogon_state->r;
383 int levels[] = { 2, 6 };
385 struct netr_NetworkInfo ninfo;
387 for (i=0;i<ARRAY_SIZE(levels);i++) {
388 printf("testing netr_LogonSamLogon with logon level %d\n", levels[i]);
390 samlogon_state->r.in.logon_level = levels[i];
391 samlogon_state->r.in.logon.network = &ninfo;
393 ninfo.logon_info.domain_name.string = lp_workgroup();
394 ninfo.logon_info.parameter_control = 0;
395 ninfo.logon_info.logon_id_low = 0;
396 ninfo.logon_info.logon_id_high = 0;
397 ninfo.logon_info.username.string = samlogon_state->username;
398 ninfo.logon_info.workstation.string = TEST_MACHINE_NAME;
400 memcpy(ninfo.challenge, chall->data, 8);
402 switch (break_which) {
406 if (lm_response && lm_response->data) {
407 lm_response->data[0]++;
411 if (nt_response && nt_response->data) {
412 nt_response->data[0]++;
416 data_blob_free(lm_response);
419 data_blob_free(nt_response);
424 ninfo.nt.data = nt_response->data;
425 ninfo.nt.length = nt_response->length;
427 ninfo.nt.data = NULL;
432 ninfo.lm.data = lm_response->data;
433 ninfo.lm.length = lm_response->length;
435 ninfo.lm.data = NULL;
439 ZERO_STRUCT(samlogon_state->auth2);
440 creds_client_authenticator(&samlogon_state->creds, &samlogon_state->auth);
442 r->out.authenticator = NULL;
443 status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
444 if (!NT_STATUS_IS_OK(status)) {
446 *error_string = strdup(nt_errstr(status));
450 if (!r->out.authenticator ||
451 !creds_client_check(&samlogon_state->creds, &r->out.authenticator->cred)) {
452 printf("Credential chaining failed\n");
455 if (!NT_STATUS_IS_OK(status)) {
456 /* we cannot check the session key, if the logon failed... */
460 /* find and decyrpt the session keys, return in parameters above */
461 if (r->in.validation_level == 2) {
462 static const char zeros[16];
464 if (memcmp(r->out.validation.sam->LMSessKey.key, zeros,
465 sizeof(r->out.validation.sam->LMSessKey.key)) != 0) {
466 creds_arcfour_crypt(&samlogon_state->creds,
467 r->out.validation.sam->LMSessKey.key,
468 sizeof(r->out.validation.sam->LMSessKey.key));
472 memcpy(lm_key, r->out.validation.sam->LMSessKey.key, 8);
475 if (memcmp(r->out.validation.sam->key.key, zeros, sizeof(r->out.validation.sam->key.key)) != 0) {
476 creds_arcfour_crypt(&samlogon_state->creds,
477 r->out.validation.sam->key.key,
478 sizeof(r->out.validation.sam->key.key));
481 if (user_session_key) {
482 memcpy(user_session_key, r->out.validation.sam->key.key, 16);
485 } else if (r->in.validation_level == 3) {
486 static const char zeros[16];
487 if (memcmp(r->out.validation.sam2->LMSessKey.key, zeros, sizeof(r->out.validation.sam2->LMSessKey.key)) != 0) {
488 creds_arcfour_crypt(&samlogon_state->creds,
489 r->out.validation.sam2->LMSessKey.key,
490 sizeof(r->out.validation.sam2->LMSessKey.key));
494 memcpy(lm_key, r->out.validation.sam2->LMSessKey.key, 8);
497 if (memcmp(r->out.validation.sam2->key.key, zeros, sizeof(r->out.validation.sam2->key.key)) != 0) {
498 creds_arcfour_crypt(&samlogon_state->creds,
499 r->out.validation.sam2->key.key,
500 sizeof(r->out.validation.sam2->key.key));
503 if (user_session_key) {
504 memcpy(user_session_key, r->out.validation.sam2->key.key, 16);
513 * Test the normal 'LM and NTLM' combination
516 static BOOL test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
520 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
521 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
522 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
525 uchar user_session_key[16];
530 ZERO_STRUCT(user_session_key);
532 SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
533 E_deshash(samlogon_state->password, lm_hash);
535 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
537 E_md4hash(samlogon_state->password, nt_hash);
538 SMBsesskeygen_ntv1(nt_hash, session_key.data);
540 nt_status = check_samlogon(samlogon_state,
542 &samlogon_state->chall,
549 data_blob_free(&lm_response);
551 if (!NT_STATUS_IS_OK(nt_status)) {
552 return break_which == BREAK_NT;
555 if (memcmp(lm_hash, lm_key,
556 sizeof(lm_key)) != 0) {
557 printf("LM Key does not match expectations!\n");
559 dump_data(1, (const char *)lm_key, 8);
560 printf("expected:\n");
561 dump_data(1, (const char *)lm_hash, 8);
565 if (break_which == NO_NT) {
566 char lm_key_expected[16];
567 memcpy(lm_key_expected, lm_hash, 8);
568 memset(lm_key_expected+8, '\0', 8);
569 if (memcmp(lm_key_expected, user_session_key,
571 printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
572 printf("user_session_key:\n");
573 dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
574 printf("expected:\n");
575 dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
579 if (memcmp(session_key.data, user_session_key,
580 sizeof(user_session_key)) != 0) {
581 printf("NT Session Key does not match expectations!\n");
582 printf("user_session_key:\n");
583 dump_data(1, (const char *)user_session_key, 16);
584 printf("expected:\n");
585 dump_data(1, (const char *)session_key.data, session_key.length);
593 * Test LM authentication, no NT response supplied
596 static BOOL test_lm(struct samlogon_state *samlogon_state, char **error_string)
599 return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
603 * Test the NTLM response only, no LM.
606 static BOOL test_ntlm(struct samlogon_state *samlogon_state, char **error_string)
608 return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
612 * Test the NTLM response only, but in the LM field.
615 static BOOL test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string)
619 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
623 uchar user_session_key[16];
625 ZERO_STRUCT(user_session_key);
627 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
629 E_deshash(samlogon_state->password, lm_hash);
631 nt_status = check_samlogon(samlogon_state,
633 &samlogon_state->chall,
640 if (!NT_STATUS_IS_OK(nt_status)) {
644 if (memcmp(lm_hash, lm_key,
645 sizeof(lm_key)) != 0) {
646 printf("LM Key does not match expectations!\n");
648 dump_data(1, (const char *)lm_key, 8);
649 printf("expected:\n");
650 dump_data(1, (const char *)lm_hash, 8);
653 if (memcmp(lm_hash, user_session_key, 8) != 0) {
654 char lm_key_expected[16];
655 memcpy(lm_key_expected, lm_hash, 8);
656 memset(lm_key_expected+8, '\0', 8);
657 if (memcmp(lm_key_expected, user_session_key,
659 printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
660 printf("user_session_key:\n");
661 dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
662 printf("expected:\n");
663 dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
671 * Test the NTLM response only, but in the both the NT and LM fields.
674 static BOOL test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string)
678 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
679 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
683 char user_session_key[16];
687 ZERO_STRUCT(user_session_key);
689 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
691 E_md4hash(samlogon_state->password, (unsigned char *)nt_hash);
692 SMBsesskeygen_ntv1((const unsigned char *)nt_hash,
695 E_deshash(samlogon_state->password, (unsigned char *)lm_hash);
697 nt_status = check_samlogon(samlogon_state,
699 &samlogon_state->chall,
706 if (!NT_STATUS_IS_OK(nt_status)) {
710 if (memcmp(lm_hash, lm_key,
711 sizeof(lm_key)) != 0) {
712 printf("LM Key does not match expectations!\n");
714 dump_data(1, lm_key, 8);
715 printf("expected:\n");
716 dump_data(1, lm_hash, 8);
719 if (memcmp(session_key.data, user_session_key,
720 sizeof(user_session_key)) != 0) {
721 printf("NT Session Key does not match expectations!\n");
722 printf("user_session_key:\n");
723 dump_data(1, user_session_key, 16);
724 printf("expected:\n");
725 dump_data(1, (const char *)session_key.data, session_key.length);
734 * Test the NTLMv2 and LMv2 responses
737 static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
741 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
742 DATA_BLOB lmv2_response = data_blob(NULL, 0);
743 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
744 DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, lp_netbios_name(), lp_workgroup());
746 uchar user_session_key[16];
748 ZERO_STRUCT(user_session_key);
750 /* TODO - test with various domain cases, and without domain */
751 if (!SMBNTLMv2encrypt(samlogon_state->username, lp_workgroup(),
752 samlogon_state->password, &samlogon_state->chall,
754 &lmv2_response, &ntlmv2_response,
755 &ntlmv2_session_key)) {
756 data_blob_free(&names_blob);
759 data_blob_free(&names_blob);
761 nt_status = check_samlogon(samlogon_state,
763 &samlogon_state->chall,
770 data_blob_free(&lmv2_response);
771 data_blob_free(&ntlmv2_response);
773 if (!NT_STATUS_IS_OK(nt_status)) {
774 return break_which == BREAK_NT;
777 if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key,
778 sizeof(user_session_key)) != 0) {
779 printf("USER (NTLMv2) Session Key does not match expectations!\n");
780 printf("user_session_key:\n");
781 dump_data(1, (const char *)user_session_key, 16);
782 printf("expected:\n");
783 dump_data(1, (const char *)ntlmv2_session_key.data, ntlmv2_session_key.length);
790 * Test the NTLMv2 and LMv2 responses
793 static BOOL test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
795 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, error_string);
799 * Test the LMv2 response only
802 static BOOL test_lmv2(struct samlogon_state *samlogon_state, char **error_string)
804 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, error_string);
808 * Test the NTLMv2 response only
811 static BOOL test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
813 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, error_string);
816 static BOOL test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string)
818 return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
821 static BOOL test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string)
823 return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
826 static BOOL test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string)
828 return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
831 static BOOL test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
833 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, error_string);
836 static BOOL test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
838 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, error_string);
841 static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
844 DATA_BLOB nt_response = data_blob(NULL, 0);
845 DATA_BLOB lm_response = data_blob(NULL, 0);
848 smb_ucs2_t *unicodepw;
850 uchar user_session_key[16];
852 static const uchar zeros[8];
853 DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
855 ZERO_STRUCT(user_session_key);
857 if ((push_ucs2_talloc(samlogon_state->mem_ctx, (smb_ucs2_t **)&unicodepw,
858 samlogon_state->password)) == -1) {
859 DEBUG(0, ("push_ucs2_allocate failed!\n"));
863 nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw,
864 strlen_w(((void *)unicodepw))*sizeof(smb_ucs2_t));
866 password = strdup_upper(samlogon_state->password);
868 if ((convert_string_talloc(samlogon_state->mem_ctx, CH_UNIX,
871 (const void**)&dospw)) == -1) {
872 DEBUG(0, ("push_ascii_allocate failed!\n"));
878 lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
880 nt_status = check_samlogon(samlogon_state,
889 if (!NT_STATUS_IS_OK(nt_status)) {
890 return break_which == BREAK_NT;
896 static BOOL test_plaintext_none_broken(struct samlogon_state *samlogon_state,
897 char **error_string) {
898 return test_plaintext(samlogon_state, BREAK_NONE, error_string);
901 static BOOL test_plaintext_lm_broken(struct samlogon_state *samlogon_state,
902 char **error_string) {
903 return test_plaintext(samlogon_state, BREAK_LM, error_string);
906 static BOOL test_plaintext_nt_broken(struct samlogon_state *samlogon_state,
907 char **error_string) {
908 return test_plaintext(samlogon_state, BREAK_NT, error_string);
911 static BOOL test_plaintext_nt_only(struct samlogon_state *samlogon_state,
912 char **error_string) {
913 return test_plaintext(samlogon_state, NO_LM, error_string);
916 static BOOL test_plaintext_lm_only(struct samlogon_state *samlogon_state,
917 char **error_string) {
918 return test_plaintext(samlogon_state, NO_NT, error_string);
932 - plaintext tests (in challenge-response feilds)
934 check we get the correct session key in each case
935 check what values we get for the LM session key
939 static const struct ntlm_tests {
940 BOOL (*fn)(struct samlogon_state *, char **);
944 {test_lm, "LM", False},
945 {test_lm_ntlm, "LM and NTLM", False},
946 {test_ntlm, "NTLM", False},
947 {test_ntlm_in_lm, "NTLM in LM", False},
948 {test_ntlm_in_both, "NTLM in both", False},
949 {test_ntlmv2, "NTLMv2", False},
950 {test_lmv2_ntlmv2, "NTLMv2 and LMv2", False},
951 {test_lmv2, "LMv2", False},
952 {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False},
953 {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False},
954 {test_ntlm_lm_broken, "NTLM and LM, LM broken", False},
955 {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False},
956 {test_plaintext_none_broken, "Plaintext", True},
957 {test_plaintext_lm_broken, "Plaintext LM broken", True},
958 {test_plaintext_nt_broken, "Plaintext NT broken", True},
959 {test_plaintext_nt_only, "Plaintext NT only", True},
960 {test_plaintext_lm_only, "Plaintext LM only", True},
965 try a netlogon SamLogon
967 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
972 struct samlogon_state samlogon_state;
974 samlogon_state.mem_ctx = mem_ctx;
975 samlogon_state.username = lp_parm_string(-1, "torture", "username");
976 samlogon_state.password = lp_parm_string(-1, "torture", "password");
977 samlogon_state.p = p;
979 samlogon_state.chall = data_blob_talloc(mem_ctx, NULL, 8);
981 generate_random_buffer(samlogon_state.chall.data,
984 if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
988 samlogon_state.r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
989 samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
990 samlogon_state.r.in.credential = &samlogon_state.auth;
991 samlogon_state.r.in.authenticator = &samlogon_state.auth2;
994 samlogon_state.r.in.validation_level = i;
995 for (j=0; test_table[j].fn; j++) {
996 char *error_string = NULL;
997 printf("Testing SamLogon with '%s' at validation level %d\n", test_table[j].name, i);
999 if (!test_table[j].fn(&samlogon_state, &error_string)) {
1000 if (test_table[j].expect_fail) {
1001 printf("Test %s failed (expected, test incomplete): %s\n", test_table[j].name, error_string);
1003 printf("Test %s failed: %s\n", test_table[j].name, error_string);
1006 SAFE_FREE(error_string);
1016 try a change password for our machine account
1018 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1021 struct netr_ServerPasswordSet r;
1022 const char *password;
1023 struct creds_CredentialState creds;
1025 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1029 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1030 r.in.username = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
1031 r.in.secure_channel_type = SEC_CHAN_BDC;
1032 r.in.computer_name = TEST_MACHINE_NAME;
1034 password = generate_random_str(mem_ctx, 8);
1035 E_md4hash(password, r.in.new_password.data);
1037 creds_des_encrypt(&creds, &r.in.new_password);
1039 printf("Testing ServerPasswordSet on machine account\n");
1040 printf("Changing machine account password to '%s'\n", password);
1042 creds_client_authenticator(&creds, &r.in.credential);
1044 status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
1045 if (!NT_STATUS_IS_OK(status)) {
1046 printf("ServerPasswordSet - %s\n", nt_errstr(status));
1050 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1051 printf("Credential chaining failed\n");
1054 /* by changing the machine password twice we test the
1055 credentials chaining fully, and we verify that the server
1056 allows the password to be set to the same value twice in a
1057 row (match win2k3) */
1058 printf("Testing a second ServerPasswordSet on machine account\n");
1059 printf("Changing machine account password to '%s' (same as pervsious run)\n", password);
1061 creds_client_authenticator(&creds, &r.in.credential);
1063 status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
1064 if (!NT_STATUS_IS_OK(status)) {
1065 printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
1069 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1070 printf("Credential chaining failed\n");
1073 join.machine_password = password;
1075 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1076 printf("ServerPasswordSet failed to actually change the password\n");
1084 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
1085 static uint64_t sequence_nums[3];
1088 try a netlogon DatabaseSync
1090 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1093 struct netr_DatabaseSync r;
1094 struct creds_CredentialState creds;
1095 const uint32 database_ids[] = {0, 1, 2};
1099 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1103 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1104 r.in.computername = TEST_MACHINE_NAME;
1105 r.in.preferredmaximumlength = (uint32)-1;
1106 ZERO_STRUCT(r.in.return_authenticator);
1108 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1109 r.in.sync_context = 0;
1110 r.in.database_id = database_ids[i];
1112 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
1115 creds_client_authenticator(&creds, &r.in.credential);
1117 status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
1118 if (!NT_STATUS_IS_OK(status) &&
1119 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1120 printf("DatabaseSync - %s\n", nt_errstr(status));
1125 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1126 printf("Credential chaining failed\n");
1129 r.in.sync_context = r.out.sync_context;
1131 if (r.out.delta_enum_array &&
1132 r.out.delta_enum_array->num_deltas > 0 &&
1133 r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
1134 r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
1135 sequence_nums[r.in.database_id] =
1136 r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
1137 printf("\tsequence_nums[%d]=%llu\n",
1139 sequence_nums[r.in.database_id]);
1141 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1149 try a netlogon DatabaseDeltas
1151 static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1154 struct netr_DatabaseDeltas r;
1155 struct creds_CredentialState creds;
1156 const uint32 database_ids[] = {0, 1, 2};
1160 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1164 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1165 r.in.computername = TEST_MACHINE_NAME;
1166 r.in.preferredmaximumlength = (uint32)-1;
1167 ZERO_STRUCT(r.in.return_authenticator);
1169 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1170 r.in.database_id = database_ids[i];
1171 r.in.sequence_num = sequence_nums[r.in.database_id];
1173 if (r.in.sequence_num == 0) continue;
1175 r.in.sequence_num -= 1;
1178 printf("Testing DatabaseDeltas of id %d at %llu\n",
1179 r.in.database_id, r.in.sequence_num);
1182 creds_client_authenticator(&creds, &r.in.credential);
1184 status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
1185 if (!NT_STATUS_IS_OK(status) &&
1186 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1187 printf("DatabaseDeltas - %s\n", nt_errstr(status));
1192 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1193 printf("Credential chaining failed\n");
1196 r.in.sequence_num++;
1197 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1205 try a netlogon AccountDeltas
1207 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1210 struct netr_AccountDeltas r;
1211 struct creds_CredentialState creds;
1214 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1218 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1219 r.in.computername = TEST_MACHINE_NAME;
1220 ZERO_STRUCT(r.in.return_authenticator);
1221 creds_client_authenticator(&creds, &r.in.credential);
1222 ZERO_STRUCT(r.in.uas);
1225 r.in.buffersize=100;
1227 printf("Testing AccountDeltas\n");
1229 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1230 status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
1231 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1232 printf("AccountDeltas - %s\n", nt_errstr(status));
1240 try a netlogon AccountSync
1242 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1245 struct netr_AccountSync r;
1246 struct creds_CredentialState creds;
1249 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1253 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1254 r.in.computername = TEST_MACHINE_NAME;
1255 ZERO_STRUCT(r.in.return_authenticator);
1256 creds_client_authenticator(&creds, &r.in.credential);
1257 ZERO_STRUCT(r.in.recordid);
1260 r.in.buffersize=100;
1262 printf("Testing AccountSync\n");
1264 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1265 status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
1266 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1267 printf("AccountSync - %s\n", nt_errstr(status));
1275 try a netlogon GetDcName
1277 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1280 struct netr_GetDcName r;
1282 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1283 r.in.domainname = lp_workgroup();
1285 printf("Testing GetDcName\n");
1287 status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
1288 if (!NT_STATUS_IS_OK(status)) {
1289 printf("GetDcName - %s\n", nt_errstr(status));
1293 printf("\tDC is at '%s'\n", r.out.dcname);
1299 try a netlogon LogonControl
1301 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1304 struct netr_LogonControl r;
1308 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1309 r.in.function_code = 1;
1314 printf("Testing LogonControl level %d\n", i);
1316 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
1317 if (!NT_STATUS_IS_OK(status)) {
1318 printf("LogonControl - %s\n", nt_errstr(status));
1328 try a netlogon GetAnyDCName
1330 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1333 struct netr_GetAnyDCName r;
1335 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1336 r.in.domainname = lp_workgroup();
1338 printf("Testing GetAnyDCName\n");
1340 status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 printf("GetAnyDCName - %s\n", nt_errstr(status));
1347 printf("\tDC is at '%s'\n", r.out.dcname);
1355 try a netlogon LogonControl2
1357 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1360 struct netr_LogonControl2 r;
1364 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1366 r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1367 r.in.data.domain = lp_workgroup();
1372 printf("Testing LogonControl2 level %d function %d\n",
1373 i, r.in.function_code);
1375 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1376 if (!NT_STATUS_IS_OK(status)) {
1377 printf("LogonControl - %s\n", nt_errstr(status));
1382 r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1383 r.in.data.domain = lp_workgroup();
1388 printf("Testing LogonControl2 level %d function %d\n",
1389 i, r.in.function_code);
1391 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1392 if (!NT_STATUS_IS_OK(status)) {
1393 printf("LogonControl - %s\n", nt_errstr(status));
1398 r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1399 r.in.data.domain = lp_workgroup();
1404 printf("Testing LogonControl2 level %d function %d\n",
1405 i, r.in.function_code);
1407 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1408 if (!NT_STATUS_IS_OK(status)) {
1409 printf("LogonControl - %s\n", nt_errstr(status));
1414 r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1415 r.in.data.debug_level = ~0;
1420 printf("Testing LogonControl2 level %d function %d\n",
1421 i, r.in.function_code);
1423 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1424 if (!NT_STATUS_IS_OK(status)) {
1425 printf("LogonControl - %s\n", nt_errstr(status));
1434 try a netlogon DatabaseSync2
1436 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1439 struct netr_DatabaseSync2 r;
1440 struct creds_CredentialState creds;
1441 const uint32 database_ids[] = {0, 1, 2};
1445 if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &creds)) {
1449 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1450 r.in.computername = TEST_MACHINE_NAME;
1451 r.in.preferredmaximumlength = (uint32)-1;
1452 ZERO_STRUCT(r.in.return_authenticator);
1454 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1455 r.in.sync_context = 0;
1456 r.in.database_id = database_ids[i];
1457 r.in.restart_state = 0;
1459 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
1462 creds_client_authenticator(&creds, &r.in.credential);
1464 status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
1465 if (!NT_STATUS_IS_OK(status) &&
1466 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1467 printf("DatabaseSync2 - %s\n", nt_errstr(status));
1472 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1473 printf("Credential chaining failed\n");
1476 r.in.sync_context = r.out.sync_context;
1477 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1485 try a netlogon LogonControl2Ex
1487 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1490 struct netr_LogonControl2Ex r;
1494 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1496 r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1497 r.in.data.domain = lp_workgroup();
1502 printf("Testing LogonControl2Ex level %d function %d\n",
1503 i, r.in.function_code);
1505 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1506 if (!NT_STATUS_IS_OK(status)) {
1507 printf("LogonControl - %s\n", nt_errstr(status));
1512 r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1513 r.in.data.domain = lp_workgroup();
1518 printf("Testing LogonControl2Ex level %d function %d\n",
1519 i, r.in.function_code);
1521 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1522 if (!NT_STATUS_IS_OK(status)) {
1523 printf("LogonControl - %s\n", nt_errstr(status));
1528 r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1529 r.in.data.domain = lp_workgroup();
1534 printf("Testing LogonControl2Ex level %d function %d\n",
1535 i, r.in.function_code);
1537 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1538 if (!NT_STATUS_IS_OK(status)) {
1539 printf("LogonControl - %s\n", nt_errstr(status));
1544 r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1545 r.in.data.debug_level = ~0;
1550 printf("Testing LogonControl2Ex level %d function %d\n",
1551 i, r.in.function_code);
1553 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 printf("LogonControl - %s\n", nt_errstr(status));
1565 BOOL torture_rpc_netlogon(int dummy)
1568 struct dcerpc_pipe *p;
1569 TALLOC_CTX *mem_ctx;
1572 mem_ctx = talloc_init("torture_rpc_netlogon");
1574 if (!join_domain_bdc(mem_ctx)) {
1575 printf("Failed to join as BDC\n");
1579 status = torture_rpc_connection(&p,
1580 DCERPC_NETLOGON_NAME,
1581 DCERPC_NETLOGON_UUID,
1582 DCERPC_NETLOGON_VERSION);
1583 if (!NT_STATUS_IS_OK(status)) {
1587 if (!test_LogonUasLogon(p, mem_ctx)) {
1591 if (!test_LogonUasLogoff(p, mem_ctx)) {
1595 if (!test_SetPassword(p, mem_ctx)) {
1599 if (!test_SamLogon(p, mem_ctx)) {
1603 if (!test_DatabaseSync(p, mem_ctx)) {
1607 if (!test_DatabaseDeltas(p, mem_ctx)) {
1611 if (!test_AccountDeltas(p, mem_ctx)) {
1615 if (!test_AccountSync(p, mem_ctx)) {
1619 if (!test_GetDcName(p, mem_ctx)) {
1623 if (!test_LogonControl(p, mem_ctx)) {
1627 if (!test_GetAnyDCName(p, mem_ctx)) {
1631 if (!test_LogonControl2(p, mem_ctx)) {
1635 if (!test_DatabaseSync2(p, mem_ctx)) {
1639 if (!test_LogonControl2Ex(p, mem_ctx)) {
1643 torture_rpc_close(p);
1645 if (!leave_domain_bdc(mem_ctx)) {
1646 printf("Failed to delete BDC machine account\n");