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"
30 /* for the timebeing, use the same neg flags as Samba3. */
31 /* The 7 here seems to be required to get Win2k not to downgrade us
32 to NT4. Actually, anything other than 1ff would seem to do... */
33 #define NETLOGON_NEG_AUTH2_FLAGS 0x000701ff
35 #define NETLOGON_NEG_SCHANNEL 0x40000000
39 struct dcerpc_pipe *p;
40 const char *machine_password;
41 struct policy_handle acct_handle;
45 join the domain as a BDC
47 static BOOL join_domain_bdc(TALLOC_CTX *mem_ctx)
50 struct samr_Connect c;
51 struct samr_CreateUser2 r;
52 struct samr_OpenDomain o;
53 struct samr_LookupDomain l;
54 struct samr_SetUserInfo s;
55 union samr_UserInfo u;
56 struct policy_handle handle;
57 struct policy_handle domain_handle;
58 uint32 access_granted;
61 DATA_BLOB session_key;
62 struct samr_Name name;
64 printf("Connecting to SAMR\n");
66 status = torture_rpc_connection(&join.p,
70 if (!NT_STATUS_IS_OK(status)) {
74 c.in.system_name = NULL;
75 c.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
76 c.out.handle = &handle;
78 status = dcerpc_samr_Connect(join.p, mem_ctx, &c);
79 if (!NT_STATUS_IS_OK(status)) {
80 printf("samr_Connect failed - %s\n", nt_errstr(status));
84 printf("Opening domain %s\n", lp_workgroup());
86 name.name = lp_workgroup();
87 l.in.handle = &handle;
90 status = dcerpc_samr_LookupDomain(join.p, mem_ctx, &l);
91 if (!NT_STATUS_IS_OK(status)) {
92 printf("LookupDomain failed - %s\n", nt_errstr(status));
96 o.in.handle = &handle;
97 o.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
99 o.out.domain_handle = &domain_handle;
101 status = dcerpc_samr_OpenDomain(join.p, mem_ctx, &o);
102 if (!NT_STATUS_IS_OK(status)) {
103 printf("OpenDomain failed - %s\n", nt_errstr(status));
107 printf("Creating machine account %s\n", TEST_MACHINE_NAME);
110 name.name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
111 r.in.handle = &domain_handle;
112 r.in.username = &name;
113 r.in.acct_flags = ACB_SVRTRUST;
114 r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
115 r.out.acct_handle = &join.acct_handle;
116 r.out.access_granted = &access_granted;
119 status = dcerpc_samr_CreateUser2(join.p, mem_ctx, &r);
121 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS) &&
122 test_DeleteUser_byname(join.p, mem_ctx, &domain_handle, name.name)) {
126 if (!NT_STATUS_IS_OK(status)) {
127 printf("CreateUser2 failed - %s\n", nt_errstr(status));
131 join.machine_password = generate_random_str(8);
133 printf("Setting machine account password '%s'\n", join.machine_password);
135 s.in.handle = &join.acct_handle;
139 encode_pw_buffer(u.info24.password.data, join.machine_password, STR_UNICODE);
140 u.info24.pw_len = strlen(join.machine_password);
142 status = dcerpc_fetch_session_key(join.p, &session_key);
143 if (!NT_STATUS_IS_OK(status)) {
144 printf("SetUserInfo level %u - no session key - %s\n",
145 s.in.level, nt_errstr(status));
149 SamOEMhashBlob(u.info24.password.data, 516, &session_key);
151 status = dcerpc_samr_SetUserInfo(join.p, mem_ctx, &s);
152 if (!NT_STATUS_IS_OK(status)) {
153 printf("SetUserInfo failed - %s\n", nt_errstr(status));
157 s.in.handle = &join.acct_handle;
161 u.info16.acct_flags = ACB_SVRTRUST;
163 printf("Resetting ACB flags\n");
165 status = dcerpc_samr_SetUserInfo(join.p, mem_ctx, &s);
166 if (!NT_STATUS_IS_OK(status)) {
167 printf("SetUserInfo failed - %s\n", nt_errstr(status));
175 leave the domain as a BDC
177 static BOOL leave_domain_bdc(TALLOC_CTX *mem_ctx)
179 struct samr_DeleteUser d;
182 d.in.handle = &join.acct_handle;
183 d.out.handle = &join.acct_handle;
185 status = dcerpc_samr_DeleteUser(join.p, mem_ctx, &d);
186 if (!NT_STATUS_IS_OK(status)) {
187 printf("Delete of machine account failed\n");
194 static BOOL test_LogonUasLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
197 struct netr_LogonUasLogon r;
199 r.in.server_name = NULL;
200 r.in.username = lp_parm_string(-1, "torture", "username");
201 r.in.workstation = TEST_MACHINE_NAME;
203 printf("Testing LogonUasLogon\n");
205 status = dcerpc_netr_LogonUasLogon(p, mem_ctx, &r);
206 if (!NT_STATUS_IS_OK(status)) {
207 printf("LogonUasLogon - %s\n", nt_errstr(status));
215 static BOOL test_LogonUasLogoff(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
218 struct netr_LogonUasLogoff r;
220 r.in.server_name = NULL;
221 r.in.username = lp_parm_string(-1, "torture", "username");
222 r.in.workstation = TEST_MACHINE_NAME;
224 printf("Testing LogonUasLogoff\n");
226 status = dcerpc_netr_LogonUasLogoff(p, mem_ctx, &r);
227 if (!NT_STATUS_IS_OK(status)) {
228 printf("LogonUasLogoff - %s\n", nt_errstr(status));
236 static BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
237 struct creds_CredentialState *creds)
240 struct netr_ServerReqChallenge r;
241 struct netr_ServerAuthenticate a;
242 const char *plain_pass;
245 printf("Testing ServerReqChallenge\n");
247 r.in.server_name = NULL;
248 r.in.computer_name = TEST_MACHINE_NAME;
249 generate_random_buffer(r.in.credentials.data, sizeof(r.in.credentials.data), False);
251 status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
252 if (!NT_STATUS_IS_OK(status)) {
253 printf("ServerReqChallenge - %s\n", nt_errstr(status));
257 plain_pass = join.machine_password;
259 printf("Unable to fetch machine password!\n");
263 E_md4hash(plain_pass, mach_pwd);
265 creds_client_init(creds, &r.in.credentials, &r.out.credentials, mach_pwd,
268 a.in.server_name = NULL;
269 a.in.username = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
270 a.in.secure_channel_type = SEC_CHAN_BDC;
271 a.in.computer_name = TEST_MACHINE_NAME;
273 printf("Testing ServerAuthenticate\n");
275 status = dcerpc_netr_ServerAuthenticate(p, mem_ctx, &a);
276 if (!NT_STATUS_IS_OK(status)) {
277 printf("ServerAuthenticate - %s\n", nt_errstr(status));
281 if (!creds_client_check(creds, &a.out.credentials)) {
282 printf("Credential chaining failed\n");
289 static BOOL test_SetupCredentials2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
290 uint32 negotiate_flags,
291 struct creds_CredentialState *creds)
294 struct netr_ServerReqChallenge r;
295 struct netr_ServerAuthenticate2 a;
296 const char *plain_pass;
299 printf("Testing ServerReqChallenge\n");
301 r.in.server_name = NULL;
302 r.in.computer_name = TEST_MACHINE_NAME;
303 generate_random_buffer(r.in.credentials.data, sizeof(r.in.credentials.data), False);
305 status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
306 if (!NT_STATUS_IS_OK(status)) {
307 printf("ServerReqChallenge - %s\n", nt_errstr(status));
311 plain_pass = join.machine_password;
313 printf("Unable to fetch machine password!\n");
317 E_md4hash(plain_pass, mach_pwd);
319 creds_client_init(creds, &r.in.credentials, &r.out.credentials, mach_pwd,
322 a.in.server_name = NULL;
323 a.in.username = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
324 a.in.secure_channel_type = SEC_CHAN_BDC;
325 a.in.computer_name = TEST_MACHINE_NAME;
326 a.in.negotiate_flags = &negotiate_flags;
327 a.out.negotiate_flags = &negotiate_flags;
329 printf("Testing ServerAuthenticate2\n");
331 status = dcerpc_netr_ServerAuthenticate2(p, mem_ctx, &a);
332 if (!NT_STATUS_IS_OK(status)) {
333 printf("ServerAuthenticate2 - %s\n", nt_errstr(status));
337 if (!creds_client_check(creds, &a.out.credentials)) {
338 printf("Credential chaining failed\n");
342 printf("negotiate_flags=0x%08x\n", negotiate_flags);
355 struct samlogon_state {
357 const char *username;
358 const char *password;
359 struct dcerpc_pipe *p;
360 struct netr_LogonSamLogon r;
361 struct netr_Authenticator auth, auth2;
362 struct creds_CredentialState creds;
367 Authenticate a user with a challenge/response, checking session key
368 and valid authentication types
371 static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
372 enum ntlm_break break_which,
374 DATA_BLOB *lm_response,
375 DATA_BLOB *nt_response,
377 uint8 user_session_key[16],
381 struct netr_LogonSamLogon *r = &samlogon_state->r;
383 struct netr_NetworkInfo ninfo;
384 samlogon_state->r.in.logon_level = 2;
385 samlogon_state->r.in.logon.network = &ninfo;
387 ninfo.logon_info.domain_name.string = lp_workgroup();
388 ninfo.logon_info.parameter_control = 0;
389 ninfo.logon_info.logon_id_low = 0;
390 ninfo.logon_info.logon_id_high = 0;
391 ninfo.logon_info.username.string = samlogon_state->username;
392 ninfo.logon_info.workstation.string = TEST_MACHINE_NAME;
394 memcpy(ninfo.challenge, chall->data, 8);
396 switch (break_which) {
400 if (lm_response && lm_response->data) {
401 lm_response->data[0]++;
405 if (nt_response && nt_response->data) {
406 nt_response->data[0]++;
410 data_blob_free(lm_response);
413 data_blob_free(nt_response);
418 ninfo.nt.data = nt_response->data;
419 ninfo.nt.length = nt_response->length;
421 ninfo.nt.data = NULL;
426 ninfo.lm.data = lm_response->data;
427 ninfo.lm.length = lm_response->length;
429 ninfo.lm.data = NULL;
433 ZERO_STRUCT(samlogon_state->auth2);
434 creds_client_authenticator(&samlogon_state->creds, &samlogon_state->auth);
436 status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
437 if (!NT_STATUS_IS_OK(status)) {
439 *error_string = strdup(nt_errstr(status));
443 if (!creds_client_check(&samlogon_state->creds, &r->out.authenticator->cred)) {
444 printf("Credential chaining failed\n");
447 if (!NT_STATUS_IS_OK(status)) {
448 /* we cannot check the session key, if the logon failed... */
452 /* find and decyrpt the session keys, return in parameters above */
453 if (r->in.validation_level == 2) {
454 static const char zeros[16];
456 if (memcmp(r->out.validation.sam->LMSessKey.key, zeros, sizeof(r->out.validation.sam->LMSessKey.key)) != 0) {
457 creds_arcfour_crypt(&samlogon_state->creds,
458 r->out.validation.sam->LMSessKey.key,
459 sizeof(r->out.validation.sam->LMSessKey.key));
463 memcpy(lm_key, r->out.validation.sam->LMSessKey.key, 8);
466 if (memcmp(r->out.validation.sam->key.key, zeros, sizeof(r->out.validation.sam->key.key)) != 0) {
467 creds_arcfour_crypt(&samlogon_state->creds,
468 r->out.validation.sam->key.key,
469 sizeof(r->out.validation.sam->key.key));
472 if (user_session_key) {
473 memcpy(user_session_key, r->out.validation.sam->key.key, 16);
476 } else if (r->in.validation_level == 3) {
477 static const char zeros[16];
478 if (memcmp(r->out.validation.sam2->LMSessKey.key, zeros, sizeof(r->out.validation.sam2->LMSessKey.key)) != 0) {
479 creds_arcfour_crypt(&samlogon_state->creds,
480 r->out.validation.sam2->LMSessKey.key,
481 sizeof(r->out.validation.sam2->LMSessKey.key));
485 memcpy(lm_key, r->out.validation.sam2->LMSessKey.key, 8);
488 if (memcmp(r->out.validation.sam2->key.key, zeros, sizeof(r->out.validation.sam2->key.key)) != 0) {
489 creds_arcfour_crypt(&samlogon_state->creds,
490 r->out.validation.sam2->key.key,
491 sizeof(r->out.validation.sam2->key.key));
494 if (user_session_key) {
495 memcpy(user_session_key, r->out.validation.sam2->key.key, 16);
503 * Test the normal 'LM and NTLM' combination
506 static BOOL test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
510 DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
511 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
512 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
515 uchar user_session_key[16];
520 ZERO_STRUCT(user_session_key);
522 SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
523 E_deshash(samlogon_state->password, lm_hash);
525 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
527 E_md4hash(samlogon_state->password, nt_hash);
528 SMBsesskeygen_ntv1(nt_hash, session_key.data);
530 nt_status = check_samlogon(samlogon_state,
532 &samlogon_state->chall,
539 data_blob_free(&lm_response);
541 if (!NT_STATUS_IS_OK(nt_status)) {
542 return break_which == BREAK_NT;
545 if (memcmp(lm_hash, lm_key,
546 sizeof(lm_key)) != 0) {
547 printf("LM Key does not match expectations!\n");
549 dump_data(1, (const char *)lm_key, 8);
550 printf("expected:\n");
551 dump_data(1, (const char *)lm_hash, 8);
555 if (break_which == NO_NT) {
556 char lm_key_expected[16];
557 memcpy(lm_key_expected, lm_hash, 8);
558 memset(lm_key_expected+8, '\0', 8);
559 if (memcmp(lm_key_expected, user_session_key,
561 printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
562 printf("user_session_key:\n");
563 dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
564 printf("expected:\n");
565 dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
569 if (memcmp(session_key.data, user_session_key,
570 sizeof(user_session_key)) != 0) {
571 printf("NT Session Key does not match expectations!\n");
572 printf("user_session_key:\n");
573 dump_data(1, (const char *)user_session_key, 16);
574 printf("expected:\n");
575 dump_data(1, (const char *)session_key.data, session_key.length);
583 * Test LM authentication, no NT response supplied
586 static BOOL test_lm(struct samlogon_state *samlogon_state, char **error_string)
589 return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
593 * Test the NTLM response only, no LM.
596 static BOOL test_ntlm(struct samlogon_state *samlogon_state, char **error_string)
598 return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
602 * Test the NTLM response only, but in the LM field.
605 static BOOL test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string)
609 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
613 uchar user_session_key[16];
615 ZERO_STRUCT(user_session_key);
617 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
619 E_deshash(samlogon_state->password, lm_hash);
621 nt_status = check_samlogon(samlogon_state,
623 &samlogon_state->chall,
630 if (!NT_STATUS_IS_OK(nt_status)) {
634 if (memcmp(lm_hash, lm_key,
635 sizeof(lm_key)) != 0) {
636 printf("LM Key does not match expectations!\n");
638 dump_data(1, (const char *)lm_key, 8);
639 printf("expected:\n");
640 dump_data(1, (const char *)lm_hash, 8);
643 if (memcmp(lm_hash, user_session_key, 8) != 0) {
644 char lm_key_expected[16];
645 memcpy(lm_key_expected, lm_hash, 8);
646 memset(lm_key_expected+8, '\0', 8);
647 if (memcmp(lm_key_expected, user_session_key,
649 printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
650 printf("user_session_key:\n");
651 dump_data(1, (const char *)user_session_key, sizeof(user_session_key));
652 printf("expected:\n");
653 dump_data(1, (const char *)lm_key_expected, sizeof(lm_key_expected));
661 * Test the NTLM response only, but in the both the NT and LM fields.
664 static BOOL test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string)
668 DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
669 DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
673 char user_session_key[16];
677 ZERO_STRUCT(user_session_key);
679 SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data,
681 E_md4hash(samlogon_state->password, (unsigned char *)nt_hash);
682 SMBsesskeygen_ntv1((const unsigned char *)nt_hash,
685 E_deshash(samlogon_state->password, (unsigned char *)lm_hash);
687 nt_status = check_samlogon(samlogon_state,
689 &samlogon_state->chall,
696 if (!NT_STATUS_IS_OK(nt_status)) {
700 if (memcmp(lm_hash, lm_key,
701 sizeof(lm_key)) != 0) {
702 printf("LM Key does not match expectations!\n");
704 dump_data(1, lm_key, 8);
705 printf("expected:\n");
706 dump_data(1, lm_hash, 8);
709 if (memcmp(session_key.data, user_session_key,
710 sizeof(user_session_key)) != 0) {
711 printf("NT Session Key does not match expectations!\n");
712 printf("user_session_key:\n");
713 dump_data(1, user_session_key, 16);
714 printf("expected:\n");
715 dump_data(1, (const char *)session_key.data, session_key.length);
724 * Test the NTLMv2 and LMv2 responses
727 static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
731 DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
732 DATA_BLOB lmv2_response = data_blob(NULL, 0);
733 DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
734 DATA_BLOB names_blob = NTLMv2_generate_names_blob(lp_netbios_name(), lp_workgroup());
736 uchar user_session_key[16];
738 ZERO_STRUCT(user_session_key);
740 if (!SMBNTLMv2encrypt(samlogon_state->username, lp_workgroup(), samlogon_state->password, &samlogon_state->chall,
742 &lmv2_response, &ntlmv2_response,
743 &ntlmv2_session_key)) {
744 data_blob_free(&names_blob);
747 data_blob_free(&names_blob);
749 nt_status = check_samlogon(samlogon_state,
751 &samlogon_state->chall,
758 data_blob_free(&lmv2_response);
759 data_blob_free(&ntlmv2_response);
761 if (!NT_STATUS_IS_OK(nt_status)) {
762 return break_which == BREAK_NT;
765 if (break_which != NO_NT && break_which != BREAK_NT && memcmp(ntlmv2_session_key.data, user_session_key,
766 sizeof(user_session_key)) != 0) {
767 printf("USER (NTLMv2) Session Key does not match expectations!\n");
768 printf("user_session_key:\n");
769 dump_data(1, (const char *)user_session_key, 16);
770 printf("expected:\n");
771 dump_data(1, (const char *)ntlmv2_session_key.data, ntlmv2_session_key.length);
778 * Test the NTLMv2 and LMv2 responses
781 static BOOL test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
783 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, error_string);
787 * Test the LMv2 response only
790 static BOOL test_lmv2(struct samlogon_state *samlogon_state, char **error_string)
792 return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, error_string);
796 * Test the NTLMv2 response only
799 static BOOL test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string)
801 return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, error_string);
804 static BOOL test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string)
806 return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
809 static BOOL test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string)
811 return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
814 static BOOL test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string)
816 return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
819 static BOOL test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
821 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, error_string);
824 static BOOL test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string)
826 return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, error_string);
829 static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
832 DATA_BLOB nt_response = data_blob(NULL, 0);
833 DATA_BLOB lm_response = data_blob(NULL, 0);
836 smb_ucs2_t *unicodepw;
838 uchar user_session_key[16];
840 static const uchar zeros[8];
841 DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
843 ZERO_STRUCT(user_session_key);
845 if ((push_ucs2_talloc(samlogon_state->mem_ctx, (smb_ucs2_t **)&unicodepw,
846 samlogon_state->password)) == -1) {
847 DEBUG(0, ("push_ucs2_allocate failed!\n"));
851 nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw,
852 strlen_w(((void *)unicodepw))*sizeof(smb_ucs2_t));
854 password = strdup_upper(samlogon_state->password);
856 if ((convert_string_talloc(samlogon_state->mem_ctx, CH_UNIX,
859 (const void**)&dospw)) == -1) {
860 DEBUG(0, ("push_ascii_allocate failed!\n"));
866 lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
868 nt_status = check_samlogon(samlogon_state,
877 if (!NT_STATUS_IS_OK(nt_status)) {
878 return break_which == BREAK_NT;
884 static BOOL test_plaintext_none_broken(struct samlogon_state *samlogon_state,
885 char **error_string) {
886 return test_plaintext(samlogon_state, BREAK_NONE, error_string);
889 static BOOL test_plaintext_lm_broken(struct samlogon_state *samlogon_state,
890 char **error_string) {
891 return test_plaintext(samlogon_state, BREAK_LM, error_string);
894 static BOOL test_plaintext_nt_broken(struct samlogon_state *samlogon_state,
895 char **error_string) {
896 return test_plaintext(samlogon_state, BREAK_NT, error_string);
899 static BOOL test_plaintext_nt_only(struct samlogon_state *samlogon_state,
900 char **error_string) {
901 return test_plaintext(samlogon_state, NO_LM, error_string);
904 static BOOL test_plaintext_lm_only(struct samlogon_state *samlogon_state,
905 char **error_string) {
906 return test_plaintext(samlogon_state, NO_NT, error_string);
920 - plaintext tests (in challenge-response feilds)
922 check we get the correct session key in each case
923 check what values we get for the LM session key
927 static const struct ntlm_tests {
928 BOOL (*fn)(struct samlogon_state *, char **);
932 {test_lm, "LM", False},
933 {test_lm_ntlm, "LM and NTLM", False},
934 {test_ntlm, "NTLM", False},
935 {test_ntlm_in_lm, "NTLM in LM", False},
936 {test_ntlm_in_both, "NTLM in both", False},
937 {test_ntlmv2, "NTLMv2", False},
938 {test_lmv2_ntlmv2, "NTLMv2 and LMv2", False},
939 {test_lmv2, "LMv2", False},
940 {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", False},
941 {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", False},
942 {test_ntlm_lm_broken, "NTLM and LM, LM broken", False},
943 {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", False},
944 {test_plaintext_none_broken, "Plaintext", True},
945 {test_plaintext_lm_broken, "Plaintext LM broken", True},
946 {test_plaintext_nt_broken, "Plaintext NT broken", True},
947 {test_plaintext_nt_only, "Plaintext NT only", True},
948 {test_plaintext_lm_only, "Plaintext LM only", True},
953 try a netlogon SamLogon
955 static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
960 struct samlogon_state samlogon_state;
962 samlogon_state.mem_ctx = mem_ctx;
963 samlogon_state.username = lp_parm_string(-1, "torture", "username");
964 samlogon_state.password = lp_parm_string(-1, "torture", "password");
965 samlogon_state.p = p;
967 samlogon_state.chall = data_blob_talloc(mem_ctx, NULL, 8);
969 generate_random_buffer(samlogon_state.chall.data,
972 if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
976 samlogon_state.r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
977 samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
978 samlogon_state.r.in.credential = &samlogon_state.auth;
979 samlogon_state.r.in.authenticator = &samlogon_state.auth2;
982 samlogon_state.r.in.validation_level = i;
983 for (j=0; test_table[j].fn; j++) {
984 char *error_string = NULL;
985 printf("Testing SamLogon with '%s' at validation level %d\n", test_table[j].name, i);
987 if (!test_table[j].fn(&samlogon_state, &error_string)) {
988 if (test_table[j].expect_fail) {
989 printf("Test %s failed (expected, test incomplete): %s\n", test_table[j].name, error_string);
991 printf("Test %s failed: %s\n", test_table[j].name, error_string);
994 SAFE_FREE(error_string);
1004 try a change password for our machine account
1006 static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1009 struct netr_ServerPasswordSet r;
1010 const char *password;
1011 struct creds_CredentialState creds;
1013 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1017 r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1018 r.in.username = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
1019 r.in.secure_channel_type = SEC_CHAN_BDC;
1020 r.in.computer_name = TEST_MACHINE_NAME;
1022 password = generate_random_str(8);
1023 E_md4hash(password, r.in.new_password.data);
1025 creds_des_encrypt(&creds, &r.in.new_password);
1027 printf("Testing ServerPasswordSet on machine account\n");
1029 creds_client_authenticator(&creds, &r.in.credential);
1031 status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
1032 if (!NT_STATUS_IS_OK(status)) {
1033 printf("ServerPasswordSet - %s\n", nt_errstr(status));
1037 join.machine_password = password;
1039 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1040 printf("Credential chaining failed\n");
1043 /* by changing the machine password twice we test the credentials
1045 printf("Testing a second ServerPasswordSet on machine account\n");
1047 creds_client_authenticator(&creds, &r.in.credential);
1049 status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
1050 if (!NT_STATUS_IS_OK(status)) {
1051 printf("ServerPasswordSet - %s\n", nt_errstr(status));
1055 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1056 printf("Credential chaining failed\n");
1063 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
1064 static struct ULONG8 sequence_nums[3];
1067 try a netlogon DatabaseSync
1069 static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1072 struct netr_DatabaseSync r;
1073 struct creds_CredentialState creds;
1074 const uint32 database_ids[] = {0, 1, 2};
1078 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1082 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1083 r.in.computername = TEST_MACHINE_NAME;
1084 r.in.preferredmaximumlength = (uint32)-1;
1085 ZERO_STRUCT(r.in.return_authenticator);
1087 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1088 r.in.sync_context = 0;
1089 r.in.database_id = database_ids[i];
1091 printf("Testing DatabaseSync of id %d\n", r.in.database_id);
1094 creds_client_authenticator(&creds, &r.in.credential);
1096 status = dcerpc_netr_DatabaseSync(p, mem_ctx, &r);
1097 if (!NT_STATUS_IS_OK(status) &&
1098 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1099 printf("DatabaseSync - %s\n", nt_errstr(status));
1104 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1105 printf("Credential chaining failed\n");
1108 r.in.sync_context = r.out.sync_context;
1110 if (r.out.delta_enum_array &&
1111 r.out.delta_enum_array->num_deltas > 0 &&
1112 r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
1113 r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
1114 sequence_nums[r.in.database_id] =
1115 r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
1116 printf("\tsequence_nums[%d]=0x%08x%08x\n",
1118 sequence_nums[r.in.database_id].high,
1119 sequence_nums[r.in.database_id].low);
1121 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1129 try a netlogon DatabaseDeltas
1131 static BOOL test_DatabaseDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1134 struct netr_DatabaseDeltas r;
1135 struct creds_CredentialState creds;
1136 const uint32 database_ids[] = {0, 1, 2};
1140 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1144 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1145 r.in.computername = TEST_MACHINE_NAME;
1146 r.in.preferredmaximumlength = (uint32)-1;
1147 ZERO_STRUCT(r.in.return_authenticator);
1149 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1150 r.in.database_id = database_ids[i];
1151 r.in.sequence_num = sequence_nums[r.in.database_id];
1153 if (r.in.sequence_num.low == 0) continue;
1155 r.in.sequence_num.low -= 1;
1158 printf("Testing DatabaseDeltas of id %d at %d\n",
1159 r.in.database_id, r.in.sequence_num.low);
1162 creds_client_authenticator(&creds, &r.in.credential);
1164 status = dcerpc_netr_DatabaseDeltas(p, mem_ctx, &r);
1165 if (!NT_STATUS_IS_OK(status) &&
1166 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1167 printf("DatabaseDeltas - %s\n", nt_errstr(status));
1172 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1173 printf("Credential chaining failed\n");
1176 r.in.sequence_num.low++;
1177 r.in.sequence_num.high = 0;
1178 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1186 try a netlogon AccountDeltas
1188 static BOOL test_AccountDeltas(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1191 struct netr_AccountDeltas r;
1192 struct creds_CredentialState creds;
1195 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1199 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1200 r.in.computername = TEST_MACHINE_NAME;
1201 ZERO_STRUCT(r.in.return_authenticator);
1202 creds_client_authenticator(&creds, &r.in.credential);
1203 ZERO_STRUCT(r.in.uas);
1206 r.in.buffersize=100;
1208 printf("Testing AccountDeltas\n");
1210 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1211 status = dcerpc_netr_AccountDeltas(p, mem_ctx, &r);
1212 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1213 printf("AccountDeltas - %s\n", nt_errstr(status));
1221 try a netlogon AccountSync
1223 static BOOL test_AccountSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1226 struct netr_AccountSync r;
1227 struct creds_CredentialState creds;
1230 if (!test_SetupCredentials(p, mem_ctx, &creds)) {
1234 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1235 r.in.computername = TEST_MACHINE_NAME;
1236 ZERO_STRUCT(r.in.return_authenticator);
1237 creds_client_authenticator(&creds, &r.in.credential);
1238 ZERO_STRUCT(r.in.recordid);
1241 r.in.buffersize=100;
1243 printf("Testing AccountSync\n");
1245 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1246 status = dcerpc_netr_AccountSync(p, mem_ctx, &r);
1247 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
1248 printf("AccountSync - %s\n", nt_errstr(status));
1256 try a netlogon GetDcName
1258 static BOOL test_GetDcName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1261 struct netr_GetDcName r;
1263 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1264 r.in.domainname = lp_workgroup();
1266 printf("Testing GetDcName\n");
1268 status = dcerpc_netr_GetDcName(p, mem_ctx, &r);
1269 if (!NT_STATUS_IS_OK(status)) {
1270 printf("GetDcName - %s\n", nt_errstr(status));
1274 printf("\tDC is at '%s'\n", r.out.dcname);
1280 try a netlogon LogonControl
1282 static BOOL test_LogonControl(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1285 struct netr_LogonControl r;
1289 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1290 r.in.function_code = 1;
1295 printf("Testing LogonControl level %d\n", i);
1297 status = dcerpc_netr_LogonControl(p, mem_ctx, &r);
1298 if (!NT_STATUS_IS_OK(status)) {
1299 printf("LogonControl - %s\n", nt_errstr(status));
1309 try a netlogon GetAnyDCName
1311 static BOOL test_GetAnyDCName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1314 struct netr_GetAnyDCName r;
1316 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1317 r.in.domainname = lp_workgroup();
1319 printf("Testing GetAnyDCName\n");
1321 status = dcerpc_netr_GetAnyDCName(p, mem_ctx, &r);
1322 if (!NT_STATUS_IS_OK(status)) {
1323 printf("GetAnyDCName - %s\n", nt_errstr(status));
1328 printf("\tDC is at '%s'\n", r.out.dcname);
1336 try a netlogon LogonControl2
1338 static BOOL test_LogonControl2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1341 struct netr_LogonControl2 r;
1345 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1347 r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1348 r.in.data.domain = lp_workgroup();
1353 printf("Testing LogonControl2 level %d function %d\n",
1354 i, r.in.function_code);
1356 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1357 if (!NT_STATUS_IS_OK(status)) {
1358 printf("LogonControl - %s\n", nt_errstr(status));
1363 r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1364 r.in.data.domain = lp_workgroup();
1369 printf("Testing LogonControl2 level %d function %d\n",
1370 i, r.in.function_code);
1372 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1373 if (!NT_STATUS_IS_OK(status)) {
1374 printf("LogonControl - %s\n", nt_errstr(status));
1379 r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1380 r.in.data.domain = lp_workgroup();
1385 printf("Testing LogonControl2 level %d function %d\n",
1386 i, r.in.function_code);
1388 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1389 if (!NT_STATUS_IS_OK(status)) {
1390 printf("LogonControl - %s\n", nt_errstr(status));
1395 r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1396 r.in.data.debug_level = ~0;
1401 printf("Testing LogonControl2 level %d function %d\n",
1402 i, r.in.function_code);
1404 status = dcerpc_netr_LogonControl2(p, mem_ctx, &r);
1405 if (!NT_STATUS_IS_OK(status)) {
1406 printf("LogonControl - %s\n", nt_errstr(status));
1415 try a netlogon DatabaseSync2
1417 static BOOL test_DatabaseSync2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1420 struct netr_DatabaseSync2 r;
1421 struct creds_CredentialState creds;
1422 const uint32 database_ids[] = {0, 1, 2};
1426 if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &creds)) {
1430 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1431 r.in.computername = TEST_MACHINE_NAME;
1432 r.in.preferredmaximumlength = (uint32)-1;
1433 ZERO_STRUCT(r.in.return_authenticator);
1435 for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1436 r.in.sync_context = 0;
1437 r.in.database_id = database_ids[i];
1438 r.in.restart_state = 0;
1440 printf("Testing DatabaseSync2 of id %d\n", r.in.database_id);
1443 creds_client_authenticator(&creds, &r.in.credential);
1445 status = dcerpc_netr_DatabaseSync2(p, mem_ctx, &r);
1446 if (!NT_STATUS_IS_OK(status) &&
1447 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1448 printf("DatabaseSync2 - %s\n", nt_errstr(status));
1453 if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
1454 printf("Credential chaining failed\n");
1457 r.in.sync_context = r.out.sync_context;
1458 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1466 try a netlogon LogonControl2Ex
1468 static BOOL test_LogonControl2Ex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1471 struct netr_LogonControl2Ex r;
1475 r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1477 r.in.function_code = NETLOGON_CONTROL_REDISCOVER;
1478 r.in.data.domain = lp_workgroup();
1483 printf("Testing LogonControl2Ex level %d function %d\n",
1484 i, r.in.function_code);
1486 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1487 if (!NT_STATUS_IS_OK(status)) {
1488 printf("LogonControl - %s\n", nt_errstr(status));
1493 r.in.function_code = NETLOGON_CONTROL_TC_QUERY;
1494 r.in.data.domain = lp_workgroup();
1499 printf("Testing LogonControl2Ex level %d function %d\n",
1500 i, r.in.function_code);
1502 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1503 if (!NT_STATUS_IS_OK(status)) {
1504 printf("LogonControl - %s\n", nt_errstr(status));
1509 r.in.function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY;
1510 r.in.data.domain = lp_workgroup();
1515 printf("Testing LogonControl2Ex level %d function %d\n",
1516 i, r.in.function_code);
1518 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1519 if (!NT_STATUS_IS_OK(status)) {
1520 printf("LogonControl - %s\n", nt_errstr(status));
1525 r.in.function_code = NETLOGON_CONTROL_SET_DBFLAG;
1526 r.in.data.debug_level = ~0;
1531 printf("Testing LogonControl2Ex level %d function %d\n",
1532 i, r.in.function_code);
1534 status = dcerpc_netr_LogonControl2Ex(p, mem_ctx, &r);
1535 if (!NT_STATUS_IS_OK(status)) {
1536 printf("LogonControl - %s\n", nt_errstr(status));
1546 BOOL torture_rpc_netlogon(int dummy)
1549 struct dcerpc_pipe *p;
1550 TALLOC_CTX *mem_ctx;
1553 mem_ctx = talloc_init("torture_rpc_netlogon");
1555 if (!join_domain_bdc(mem_ctx)) {
1556 printf("Failed to join as BDC\n");
1560 status = torture_rpc_connection(&p,
1561 DCERPC_NETLOGON_NAME,
1562 DCERPC_NETLOGON_UUID,
1563 DCERPC_NETLOGON_VERSION);
1564 if (!NT_STATUS_IS_OK(status)) {
1568 if (!test_LogonUasLogon(p, mem_ctx)) {
1572 if (!test_LogonUasLogoff(p, mem_ctx)) {
1576 if (!test_SetPassword(p, mem_ctx)) {
1580 if (!test_SamLogon(p, mem_ctx)) {
1584 if (!test_DatabaseSync(p, mem_ctx)) {
1588 if (!test_DatabaseDeltas(p, mem_ctx)) {
1592 if (!test_AccountDeltas(p, mem_ctx)) {
1596 if (!test_AccountSync(p, mem_ctx)) {
1600 if (!test_GetDcName(p, mem_ctx)) {
1604 if (!test_LogonControl(p, mem_ctx)) {
1608 if (!test_GetAnyDCName(p, mem_ctx)) {
1612 if (!test_LogonControl2(p, mem_ctx)) {
1616 if (!test_DatabaseSync2(p, mem_ctx)) {
1620 if (!test_LogonControl2Ex(p, mem_ctx)) {
1624 torture_rpc_close(p);
1626 if (!leave_domain_bdc(mem_ctx)) {
1627 printf("Failed to delete BDC machine account\n");