2 Unix SMB/CIFS implementation.
4 dcerpc torture tests, designed to walk Samba3 code paths
6 Copyright (C) Volker Lendecke 2006
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "libcli/raw/libcliraw.h"
25 #include "libcli/rap/rap.h"
26 #include "torture/torture.h"
27 #include "torture/util.h"
28 #include "torture/rap/proto.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "librpc/gen_ndr/ndr_lsa_c.h"
31 #include "librpc/gen_ndr/ndr_samr.h"
32 #include "librpc/gen_ndr/ndr_samr_c.h"
33 #include "librpc/gen_ndr/ndr_netlogon.h"
34 #include "librpc/gen_ndr/ndr_netlogon_c.h"
35 #include "librpc/gen_ndr/ndr_srvsvc.h"
36 #include "librpc/gen_ndr/ndr_srvsvc_c.h"
37 #include "librpc/gen_ndr/ndr_spoolss.h"
38 #include "librpc/gen_ndr/ndr_spoolss_c.h"
39 #include "librpc/gen_ndr/ndr_winreg.h"
40 #include "librpc/gen_ndr/ndr_winreg_c.h"
41 #include "librpc/gen_ndr/ndr_wkssvc.h"
42 #include "librpc/gen_ndr/ndr_wkssvc_c.h"
43 #include "lib/cmdline/popt_common.h"
44 #include "librpc/rpc/dcerpc.h"
45 #include "torture/rpc/rpc.h"
46 #include "libcli/libcli.h"
47 #include "libcli/composite/composite.h"
48 #include "libcli/smb_composite/smb_composite.h"
49 #include "libcli/auth/libcli_auth.h"
50 #include "lib/crypto/crypto.h"
51 #include "libcli/security/proto.h"
53 static struct cli_credentials
*create_anon_creds(TALLOC_CTX
*mem_ctx
)
55 struct cli_credentials
*result
;
57 if (!(result
= cli_credentials_init(mem_ctx
))) {
61 cli_credentials_set_conf(result
);
62 cli_credentials_set_anonymous(result
);
68 * This tests a RPC call using an invalid vuid
71 BOOL
torture_bind_authcontext(struct torture_context
*torture
)
76 struct lsa_ObjectAttribute objectattr
;
77 struct lsa_OpenPolicy2 openpolicy
;
78 struct policy_handle handle
;
79 struct lsa_Close close_handle
;
80 struct smbcli_session
*tmp
;
81 struct smbcli_session
*session2
;
82 struct smbcli_state
*cli
;
83 struct dcerpc_pipe
*lsa_pipe
;
84 struct cli_credentials
*anon_creds
;
85 struct smb_composite_sesssetup setup
;
87 mem_ctx
= talloc_init("torture_bind_authcontext");
89 if (mem_ctx
== NULL
) {
90 d_printf("talloc_init failed\n");
94 status
= smbcli_full_connection(mem_ctx
, &cli
,
95 torture_setting_string(torture
, "host", NULL
),
96 "IPC$", NULL
, cmdline_credentials
,
98 if (!NT_STATUS_IS_OK(status
)) {
99 d_printf("smbcli_full_connection failed: %s\n",
104 lsa_pipe
= dcerpc_pipe_init(mem_ctx
, cli
->transport
->socket
->event
.ctx
);
105 if (lsa_pipe
== NULL
) {
106 d_printf("dcerpc_pipe_init failed\n");
110 status
= dcerpc_pipe_open_smb(lsa_pipe
, cli
->tree
, "\\lsarpc");
111 if (!NT_STATUS_IS_OK(status
)) {
112 d_printf("dcerpc_pipe_open_smb failed: %s\n",
117 status
= dcerpc_bind_auth_none(lsa_pipe
, &dcerpc_table_lsarpc
);
118 if (!NT_STATUS_IS_OK(status
)) {
119 d_printf("dcerpc_bind_auth_none failed: %s\n",
124 openpolicy
.in
.system_name
=talloc_asprintf(
125 mem_ctx
, "\\\\%s", dcerpc_server_name(lsa_pipe
));
126 ZERO_STRUCT(objectattr
);
127 openpolicy
.in
.attr
= &objectattr
;
128 openpolicy
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
129 openpolicy
.out
.handle
= &handle
;
131 status
= dcerpc_lsa_OpenPolicy2(lsa_pipe
, mem_ctx
, &openpolicy
);
133 if (!NT_STATUS_IS_OK(status
)) {
134 d_printf("dcerpc_lsa_OpenPolicy2 failed: %s\n",
139 close_handle
.in
.handle
= &handle
;
140 close_handle
.out
.handle
= &handle
;
142 status
= dcerpc_lsa_Close(lsa_pipe
, mem_ctx
, &close_handle
);
143 if (!NT_STATUS_IS_OK(status
)) {
144 d_printf("dcerpc_lsa_Close failed: %s\n",
149 session2
= smbcli_session_init(cli
->transport
, mem_ctx
, False
);
150 if (session2
== NULL
) {
151 d_printf("smbcli_session_init failed\n");
155 if (!(anon_creds
= create_anon_creds(mem_ctx
))) {
156 d_printf("create_anon_creds failed\n");
160 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
161 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
162 setup
.in
.workgroup
= "";
163 setup
.in
.credentials
= anon_creds
;
165 status
= smb_composite_sesssetup(session2
, &setup
);
166 if (!NT_STATUS_IS_OK(status
)) {
167 d_printf("anon session setup failed: %s\n",
171 session2
->vuid
= setup
.out
.vuid
;
173 tmp
= cli
->tree
->session
;
174 cli
->tree
->session
= session2
;
176 status
= dcerpc_lsa_OpenPolicy2(lsa_pipe
, mem_ctx
, &openpolicy
);
178 cli
->tree
->session
= tmp
;
179 talloc_free(lsa_pipe
);
182 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_HANDLE
)) {
183 d_printf("dcerpc_lsa_OpenPolicy2 with wrong vuid gave %s, "
184 "expected NT_STATUS_INVALID_HANDLE\n",
191 talloc_free(mem_ctx
);
196 * Bind to lsa using a specific auth method
199 static BOOL
bindtest(struct smbcli_state
*cli
,
200 struct cli_credentials
*credentials
,
201 uint8_t auth_type
, uint8_t auth_level
)
207 struct dcerpc_pipe
*lsa_pipe
;
208 struct lsa_ObjectAttribute objectattr
;
209 struct lsa_OpenPolicy2 openpolicy
;
210 struct lsa_QueryInfoPolicy query
;
211 struct policy_handle handle
;
212 struct lsa_Close close_handle
;
214 if ((mem_ctx
= talloc_init("bindtest")) == NULL
) {
215 d_printf("talloc_init failed\n");
219 lsa_pipe
= dcerpc_pipe_init(mem_ctx
,
220 cli
->transport
->socket
->event
.ctx
);
221 if (lsa_pipe
== NULL
) {
222 d_printf("dcerpc_pipe_init failed\n");
226 status
= dcerpc_pipe_open_smb(lsa_pipe
, cli
->tree
, "\\lsarpc");
227 if (!NT_STATUS_IS_OK(status
)) {
228 d_printf("dcerpc_pipe_open_smb failed: %s\n",
233 status
= dcerpc_bind_auth(lsa_pipe
, &dcerpc_table_lsarpc
,
234 credentials
, auth_type
, auth_level
,
236 if (!NT_STATUS_IS_OK(status
)) {
237 d_printf("dcerpc_bind_auth failed: %s\n", nt_errstr(status
));
241 openpolicy
.in
.system_name
=talloc_asprintf(
242 mem_ctx
, "\\\\%s", dcerpc_server_name(lsa_pipe
));
243 ZERO_STRUCT(objectattr
);
244 openpolicy
.in
.attr
= &objectattr
;
245 openpolicy
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
246 openpolicy
.out
.handle
= &handle
;
248 status
= dcerpc_lsa_OpenPolicy2(lsa_pipe
, mem_ctx
, &openpolicy
);
250 if (!NT_STATUS_IS_OK(status
)) {
251 d_printf("dcerpc_lsa_OpenPolicy2 failed: %s\n",
256 query
.in
.handle
= &handle
;
257 query
.in
.level
= LSA_POLICY_INFO_DOMAIN
;
259 status
= dcerpc_lsa_QueryInfoPolicy(lsa_pipe
, mem_ctx
, &query
);
260 if (!NT_STATUS_IS_OK(status
)) {
261 d_printf("dcerpc_lsa_QueryInfoPolicy failed: %s\n",
266 close_handle
.in
.handle
= &handle
;
267 close_handle
.out
.handle
= &handle
;
269 status
= dcerpc_lsa_Close(lsa_pipe
, mem_ctx
, &close_handle
);
270 if (!NT_STATUS_IS_OK(status
)) {
271 d_printf("dcerpc_lsa_Close failed: %s\n",
278 talloc_free(mem_ctx
);
283 * test authenticated RPC binds with the variants Samba3 does support
286 BOOL
torture_bind_samba3(struct torture_context
*torture
)
291 struct smbcli_state
*cli
;
293 mem_ctx
= talloc_init("torture_bind_authcontext");
295 if (mem_ctx
== NULL
) {
296 d_printf("talloc_init failed\n");
300 status
= smbcli_full_connection(mem_ctx
, &cli
,
301 torture_setting_string(torture
, "host", NULL
),
302 "IPC$", NULL
, cmdline_credentials
,
304 if (!NT_STATUS_IS_OK(status
)) {
305 d_printf("smbcli_full_connection failed: %s\n",
312 ret
&= bindtest(cli
, cmdline_credentials
, DCERPC_AUTH_TYPE_NTLMSSP
,
313 DCERPC_AUTH_LEVEL_INTEGRITY
);
314 ret
&= bindtest(cli
, cmdline_credentials
, DCERPC_AUTH_TYPE_NTLMSSP
,
315 DCERPC_AUTH_LEVEL_PRIVACY
);
316 ret
&= bindtest(cli
, cmdline_credentials
, DCERPC_AUTH_TYPE_SPNEGO
,
317 DCERPC_AUTH_LEVEL_INTEGRITY
);
318 ret
&= bindtest(cli
, cmdline_credentials
, DCERPC_AUTH_TYPE_SPNEGO
,
319 DCERPC_AUTH_LEVEL_PRIVACY
);
322 talloc_free(mem_ctx
);
327 * Lookup or create a user and return all necessary info
330 static NTSTATUS
get_usr_handle(struct smbcli_state
*cli
,
332 struct cli_credentials
*admin_creds
,
335 const char *username
,
337 struct dcerpc_pipe
**result_pipe
,
338 struct policy_handle
**result_handle
,
339 struct dom_sid
**sid
)
341 struct dcerpc_pipe
*samr_pipe
;
343 struct policy_handle conn_handle
;
344 struct policy_handle domain_handle
;
345 struct policy_handle
*user_handle
;
346 struct samr_Connect2 conn
;
347 struct samr_EnumDomains enumdom
;
348 uint32_t resume_handle
= 0;
349 struct samr_LookupDomain l
;
351 struct lsa_String domain_name
;
352 struct lsa_String user_name
;
353 struct samr_OpenDomain o
;
354 struct samr_CreateUser2 c
;
355 uint32_t user_rid
,access_granted
;
357 samr_pipe
= dcerpc_pipe_init(mem_ctx
,
358 cli
->transport
->socket
->event
.ctx
);
359 if (samr_pipe
== NULL
) {
360 d_printf("dcerpc_pipe_init failed\n");
361 status
= NT_STATUS_NO_MEMORY
;
365 status
= dcerpc_pipe_open_smb(samr_pipe
, cli
->tree
, "\\samr");
366 if (!NT_STATUS_IS_OK(status
)) {
367 d_printf("dcerpc_pipe_open_smb failed: %s\n",
372 if (admin_creds
!= NULL
) {
373 status
= dcerpc_bind_auth(samr_pipe
, &dcerpc_table_samr
,
374 admin_creds
, auth_type
, auth_level
,
376 if (!NT_STATUS_IS_OK(status
)) {
377 d_printf("dcerpc_bind_auth failed: %s\n",
382 /* We must have an authenticated SMB connection */
383 status
= dcerpc_bind_auth_none(samr_pipe
, &dcerpc_table_samr
);
384 if (!NT_STATUS_IS_OK(status
)) {
385 d_printf("dcerpc_bind_auth_none failed: %s\n",
391 conn
.in
.system_name
= talloc_asprintf(
392 mem_ctx
, "\\\\%s", dcerpc_server_name(samr_pipe
));
393 conn
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
394 conn
.out
.connect_handle
= &conn_handle
;
396 status
= dcerpc_samr_Connect2(samr_pipe
, mem_ctx
, &conn
);
397 if (!NT_STATUS_IS_OK(status
)) {
398 d_printf("samr_Connect2 failed: %s\n", nt_errstr(status
));
402 enumdom
.in
.connect_handle
= &conn_handle
;
403 enumdom
.in
.resume_handle
= &resume_handle
;
404 enumdom
.in
.buf_size
= (uint32_t)-1;
405 enumdom
.out
.resume_handle
= &resume_handle
;
407 status
= dcerpc_samr_EnumDomains(samr_pipe
, mem_ctx
, &enumdom
);
408 if (!NT_STATUS_IS_OK(status
)) {
409 d_printf("samr_EnumDomains failed: %s\n", nt_errstr(status
));
413 if (enumdom
.out
.num_entries
!= 2) {
414 d_printf("samr_EnumDomains returned %d entries, expected 2\n",
415 enumdom
.out
.num_entries
);
416 status
= NT_STATUS_UNSUCCESSFUL
;
420 dom_idx
= strequal(enumdom
.out
.sam
->entries
[0].name
.string
,
423 l
.in
.connect_handle
= &conn_handle
;
424 domain_name
.string
= enumdom
.out
.sam
->entries
[0].name
.string
;
425 *domain
= talloc_strdup(mem_ctx
, domain_name
.string
);
426 l
.in
.domain_name
= &domain_name
;
428 status
= dcerpc_samr_LookupDomain(samr_pipe
, mem_ctx
, &l
);
429 if (!NT_STATUS_IS_OK(status
)) {
430 d_printf("samr_LookupDomain failed: %s\n", nt_errstr(status
));
434 o
.in
.connect_handle
= &conn_handle
;
435 o
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
436 o
.in
.sid
= l
.out
.sid
;
437 o
.out
.domain_handle
= &domain_handle
;
439 status
= dcerpc_samr_OpenDomain(samr_pipe
, mem_ctx
, &o
);
440 if (!NT_STATUS_IS_OK(status
)) {
441 d_printf("samr_OpenDomain failed: %s\n", nt_errstr(status
));
445 c
.in
.domain_handle
= &domain_handle
;
446 user_name
.string
= username
;
447 c
.in
.account_name
= &user_name
;
448 c
.in
.acct_flags
= ACB_NORMAL
;
449 c
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
450 user_handle
= talloc(mem_ctx
, struct policy_handle
);
451 c
.out
.user_handle
= user_handle
;
452 c
.out
.access_granted
= &access_granted
;
453 c
.out
.rid
= &user_rid
;
455 status
= dcerpc_samr_CreateUser2(samr_pipe
, mem_ctx
, &c
);
457 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_EXISTS
)) {
458 struct samr_LookupNames ln
;
459 struct samr_OpenUser ou
;
461 ln
.in
.domain_handle
= &domain_handle
;
463 ln
.in
.names
= &user_name
;
465 status
= dcerpc_samr_LookupNames(samr_pipe
, mem_ctx
, &ln
);
466 if (!NT_STATUS_IS_OK(status
)) {
467 d_printf("samr_LookupNames failed: %s\n",
472 ou
.in
.domain_handle
= &domain_handle
;
473 ou
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
474 user_rid
= ou
.in
.rid
= ln
.out
.rids
.ids
[0];
475 ou
.out
.user_handle
= user_handle
;
477 status
= dcerpc_samr_OpenUser(samr_pipe
, mem_ctx
, &ou
);
478 if (!NT_STATUS_IS_OK(status
)) {
479 d_printf("samr_OpenUser failed: %s\n",
485 if (!NT_STATUS_IS_OK(status
)) {
486 d_printf("samr_CreateUser failed: %s\n", nt_errstr(status
));
490 *result_pipe
= samr_pipe
;
491 *result_handle
= user_handle
;
493 *sid
= dom_sid_add_rid(mem_ctx
, l
.out
.sid
, user_rid
);
505 static BOOL
create_user(TALLOC_CTX
*mem_ctx
, struct smbcli_state
*cli
,
506 struct cli_credentials
*admin_creds
,
507 const char *username
, const char *password
,
509 struct dom_sid
**user_sid
)
513 struct dcerpc_pipe
*samr_pipe
;
514 struct policy_handle
*wks_handle
;
517 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
518 d_printf("talloc_init failed\n");
522 status
= get_usr_handle(cli
, tmp_ctx
, admin_creds
,
523 DCERPC_AUTH_TYPE_NTLMSSP
,
524 DCERPC_AUTH_LEVEL_INTEGRITY
,
525 username
, domain_name
, &samr_pipe
, &wks_handle
,
527 if (!NT_STATUS_IS_OK(status
)) {
528 d_printf("get_wks_handle failed: %s\n", nt_errstr(status
));
533 struct samr_SetUserInfo2 sui2
;
534 struct samr_SetUserInfo sui
;
535 struct samr_QueryUserInfo qui
;
536 union samr_UserInfo u_info
;
537 DATA_BLOB session_key
;
539 encode_pw_buffer(u_info
.info24
.password
.data
, password
,
541 u_info
.info24
.pw_len
= strlen_m(password
)*2;
543 status
= dcerpc_fetch_session_key(samr_pipe
, &session_key
);
544 if (!NT_STATUS_IS_OK(status
)) {
545 d_printf("dcerpc_fetch_session_key failed\n");
548 arcfour_crypt_blob(u_info
.info24
.password
.data
, 516,
550 sui2
.in
.user_handle
= wks_handle
;
551 sui2
.in
.info
= &u_info
;
554 status
= dcerpc_samr_SetUserInfo2(samr_pipe
, tmp_ctx
, &sui2
);
555 if (!NT_STATUS_IS_OK(status
)) {
556 d_printf("samr_SetUserInfo(24) failed: %s\n",
561 u_info
.info16
.acct_flags
= ACB_NORMAL
;
562 sui
.in
.user_handle
= wks_handle
;
563 sui
.in
.info
= &u_info
;
566 status
= dcerpc_samr_SetUserInfo(samr_pipe
, tmp_ctx
, &sui
);
567 if (!NT_STATUS_IS_OK(status
)) {
568 d_printf("samr_SetUserInfo(16) failed\n");
572 qui
.in
.user_handle
= wks_handle
;
575 status
= dcerpc_samr_QueryUserInfo(samr_pipe
, tmp_ctx
, &qui
);
576 if (!NT_STATUS_IS_OK(status
)) {
577 d_printf("samr_QueryUserInfo(21) failed\n");
581 qui
.out
.info
->info21
.allow_password_change
= 0;
582 qui
.out
.info
->info21
.force_password_change
= 0;
583 qui
.out
.info
->info21
.account_name
.string
= NULL
;
584 qui
.out
.info
->info21
.rid
= 0;
585 qui
.out
.info
->info21
.acct_expiry
= 0;
586 qui
.out
.info
->info21
.fields_present
= 0x81827fa; /* copy usrmgr.exe */
588 u_info
.info21
= qui
.out
.info
->info21
;
589 sui
.in
.user_handle
= wks_handle
;
590 sui
.in
.info
= &u_info
;
593 status
= dcerpc_samr_SetUserInfo(samr_pipe
, tmp_ctx
, &sui
);
594 if (!NT_STATUS_IS_OK(status
)) {
595 d_printf("samr_SetUserInfo(21) failed\n");
600 *domain_name
= talloc_steal(mem_ctx
, *domain_name
);
601 *user_sid
= talloc_steal(mem_ctx
, *user_sid
);
604 talloc_free(tmp_ctx
);
612 static BOOL
delete_user(struct smbcli_state
*cli
,
613 struct cli_credentials
*admin_creds
,
614 const char *username
)
619 struct dcerpc_pipe
*samr_pipe
;
620 struct policy_handle
*user_handle
;
623 if ((mem_ctx
= talloc_init("leave")) == NULL
) {
624 d_printf("talloc_init failed\n");
628 status
= get_usr_handle(cli
, mem_ctx
, admin_creds
,
629 DCERPC_AUTH_TYPE_NTLMSSP
,
630 DCERPC_AUTH_LEVEL_INTEGRITY
,
631 username
, &dom_name
, &samr_pipe
,
634 if (!NT_STATUS_IS_OK(status
)) {
635 d_printf("get_wks_handle failed: %s\n", nt_errstr(status
));
640 struct samr_DeleteUser d
;
642 d
.in
.user_handle
= user_handle
;
643 d
.out
.user_handle
= user_handle
;
645 status
= dcerpc_samr_DeleteUser(samr_pipe
, mem_ctx
, &d
);
646 if (!NT_STATUS_IS_OK(status
)) {
647 d_printf("samr_DeleteUser failed\n");
655 talloc_free(mem_ctx
);
660 * Do a Samba3-style join
663 static BOOL
join3(struct smbcli_state
*cli
,
665 struct cli_credentials
*admin_creds
,
666 struct cli_credentials
*wks_creds
)
671 struct dcerpc_pipe
*samr_pipe
;
672 struct policy_handle
*wks_handle
;
675 if ((mem_ctx
= talloc_init("join3")) == NULL
) {
676 d_printf("talloc_init failed\n");
680 status
= get_usr_handle(
681 cli
, mem_ctx
, admin_creds
,
682 DCERPC_AUTH_TYPE_NTLMSSP
,
683 DCERPC_AUTH_LEVEL_PRIVACY
,
684 talloc_asprintf(mem_ctx
, "%s$",
685 cli_credentials_get_workstation(wks_creds
)),
686 &dom_name
, &samr_pipe
, &wks_handle
, NULL
);
688 if (!NT_STATUS_IS_OK(status
)) {
689 d_printf("get_wks_handle failed: %s\n", nt_errstr(status
));
693 cli_credentials_set_domain(wks_creds
, dom_name
, CRED_SPECIFIED
);
696 struct samr_SetUserInfo2 sui2
;
697 union samr_UserInfo u_info
;
698 struct samr_UserInfo21
*i21
= &u_info
.info25
.info
;
699 DATA_BLOB session_key
;
700 DATA_BLOB confounded_session_key
= data_blob_talloc(
702 struct MD5Context ctx
;
703 uint8_t confounder
[16];
707 i21
->full_name
.string
= talloc_asprintf(
709 cli_credentials_get_workstation(wks_creds
));
710 i21
->acct_flags
= ACB_WSTRUST
;
711 i21
->fields_present
= SAMR_FIELD_FULL_NAME
|
712 SAMR_FIELD_ACCT_FLAGS
| SAMR_FIELD_PASSWORD
;
714 encode_pw_buffer(u_info
.info25
.password
.data
,
715 cli_credentials_get_password(wks_creds
),
717 status
= dcerpc_fetch_session_key(samr_pipe
, &session_key
);
718 if (!NT_STATUS_IS_OK(status
)) {
719 d_printf("dcerpc_fetch_session_key failed: %s\n",
723 generate_random_buffer((uint8_t *)confounder
, 16);
726 MD5Update(&ctx
, confounder
, 16);
727 MD5Update(&ctx
, session_key
.data
, session_key
.length
);
728 MD5Final(confounded_session_key
.data
, &ctx
);
730 arcfour_crypt_blob(u_info
.info25
.password
.data
, 516,
731 &confounded_session_key
);
732 memcpy(&u_info
.info25
.password
.data
[516], confounder
, 16);
734 sui2
.in
.user_handle
= wks_handle
;
736 sui2
.in
.info
= &u_info
;
738 status
= dcerpc_samr_SetUserInfo2(samr_pipe
, mem_ctx
, &sui2
);
739 if (!NT_STATUS_IS_OK(status
)) {
740 d_printf("samr_SetUserInfo2(25) failed: %s\n",
745 struct samr_SetUserInfo2 sui2
;
746 struct samr_SetUserInfo sui
;
747 union samr_UserInfo u_info
;
748 DATA_BLOB session_key
;
750 encode_pw_buffer(u_info
.info24
.password
.data
,
751 cli_credentials_get_password(wks_creds
),
753 u_info
.info24
.pw_len
=
754 strlen_m(cli_credentials_get_password(wks_creds
))*2;
756 status
= dcerpc_fetch_session_key(samr_pipe
, &session_key
);
757 if (!NT_STATUS_IS_OK(status
)) {
758 d_printf("dcerpc_fetch_session_key failed\n");
761 arcfour_crypt_blob(u_info
.info24
.password
.data
, 516,
763 sui2
.in
.user_handle
= wks_handle
;
764 sui2
.in
.info
= &u_info
;
767 status
= dcerpc_samr_SetUserInfo2(samr_pipe
, mem_ctx
, &sui2
);
768 if (!NT_STATUS_IS_OK(status
)) {
769 d_printf("samr_SetUserInfo(24) failed: %s\n",
774 u_info
.info16
.acct_flags
= ACB_WSTRUST
;
775 sui
.in
.user_handle
= wks_handle
;
776 sui
.in
.info
= &u_info
;
779 status
= dcerpc_samr_SetUserInfo(samr_pipe
, mem_ctx
, &sui
);
780 if (!NT_STATUS_IS_OK(status
)) {
781 d_printf("samr_SetUserInfo(16) failed\n");
789 talloc_free(mem_ctx
);
794 * Do a ReqChallenge/Auth2 and get the wks creds
797 static BOOL
auth2(struct smbcli_state
*cli
,
798 struct cli_credentials
*wks_cred
)
801 struct dcerpc_pipe
*net_pipe
;
804 struct netr_ServerReqChallenge r
;
805 struct netr_Credential netr_cli_creds
;
806 struct netr_Credential netr_srv_creds
;
807 uint32_t negotiate_flags
;
808 struct netr_ServerAuthenticate2 a
;
809 struct creds_CredentialState
*creds_state
;
810 struct netr_Credential netr_cred
;
811 struct samr_Password mach_pw
;
813 mem_ctx
= talloc_new(NULL
);
814 if (mem_ctx
== NULL
) {
815 d_printf("talloc_new failed\n");
819 net_pipe
= dcerpc_pipe_init(mem_ctx
,
820 cli
->transport
->socket
->event
.ctx
);
821 if (net_pipe
== NULL
) {
822 d_printf("dcerpc_pipe_init failed\n");
826 status
= dcerpc_pipe_open_smb(net_pipe
, cli
->tree
, "\\netlogon");
827 if (!NT_STATUS_IS_OK(status
)) {
828 d_printf("dcerpc_pipe_open_smb failed: %s\n",
833 status
= dcerpc_bind_auth_none(net_pipe
, &dcerpc_table_netlogon
);
834 if (!NT_STATUS_IS_OK(status
)) {
835 d_printf("dcerpc_bind_auth_none failed: %s\n",
840 r
.in
.computer_name
= cli_credentials_get_workstation(wks_cred
);
841 r
.in
.server_name
= talloc_asprintf(
842 mem_ctx
, "\\\\%s", dcerpc_server_name(net_pipe
));
843 if (r
.in
.server_name
== NULL
) {
844 d_printf("talloc_asprintf failed\n");
847 generate_random_buffer(netr_cli_creds
.data
,
848 sizeof(netr_cli_creds
.data
));
849 r
.in
.credentials
= &netr_cli_creds
;
850 r
.out
.credentials
= &netr_srv_creds
;
852 status
= dcerpc_netr_ServerReqChallenge(net_pipe
, mem_ctx
, &r
);
853 if (!NT_STATUS_IS_OK(status
)) {
854 d_printf("netr_ServerReqChallenge failed: %s\n",
859 negotiate_flags
= NETLOGON_NEG_AUTH2_FLAGS
;
860 E_md4hash(cli_credentials_get_password(wks_cred
), mach_pw
.hash
);
862 creds_state
= talloc(mem_ctx
, struct creds_CredentialState
);
863 creds_client_init(creds_state
, r
.in
.credentials
,
864 r
.out
.credentials
, &mach_pw
,
865 &netr_cred
, negotiate_flags
);
867 a
.in
.server_name
= talloc_asprintf(
868 mem_ctx
, "\\\\%s", dcerpc_server_name(net_pipe
));
869 a
.in
.account_name
= talloc_asprintf(
870 mem_ctx
, "%s$", cli_credentials_get_workstation(wks_cred
));
871 a
.in
.computer_name
= cli_credentials_get_workstation(wks_cred
);
872 a
.in
.secure_channel_type
= SEC_CHAN_WKSTA
;
873 a
.in
.negotiate_flags
= &negotiate_flags
;
874 a
.out
.negotiate_flags
= &negotiate_flags
;
875 a
.in
.credentials
= &netr_cred
;
876 a
.out
.credentials
= &netr_cred
;
878 status
= dcerpc_netr_ServerAuthenticate2(net_pipe
, mem_ctx
, &a
);
879 if (!NT_STATUS_IS_OK(status
)) {
880 d_printf("netr_ServerServerAuthenticate2 failed: %s\n",
885 if (!creds_client_check(creds_state
, a
.out
.credentials
)) {
886 d_printf("creds_client_check failed\n");
890 cli_credentials_set_netlogon_creds(wks_cred
, creds_state
);
895 talloc_free(mem_ctx
);
900 * Do a couple of schannel protected Netlogon ops: Interactive and Network
901 * login, and change the wks password
904 static BOOL
schan(struct smbcli_state
*cli
,
905 struct cli_credentials
*wks_creds
,
906 struct cli_credentials
*user_creds
)
911 struct dcerpc_pipe
*net_pipe
;
914 mem_ctx
= talloc_new(NULL
);
915 if (mem_ctx
== NULL
) {
916 d_printf("talloc_new failed\n");
920 net_pipe
= dcerpc_pipe_init(mem_ctx
,
921 cli
->transport
->socket
->event
.ctx
);
922 if (net_pipe
== NULL
) {
923 d_printf("dcerpc_pipe_init failed\n");
927 status
= dcerpc_pipe_open_smb(net_pipe
, cli
->tree
, "\\netlogon");
928 if (!NT_STATUS_IS_OK(status
)) {
929 d_printf("dcerpc_pipe_open_smb failed: %s\n",
935 net_pipe
->conn
->flags
|= DCERPC_DEBUG_PRINT_IN
|
936 DCERPC_DEBUG_PRINT_OUT
;
939 net_pipe
->conn
->flags
|= (DCERPC_SIGN
| DCERPC_SEAL
);
940 status
= dcerpc_bind_auth(net_pipe
, &dcerpc_table_netlogon
,
941 wks_creds
, DCERPC_AUTH_TYPE_SCHANNEL
,
942 DCERPC_AUTH_LEVEL_PRIVACY
,
945 status
= dcerpc_bind_auth_none(net_pipe
, &dcerpc_table_netlogon
);
947 if (!NT_STATUS_IS_OK(status
)) {
948 d_printf("schannel bind failed: %s\n", nt_errstr(status
));
953 for (i
=2; i
<4; i
++) {
955 DATA_BLOB chal
, nt_resp
, lm_resp
, names_blob
, session_key
;
956 struct creds_CredentialState
*creds_state
;
957 struct netr_Authenticator netr_auth
, netr_auth2
;
958 struct netr_NetworkInfo ninfo
;
959 struct netr_PasswordInfo pinfo
;
960 struct netr_LogonSamLogon r
;
962 flags
= CLI_CRED_LANMAN_AUTH
| CLI_CRED_NTLM_AUTH
|
963 CLI_CRED_NTLMv2_AUTH
;
965 chal
= data_blob_talloc(mem_ctx
, NULL
, 8);
966 if (chal
.data
== NULL
) {
967 d_printf("data_blob_talloc failed\n");
971 generate_random_buffer(chal
.data
, chal
.length
);
972 names_blob
= NTLMv2_generate_names_blob(
973 mem_ctx
, cli_credentials_get_workstation(user_creds
),
974 cli_credentials_get_domain(user_creds
));
975 status
= cli_credentials_get_ntlm_response(
976 user_creds
, mem_ctx
, &flags
, chal
, names_blob
,
977 &lm_resp
, &nt_resp
, NULL
, NULL
);
978 if (!NT_STATUS_IS_OK(status
)) {
979 d_printf("cli_credentials_get_ntlm_response failed:"
980 " %s\n", nt_errstr(status
));
984 creds_state
= cli_credentials_get_netlogon_creds(wks_creds
);
985 creds_client_authenticator(creds_state
, &netr_auth
);
987 ninfo
.identity_info
.account_name
.string
=
988 cli_credentials_get_username(user_creds
);
989 ninfo
.identity_info
.domain_name
.string
=
990 cli_credentials_get_domain(user_creds
);
991 ninfo
.identity_info
.parameter_control
= 0;
992 ninfo
.identity_info
.logon_id_low
= 0;
993 ninfo
.identity_info
.logon_id_high
= 0;
994 ninfo
.identity_info
.workstation
.string
=
995 cli_credentials_get_workstation(user_creds
);
996 memcpy(ninfo
.challenge
, chal
.data
, sizeof(ninfo
.challenge
));
997 ninfo
.nt
.length
= nt_resp
.length
;
998 ninfo
.nt
.data
= nt_resp
.data
;
999 ninfo
.lm
.length
= lm_resp
.length
;
1000 ninfo
.lm
.data
= lm_resp
.data
;
1002 r
.in
.server_name
= talloc_asprintf(
1003 mem_ctx
, "\\\\%s", dcerpc_server_name(net_pipe
));
1004 ZERO_STRUCT(netr_auth2
);
1005 r
.in
.computer_name
=
1006 cli_credentials_get_workstation(wks_creds
);
1007 r
.in
.credential
= &netr_auth
;
1008 r
.in
.return_authenticator
= &netr_auth2
;
1009 r
.in
.logon_level
= 2;
1010 r
.in
.validation_level
= i
;
1011 r
.in
.logon
.network
= &ninfo
;
1012 r
.out
.return_authenticator
= NULL
;
1014 status
= dcerpc_netr_LogonSamLogon(net_pipe
, mem_ctx
, &r
);
1015 if (!NT_STATUS_IS_OK(status
)) {
1016 d_printf("netr_LogonSamLogon failed: %s\n",
1021 if ((r
.out
.return_authenticator
== NULL
) ||
1022 (!creds_client_check(creds_state
,
1023 &r
.out
.return_authenticator
->cred
))) {
1024 d_printf("Credentials check failed!\n");
1028 creds_client_authenticator(creds_state
, &netr_auth
);
1030 pinfo
.identity_info
= ninfo
.identity_info
;
1031 ZERO_STRUCT(pinfo
.lmpassword
.hash
);
1032 E_md4hash(cli_credentials_get_password(user_creds
),
1033 pinfo
.ntpassword
.hash
);
1034 session_key
= data_blob_talloc(mem_ctx
,
1035 creds_state
->session_key
, 16);
1036 arcfour_crypt_blob(pinfo
.ntpassword
.hash
,
1037 sizeof(pinfo
.ntpassword
.hash
),
1040 r
.in
.logon_level
= 1;
1041 r
.in
.logon
.password
= &pinfo
;
1042 r
.out
.return_authenticator
= NULL
;
1044 status
= dcerpc_netr_LogonSamLogon(net_pipe
, mem_ctx
, &r
);
1045 if (!NT_STATUS_IS_OK(status
)) {
1046 d_printf("netr_LogonSamLogon failed: %s\n",
1051 if ((r
.out
.return_authenticator
== NULL
) ||
1052 (!creds_client_check(creds_state
,
1053 &r
.out
.return_authenticator
->cred
))) {
1054 d_printf("Credentials check failed!\n");
1060 struct netr_ServerPasswordSet s
;
1061 char *password
= generate_random_str(wks_creds
, 8);
1062 struct creds_CredentialState
*creds_state
;
1064 s
.in
.server_name
= talloc_asprintf(
1065 mem_ctx
, "\\\\%s", dcerpc_server_name(net_pipe
));
1066 s
.in
.computer_name
= cli_credentials_get_workstation(wks_creds
);
1067 s
.in
.account_name
= talloc_asprintf(
1068 mem_ctx
, "%s$", s
.in
.computer_name
);
1069 s
.in
.secure_channel_type
= SEC_CHAN_WKSTA
;
1070 E_md4hash(password
, s
.in
.new_password
.hash
);
1072 creds_state
= cli_credentials_get_netlogon_creds(wks_creds
);
1073 creds_des_encrypt(creds_state
, &s
.in
.new_password
);
1074 creds_client_authenticator(creds_state
, &s
.in
.credential
);
1076 status
= dcerpc_netr_ServerPasswordSet(net_pipe
, mem_ctx
, &s
);
1077 if (!NT_STATUS_IS_OK(status
)) {
1078 printf("ServerPasswordSet - %s\n", nt_errstr(status
));
1082 if (!creds_client_check(creds_state
,
1083 &s
.out
.return_authenticator
.cred
)) {
1084 printf("Credential chaining failed\n");
1087 cli_credentials_set_password(wks_creds
, password
,
1093 talloc_free(mem_ctx
);
1098 * Delete the wks account again
1101 static BOOL
leave(struct smbcli_state
*cli
,
1102 struct cli_credentials
*admin_creds
,
1103 struct cli_credentials
*wks_creds
)
1105 char *wks_name
= talloc_asprintf(
1106 NULL
, "%s$", cli_credentials_get_workstation(wks_creds
));
1109 ret
= delete_user(cli
, admin_creds
, wks_name
);
1110 talloc_free(wks_name
);
1115 * Test the Samba3 DC code a bit. Join, do some schan netlogon ops, leave
1118 BOOL
torture_netlogon_samba3(struct torture_context
*torture
)
1120 TALLOC_CTX
*mem_ctx
;
1123 struct smbcli_state
*cli
;
1124 struct cli_credentials
*anon_creds
;
1125 struct cli_credentials
*wks_creds
;
1126 const char *wks_name
;
1129 wks_name
= torture_setting_string(torture
, "wksname", NULL
);
1130 if (wks_name
== NULL
) {
1131 wks_name
= get_myname();
1134 mem_ctx
= talloc_init("torture_netlogon_samba3");
1136 if (mem_ctx
== NULL
) {
1137 d_printf("talloc_init failed\n");
1141 if (!(anon_creds
= create_anon_creds(mem_ctx
))) {
1142 d_printf("create_anon_creds failed\n");
1146 status
= smbcli_full_connection(mem_ctx
, &cli
,
1147 torture_setting_string(torture
, "host", NULL
),
1148 "IPC$", NULL
, anon_creds
, NULL
);
1149 if (!NT_STATUS_IS_OK(status
)) {
1150 d_printf("smbcli_full_connection failed: %s\n",
1155 wks_creds
= cli_credentials_init(mem_ctx
);
1156 if (wks_creds
== NULL
) {
1157 d_printf("cli_credentials_init failed\n");
1161 cli_credentials_set_conf(wks_creds
);
1162 cli_credentials_set_secure_channel_type(wks_creds
, SEC_CHAN_WKSTA
);
1163 cli_credentials_set_username(wks_creds
, wks_name
, CRED_SPECIFIED
);
1164 cli_credentials_set_workstation(wks_creds
, wks_name
, CRED_SPECIFIED
);
1165 cli_credentials_set_password(wks_creds
,
1166 generate_random_str(wks_creds
, 8),
1169 if (!join3(cli
, False
, cmdline_credentials
, wks_creds
)) {
1170 d_printf("join failed\n");
1174 cli_credentials_set_domain(
1175 cmdline_credentials
, cli_credentials_get_domain(wks_creds
),
1178 for (i
=0; i
<2; i
++) {
1180 /* Do this more than once, the routine "schan" changes
1181 * the workstation password using the netlogon
1182 * password change routine */
1186 if (!auth2(cli
, wks_creds
)) {
1187 d_printf("auth2 failed\n");
1191 for (j
=0; j
<2; j
++) {
1192 if (!schan(cli
, wks_creds
, cmdline_credentials
)) {
1193 d_printf("schan failed\n");
1199 if (!leave(cli
, cmdline_credentials
, wks_creds
)) {
1200 d_printf("leave failed\n");
1207 talloc_free(mem_ctx
);
1212 * Do a simple join, testjoin and leave using specified smb and samr
1216 static BOOL
test_join3(TALLOC_CTX
*mem_ctx
,
1218 struct cli_credentials
*smb_creds
,
1219 struct cli_credentials
*samr_creds
,
1220 const char *wks_name
)
1224 struct smbcli_state
*cli
;
1225 struct cli_credentials
*wks_creds
;
1227 status
= smbcli_full_connection(mem_ctx
, &cli
,
1228 lp_parm_string(-1, "torture", "host"),
1229 "IPC$", NULL
, smb_creds
, NULL
);
1230 if (!NT_STATUS_IS_OK(status
)) {
1231 d_printf("smbcli_full_connection failed: %s\n",
1236 wks_creds
= cli_credentials_init(cli
);
1237 if (wks_creds
== NULL
) {
1238 d_printf("cli_credentials_init failed\n");
1242 cli_credentials_set_conf(wks_creds
);
1243 cli_credentials_set_secure_channel_type(wks_creds
, SEC_CHAN_WKSTA
);
1244 cli_credentials_set_username(wks_creds
, wks_name
, CRED_SPECIFIED
);
1245 cli_credentials_set_workstation(wks_creds
, wks_name
, CRED_SPECIFIED
);
1246 cli_credentials_set_password(wks_creds
,
1247 generate_random_str(wks_creds
, 8),
1250 if (!join3(cli
, use_level25
, samr_creds
, wks_creds
)) {
1251 d_printf("join failed\n");
1255 cli_credentials_set_domain(
1256 cmdline_credentials
, cli_credentials_get_domain(wks_creds
),
1259 if (!auth2(cli
, wks_creds
)) {
1260 d_printf("auth2 failed\n");
1264 if (!leave(cli
, samr_creds
, wks_creds
)) {
1265 d_printf("leave failed\n");
1278 * Test the different session key variants. Do it by joining, this uses the
1279 * session key in the setpassword routine. Test the join by doing the auth2.
1282 BOOL
torture_samba3_sessionkey(struct torture_context
*torture
)
1284 TALLOC_CTX
*mem_ctx
;
1286 struct cli_credentials
*anon_creds
;
1287 const char *wks_name
;
1289 wks_name
= torture_setting_string(torture
, "wksname", get_myname());
1291 mem_ctx
= talloc_init("torture_samba3_sessionkey");
1293 if (mem_ctx
== NULL
) {
1294 d_printf("talloc_init failed\n");
1298 if (!(anon_creds
= create_anon_creds(mem_ctx
))) {
1299 d_printf("create_anon_creds failed\n");
1305 if (!torture_setting_bool(torture
, "samba3", False
)) {
1307 /* Samba3 in the build farm right now does this happily. Need
1310 if (test_join3(mem_ctx
, False
, anon_creds
, NULL
, wks_name
)) {
1311 d_printf("join using anonymous bind on an anonymous smb "
1312 "connection succeeded -- HUH??\n");
1317 if (!test_join3(mem_ctx
, False
, anon_creds
, cmdline_credentials
,
1319 d_printf("join using ntlmssp bind on an anonymous smb "
1320 "connection failed\n");
1324 if (!test_join3(mem_ctx
, False
, cmdline_credentials
, NULL
, wks_name
)) {
1325 d_printf("join using anonymous bind on an authenticated smb "
1326 "connection failed\n");
1330 if (!test_join3(mem_ctx
, False
, cmdline_credentials
,
1331 cmdline_credentials
,
1333 d_printf("join using ntlmssp bind on an authenticated smb "
1334 "connection failed\n");
1339 * The following two are tests for setuserinfolevel 25
1342 if (!test_join3(mem_ctx
, True
, anon_creds
, cmdline_credentials
,
1344 d_printf("join using ntlmssp bind on an anonymous smb "
1345 "connection failed\n");
1349 if (!test_join3(mem_ctx
, True
, cmdline_credentials
, NULL
, wks_name
)) {
1350 d_printf("join using anonymous bind on an authenticated smb "
1351 "connection failed\n");
1361 * open pipe and bind, given an IPC$ context
1364 static NTSTATUS
pipe_bind_smb(TALLOC_CTX
*mem_ctx
,
1365 struct smbcli_tree
*tree
,
1366 const char *pipe_name
,
1367 const struct dcerpc_interface_table
*iface
,
1368 struct dcerpc_pipe
**p
)
1370 struct dcerpc_pipe
*result
;
1373 if (!(result
= dcerpc_pipe_init(
1374 mem_ctx
, tree
->session
->transport
->socket
->event
.ctx
))) {
1375 return NT_STATUS_NO_MEMORY
;
1378 status
= dcerpc_pipe_open_smb(result
, tree
, pipe_name
);
1379 if (!NT_STATUS_IS_OK(status
)) {
1380 d_printf("dcerpc_pipe_open_smb failed: %s\n",
1382 talloc_free(result
);
1386 status
= dcerpc_bind_auth_none(result
, iface
);
1387 if (!NT_STATUS_IS_OK(status
)) {
1388 d_printf("schannel bind failed: %s\n", nt_errstr(status
));
1389 talloc_free(result
);
1394 return NT_STATUS_OK
;
1398 * Sane wrapper around lsa_LookupNames
1401 static struct dom_sid
*name2sid(TALLOC_CTX
*mem_ctx
,
1402 struct dcerpc_pipe
*p
,
1406 struct lsa_ObjectAttribute attr
;
1407 struct lsa_QosInfo qos
;
1408 struct lsa_OpenPolicy2 r
;
1411 struct policy_handle handle
;
1412 struct lsa_LookupNames l
;
1413 struct lsa_TransSidArray sids
;
1414 struct lsa_String lsa_name
;
1416 struct dom_sid
*result
;
1417 TALLOC_CTX
*tmp_ctx
;
1419 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
1424 qos
.impersonation_level
= 2;
1425 qos
.context_mode
= 1;
1426 qos
.effective_only
= 0;
1429 attr
.root_dir
= NULL
;
1430 attr
.object_name
= NULL
;
1431 attr
.attributes
= 0;
1432 attr
.sec_desc
= NULL
;
1433 attr
.sec_qos
= &qos
;
1435 r
.in
.system_name
= "\\";
1437 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1438 r
.out
.handle
= &handle
;
1440 status
= dcerpc_lsa_OpenPolicy2(p
, tmp_ctx
, &r
);
1441 if (!NT_STATUS_IS_OK(status
)) {
1442 printf("OpenPolicy2 failed - %s\n", nt_errstr(status
));
1443 talloc_free(tmp_ctx
);
1450 lsa_name
.string
= talloc_asprintf(tmp_ctx
, "%s\\%s", domain
, name
);
1452 l
.in
.handle
= &handle
;
1454 l
.in
.names
= &lsa_name
;
1457 l
.in
.count
= &count
;
1458 l
.out
.count
= &count
;
1461 status
= dcerpc_lsa_LookupNames(p
, tmp_ctx
, &l
);
1462 if (!NT_STATUS_IS_OK(status
)) {
1463 printf("LookupNames of %s failed - %s\n", lsa_name
.string
,
1465 talloc_free(tmp_ctx
);
1469 result
= dom_sid_add_rid(mem_ctx
, l
.out
.domains
->domains
[0].sid
,
1470 l
.out
.sids
->sids
[0].rid
);
1472 c
.in
.handle
= &handle
;
1473 c
.out
.handle
= &handle
;
1475 status
= dcerpc_lsa_Close(p
, tmp_ctx
, &c
);
1476 if (!NT_STATUS_IS_OK(status
)) {
1477 printf("dcerpc_lsa_Close failed - %s\n", nt_errstr(status
));
1478 talloc_free(tmp_ctx
);
1482 talloc_free(tmp_ctx
);
1487 * Find out the user SID on this connection
1490 static struct dom_sid
*whoami(TALLOC_CTX
*mem_ctx
, struct smbcli_tree
*tree
)
1492 struct dcerpc_pipe
*lsa
;
1493 struct lsa_GetUserName r
;
1495 struct lsa_StringPointer authority_name_p
;
1496 struct dom_sid
*result
;
1498 status
= pipe_bind_smb(mem_ctx
, tree
, "\\pipe\\lsarpc",
1499 &dcerpc_table_lsarpc
, &lsa
);
1500 if (!NT_STATUS_IS_OK(status
)) {
1501 d_printf("(%s) Could not bind to LSA: %s\n",
1502 __location__
, nt_errstr(status
));
1506 r
.in
.system_name
= "\\";
1507 r
.in
.account_name
= NULL
;
1508 authority_name_p
.string
= NULL
;
1509 r
.in
.authority_name
= &authority_name_p
;
1511 status
= dcerpc_lsa_GetUserName(lsa
, mem_ctx
, &r
);
1513 if (!NT_STATUS_IS_OK(status
)) {
1514 printf("(%s) GetUserName failed - %s\n",
1515 __location__
, nt_errstr(status
));
1520 result
= name2sid(mem_ctx
, lsa
, r
.out
.account_name
->string
,
1521 r
.out
.authority_name
->string
->string
);
1528 * Do a tcon, given a session
1531 NTSTATUS
secondary_tcon(TALLOC_CTX
*mem_ctx
,
1532 struct smbcli_session
*session
,
1533 const char *sharename
,
1534 struct smbcli_tree
**res
)
1536 struct smbcli_tree
*result
;
1537 TALLOC_CTX
*tmp_ctx
;
1538 union smb_tcon tcon
;
1541 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
1542 return NT_STATUS_NO_MEMORY
;
1545 if (!(result
= smbcli_tree_init(session
, mem_ctx
, False
))) {
1546 talloc_free(tmp_ctx
);
1547 return NT_STATUS_NO_MEMORY
;
1550 tcon
.generic
.level
= RAW_TCON_TCONX
;
1551 tcon
.tconx
.in
.flags
= 0;
1552 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
1553 tcon
.tconx
.in
.path
= sharename
;
1554 tcon
.tconx
.in
.device
= "?????";
1556 status
= smb_raw_tcon(result
, tmp_ctx
, &tcon
);
1557 if (!NT_STATUS_IS_OK(status
)) {
1558 d_printf("(%s) smb_raw_tcon failed: %s\n", __location__
,
1560 talloc_free(tmp_ctx
);
1564 result
->tid
= tcon
.tconx
.out
.tid
;
1565 result
= talloc_steal(mem_ctx
, result
);
1566 talloc_free(tmp_ctx
);
1568 return NT_STATUS_OK
;
1572 * Test the getusername behaviour
1575 BOOL
torture_samba3_rpc_getusername(struct torture_context
*torture
)
1578 struct smbcli_state
*cli
;
1579 TALLOC_CTX
*mem_ctx
;
1581 struct dom_sid
*user_sid
;
1582 struct dom_sid
*created_sid
;
1583 struct cli_credentials
*anon_creds
;
1584 struct cli_credentials
*user_creds
;
1587 if (!(mem_ctx
= talloc_new(torture
))) {
1591 status
= smbcli_full_connection(
1592 mem_ctx
, &cli
, torture_setting_string(torture
, "host", NULL
),
1593 "IPC$", NULL
, cmdline_credentials
, NULL
);
1594 if (!NT_STATUS_IS_OK(status
)) {
1595 d_printf("(%s) smbcli_full_connection failed: %s\n",
1596 __location__
, nt_errstr(status
));
1601 if (!(user_sid
= whoami(mem_ctx
, cli
->tree
))) {
1602 d_printf("(%s) whoami on auth'ed connection failed\n",
1609 if (!(anon_creds
= create_anon_creds(mem_ctx
))) {
1610 d_printf("(%s) create_anon_creds failed\n", __location__
);
1615 status
= smbcli_full_connection(
1616 mem_ctx
, &cli
, torture_setting_string(torture
, "host", NULL
),
1617 "IPC$", NULL
, anon_creds
, NULL
);
1618 if (!NT_STATUS_IS_OK(status
)) {
1619 d_printf("(%s) anon smbcli_full_connection failed: %s\n",
1620 __location__
, nt_errstr(status
));
1625 if (!(user_sid
= whoami(mem_ctx
, cli
->tree
))) {
1626 d_printf("(%s) whoami on anon connection failed\n",
1632 if (!dom_sid_equal(user_sid
,
1633 dom_sid_parse_talloc(mem_ctx
, "s-1-5-7"))) {
1634 d_printf("(%s) Anon lsa_GetUserName returned %s, expected "
1635 "S-1-5-7", __location__
,
1636 dom_sid_string(mem_ctx
, user_sid
));
1640 if (!(user_creds
= cli_credentials_init(mem_ctx
))) {
1641 d_printf("(%s) cli_credentials_init failed\n", __location__
);
1646 cli_credentials_set_conf(user_creds
);
1647 cli_credentials_set_username(user_creds
, "torture_username",
1649 cli_credentials_set_password(user_creds
,
1650 generate_random_str(user_creds
, 8),
1653 if (!create_user(mem_ctx
, cli
, cmdline_credentials
,
1654 cli_credentials_get_username(user_creds
),
1655 cli_credentials_get_password(user_creds
),
1656 &domain_name
, &created_sid
)) {
1657 d_printf("(%s) create_user failed\n", __location__
);
1662 cli_credentials_set_domain(user_creds
, domain_name
,
1666 struct smbcli_session
*session2
;
1667 struct smb_composite_sesssetup setup
;
1668 struct smbcli_tree
*tree
;
1670 session2
= smbcli_session_init(cli
->transport
, mem_ctx
, False
);
1671 if (session2
== NULL
) {
1672 d_printf("(%s) smbcli_session_init failed\n",
1677 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
1678 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
1679 setup
.in
.workgroup
= "";
1680 setup
.in
.credentials
= user_creds
;
1682 status
= smb_composite_sesssetup(session2
, &setup
);
1683 if (!NT_STATUS_IS_OK(status
)) {
1684 d_printf("(%s) session setup with new user failed: "
1685 "%s\n", __location__
, nt_errstr(status
));
1689 session2
->vuid
= setup
.out
.vuid
;
1691 if (!NT_STATUS_IS_OK(secondary_tcon(mem_ctx
, session2
,
1693 d_printf("(%s) secondary_tcon failed\n",
1699 if (!(user_sid
= whoami(mem_ctx
, tree
))) {
1700 d_printf("(%s) whoami on user connection failed\n",
1709 d_printf("Created %s, found %s\n",
1710 dom_sid_string(mem_ctx
, created_sid
),
1711 dom_sid_string(mem_ctx
, user_sid
));
1713 if (!dom_sid_equal(created_sid
, user_sid
)) {
1718 if (!delete_user(cli
, cmdline_credentials
,
1719 cli_credentials_get_username(user_creds
))) {
1720 d_printf("(%s) delete_user failed\n", __location__
);
1725 talloc_free(mem_ctx
);
1729 static BOOL
test_NetShareGetInfo(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
1730 const char *sharename
)
1733 struct srvsvc_NetShareGetInfo r
;
1734 uint32_t levels
[] = { 0, 1, 2, 501, 502, 1004, 1005, 1006, 1007, 1501 };
1738 r
.in
.server_unc
= talloc_asprintf(mem_ctx
, "\\\\%s",
1739 dcerpc_server_name(p
));
1740 r
.in
.share_name
= sharename
;
1742 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1743 r
.in
.level
= levels
[i
];
1747 printf("testing NetShareGetInfo level %u on share '%s'\n",
1748 r
.in
.level
, r
.in
.share_name
);
1750 status
= dcerpc_srvsvc_NetShareGetInfo(p
, mem_ctx
, &r
);
1751 if (!NT_STATUS_IS_OK(status
)) {
1752 printf("NetShareGetInfo level %u on share '%s' failed"
1753 " - %s\n", r
.in
.level
, r
.in
.share_name
,
1758 if (!W_ERROR_IS_OK(r
.out
.result
)) {
1759 printf("NetShareGetInfo level %u on share '%s' failed "
1760 "- %s\n", r
.in
.level
, r
.in
.share_name
,
1761 win_errstr(r
.out
.result
));
1770 static BOOL
test_NetShareEnum(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
1771 const char **one_sharename
)
1774 struct srvsvc_NetShareEnum r
;
1775 struct srvsvc_NetShareCtr0 c0
;
1776 uint32_t levels
[] = { 0, 1, 2, 501, 502, 1004, 1005, 1006, 1007 };
1780 r
.in
.server_unc
= talloc_asprintf(mem_ctx
,"\\\\%s",dcerpc_server_name(p
));
1781 r
.in
.ctr
.ctr0
= &c0
;
1782 r
.in
.ctr
.ctr0
->count
= 0;
1783 r
.in
.ctr
.ctr0
->array
= NULL
;
1784 r
.in
.max_buffer
= (uint32_t)-1;
1785 r
.in
.resume_handle
= NULL
;
1787 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1788 r
.in
.level
= levels
[i
];
1792 printf("testing NetShareEnum level %u\n", r
.in
.level
);
1793 status
= dcerpc_srvsvc_NetShareEnum(p
, mem_ctx
, &r
);
1794 if (!NT_STATUS_IS_OK(status
)) {
1795 printf("NetShareEnum level %u failed - %s\n",
1796 r
.in
.level
, nt_errstr(status
));
1800 if (!W_ERROR_IS_OK(r
.out
.result
)) {
1801 printf("NetShareEnum level %u failed - %s\n",
1802 r
.in
.level
, win_errstr(r
.out
.result
));
1805 if (r
.in
.level
== 0) {
1806 struct srvsvc_NetShareCtr0
*ctr
= r
.out
.ctr
.ctr0
;
1807 if (ctr
->count
> 0) {
1808 *one_sharename
= ctr
->array
[0].name
;
1816 BOOL
torture_samba3_rpc_srvsvc(struct torture_context
*torture
)
1818 struct dcerpc_pipe
*p
;
1819 TALLOC_CTX
*mem_ctx
;
1821 const char *sharename
= NULL
;
1822 struct smbcli_state
*cli
;
1825 if (!(mem_ctx
= talloc_new(torture
))) {
1829 if (!(torture_open_connection_share(
1830 mem_ctx
, &cli
, torture_setting_string(torture
, "host", NULL
),
1832 talloc_free(mem_ctx
);
1836 status
= pipe_bind_smb(mem_ctx
, cli
->tree
, "\\pipe\\srvsvc",
1837 &dcerpc_table_srvsvc
, &p
);
1838 if (!NT_STATUS_IS_OK(status
)) {
1839 d_printf("(%s) could not bind to srvsvc pipe: %s\n",
1840 __location__
, nt_errstr(status
));
1845 ret
&= test_NetShareEnum(p
, mem_ctx
, &sharename
);
1846 if (sharename
== NULL
) {
1847 printf("did not get sharename\n");
1849 ret
&= test_NetShareGetInfo(p
, mem_ctx
, sharename
);
1853 talloc_free(mem_ctx
);
1857 static struct security_descriptor
*get_sharesec(TALLOC_CTX
*mem_ctx
,
1858 struct smbcli_session
*sess
,
1859 const char *sharename
)
1861 struct smbcli_tree
*tree
;
1862 TALLOC_CTX
*tmp_ctx
;
1863 struct dcerpc_pipe
*p
;
1865 struct srvsvc_NetShareGetInfo r
;
1866 struct security_descriptor
*result
;
1868 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
1869 d_printf("talloc_new failed\n");
1873 if (!NT_STATUS_IS_OK(secondary_tcon(tmp_ctx
, sess
, "IPC$", &tree
))) {
1874 d_printf("secondary_tcon failed\n");
1875 talloc_free(tmp_ctx
);
1879 status
= pipe_bind_smb(mem_ctx
, tree
, "\\pipe\\srvsvc",
1880 &dcerpc_table_srvsvc
, &p
);
1881 if (!NT_STATUS_IS_OK(status
)) {
1882 d_printf("(%s) could not bind to srvsvc pipe: %s\n",
1883 __location__
, nt_errstr(status
));
1884 talloc_free(tmp_ctx
);
1889 p
->conn
->flags
|= DCERPC_DEBUG_PRINT_IN
| DCERPC_DEBUG_PRINT_OUT
;
1892 r
.in
.server_unc
= talloc_asprintf(tmp_ctx
, "\\\\%s",
1893 dcerpc_server_name(p
));
1894 r
.in
.share_name
= sharename
;
1897 status
= dcerpc_srvsvc_NetShareGetInfo(p
, tmp_ctx
, &r
);
1898 if (!NT_STATUS_IS_OK(status
)) {
1899 d_printf("srvsvc_NetShareGetInfo failed: %s\n",
1901 talloc_free(tmp_ctx
);
1905 result
= talloc_steal(mem_ctx
, r
.out
.info
.info502
->sd
);
1906 talloc_free(tmp_ctx
);
1910 static NTSTATUS
set_sharesec(TALLOC_CTX
*mem_ctx
,
1911 struct smbcli_session
*sess
,
1912 const char *sharename
,
1913 struct security_descriptor
*sd
)
1915 struct smbcli_tree
*tree
;
1916 TALLOC_CTX
*tmp_ctx
;
1917 struct dcerpc_pipe
*p
;
1919 struct sec_desc_buf i
;
1920 struct srvsvc_NetShareSetInfo r
;
1923 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
1924 d_printf("talloc_new failed\n");
1925 return NT_STATUS_NO_MEMORY
;
1928 if (!NT_STATUS_IS_OK(secondary_tcon(tmp_ctx
, sess
, "IPC$", &tree
))) {
1929 d_printf("secondary_tcon failed\n");
1930 talloc_free(tmp_ctx
);
1931 return NT_STATUS_UNSUCCESSFUL
;
1934 status
= pipe_bind_smb(mem_ctx
, tree
, "\\pipe\\srvsvc",
1935 &dcerpc_table_srvsvc
, &p
);
1936 if (!NT_STATUS_IS_OK(status
)) {
1937 d_printf("(%s) could not bind to srvsvc pipe: %s\n",
1938 __location__
, nt_errstr(status
));
1939 talloc_free(tmp_ctx
);
1940 return NT_STATUS_UNSUCCESSFUL
;
1944 p
->conn
->flags
|= DCERPC_DEBUG_PRINT_IN
| DCERPC_DEBUG_PRINT_OUT
;
1947 r
.in
.server_unc
= talloc_asprintf(tmp_ctx
, "\\\\%s",
1948 dcerpc_server_name(p
));
1949 r
.in
.share_name
= sharename
;
1952 r
.in
.info
.info1501
= &i
;
1953 r
.in
.parm_error
= &error
;
1955 status
= dcerpc_srvsvc_NetShareSetInfo(p
, tmp_ctx
, &r
);
1956 if (!NT_STATUS_IS_OK(status
)) {
1957 d_printf("srvsvc_NetShareGetInfo failed: %s\n",
1961 talloc_free(tmp_ctx
);
1965 BOOL
try_tcon(TALLOC_CTX
*mem_ctx
,
1966 struct security_descriptor
*orig_sd
,
1967 struct smbcli_session
*session
,
1968 const char *sharename
, const struct dom_sid
*user_sid
,
1969 unsigned int access_mask
, NTSTATUS expected_tcon
,
1970 NTSTATUS expected_mkdir
)
1972 TALLOC_CTX
*tmp_ctx
;
1973 struct smbcli_tree
*rmdir_tree
, *tree
;
1974 struct dom_sid
*domain_sid
;
1976 struct security_descriptor
*sd
;
1980 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
1981 d_printf("talloc_new failed\n");
1985 status
= secondary_tcon(tmp_ctx
, session
, sharename
, &rmdir_tree
);
1986 if (!NT_STATUS_IS_OK(status
)) {
1987 d_printf("first tcon to delete dir failed\n");
1988 talloc_free(tmp_ctx
);
1992 smbcli_rmdir(rmdir_tree
, "sharesec_testdir");
1994 if (!NT_STATUS_IS_OK(dom_sid_split_rid(tmp_ctx
, user_sid
,
1995 &domain_sid
, &rid
))) {
1996 d_printf("dom_sid_split_rid failed\n");
1997 talloc_free(tmp_ctx
);
2001 sd
= security_descriptor_create(
2002 tmp_ctx
, "S-1-5-32-544",
2003 dom_sid_string(mem_ctx
, dom_sid_add_rid(mem_ctx
, domain_sid
,
2005 dom_sid_string(mem_ctx
, user_sid
),
2006 SEC_ACE_TYPE_ACCESS_ALLOWED
, access_mask
, 0, NULL
);
2008 d_printf("security_descriptor_create failed\n");
2009 talloc_free(tmp_ctx
);
2013 status
= set_sharesec(mem_ctx
, session
, sharename
, sd
);
2014 if (!NT_STATUS_IS_OK(status
)) {
2015 d_printf("custom set_sharesec failed: %s\n",
2017 talloc_free(tmp_ctx
);
2021 status
= secondary_tcon(tmp_ctx
, session
, sharename
, &tree
);
2022 if (!NT_STATUS_EQUAL(status
, expected_tcon
)) {
2023 d_printf("Expected %s, got %s\n", nt_errstr(expected_tcon
),
2029 if (!NT_STATUS_IS_OK(status
)) {
2030 /* An expected non-access, no point in trying to write */
2034 status
= smbcli_mkdir(tree
, "sharesec_testdir");
2035 if (!NT_STATUS_EQUAL(status
, expected_mkdir
)) {
2036 d_printf("(%s) Expected %s, got %s\n", __location__
,
2037 nt_errstr(expected_mkdir
), nt_errstr(status
));
2042 smbcli_rmdir(rmdir_tree
, "sharesec_testdir");
2044 status
= set_sharesec(mem_ctx
, session
, sharename
, orig_sd
);
2045 if (!NT_STATUS_IS_OK(status
)) {
2046 d_printf("custom set_sharesec failed: %s\n",
2048 talloc_free(tmp_ctx
);
2052 talloc_free(tmp_ctx
);
2056 BOOL
torture_samba3_rpc_sharesec(struct torture_context
*torture
)
2058 TALLOC_CTX
*mem_ctx
;
2060 struct smbcli_state
*cli
;
2061 struct security_descriptor
*sd
;
2062 struct dom_sid
*user_sid
;
2064 if (!(mem_ctx
= talloc_new(torture
))) {
2068 if (!(torture_open_connection_share(
2069 mem_ctx
, &cli
, torture_setting_string(torture
, "host", NULL
),
2071 d_printf("IPC$ connection failed\n");
2072 talloc_free(mem_ctx
);
2076 if (!(user_sid
= whoami(mem_ctx
, cli
->tree
))) {
2077 d_printf("whoami failed\n");
2078 talloc_free(mem_ctx
);
2082 sd
= get_sharesec(mem_ctx
, cli
->session
, torture_setting_string(torture
,
2085 ret
&= try_tcon(mem_ctx
, sd
, cli
->session
,
2086 torture_setting_string(torture
, "share", NULL
),
2087 user_sid
, 0, NT_STATUS_ACCESS_DENIED
, NT_STATUS_OK
);
2089 ret
&= try_tcon(mem_ctx
, sd
, cli
->session
,
2090 torture_setting_string(torture
, "share", NULL
),
2091 user_sid
, SEC_FILE_READ_DATA
, NT_STATUS_OK
,
2092 NT_STATUS_MEDIA_WRITE_PROTECTED
);
2094 ret
&= try_tcon(mem_ctx
, sd
, cli
->session
,
2095 torture_setting_string(torture
, "share", NULL
),
2096 user_sid
, SEC_FILE_ALL
, NT_STATUS_OK
, NT_STATUS_OK
);
2098 talloc_free(mem_ctx
);
2102 BOOL
torture_samba3_rpc_lsa(struct torture_context
*torture
)
2104 TALLOC_CTX
*mem_ctx
;
2106 struct smbcli_state
*cli
;
2107 struct dcerpc_pipe
*p
;
2108 struct policy_handle lsa_handle
;
2110 struct dom_sid
*domain_sid
;
2112 if (!(mem_ctx
= talloc_new(torture
))) {
2116 if (!(torture_open_connection_share(
2117 mem_ctx
, &cli
, torture_setting_string(torture
, "host", NULL
),
2119 d_printf("IPC$ connection failed\n");
2120 talloc_free(mem_ctx
);
2124 status
= pipe_bind_smb(mem_ctx
, cli
->tree
, "\\lsarpc",
2125 &dcerpc_table_lsarpc
, &p
);
2126 if (!NT_STATUS_IS_OK(status
)) {
2127 d_printf("(%s) pipe_bind_smb failed: %s\n", __location__
,
2129 talloc_free(mem_ctx
);
2134 struct lsa_ObjectAttribute attr
;
2135 struct lsa_OpenPolicy2 o
;
2136 o
.in
.system_name
= talloc_asprintf(
2137 mem_ctx
, "\\\\%s", dcerpc_server_name(p
));
2140 o
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2141 o
.out
.handle
= &lsa_handle
;
2142 status
= dcerpc_lsa_OpenPolicy2(p
, mem_ctx
, &o
);
2143 if (!NT_STATUS_IS_OK(status
)) {
2144 d_printf("(%s) dcerpc_lsa_OpenPolicy2 failed: %s\n",
2145 __location__
, nt_errstr(status
));
2146 talloc_free(mem_ctx
);
2152 p
->conn
->flags
|= DCERPC_DEBUG_PRINT_IN
| DCERPC_DEBUG_PRINT_OUT
;
2157 int levels
[] = { 2,3,5,6 };
2159 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
2160 struct lsa_QueryInfoPolicy r
;
2161 r
.in
.handle
= &lsa_handle
;
2162 r
.in
.level
= levels
[i
];
2163 status
= dcerpc_lsa_QueryInfoPolicy(p
, mem_ctx
, &r
);
2164 if (!NT_STATUS_IS_OK(status
)) {
2165 d_printf("(%s) dcerpc_lsa_QueryInfoPolicy %d "
2166 "failed: %s\n", __location__
,
2167 levels
[i
], nt_errstr(status
));
2168 talloc_free(mem_ctx
);
2171 if (levels
[i
] == 5) {
2172 domain_sid
= r
.out
.info
->account_domain
.sid
;
2180 static NTSTATUS
get_servername(TALLOC_CTX
*mem_ctx
, struct smbcli_tree
*tree
,
2183 struct rap_WserverGetInfo r
;
2185 char servername
[17];
2188 r
.in
.bufsize
= 0xffff;
2190 status
= smbcli_rap_netservergetinfo(tree
, mem_ctx
, &r
);
2191 if (!NT_STATUS_IS_OK(status
)) {
2195 memcpy(servername
, r
.out
.info
.info0
.name
, 16);
2196 servername
[16] = '\0';
2198 if (pull_ascii_talloc(mem_ctx
, name
, servername
) < 0) {
2199 return NT_STATUS_NO_MEMORY
;
2202 return NT_STATUS_OK
;
2206 static NTSTATUS
find_printers(TALLOC_CTX
*ctx
, struct smbcli_tree
*tree
,
2207 const char ***printers
, int *num_printers
)
2209 TALLOC_CTX
*mem_ctx
;
2211 struct dcerpc_pipe
*p
;
2212 struct srvsvc_NetShareEnum r
;
2213 struct srvsvc_NetShareCtr1 c1_in
;
2214 struct srvsvc_NetShareCtr1
*c1
;
2217 mem_ctx
= talloc_new(ctx
);
2218 if (mem_ctx
== NULL
) {
2219 return NT_STATUS_NO_MEMORY
;
2222 status
= pipe_bind_smb(mem_ctx
, tree
, "\\srvsvc", &dcerpc_table_srvsvc
,
2224 if (!NT_STATUS_IS_OK(status
)) {
2225 d_printf("could not bind to srvsvc pipe\n");
2226 talloc_free(mem_ctx
);
2230 r
.in
.server_unc
= talloc_asprintf(
2231 mem_ctx
, "\\\\%s", dcerpc_server_name(p
));
2234 r
.in
.ctr
.ctr1
= &c1_in
;
2235 r
.in
.max_buffer
= (uint32_t)-1;
2236 r
.in
.resume_handle
= NULL
;
2238 status
= dcerpc_srvsvc_NetShareEnum(p
, mem_ctx
, &r
);
2239 if (!NT_STATUS_IS_OK(status
)) {
2240 d_printf("NetShareEnum level %u failed - %s\n",
2241 r
.in
.level
, nt_errstr(status
));
2242 talloc_free(mem_ctx
);
2248 c1
= r
.out
.ctr
.ctr1
;
2249 for (i
=0; i
<c1
->count
; i
++) {
2250 if (c1
->array
[i
].type
!= STYPE_PRINTQ
) {
2253 if (!add_string_to_array(ctx
, c1
->array
[i
].name
,
2254 printers
, num_printers
)) {
2256 return NT_STATUS_NO_MEMORY
;
2260 talloc_free(mem_ctx
);
2261 return NT_STATUS_OK
;
2264 static BOOL
enumprinters(TALLOC_CTX
*mem_ctx
, struct dcerpc_pipe
*pipe
,
2265 const char *servername
, int level
, int *num_printers
)
2267 struct spoolss_EnumPrinters r
;
2271 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
2272 r
.in
.server
= talloc_asprintf(mem_ctx
, "\\\\%s", servername
);
2277 status
= dcerpc_spoolss_EnumPrinters(pipe
, mem_ctx
, &r
);
2278 if (!NT_STATUS_IS_OK(status
)) {
2279 d_printf("(%s) dcerpc_spoolss_EnumPrinters failed: %s\n",
2280 __location__
, nt_errstr(status
));
2284 if (!W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2285 d_printf("(%s) EnumPrinters unexpected return code %s, should "
2286 "be WERR_INSUFFICIENT_BUFFER\n", __location__
,
2287 win_errstr(r
.out
.result
));
2291 blob
= data_blob_talloc_zero(mem_ctx
, r
.out
.needed
);
2292 if (blob
.data
== NULL
) {
2293 d_printf("(%s) data_blob_talloc failed\n", __location__
);
2297 r
.in
.buffer
= &blob
;
2298 r
.in
.offered
= r
.out
.needed
;
2300 status
= dcerpc_spoolss_EnumPrinters(pipe
, mem_ctx
, &r
);
2301 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2302 d_printf("(%s) dcerpc_spoolss_EnumPrinters failed: %s, "
2303 "%s\n", __location__
, nt_errstr(status
),
2304 win_errstr(r
.out
.result
));
2308 *num_printers
= r
.out
.count
;
2313 static NTSTATUS
getprinterinfo(TALLOC_CTX
*ctx
, struct dcerpc_pipe
*pipe
,
2314 struct policy_handle
*handle
, int level
,
2315 union spoolss_PrinterInfo
**res
)
2317 TALLOC_CTX
*mem_ctx
;
2318 struct spoolss_GetPrinter r
;
2322 mem_ctx
= talloc_new(ctx
);
2323 if (mem_ctx
== NULL
) {
2324 return NT_STATUS_NO_MEMORY
;
2327 r
.in
.handle
= handle
;
2332 status
= dcerpc_spoolss_GetPrinter(pipe
, mem_ctx
, &r
);
2333 if (!NT_STATUS_IS_OK(status
)) {
2334 d_printf("(%s) dcerpc_spoolss_GetPrinter failed: %s\n",
2335 __location__
, nt_errstr(status
));
2336 talloc_free(mem_ctx
);
2340 if (!W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2341 printf("GetPrinter unexpected return code %s, should "
2342 "be WERR_INSUFFICIENT_BUFFER\n",
2343 win_errstr(r
.out
.result
));
2344 talloc_free(mem_ctx
);
2345 return NT_STATUS_UNSUCCESSFUL
;
2348 r
.in
.handle
= handle
;
2350 blob
= data_blob_talloc(mem_ctx
, NULL
, r
.out
.needed
);
2351 if (blob
.data
== NULL
) {
2352 talloc_free(mem_ctx
);
2353 return NT_STATUS_NO_MEMORY
;
2355 memset(blob
.data
, 0, blob
.length
);
2356 r
.in
.buffer
= &blob
;
2357 r
.in
.offered
= r
.out
.needed
;
2359 status
= dcerpc_spoolss_GetPrinter(pipe
, mem_ctx
, &r
);
2360 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2361 d_printf("(%s) dcerpc_spoolss_GetPrinter failed: %s, "
2362 "%s\n", __location__
, nt_errstr(status
),
2363 win_errstr(r
.out
.result
));
2364 talloc_free(mem_ctx
);
2365 return NT_STATUS_IS_OK(status
) ?
2366 NT_STATUS_UNSUCCESSFUL
: status
;
2370 *res
= talloc_steal(ctx
, r
.out
.info
);
2373 talloc_free(mem_ctx
);
2374 return NT_STATUS_OK
;
2377 BOOL
torture_samba3_rpc_spoolss(struct torture_context
*torture
)
2379 TALLOC_CTX
*mem_ctx
;
2381 struct smbcli_state
*cli
;
2382 struct dcerpc_pipe
*p
;
2384 struct policy_handle server_handle
, printer_handle
;
2385 const char **printers
;
2387 struct spoolss_UserLevel1 userlevel1
;
2390 if (!(mem_ctx
= talloc_new(torture
))) {
2394 if (!(torture_open_connection_share(
2395 mem_ctx
, &cli
, torture_setting_string(torture
, "host", NULL
),
2397 d_printf("IPC$ connection failed\n");
2398 talloc_free(mem_ctx
);
2402 status
= get_servername(mem_ctx
, cli
->tree
, &servername
);
2403 if (!NT_STATUS_IS_OK(status
)) {
2404 d_fprintf(stderr
, "(%s) get_servername returned %s\n",
2405 __location__
, nt_errstr(status
));
2406 talloc_free(mem_ctx
);
2410 if (!NT_STATUS_IS_OK(find_printers(mem_ctx
, cli
->tree
,
2411 &printers
, &num_printers
))) {
2412 talloc_free(mem_ctx
);
2416 if (num_printers
== 0) {
2417 d_printf("Did not find printers\n");
2418 talloc_free(mem_ctx
);
2422 status
= pipe_bind_smb(mem_ctx
, cli
->tree
, "\\spoolss",
2423 &dcerpc_table_spoolss
, &p
);
2424 if (!NT_STATUS_IS_OK(status
)) {
2425 d_printf("(%s) pipe_bind_smb failed: %s\n", __location__
,
2427 talloc_free(mem_ctx
);
2431 ZERO_STRUCT(userlevel1
);
2432 userlevel1
.client
= talloc_asprintf(
2433 mem_ctx
, "\\\\%s", lp_netbios_name());
2434 userlevel1
.user
= cli_credentials_get_username(cmdline_credentials
);
2435 userlevel1
.build
= 2600;
2436 userlevel1
.major
= 3;
2437 userlevel1
.minor
= 0;
2438 userlevel1
.processor
= 0;
2441 struct spoolss_OpenPrinterEx r
;
2444 r
.in
.printername
= talloc_asprintf(mem_ctx
, "\\\\%s",
2446 r
.in
.datatype
= NULL
;
2447 r
.in
.access_mask
= 0;
2449 r
.in
.userlevel
.level1
= &userlevel1
;
2450 r
.out
.handle
= &server_handle
;
2452 status
= dcerpc_spoolss_OpenPrinterEx(p
, mem_ctx
, &r
);
2453 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2454 d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
2455 "%s, %s\n", __location__
, nt_errstr(status
),
2456 win_errstr(r
.out
.result
));
2457 talloc_free(mem_ctx
);
2463 struct spoolss_ClosePrinter r
;
2465 r
.in
.handle
= &server_handle
;
2466 r
.out
.handle
= &server_handle
;
2468 status
= dcerpc_spoolss_ClosePrinter(p
, mem_ctx
, &r
);
2469 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2470 d_printf("(%s) dcerpc_spoolss_ClosePrinter failed: "
2471 "%s, %s\n", __location__
, nt_errstr(status
),
2472 win_errstr(r
.out
.result
));
2473 talloc_free(mem_ctx
);
2479 struct spoolss_OpenPrinterEx r
;
2482 r
.in
.printername
= talloc_asprintf(
2483 mem_ctx
, "\\\\%s\\%s", servername
, printers
[0]);
2484 r
.in
.datatype
= NULL
;
2485 r
.in
.access_mask
= 0;
2487 r
.in
.userlevel
.level1
= &userlevel1
;
2488 r
.out
.handle
= &printer_handle
;
2490 status
= dcerpc_spoolss_OpenPrinterEx(p
, mem_ctx
, &r
);
2491 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2492 d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
2493 "%s, %s\n", __location__
, nt_errstr(status
),
2494 win_errstr(r
.out
.result
));
2495 talloc_free(mem_ctx
);
2503 for (i
=0; i
<8; i
++) {
2504 status
= getprinterinfo(mem_ctx
, p
, &printer_handle
,
2506 if (!NT_STATUS_IS_OK(status
)) {
2507 d_printf("(%s) getprinterinfo %d failed: %s\n",
2508 __location__
, i
, nt_errstr(status
));
2515 struct spoolss_ClosePrinter r
;
2517 r
.in
.handle
= &printer_handle
;
2518 r
.out
.handle
= &printer_handle
;
2520 status
= dcerpc_spoolss_ClosePrinter(p
, mem_ctx
, &r
);
2521 if (!NT_STATUS_IS_OK(status
)) {
2522 d_printf("(%s) dcerpc_spoolss_ClosePrinter failed: "
2523 "%s\n", __location__
, nt_errstr(status
));
2524 talloc_free(mem_ctx
);
2531 if (!enumprinters(mem_ctx
, p
, servername
, 1,
2533 d_printf("(%s) enumprinters failed\n", __location__
);
2534 talloc_free(mem_ctx
);
2537 if (num_printers
!= num_enumerated
) {
2538 d_printf("(%s) netshareenum gave %d printers, "
2539 "enumprinters lvl 1 gave %d\n", __location__
,
2540 num_printers
, num_enumerated
);
2541 talloc_free(mem_ctx
);
2548 if (!enumprinters(mem_ctx
, p
, servername
, 2,
2550 d_printf("(%s) enumprinters failed\n", __location__
);
2551 talloc_free(mem_ctx
);
2554 if (num_printers
!= num_enumerated
) {
2555 d_printf("(%s) netshareenum gave %d printers, "
2556 "enumprinters lvl 2 gave %d\n", __location__
,
2557 num_printers
, num_enumerated
);
2558 talloc_free(mem_ctx
);
2563 talloc_free(mem_ctx
);
2568 BOOL
torture_samba3_rpc_wkssvc(struct torture_context
*torture
)
2570 TALLOC_CTX
*mem_ctx
;
2571 struct smbcli_state
*cli
;
2572 struct dcerpc_pipe
*p
;
2576 if (!(mem_ctx
= talloc_new(torture
))) {
2580 if (!(torture_open_connection_share(
2581 mem_ctx
, &cli
, torture_setting_string(torture
, "host", NULL
),
2583 d_printf("IPC$ connection failed\n");
2584 talloc_free(mem_ctx
);
2588 status
= get_servername(mem_ctx
, cli
->tree
, &servername
);
2589 if (!NT_STATUS_IS_OK(status
)) {
2590 d_fprintf(stderr
, "(%s) get_servername returned %s\n",
2591 __location__
, nt_errstr(status
));
2592 talloc_free(mem_ctx
);
2596 status
= pipe_bind_smb(mem_ctx
, cli
->tree
, "\\wkssvc",
2597 &dcerpc_table_wkssvc
, &p
);
2598 if (!NT_STATUS_IS_OK(status
)) {
2599 d_printf("(%s) pipe_bind_smb failed: %s\n", __location__
,
2601 talloc_free(mem_ctx
);
2606 struct wkssvc_NetWkstaInfo100 wks100
;
2607 union wkssvc_NetWkstaInfo info
;
2608 struct wkssvc_NetWkstaGetInfo r
;
2610 r
.in
.server_name
= "\\foo";
2612 info
.info100
= &wks100
;
2615 status
= dcerpc_wkssvc_NetWkstaGetInfo(p
, mem_ctx
, &r
);
2616 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2617 d_printf("(%s) dcerpc_wkssvc_NetWksGetInfo failed: "
2618 "%s, %s\n", __location__
, nt_errstr(status
),
2619 win_errstr(r
.out
.result
));
2620 talloc_free(mem_ctx
);
2624 if (strcmp(servername
,
2625 r
.out
.info
->info100
->server_name
) != 0) {
2626 d_printf("(%s) servername inconsistency: RAP=%s, "
2627 "dcerpc_wkssvc_NetWksGetInfo=%s",
2628 __location__
, servername
,
2629 r
.out
.info
->info100
->server_name
);
2630 talloc_free(mem_ctx
);
2635 talloc_free(mem_ctx
);
2639 static NTSTATUS
winreg_close(struct dcerpc_pipe
*p
,
2640 struct policy_handle
*handle
)
2642 struct winreg_CloseKey c
;
2644 TALLOC_CTX
*mem_ctx
;
2646 c
.in
.handle
= c
.out
.handle
= handle
;
2648 if (!(mem_ctx
= talloc_new(p
))) {
2649 return NT_STATUS_NO_MEMORY
;
2652 status
= dcerpc_winreg_CloseKey(p
, mem_ctx
, &c
);
2653 talloc_free(mem_ctx
);
2655 if (!NT_STATUS_IS_OK(status
)) {
2659 if (!W_ERROR_IS_OK(c
.out
.result
)) {
2660 return werror_to_ntstatus(c
.out
.result
);
2663 return NT_STATUS_OK
;
2666 static NTSTATUS
enumvalues(struct dcerpc_pipe
*p
, struct policy_handle
*handle
,
2667 TALLOC_CTX
*mem_ctx
)
2669 uint32_t enum_index
= 0;
2672 struct winreg_EnumValue r
;
2673 struct winreg_StringBuf name
;
2674 enum winreg_Type type
= 0;
2677 uint32_t size
, length
;
2679 r
.in
.handle
= handle
;
2680 r
.in
.enum_index
= enum_index
;
2683 r
.in
.name
= r
.out
.name
= &name
;
2689 r
.in
.length
= &length
;
2691 status
= dcerpc_winreg_EnumValue(p
, mem_ctx
, &r
);
2692 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2693 return NT_STATUS_OK
;
2699 static NTSTATUS
enumkeys(struct dcerpc_pipe
*p
, struct policy_handle
*handle
,
2700 TALLOC_CTX
*mem_ctx
, int depth
)
2702 struct winreg_EnumKey r
;
2703 struct winreg_StringBuf
class, name
;
2708 return NT_STATUS_OK
;
2714 r
.in
.handle
= handle
;
2715 r
.in
.enum_index
= 0;
2717 r
.in
.keyclass
= &class;
2719 r
.in
.last_changed_time
= &t
;
2722 TALLOC_CTX
*tmp_ctx
;
2723 struct winreg_OpenKey o
;
2724 struct policy_handle key_handle
;
2727 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
2728 return NT_STATUS_NO_MEMORY
;
2734 status
= dcerpc_winreg_EnumKey(p
, tmp_ctx
, &r
);
2735 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2736 /* We're done enumerating */
2737 talloc_free(tmp_ctx
);
2738 return NT_STATUS_OK
;
2741 for (i
=0; i
<10-depth
; i
++)
2743 printf("%s\n", r
.out
.name
->name
);
2746 o
.in
.parent_handle
= handle
;
2747 o
.in
.keyname
.name
= r
.out
.name
->name
;
2749 o
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2750 o
.out
.handle
= &key_handle
;
2752 status
= dcerpc_winreg_OpenKey(p
, tmp_ctx
, &o
);
2753 if (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(o
.out
.result
)) {
2754 enumkeys(p
, &key_handle
, tmp_ctx
, depth
-1);
2755 enumvalues(p
, &key_handle
, tmp_ctx
);
2756 status
= winreg_close(p
, &key_handle
);
2757 if (!NT_STATUS_IS_OK(status
)) {
2762 talloc_free(tmp_ctx
);
2764 r
.in
.enum_index
+= 1;
2767 return NT_STATUS_OK
;
2770 typedef NTSTATUS (*winreg_open_fn
)(struct dcerpc_pipe
*, TALLOC_CTX
*, void *);
2772 static BOOL
test_Open3(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
2773 const char *name
, winreg_open_fn open_fn
)
2775 struct policy_handle handle
;
2776 struct winreg_OpenHKLM r
;
2779 r
.in
.system_name
= 0;
2780 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2781 r
.out
.handle
= &handle
;
2783 status
= open_fn(p
, mem_ctx
, &r
);
2784 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2785 d_printf("(%s) %s failed: %s, %s\n", __location__
, name
,
2786 nt_errstr(status
), win_errstr(r
.out
.result
));
2790 enumkeys(p
, &handle
, mem_ctx
, 4);
2792 status
= winreg_close(p
, &handle
);
2793 if (!NT_STATUS_IS_OK(status
)) {
2794 d_printf("(%s) dcerpc_CloseKey failed: %s\n",
2795 __location__
, nt_errstr(status
));
2802 BOOL
torture_samba3_rpc_winreg(struct torture_context
*torture
)
2805 struct dcerpc_pipe
*p
;
2806 TALLOC_CTX
*mem_ctx
;
2812 {"OpenHKLM", (winreg_open_fn
)dcerpc_winreg_OpenHKLM
},
2813 {"OpenHKU", (winreg_open_fn
)dcerpc_winreg_OpenHKU
},
2814 {"OpenHKPD", (winreg_open_fn
)dcerpc_winreg_OpenHKPD
},
2815 {"OpenHKPT", (winreg_open_fn
)dcerpc_winreg_OpenHKPT
},
2816 {"OpenHKCR", (winreg_open_fn
)dcerpc_winreg_OpenHKCR
}};
2821 mem_ctx
= talloc_init("torture_rpc_winreg");
2823 status
= torture_rpc_connection(mem_ctx
, &p
, &dcerpc_table_winreg
);
2825 if (!NT_STATUS_IS_OK(status
)) {
2826 talloc_free(mem_ctx
);
2831 ret
= test_Open3(p
, mem_ctx
, open_fns
[0].name
, open_fns
[0].fn
);
2833 for (i
= 0; i
< ARRAY_SIZE(open_fns
); i
++) {
2834 if (!test_Open3(p
, mem_ctx
, open_fns
[i
].name
, open_fns
[i
].fn
))
2839 talloc_free(mem_ctx
);