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(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(), samlogon_state->password, &samlogon_state->chall,
753 &lmv2_response, &ntlmv2_response,
754 &ntlmv2_session_key)) {
755 data_blob_free(&names_blob);
758 data_blob_free(&names_blob);
760 nt_status = check_samlogon(samlogon_state,
762 &samlogon_state->chall,
769 data_blob_free(&lmv2_response);
770 data_blob_free(&ntlmv2_response);
772 if (!NT_STATUS_IS_OK(nt_status)) {
773 return break_which == BREAK_NT;
776 if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key,
777 sizeof(user_session_key)) != 0) {
778 printf("USER (NTLMv2) Session Key does not match expectations!\n");
779 printf("user_session_key:\n");
780 dump_data(1, (const char *)user_session_key, 16);
781 printf("expected:\n");
782 dump_data(1, (const char *)ntlmv2_session_key.data, ntlmv2_session_key.length);
789 * Test the NTLMv2 and LMv2 responses
792 static BOOL test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
794 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, error_string);
798 * Test the LMv2 response only
801 static BOOL test_lmv2(struct samlogon_state *samlogon_state, char **error_string)
803 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, error_string);
807 * Test the NTLMv2 response only
810 static BOOL test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
812 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, error_string);
815 static BOOL test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string)
817 return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
820 static BOOL test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string)
822 return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
825 static BOOL test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string)
827 return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
830 static BOOL test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
832 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, error_string);
835 static BOOL test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
837 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, error_string);
840 static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
843 DATA_BLOB nt_response = data_blob(NULL, 0);
844 DATA_BLOB lm_response = data_blob(NULL, 0);
847 smb_ucs2_t *unicodepw;
849 uchar user_session_key[16];
851 static const uchar zeros[8];
852 DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
854 ZERO_STRUCT(user_session_key);
856 if ((push_ucs2_talloc(samlogon_state->mem_ctx, (smb_ucs2_t **)&unicodepw,
857 samlogon_state->password)) == -1) {
858 DEBUG(0, ("push_ucs2_allocate failed!\n"));
862 nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw,
863 strlen_w(((void *)unicodepw))*sizeof(smb_ucs2_t));
865 password = strdup_upper(samlogon_state->password);
867 if ((convert_string_talloc(samlogon_state->mem_ctx, CH_UNIX,
870 (const void**)&dospw)) == -1) {
871 DEBUG(0, ("push_ascii_allocate failed!\n"));
877 lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
879 nt_status = check_samlogon(samlogon_state,
888 if (!NT_STATUS_IS_OK(nt_status)) {
889 return break_which == BREAK_NT;
895 static BOOL test_plaintext_none_broken(struct samlogon_state *samlogon_state,
896 char **error_string) {
897 return test_plaintext(samlogon_state, BREAK_NONE, error_string);
900 static BOOL test_plaintext_lm_broken(struct samlogon_state *samlogon_state,
901 char **error_string) {
902 return test_plaintext(samlogon_state, BREAK_LM, error_string);
905 static BOOL test_plaintext_nt_broken(struct samlogon_state *samlogon_state,
906 char **error_string) {
907 return test_plaintext(samlogon_state, BREAK_NT, error_string);
910 static BOOL test_plaintext_nt_only(struct samlogon_state *samlogon_state,
911 char **error_string) {
912 return test_plaintext(samlogon_state, NO_LM, error_string);
915 static BOOL test_plaintext_lm_only(struct samlogon_state *samlogon_state,
916 char **error_string) {
917 return test_plaintext(samlogon_state, NO_NT, error_string);
931 - plaintext tests (in challenge-response feilds)
933 check we get the correct session key in each case
934 check what values we get for the LM session key
938 static const struct ntlm_tests {
939 BOOL (*fn)(struct samlogon_state *, char **);
943 {test_lm, "LM", False},
944 {test_lm_ntlm, "LM and NTLM", False},
945 {test_ntlm, "NTLM", False},
946 {test_ntlm_in_lm, "NTLM in LM", False},
947 {test_ntlm_in_both, "NTLM in both", False},
948 {test_ntlmv2, "NTLMv2", False},
949 {test_lmv2_ntlmv2, "NTLMv2 and LMv2", False},
950 {test_lmv2, "LMv2", False},
951 {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False},
952 {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False},
953 {test_ntlm_lm_broken, "NTLM and LM, LM broken", False},
954 {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False},
955 {test_plaintext_none_broken, "Plaintext", True},
956 {test_plaintext_lm_broken, "Plaintext LM broken", True},
957 {test_plaintext_nt_broken, "Plaintext NT broken", True},
958 {test_plaintext_nt_only, "Plaintext NT only", True},
959 {test_plaintext_lm_only, "Plaintext LM only", True},
964 try a netlogon SamLogon
966 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
971 struct samlogon_state samlogon_state;
973 samlogon_state.mem_ctx = mem_ctx;
974 samlogon_state.username = lp_parm_string(-1, "torture", "username");
975 samlogon_state.password = lp_parm_string(-1, "torture", "password");
976 samlogon_state.p = p;
978 samlogon_state.chall = data_blob_talloc(mem_ctx, NULL, 8);
980 generate_random_buffer(samlogon_state.chall.data,
983 if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
987 samlogon_state.r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
988 samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
989 samlogon_state.r.in.credential = &samlogon_state.auth;
990 samlogon_state.r.in.authenticator = &samlogon_state.auth2;
993 samlogon_state.r.in.validation_level = i;
994 for (j=0; test_table[j].fn; j++) {
995 char *error_string = NULL;
996 printf("Testing SamLogon with '%s' at validation level %d\n", test_table[j].name, i);
998 if (!test_table[j].fn(&samlogon_state, &error_string)) {
999 if (test_table[j].expect_fail) {
1000 printf("Test %s failed (expected, test incomplete): %s\n", test_table[j].name, error_string);
1002 printf("Test %s failed: %s\n", test_table[j].name, error_string);
1005 SAFE_FREE(error_string);
1015 try a change password for our machine account
1017 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1020 struct netr_ServerPasswordSet r;
1021 const char *password;
1022 struct creds_CredentialState creds;
1024 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1028 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1029 r.in.username = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
1030 r.in.secure_channel_type = SEC_CHAN_BDC;
1031 r.in.computer_name = TEST_MACHINE_NAME;
1033 password = generate_random_str(mem_ctx, 8);
1034 E_md4hash(password, r.in.new_password.data);
1036 creds_des_encrypt(&creds, &r.in.new_password);
1038 printf("Testing ServerPasswordSet on machine account\n");
1039 printf("Changing machine account password to '%s'\n", password);
1041 creds_client_authenticator(&creds, &r.in.credential);
1043 status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
1044 if (!NT_STATUS_IS_OK(status)) {
1045 printf("ServerPasswordSet - %s\n", nt_errstr(status));
1049 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1050 printf("Credential chaining failed\n");
1053 /* by changing the machine password twice we test the
1054 credentials chaining fully, and we verify that the server
1055 allows the password to be set to the same value twice in a
1056 row (match win2k3) */
1057 printf("Testing a second ServerPasswordSet on machine account\n");
1058 printf("Changing machine account password to '%s' (same as pervsious run)\n", password);
1060 creds_client_authenticator(&creds, &r.in.credential);
1062 status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
1063 if (!NT_STATUS_IS_OK(status)) {
1064 printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
1068 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1069 printf("Credential chaining failed\n");
1072 join.machine_password = password;
1074 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1075 printf("ServerPasswordSet failed to actually change the password\n");
1083 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
1084 static struct ULONG8 sequence_nums[3];
1087 try a netlogon DatabaseSync
1089 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1092 struct netr_DatabaseSync r;
1093 struct creds_CredentialState creds;
1094 const uint32 database_ids[] = {0, 1, 2};
1098 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1102 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1103 r.in.computername = TEST_MACHINE_NAME;
1104 r.in.preferredmaximumlength = (uint32)-1;
1105 ZERO_STRUCT(r.in.return_authenticator);
1107 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1108 r.in.sync_context = 0;
1109 r.in.database_id = database_ids[i];
1111 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
1114 creds_client_authenticator(&creds, &r.in.credential);
1116 status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
1117 if (!NT_STATUS_IS_OK(status) &&
1118 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1119 printf("DatabaseSync - %s\n", nt_errstr(status));
1124 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1125 printf("Credential chaining failed\n");
1128 r.in.sync_context = r.out.sync_context;
1130 if (r.out.delta_enum_array &&
1131 r.out.delta_enum_array->num_deltas > 0 &&
1132 r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
1133 r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
1134 sequence_nums[r.in.database_id] =
1135 r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
1136 printf("\tsequence_nums[%d]=0x%08x%08x\n",
1138 sequence_nums[r.in.database_id].high,
1139 sequence_nums[r.in.database_id].low);
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.low == 0) continue;
1175 r.in.sequence_num.low -= 1;
1178 printf("Testing DatabaseDeltas of id %d at %d\n",
1179 r.in.database_id, r.in.sequence_num.low);
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.low++;
1197 r.in.sequence_num.high = 0;
1198 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1206 try a netlogon AccountDeltas
1208 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1211 struct netr_AccountDeltas r;
1212 struct creds_CredentialState creds;
1215 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1219 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1220 r.in.computername = TEST_MACHINE_NAME;
1221 ZERO_STRUCT(r.in.return_authenticator);
1222 creds_client_authenticator(&creds, &r.in.credential);
1223 ZERO_STRUCT(r.in.uas);
1226 r.in.buffersize=100;
1228 printf("Testing AccountDeltas\n");
1230 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1231 status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
1232 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1233 printf("AccountDeltas - %s\n", nt_errstr(status));
1241 try a netlogon AccountSync
1243 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1246 struct netr_AccountSync r;
1247 struct creds_CredentialState creds;
1250 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1254 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1255 r.in.computername = TEST_MACHINE_NAME;
1256 ZERO_STRUCT(r.in.return_authenticator);
1257 creds_client_authenticator(&creds, &r.in.credential);
1258 ZERO_STRUCT(r.in.recordid);
1261 r.in.buffersize=100;
1263 printf("Testing AccountSync\n");
1265 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1266 status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
1267 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1268 printf("AccountSync - %s\n", nt_errstr(status));
1276 try a netlogon GetDcName
1278 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1281 struct netr_GetDcName r;
1283 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1284 r.in.domainname = lp_workgroup();
1286 printf("Testing GetDcName\n");
1288 status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 printf("GetDcName - %s\n", nt_errstr(status));
1294 printf("\tDC is at '%s'\n", r.out.dcname);
1300 try a netlogon LogonControl
1302 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1305 struct netr_LogonControl r;
1309 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1310 r.in.function_code = 1;
1315 printf("Testing LogonControl level %d\n", i);
1317 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
1318 if (!NT_STATUS_IS_OK(status)) {
1319 printf("LogonControl - %s\n", nt_errstr(status));
1329 try a netlogon GetAnyDCName
1331 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1334 struct netr_GetAnyDCName r;
1336 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1337 r.in.domainname = lp_workgroup();
1339 printf("Testing GetAnyDCName\n");
1341 status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
1342 if (!NT_STATUS_IS_OK(status)) {
1343 printf("GetAnyDCName - %s\n", nt_errstr(status));
1348 printf("\tDC is at '%s'\n", r.out.dcname);
1356 try a netlogon LogonControl2
1358 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1361 struct netr_LogonControl2 r;
1365 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1367 r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1368 r.in.data.domain = lp_workgroup();
1373 printf("Testing LogonControl2 level %d function %d\n",
1374 i, r.in.function_code);
1376 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1377 if (!NT_STATUS_IS_OK(status)) {
1378 printf("LogonControl - %s\n", nt_errstr(status));
1383 r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1384 r.in.data.domain = lp_workgroup();
1389 printf("Testing LogonControl2 level %d function %d\n",
1390 i, r.in.function_code);
1392 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1393 if (!NT_STATUS_IS_OK(status)) {
1394 printf("LogonControl - %s\n", nt_errstr(status));
1399 r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1400 r.in.data.domain = lp_workgroup();
1405 printf("Testing LogonControl2 level %d function %d\n",
1406 i, r.in.function_code);
1408 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1409 if (!NT_STATUS_IS_OK(status)) {
1410 printf("LogonControl - %s\n", nt_errstr(status));
1415 r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1416 r.in.data.debug_level = ~0;
1421 printf("Testing LogonControl2 level %d function %d\n",
1422 i, r.in.function_code);
1424 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1425 if (!NT_STATUS_IS_OK(status)) {
1426 printf("LogonControl - %s\n", nt_errstr(status));
1435 try a netlogon DatabaseSync2
1437 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1440 struct netr_DatabaseSync2 r;
1441 struct creds_CredentialState creds;
1442 const uint32 database_ids[] = {0, 1, 2};
1446 if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &creds)) {
1450 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1451 r.in.computername = TEST_MACHINE_NAME;
1452 r.in.preferredmaximumlength = (uint32)-1;
1453 ZERO_STRUCT(r.in.return_authenticator);
1455 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1456 r.in.sync_context = 0;
1457 r.in.database_id = database_ids[i];
1458 r.in.restart_state = 0;
1460 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
1463 creds_client_authenticator(&creds, &r.in.credential);
1465 status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
1466 if (!NT_STATUS_IS_OK(status) &&
1467 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1468 printf("DatabaseSync2 - %s\n", nt_errstr(status));
1473 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1474 printf("Credential chaining failed\n");
1477 r.in.sync_context = r.out.sync_context;
1478 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1486 try a netlogon LogonControl2Ex
1488 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1491 struct netr_LogonControl2Ex r;
1495 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1497 r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1498 r.in.data.domain = lp_workgroup();
1503 printf("Testing LogonControl2Ex level %d function %d\n",
1504 i, r.in.function_code);
1506 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1507 if (!NT_STATUS_IS_OK(status)) {
1508 printf("LogonControl - %s\n", nt_errstr(status));
1513 r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1514 r.in.data.domain = lp_workgroup();
1519 printf("Testing LogonControl2Ex level %d function %d\n",
1520 i, r.in.function_code);
1522 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1523 if (!NT_STATUS_IS_OK(status)) {
1524 printf("LogonControl - %s\n", nt_errstr(status));
1529 r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1530 r.in.data.domain = lp_workgroup();
1535 printf("Testing LogonControl2Ex level %d function %d\n",
1536 i, r.in.function_code);
1538 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1539 if (!NT_STATUS_IS_OK(status)) {
1540 printf("LogonControl - %s\n", nt_errstr(status));
1545 r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1546 r.in.data.debug_level = ~0;
1551 printf("Testing LogonControl2Ex level %d function %d\n",
1552 i, r.in.function_code);
1554 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1555 if (!NT_STATUS_IS_OK(status)) {
1556 printf("LogonControl - %s\n", nt_errstr(status));
1566 BOOL torture_rpc_netlogon(int dummy)
1569 struct dcerpc_pipe *p;
1570 TALLOC_CTX *mem_ctx;
1573 mem_ctx = talloc_init("torture_rpc_netlogon");
1575 if (!join_domain_bdc(mem_ctx)) {
1576 printf("Failed to join as BDC\n");
1580 status = torture_rpc_connection(&p,
1581 DCERPC_NETLOGON_NAME,
1582 DCERPC_NETLOGON_UUID,
1583 DCERPC_NETLOGON_VERSION);
1584 if (!NT_STATUS_IS_OK(status)) {
1588 if (!test_LogonUasLogon(p, mem_ctx)) {
1592 if (!test_LogonUasLogoff(p, mem_ctx)) {
1596 if (!test_SetPassword(p, mem_ctx)) {
1600 if (!test_SamLogon(p, mem_ctx)) {
1604 if (!test_DatabaseSync(p, mem_ctx)) {
1608 if (!test_DatabaseDeltas(p, mem_ctx)) {
1612 if (!test_AccountDeltas(p, mem_ctx)) {
1616 if (!test_AccountSync(p, mem_ctx)) {
1620 if (!test_GetDcName(p, mem_ctx)) {
1624 if (!test_LogonControl(p, mem_ctx)) {
1628 if (!test_GetAnyDCName(p, mem_ctx)) {
1632 if (!test_LogonControl2(p, mem_ctx)) {
1636 if (!test_DatabaseSync2(p, mem_ctx)) {
1640 if (!test_LogonControl2Ex(p, mem_ctx)) {
1644 torture_rpc_close(p);
1646 if (!leave_domain_bdc(mem_ctx)) {
1647 printf("Failed to delete BDC machine account\n");