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 3 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, see <http://www.gnu.org/licenses/>.
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/raw/raw_proto.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 "auth/ntlmssp/ntlmssp.h"
52 #include "libcli/security/security.h"
53 #include "param/param.h"
54 #include "lib/registry/registry.h"
55 #include "libcli/resolve/resolve.h"
58 * This tests a RPC call using an invalid vuid
61 bool torture_bind_authcontext(struct torture_context
*torture
)
66 struct lsa_ObjectAttribute objectattr
;
67 struct lsa_OpenPolicy2 openpolicy
;
68 struct policy_handle handle
;
69 struct lsa_Close close_handle
;
70 struct smbcli_session
*tmp
;
71 struct smbcli_session
*session2
;
72 struct smbcli_state
*cli
;
73 struct dcerpc_pipe
*lsa_pipe
;
74 struct cli_credentials
*anon_creds
;
75 struct smb_composite_sesssetup setup
;
76 struct smbcli_options options
;
77 struct smbcli_session_options session_options
;
79 mem_ctx
= talloc_init("torture_bind_authcontext");
81 if (mem_ctx
== NULL
) {
82 d_printf("talloc_init failed\n");
86 lp_smbcli_options(torture
->lp_ctx
, &options
);
87 lp_smbcli_session_options(torture
->lp_ctx
, &session_options
);
89 status
= smbcli_full_connection(mem_ctx
, &cli
,
90 torture_setting_string(torture
, "host", NULL
),
91 lp_smb_ports(torture
->lp_ctx
),
93 lp_socket_options(torture
->lp_ctx
),
95 lp_resolve_context(torture
->lp_ctx
),
96 torture
->ev
, &options
, &session_options
,
97 lp_iconv_convenience(torture
->lp_ctx
),
98 lp_gensec_settings(torture
, torture
->lp_ctx
));
99 if (!NT_STATUS_IS_OK(status
)) {
100 d_printf("smbcli_full_connection failed: %s\n",
105 lsa_pipe
= dcerpc_pipe_init(mem_ctx
, cli
->transport
->socket
->event
.ctx
,
106 lp_iconv_convenience(torture
->lp_ctx
));
107 if (lsa_pipe
== NULL
) {
108 d_printf("dcerpc_pipe_init failed\n");
112 status
= dcerpc_pipe_open_smb(lsa_pipe
, cli
->tree
, "\\lsarpc");
113 if (!NT_STATUS_IS_OK(status
)) {
114 d_printf("dcerpc_pipe_open_smb failed: %s\n",
119 status
= dcerpc_bind_auth_none(lsa_pipe
, &ndr_table_lsarpc
);
120 if (!NT_STATUS_IS_OK(status
)) {
121 d_printf("dcerpc_bind_auth_none failed: %s\n",
126 openpolicy
.in
.system_name
=talloc_asprintf(
127 mem_ctx
, "\\\\%s", dcerpc_server_name(lsa_pipe
));
128 ZERO_STRUCT(objectattr
);
129 openpolicy
.in
.attr
= &objectattr
;
130 openpolicy
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
131 openpolicy
.out
.handle
= &handle
;
133 status
= dcerpc_lsa_OpenPolicy2(lsa_pipe
, mem_ctx
, &openpolicy
);
135 if (!NT_STATUS_IS_OK(status
)) {
136 d_printf("dcerpc_lsa_OpenPolicy2 failed: %s\n",
141 close_handle
.in
.handle
= &handle
;
142 close_handle
.out
.handle
= &handle
;
144 status
= dcerpc_lsa_Close(lsa_pipe
, mem_ctx
, &close_handle
);
145 if (!NT_STATUS_IS_OK(status
)) {
146 d_printf("dcerpc_lsa_Close failed: %s\n",
151 session2
= smbcli_session_init(cli
->transport
, mem_ctx
, false, session_options
);
152 if (session2
== NULL
) {
153 d_printf("smbcli_session_init failed\n");
157 if (!(anon_creds
= cli_credentials_init_anon(mem_ctx
))) {
158 d_printf("create_anon_creds failed\n");
162 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
163 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
164 setup
.in
.workgroup
= "";
165 setup
.in
.credentials
= anon_creds
;
166 setup
.in
.gensec_settings
= lp_gensec_settings(torture
, torture
->lp_ctx
);
168 status
= smb_composite_sesssetup(session2
, &setup
);
169 if (!NT_STATUS_IS_OK(status
)) {
170 d_printf("anon session setup failed: %s\n",
174 session2
->vuid
= setup
.out
.vuid
;
176 tmp
= cli
->tree
->session
;
177 cli
->tree
->session
= session2
;
179 status
= dcerpc_lsa_OpenPolicy2(lsa_pipe
, mem_ctx
, &openpolicy
);
181 cli
->tree
->session
= tmp
;
182 talloc_free(lsa_pipe
);
185 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_HANDLE
)) {
186 d_printf("dcerpc_lsa_OpenPolicy2 with wrong vuid gave %s, "
187 "expected NT_STATUS_INVALID_HANDLE\n",
194 talloc_free(mem_ctx
);
199 * Bind to lsa using a specific auth method
202 static bool bindtest(struct smbcli_state
*cli
,
203 struct cli_credentials
*credentials
,
204 struct loadparm_context
*lp_ctx
,
205 uint8_t auth_type
, uint8_t auth_level
)
211 struct dcerpc_pipe
*lsa_pipe
;
212 struct lsa_ObjectAttribute objectattr
;
213 struct lsa_OpenPolicy2 openpolicy
;
214 struct lsa_QueryInfoPolicy query
;
215 union lsa_PolicyInformation
*info
= NULL
;
216 struct policy_handle handle
;
217 struct lsa_Close close_handle
;
219 if ((mem_ctx
= talloc_init("bindtest")) == NULL
) {
220 d_printf("talloc_init failed\n");
224 lsa_pipe
= dcerpc_pipe_init(mem_ctx
,
225 cli
->transport
->socket
->event
.ctx
,
226 lp_iconv_convenience(lp_ctx
));
227 if (lsa_pipe
== NULL
) {
228 d_printf("dcerpc_pipe_init failed\n");
232 status
= dcerpc_pipe_open_smb(lsa_pipe
, cli
->tree
, "\\lsarpc");
233 if (!NT_STATUS_IS_OK(status
)) {
234 d_printf("dcerpc_pipe_open_smb failed: %s\n",
239 status
= dcerpc_bind_auth(lsa_pipe
, &ndr_table_lsarpc
,
240 credentials
, lp_gensec_settings(lp_ctx
, lp_ctx
), auth_type
, auth_level
,
242 if (!NT_STATUS_IS_OK(status
)) {
243 d_printf("dcerpc_bind_auth failed: %s\n", nt_errstr(status
));
247 openpolicy
.in
.system_name
=talloc_asprintf(
248 mem_ctx
, "\\\\%s", dcerpc_server_name(lsa_pipe
));
249 ZERO_STRUCT(objectattr
);
250 openpolicy
.in
.attr
= &objectattr
;
251 openpolicy
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
252 openpolicy
.out
.handle
= &handle
;
254 status
= dcerpc_lsa_OpenPolicy2(lsa_pipe
, mem_ctx
, &openpolicy
);
256 if (!NT_STATUS_IS_OK(status
)) {
257 d_printf("dcerpc_lsa_OpenPolicy2 failed: %s\n",
262 query
.in
.handle
= &handle
;
263 query
.in
.level
= LSA_POLICY_INFO_DOMAIN
;
264 query
.out
.info
= &info
;
266 status
= dcerpc_lsa_QueryInfoPolicy(lsa_pipe
, mem_ctx
, &query
);
267 if (!NT_STATUS_IS_OK(status
)) {
268 d_printf("dcerpc_lsa_QueryInfoPolicy failed: %s\n",
273 close_handle
.in
.handle
= &handle
;
274 close_handle
.out
.handle
= &handle
;
276 status
= dcerpc_lsa_Close(lsa_pipe
, mem_ctx
, &close_handle
);
277 if (!NT_STATUS_IS_OK(status
)) {
278 d_printf("dcerpc_lsa_Close failed: %s\n",
285 talloc_free(mem_ctx
);
290 * test authenticated RPC binds with the variants Samba3 does support
293 bool torture_bind_samba3(struct torture_context
*torture
)
298 struct smbcli_state
*cli
;
299 struct smbcli_options options
;
300 struct smbcli_session_options session_options
;
302 mem_ctx
= talloc_init("torture_bind_authcontext");
304 if (mem_ctx
== NULL
) {
305 d_printf("talloc_init failed\n");
309 lp_smbcli_options(torture
->lp_ctx
, &options
);
310 lp_smbcli_session_options(torture
->lp_ctx
, &session_options
);
312 status
= smbcli_full_connection(mem_ctx
, &cli
,
313 torture_setting_string(torture
, "host", NULL
),
314 lp_smb_ports(torture
->lp_ctx
),
316 lp_socket_options(torture
->lp_ctx
),
318 lp_resolve_context(torture
->lp_ctx
),
319 torture
->ev
, &options
, &session_options
,
320 lp_iconv_convenience(torture
->lp_ctx
),
321 lp_gensec_settings(torture
, torture
->lp_ctx
));
322 if (!NT_STATUS_IS_OK(status
)) {
323 d_printf("smbcli_full_connection failed: %s\n",
330 ret
&= bindtest(cli
, cmdline_credentials
, torture
->lp_ctx
, DCERPC_AUTH_TYPE_NTLMSSP
,
331 DCERPC_AUTH_LEVEL_INTEGRITY
);
332 ret
&= bindtest(cli
, cmdline_credentials
, torture
->lp_ctx
, DCERPC_AUTH_TYPE_NTLMSSP
,
333 DCERPC_AUTH_LEVEL_PRIVACY
);
334 ret
&= bindtest(cli
, cmdline_credentials
, torture
->lp_ctx
, DCERPC_AUTH_TYPE_SPNEGO
,
335 DCERPC_AUTH_LEVEL_INTEGRITY
);
336 ret
&= bindtest(cli
, cmdline_credentials
, torture
->lp_ctx
, DCERPC_AUTH_TYPE_SPNEGO
,
337 DCERPC_AUTH_LEVEL_PRIVACY
);
340 talloc_free(mem_ctx
);
345 * Lookup or create a user and return all necessary info
348 static NTSTATUS
get_usr_handle(struct smbcli_state
*cli
,
350 struct loadparm_context
*lp_ctx
,
351 struct cli_credentials
*admin_creds
,
354 const char *username
,
356 struct dcerpc_pipe
**result_pipe
,
357 struct policy_handle
**result_handle
,
358 struct dom_sid
**sid_p
)
360 struct dcerpc_pipe
*samr_pipe
;
362 struct policy_handle conn_handle
;
363 struct policy_handle domain_handle
;
364 struct policy_handle
*user_handle
;
365 struct samr_Connect2 conn
;
366 struct samr_EnumDomains enumdom
;
367 uint32_t resume_handle
= 0;
368 uint32_t num_entries
= 0;
369 struct samr_SamArray
*sam
= NULL
;
370 struct samr_LookupDomain l
;
371 struct dom_sid2
*sid
= NULL
;
373 struct lsa_String domain_name
;
374 struct lsa_String user_name
;
375 struct samr_OpenDomain o
;
376 struct samr_CreateUser2 c
;
377 uint32_t user_rid
,access_granted
;
379 samr_pipe
= dcerpc_pipe_init(mem_ctx
,
380 cli
->transport
->socket
->event
.ctx
,
381 lp_iconv_convenience(lp_ctx
));
382 if (samr_pipe
== NULL
) {
383 d_printf("dcerpc_pipe_init failed\n");
384 status
= NT_STATUS_NO_MEMORY
;
388 status
= dcerpc_pipe_open_smb(samr_pipe
, cli
->tree
, "\\samr");
389 if (!NT_STATUS_IS_OK(status
)) {
390 d_printf("dcerpc_pipe_open_smb failed: %s\n",
395 if (admin_creds
!= NULL
) {
396 status
= dcerpc_bind_auth(samr_pipe
, &ndr_table_samr
,
397 admin_creds
, lp_gensec_settings(lp_ctx
, lp_ctx
), auth_type
, auth_level
,
399 if (!NT_STATUS_IS_OK(status
)) {
400 d_printf("dcerpc_bind_auth failed: %s\n",
405 /* We must have an authenticated SMB connection */
406 status
= dcerpc_bind_auth_none(samr_pipe
, &ndr_table_samr
);
407 if (!NT_STATUS_IS_OK(status
)) {
408 d_printf("dcerpc_bind_auth_none failed: %s\n",
414 conn
.in
.system_name
= talloc_asprintf(
415 mem_ctx
, "\\\\%s", dcerpc_server_name(samr_pipe
));
416 conn
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
417 conn
.out
.connect_handle
= &conn_handle
;
419 status
= dcerpc_samr_Connect2(samr_pipe
, mem_ctx
, &conn
);
420 if (!NT_STATUS_IS_OK(status
)) {
421 d_printf("samr_Connect2 failed: %s\n", nt_errstr(status
));
425 enumdom
.in
.connect_handle
= &conn_handle
;
426 enumdom
.in
.resume_handle
= &resume_handle
;
427 enumdom
.in
.buf_size
= (uint32_t)-1;
428 enumdom
.out
.resume_handle
= &resume_handle
;
429 enumdom
.out
.num_entries
= &num_entries
;
430 enumdom
.out
.sam
= &sam
;
432 status
= dcerpc_samr_EnumDomains(samr_pipe
, mem_ctx
, &enumdom
);
433 if (!NT_STATUS_IS_OK(status
)) {
434 d_printf("samr_EnumDomains failed: %s\n", nt_errstr(status
));
438 if (*enumdom
.out
.num_entries
!= 2) {
439 d_printf("samr_EnumDomains returned %d entries, expected 2\n",
440 *enumdom
.out
.num_entries
);
441 status
= NT_STATUS_UNSUCCESSFUL
;
445 dom_idx
= strequal(sam
->entries
[0].name
.string
,
448 l
.in
.connect_handle
= &conn_handle
;
449 domain_name
.string
= sam
->entries
[dom_idx
].name
.string
;
450 *domain
= talloc_strdup(mem_ctx
, domain_name
.string
);
451 l
.in
.domain_name
= &domain_name
;
454 status
= dcerpc_samr_LookupDomain(samr_pipe
, mem_ctx
, &l
);
455 if (!NT_STATUS_IS_OK(status
)) {
456 d_printf("samr_LookupDomain failed: %s\n", nt_errstr(status
));
460 o
.in
.connect_handle
= &conn_handle
;
461 o
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
462 o
.in
.sid
= *l
.out
.sid
;
463 o
.out
.domain_handle
= &domain_handle
;
465 status
= dcerpc_samr_OpenDomain(samr_pipe
, mem_ctx
, &o
);
466 if (!NT_STATUS_IS_OK(status
)) {
467 d_printf("samr_OpenDomain failed: %s\n", nt_errstr(status
));
471 c
.in
.domain_handle
= &domain_handle
;
472 user_name
.string
= username
;
473 c
.in
.account_name
= &user_name
;
474 c
.in
.acct_flags
= ACB_NORMAL
;
475 c
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
476 user_handle
= talloc(mem_ctx
, struct policy_handle
);
477 c
.out
.user_handle
= user_handle
;
478 c
.out
.access_granted
= &access_granted
;
479 c
.out
.rid
= &user_rid
;
481 status
= dcerpc_samr_CreateUser2(samr_pipe
, mem_ctx
, &c
);
483 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_EXISTS
)) {
484 struct samr_LookupNames ln
;
485 struct samr_OpenUser ou
;
486 struct samr_Ids rids
, types
;
488 ln
.in
.domain_handle
= &domain_handle
;
490 ln
.in
.names
= &user_name
;
492 ln
.out
.types
= &types
;
494 status
= dcerpc_samr_LookupNames(samr_pipe
, mem_ctx
, &ln
);
495 if (!NT_STATUS_IS_OK(status
)) {
496 d_printf("samr_LookupNames failed: %s\n",
501 ou
.in
.domain_handle
= &domain_handle
;
502 ou
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
503 user_rid
= ou
.in
.rid
= ln
.out
.rids
->ids
[0];
504 ou
.out
.user_handle
= user_handle
;
506 status
= dcerpc_samr_OpenUser(samr_pipe
, mem_ctx
, &ou
);
507 if (!NT_STATUS_IS_OK(status
)) {
508 d_printf("samr_OpenUser failed: %s\n",
514 if (!NT_STATUS_IS_OK(status
)) {
515 d_printf("samr_CreateUser failed: %s\n", nt_errstr(status
));
519 *result_pipe
= samr_pipe
;
520 *result_handle
= user_handle
;
522 *sid_p
= dom_sid_add_rid(mem_ctx
, *l
.out
.sid
, user_rid
);
534 static bool create_user(TALLOC_CTX
*mem_ctx
, struct smbcli_state
*cli
,
535 struct loadparm_context
*lp_ctx
,
536 struct cli_credentials
*admin_creds
,
537 const char *username
, const char *password
,
539 struct dom_sid
**user_sid
)
543 struct dcerpc_pipe
*samr_pipe
;
544 struct policy_handle
*wks_handle
;
547 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
548 d_printf("talloc_init failed\n");
552 status
= get_usr_handle(cli
, tmp_ctx
, lp_ctx
, admin_creds
,
553 DCERPC_AUTH_TYPE_NTLMSSP
,
554 DCERPC_AUTH_LEVEL_INTEGRITY
,
555 username
, domain_name
, &samr_pipe
, &wks_handle
,
557 if (!NT_STATUS_IS_OK(status
)) {
558 d_printf("get_usr_handle failed: %s\n", nt_errstr(status
));
563 struct samr_SetUserInfo2 sui2
;
564 struct samr_SetUserInfo sui
;
565 struct samr_QueryUserInfo qui
;
566 union samr_UserInfo u_info
;
567 union samr_UserInfo
*info
;
568 DATA_BLOB session_key
;
572 encode_pw_buffer(u_info
.info23
.password
.data
, password
,
575 status
= dcerpc_fetch_session_key(samr_pipe
, &session_key
);
576 if (!NT_STATUS_IS_OK(status
)) {
577 d_printf("dcerpc_fetch_session_key failed\n");
580 arcfour_crypt_blob(u_info
.info23
.password
.data
, 516,
582 u_info
.info23
.info
.password_expired
= 0;
583 u_info
.info23
.info
.fields_present
= SAMR_FIELD_NT_PASSWORD_PRESENT
|
584 SAMR_FIELD_LM_PASSWORD_PRESENT
|
585 SAMR_FIELD_EXPIRED_FLAG
;
586 sui2
.in
.user_handle
= wks_handle
;
587 sui2
.in
.info
= &u_info
;
590 status
= dcerpc_samr_SetUserInfo2(samr_pipe
, tmp_ctx
, &sui2
);
591 if (!NT_STATUS_IS_OK(status
)) {
592 d_printf("samr_SetUserInfo(23) failed: %s\n",
597 u_info
.info16
.acct_flags
= ACB_NORMAL
;
598 sui
.in
.user_handle
= wks_handle
;
599 sui
.in
.info
= &u_info
;
602 status
= dcerpc_samr_SetUserInfo(samr_pipe
, tmp_ctx
, &sui
);
603 if (!NT_STATUS_IS_OK(status
)) {
604 d_printf("samr_SetUserInfo(16) failed\n");
608 qui
.in
.user_handle
= wks_handle
;
610 qui
.out
.info
= &info
;
612 status
= dcerpc_samr_QueryUserInfo(samr_pipe
, tmp_ctx
, &qui
);
613 if (!NT_STATUS_IS_OK(status
)) {
614 d_printf("samr_QueryUserInfo(21) failed\n");
618 info
->info21
.allow_password_change
= 0;
619 info
->info21
.force_password_change
= 0;
620 info
->info21
.account_name
.string
= NULL
;
621 info
->info21
.rid
= 0;
622 info
->info21
.acct_expiry
= 0;
623 info
->info21
.fields_present
= 0x81827fa; /* copy usrmgr.exe */
625 u_info
.info21
= info
->info21
;
626 sui
.in
.user_handle
= wks_handle
;
627 sui
.in
.info
= &u_info
;
630 status
= dcerpc_samr_SetUserInfo(samr_pipe
, tmp_ctx
, &sui
);
631 if (!NT_STATUS_IS_OK(status
)) {
632 d_printf("samr_SetUserInfo(21) failed\n");
637 *domain_name
= talloc_steal(mem_ctx
, *domain_name
);
638 *user_sid
= talloc_steal(mem_ctx
, *user_sid
);
641 talloc_free(tmp_ctx
);
649 static bool delete_user(struct smbcli_state
*cli
,
650 struct loadparm_context
*lp_ctx
,
651 struct cli_credentials
*admin_creds
,
652 const char *username
)
657 struct dcerpc_pipe
*samr_pipe
;
658 struct policy_handle
*user_handle
;
661 if ((mem_ctx
= talloc_init("leave")) == NULL
) {
662 d_printf("talloc_init failed\n");
666 status
= get_usr_handle(cli
, mem_ctx
, lp_ctx
, admin_creds
,
667 DCERPC_AUTH_TYPE_NTLMSSP
,
668 DCERPC_AUTH_LEVEL_INTEGRITY
,
669 username
, &dom_name
, &samr_pipe
,
672 if (!NT_STATUS_IS_OK(status
)) {
673 d_printf("get_wks_handle failed: %s\n", nt_errstr(status
));
678 struct samr_DeleteUser d
;
680 d
.in
.user_handle
= user_handle
;
681 d
.out
.user_handle
= user_handle
;
683 status
= dcerpc_samr_DeleteUser(samr_pipe
, mem_ctx
, &d
);
684 if (!NT_STATUS_IS_OK(status
)) {
685 d_printf("samr_DeleteUser failed %s\n", nt_errstr(status
));
693 talloc_free(mem_ctx
);
698 * Do a Samba3-style join
701 static bool join3(struct smbcli_state
*cli
,
702 struct loadparm_context
*lp_ctx
,
704 struct cli_credentials
*admin_creds
,
705 struct cli_credentials
*wks_creds
)
710 struct dcerpc_pipe
*samr_pipe
;
711 struct policy_handle
*wks_handle
;
713 NTTIME last_password_change
;
715 if ((mem_ctx
= talloc_init("join3")) == NULL
) {
716 d_printf("talloc_init failed\n");
720 status
= get_usr_handle(
721 cli
, mem_ctx
, lp_ctx
, admin_creds
,
722 DCERPC_AUTH_TYPE_NTLMSSP
,
723 DCERPC_AUTH_LEVEL_PRIVACY
,
724 talloc_asprintf(mem_ctx
, "%s$",
725 cli_credentials_get_workstation(wks_creds
)),
726 &dom_name
, &samr_pipe
, &wks_handle
, NULL
);
728 if (!NT_STATUS_IS_OK(status
)) {
729 d_printf("get_wks_handle failed: %s\n", nt_errstr(status
));
734 struct samr_QueryUserInfo q
;
735 union samr_UserInfo
*info
;
737 q
.in
.user_handle
= wks_handle
;
741 status
= dcerpc_samr_QueryUserInfo(samr_pipe
, mem_ctx
, &q
);
742 if (!NT_STATUS_IS_OK(status
)) {
743 d_printf("(%s) QueryUserInfo failed: %s\n",
744 __location__
, nt_errstr(status
));
748 last_password_change
= info
->info21
.last_password_change
;
751 cli_credentials_set_domain(wks_creds
, dom_name
, CRED_SPECIFIED
);
754 struct samr_SetUserInfo2 sui2
;
755 union samr_UserInfo u_info
;
756 struct samr_UserInfo21
*i21
= &u_info
.info25
.info
;
757 DATA_BLOB session_key
;
758 DATA_BLOB confounded_session_key
= data_blob_talloc(
760 struct MD5Context ctx
;
761 uint8_t confounder
[16];
765 i21
->full_name
.string
= talloc_asprintf(
767 cli_credentials_get_workstation(wks_creds
));
768 i21
->acct_flags
= ACB_WSTRUST
;
769 i21
->fields_present
= SAMR_FIELD_FULL_NAME
|
770 SAMR_FIELD_ACCT_FLAGS
| SAMR_FIELD_NT_PASSWORD_PRESENT
;
771 /* this would break the test result expectations
772 i21->fields_present |= SAMR_FIELD_EXPIRED_FLAG;
773 i21->password_expired = 1;
776 encode_pw_buffer(u_info
.info25
.password
.data
,
777 cli_credentials_get_password(wks_creds
),
779 status
= dcerpc_fetch_session_key(samr_pipe
, &session_key
);
780 if (!NT_STATUS_IS_OK(status
)) {
781 d_printf("dcerpc_fetch_session_key failed: %s\n",
785 generate_random_buffer((uint8_t *)confounder
, 16);
788 MD5Update(&ctx
, confounder
, 16);
789 MD5Update(&ctx
, session_key
.data
, session_key
.length
);
790 MD5Final(confounded_session_key
.data
, &ctx
);
792 arcfour_crypt_blob(u_info
.info25
.password
.data
, 516,
793 &confounded_session_key
);
794 memcpy(&u_info
.info25
.password
.data
[516], confounder
, 16);
796 sui2
.in
.user_handle
= wks_handle
;
798 sui2
.in
.info
= &u_info
;
800 status
= dcerpc_samr_SetUserInfo2(samr_pipe
, mem_ctx
, &sui2
);
801 if (!NT_STATUS_IS_OK(status
)) {
802 d_printf("samr_SetUserInfo2(25) failed: %s\n",
807 struct samr_SetUserInfo2 sui2
;
808 struct samr_SetUserInfo sui
;
809 union samr_UserInfo u_info
;
810 DATA_BLOB session_key
;
812 encode_pw_buffer(u_info
.info24
.password
.data
,
813 cli_credentials_get_password(wks_creds
),
815 /* just to make this test pass */
816 u_info
.info24
.password_expired
= 1;
818 status
= dcerpc_fetch_session_key(samr_pipe
, &session_key
);
819 if (!NT_STATUS_IS_OK(status
)) {
820 d_printf("dcerpc_fetch_session_key failed\n");
823 arcfour_crypt_blob(u_info
.info24
.password
.data
, 516,
825 sui2
.in
.user_handle
= wks_handle
;
826 sui2
.in
.info
= &u_info
;
829 status
= dcerpc_samr_SetUserInfo2(samr_pipe
, mem_ctx
, &sui2
);
830 if (!NT_STATUS_IS_OK(status
)) {
831 d_printf("samr_SetUserInfo(24) failed: %s\n",
836 u_info
.info16
.acct_flags
= ACB_WSTRUST
;
837 sui
.in
.user_handle
= wks_handle
;
838 sui
.in
.info
= &u_info
;
841 status
= dcerpc_samr_SetUserInfo(samr_pipe
, mem_ctx
, &sui
);
842 if (!NT_STATUS_IS_OK(status
)) {
843 d_printf("samr_SetUserInfo(16) failed\n");
849 struct samr_QueryUserInfo q
;
850 union samr_UserInfo
*info
;
852 q
.in
.user_handle
= wks_handle
;
856 status
= dcerpc_samr_QueryUserInfo(samr_pipe
, mem_ctx
, &q
);
857 if (!NT_STATUS_IS_OK(status
)) {
858 d_printf("(%s) QueryUserInfo failed: %s\n",
859 __location__
, nt_errstr(status
));
864 if (last_password_change
865 == info
->info21
.last_password_change
) {
866 d_printf("(%s) last_password_change unchanged "
867 "during join, level25 must change "
868 "it\n", __location__
);
873 if (last_password_change
874 != info
->info21
.last_password_change
) {
875 d_printf("(%s) last_password_change changed "
876 "during join, level24 doesn't "
877 "change it\n", __location__
);
886 talloc_free(mem_ctx
);
891 * Do a ReqChallenge/Auth2 and get the wks creds
894 static bool auth2(struct smbcli_state
*cli
,
895 struct loadparm_context
*lp_ctx
,
896 struct cli_credentials
*wks_cred
)
899 struct dcerpc_pipe
*net_pipe
;
902 struct netr_ServerReqChallenge r
;
903 struct netr_Credential netr_cli_creds
;
904 struct netr_Credential netr_srv_creds
;
905 uint32_t negotiate_flags
;
906 struct netr_ServerAuthenticate2 a
;
907 struct netlogon_creds_CredentialState
*creds_state
;
908 struct netr_Credential netr_cred
;
909 struct samr_Password mach_pw
;
911 mem_ctx
= talloc_new(NULL
);
912 if (mem_ctx
== NULL
) {
913 d_printf("talloc_new failed\n");
917 net_pipe
= dcerpc_pipe_init(mem_ctx
,
918 cli
->transport
->socket
->event
.ctx
,
919 lp_iconv_convenience(lp_ctx
));
920 if (net_pipe
== NULL
) {
921 d_printf("dcerpc_pipe_init failed\n");
925 status
= dcerpc_pipe_open_smb(net_pipe
, cli
->tree
, "\\netlogon");
926 if (!NT_STATUS_IS_OK(status
)) {
927 d_printf("dcerpc_pipe_open_smb failed: %s\n",
932 status
= dcerpc_bind_auth_none(net_pipe
, &ndr_table_netlogon
);
933 if (!NT_STATUS_IS_OK(status
)) {
934 d_printf("dcerpc_bind_auth_none failed: %s\n",
939 r
.in
.computer_name
= cli_credentials_get_workstation(wks_cred
);
940 r
.in
.server_name
= talloc_asprintf(
941 mem_ctx
, "\\\\%s", dcerpc_server_name(net_pipe
));
942 if (r
.in
.server_name
== NULL
) {
943 d_printf("talloc_asprintf failed\n");
946 generate_random_buffer(netr_cli_creds
.data
,
947 sizeof(netr_cli_creds
.data
));
948 r
.in
.credentials
= &netr_cli_creds
;
949 r
.out
.return_credentials
= &netr_srv_creds
;
951 status
= dcerpc_netr_ServerReqChallenge(net_pipe
, mem_ctx
, &r
);
952 if (!NT_STATUS_IS_OK(status
)) {
953 d_printf("netr_ServerReqChallenge failed: %s\n",
958 negotiate_flags
= NETLOGON_NEG_AUTH2_FLAGS
;
959 E_md4hash(cli_credentials_get_password(wks_cred
), mach_pw
.hash
);
961 a
.in
.server_name
= talloc_asprintf(
962 mem_ctx
, "\\\\%s", dcerpc_server_name(net_pipe
));
963 a
.in
.account_name
= talloc_asprintf(
964 mem_ctx
, "%s$", cli_credentials_get_workstation(wks_cred
));
965 a
.in
.computer_name
= cli_credentials_get_workstation(wks_cred
);
966 a
.in
.secure_channel_type
= SEC_CHAN_WKSTA
;
967 a
.in
.negotiate_flags
= &negotiate_flags
;
968 a
.out
.negotiate_flags
= &negotiate_flags
;
969 a
.in
.credentials
= &netr_cred
;
970 a
.out
.return_credentials
= &netr_cred
;
972 creds_state
= netlogon_creds_client_init(mem_ctx
,
976 r
.out
.return_credentials
, &mach_pw
,
977 &netr_cred
, negotiate_flags
);
979 status
= dcerpc_netr_ServerAuthenticate2(net_pipe
, mem_ctx
, &a
);
980 if (!NT_STATUS_IS_OK(status
)) {
981 d_printf("netr_ServerServerAuthenticate2 failed: %s\n",
986 if (!netlogon_creds_client_check(creds_state
, a
.out
.return_credentials
)) {
987 d_printf("creds_client_check failed\n");
991 cli_credentials_set_netlogon_creds(wks_cred
, creds_state
);
996 talloc_free(mem_ctx
);
1001 * Do a couple of schannel protected Netlogon ops: Interactive and Network
1002 * login, and change the wks password
1005 static bool schan(struct smbcli_state
*cli
,
1006 struct loadparm_context
*lp_ctx
,
1007 struct cli_credentials
*wks_creds
,
1008 struct cli_credentials
*user_creds
)
1010 TALLOC_CTX
*mem_ctx
;
1013 struct dcerpc_pipe
*net_pipe
;
1016 mem_ctx
= talloc_new(NULL
);
1017 if (mem_ctx
== NULL
) {
1018 d_printf("talloc_new failed\n");
1022 net_pipe
= dcerpc_pipe_init(mem_ctx
,
1023 cli
->transport
->socket
->event
.ctx
,
1024 lp_iconv_convenience(lp_ctx
));
1025 if (net_pipe
== NULL
) {
1026 d_printf("dcerpc_pipe_init failed\n");
1030 status
= dcerpc_pipe_open_smb(net_pipe
, cli
->tree
, "\\netlogon");
1031 if (!NT_STATUS_IS_OK(status
)) {
1032 d_printf("dcerpc_pipe_open_smb failed: %s\n",
1038 net_pipe
->conn
->flags
|= DCERPC_DEBUG_PRINT_IN
|
1039 DCERPC_DEBUG_PRINT_OUT
;
1042 net_pipe
->conn
->flags
|= (DCERPC_SIGN
| DCERPC_SEAL
);
1043 status
= dcerpc_bind_auth(net_pipe
, &ndr_table_netlogon
,
1044 wks_creds
, lp_gensec_settings(lp_ctx
, lp_ctx
), DCERPC_AUTH_TYPE_SCHANNEL
,
1045 DCERPC_AUTH_LEVEL_PRIVACY
,
1048 status
= dcerpc_bind_auth_none(net_pipe
, &ndr_table_netlogon
);
1050 if (!NT_STATUS_IS_OK(status
)) {
1051 d_printf("schannel bind failed: %s\n", nt_errstr(status
));
1056 for (i
=2; i
<4; i
++) {
1058 DATA_BLOB chal
, nt_resp
, lm_resp
, names_blob
, session_key
;
1059 struct netlogon_creds_CredentialState
*creds_state
;
1060 struct netr_Authenticator netr_auth
, netr_auth2
;
1061 struct netr_NetworkInfo ninfo
;
1062 struct netr_PasswordInfo pinfo
;
1063 struct netr_LogonSamLogon r
;
1064 union netr_LogonLevel logon
;
1065 union netr_Validation validation
;
1066 uint8_t authoritative
;
1067 struct netr_Authenticator return_authenticator
;
1069 flags
= CLI_CRED_LANMAN_AUTH
| CLI_CRED_NTLM_AUTH
|
1070 CLI_CRED_NTLMv2_AUTH
;
1072 chal
= data_blob_talloc(mem_ctx
, NULL
, 8);
1073 if (chal
.data
== NULL
) {
1074 d_printf("data_blob_talloc failed\n");
1078 generate_random_buffer(chal
.data
, chal
.length
);
1079 names_blob
= NTLMv2_generate_names_blob(
1081 cli_credentials_get_workstation(user_creds
),
1082 cli_credentials_get_domain(user_creds
));
1083 status
= cli_credentials_get_ntlm_response(
1084 user_creds
, mem_ctx
, &flags
, chal
, names_blob
,
1085 &lm_resp
, &nt_resp
, NULL
, NULL
);
1086 if (!NT_STATUS_IS_OK(status
)) {
1087 d_printf("cli_credentials_get_ntlm_response failed:"
1088 " %s\n", nt_errstr(status
));
1092 creds_state
= cli_credentials_get_netlogon_creds(wks_creds
);
1093 netlogon_creds_client_authenticator(creds_state
, &netr_auth
);
1095 ninfo
.identity_info
.account_name
.string
=
1096 cli_credentials_get_username(user_creds
);
1097 ninfo
.identity_info
.domain_name
.string
=
1098 cli_credentials_get_domain(user_creds
);
1099 ninfo
.identity_info
.parameter_control
= 0;
1100 ninfo
.identity_info
.logon_id_low
= 0;
1101 ninfo
.identity_info
.logon_id_high
= 0;
1102 ninfo
.identity_info
.workstation
.string
=
1103 cli_credentials_get_workstation(user_creds
);
1104 memcpy(ninfo
.challenge
, chal
.data
, sizeof(ninfo
.challenge
));
1105 ninfo
.nt
.length
= nt_resp
.length
;
1106 ninfo
.nt
.data
= nt_resp
.data
;
1107 ninfo
.lm
.length
= lm_resp
.length
;
1108 ninfo
.lm
.data
= lm_resp
.data
;
1110 logon
.network
= &ninfo
;
1112 r
.in
.server_name
= talloc_asprintf(
1113 mem_ctx
, "\\\\%s", dcerpc_server_name(net_pipe
));
1114 ZERO_STRUCT(netr_auth2
);
1115 r
.in
.computer_name
=
1116 cli_credentials_get_workstation(wks_creds
);
1117 r
.in
.credential
= &netr_auth
;
1118 r
.in
.return_authenticator
= &netr_auth2
;
1119 r
.in
.logon_level
= 2;
1120 r
.in
.validation_level
= i
;
1121 r
.in
.logon
= &logon
;
1122 r
.out
.validation
= &validation
;
1123 r
.out
.authoritative
= &authoritative
;
1124 r
.out
.return_authenticator
= &return_authenticator
;
1126 status
= dcerpc_netr_LogonSamLogon(net_pipe
, mem_ctx
, &r
);
1127 if (!NT_STATUS_IS_OK(status
)) {
1128 d_printf("netr_LogonSamLogon failed: %s\n",
1133 if ((r
.out
.return_authenticator
== NULL
) ||
1134 (!netlogon_creds_client_check(creds_state
,
1135 &r
.out
.return_authenticator
->cred
))) {
1136 d_printf("Credentials check failed!\n");
1140 netlogon_creds_client_authenticator(creds_state
, &netr_auth
);
1142 pinfo
.identity_info
= ninfo
.identity_info
;
1143 ZERO_STRUCT(pinfo
.lmpassword
.hash
);
1144 E_md4hash(cli_credentials_get_password(user_creds
),
1145 pinfo
.ntpassword
.hash
);
1146 session_key
= data_blob_talloc(mem_ctx
,
1147 creds_state
->session_key
, 16);
1148 arcfour_crypt_blob(pinfo
.ntpassword
.hash
,
1149 sizeof(pinfo
.ntpassword
.hash
),
1152 logon
.password
= &pinfo
;
1154 r
.in
.logon_level
= 1;
1155 r
.in
.logon
= &logon
;
1156 r
.out
.return_authenticator
= &return_authenticator
;
1158 status
= dcerpc_netr_LogonSamLogon(net_pipe
, mem_ctx
, &r
);
1159 if (!NT_STATUS_IS_OK(status
)) {
1160 d_printf("netr_LogonSamLogon failed: %s\n",
1165 if ((r
.out
.return_authenticator
== NULL
) ||
1166 (!netlogon_creds_client_check(creds_state
,
1167 &r
.out
.return_authenticator
->cred
))) {
1168 d_printf("Credentials check failed!\n");
1174 struct netr_ServerPasswordSet s
;
1175 char *password
= generate_random_str(wks_creds
, 8);
1176 struct netlogon_creds_CredentialState
*creds_state
;
1177 struct netr_Authenticator credential
, return_authenticator
;
1178 struct samr_Password new_password
;
1180 s
.in
.server_name
= talloc_asprintf(
1181 mem_ctx
, "\\\\%s", dcerpc_server_name(net_pipe
));
1182 s
.in
.computer_name
= cli_credentials_get_workstation(wks_creds
);
1183 s
.in
.account_name
= talloc_asprintf(
1184 mem_ctx
, "%s$", s
.in
.computer_name
);
1185 s
.in
.secure_channel_type
= SEC_CHAN_WKSTA
;
1186 s
.in
.credential
= &credential
;
1187 s
.in
.new_password
= &new_password
;
1188 s
.out
.return_authenticator
= &return_authenticator
;
1190 E_md4hash(password
, new_password
.hash
);
1192 creds_state
= cli_credentials_get_netlogon_creds(wks_creds
);
1193 netlogon_creds_des_encrypt(creds_state
, &new_password
);
1194 netlogon_creds_client_authenticator(creds_state
, &credential
);
1196 status
= dcerpc_netr_ServerPasswordSet(net_pipe
, mem_ctx
, &s
);
1197 if (!NT_STATUS_IS_OK(status
)) {
1198 printf("ServerPasswordSet - %s\n", nt_errstr(status
));
1202 if (!netlogon_creds_client_check(creds_state
,
1203 &s
.out
.return_authenticator
->cred
)) {
1204 printf("Credential chaining failed\n");
1207 cli_credentials_set_password(wks_creds
, password
,
1213 talloc_free(mem_ctx
);
1218 * Delete the wks account again
1221 static bool leave(struct smbcli_state
*cli
,
1222 struct loadparm_context
*lp_ctx
,
1223 struct cli_credentials
*admin_creds
,
1224 struct cli_credentials
*wks_creds
)
1226 char *wks_name
= talloc_asprintf(
1227 NULL
, "%s$", cli_credentials_get_workstation(wks_creds
));
1230 ret
= delete_user(cli
, lp_ctx
, admin_creds
, wks_name
);
1231 talloc_free(wks_name
);
1236 * Test the Samba3 DC code a bit. Join, do some schan netlogon ops, leave
1239 bool torture_netlogon_samba3(struct torture_context
*torture
)
1241 TALLOC_CTX
*mem_ctx
;
1244 struct smbcli_state
*cli
;
1245 struct cli_credentials
*anon_creds
;
1246 struct cli_credentials
*wks_creds
;
1247 const char *wks_name
;
1249 struct smbcli_options options
;
1250 struct smbcli_session_options session_options
;
1252 wks_name
= torture_setting_string(torture
, "wksname", NULL
);
1253 if (wks_name
== NULL
) {
1254 wks_name
= get_myname(torture
);
1257 mem_ctx
= talloc_init("torture_netlogon_samba3");
1259 if (mem_ctx
== NULL
) {
1260 d_printf("talloc_init failed\n");
1264 if (!(anon_creds
= cli_credentials_init_anon(mem_ctx
))) {
1265 d_printf("create_anon_creds failed\n");
1269 lp_smbcli_options(torture
->lp_ctx
, &options
);
1270 lp_smbcli_session_options(torture
->lp_ctx
, &session_options
);
1272 status
= smbcli_full_connection(mem_ctx
, &cli
,
1273 torture_setting_string(torture
, "host", NULL
),
1274 lp_smb_ports(torture
->lp_ctx
),
1276 lp_socket_options(torture
->lp_ctx
),
1278 lp_resolve_context(torture
->lp_ctx
),
1279 torture
->ev
, &options
, &session_options
,
1280 lp_iconv_convenience(torture
->lp_ctx
),
1281 lp_gensec_settings(torture
, torture
->lp_ctx
));
1282 if (!NT_STATUS_IS_OK(status
)) {
1283 d_printf("smbcli_full_connection failed: %s\n",
1288 wks_creds
= cli_credentials_init(mem_ctx
);
1289 if (wks_creds
== NULL
) {
1290 d_printf("cli_credentials_init failed\n");
1294 cli_credentials_set_conf(wks_creds
, torture
->lp_ctx
);
1295 cli_credentials_set_secure_channel_type(wks_creds
, SEC_CHAN_WKSTA
);
1296 cli_credentials_set_username(wks_creds
, wks_name
, CRED_SPECIFIED
);
1297 cli_credentials_set_workstation(wks_creds
, wks_name
, CRED_SPECIFIED
);
1298 cli_credentials_set_password(wks_creds
,
1299 generate_random_str(wks_creds
, 8),
1302 if (!join3(cli
, torture
->lp_ctx
, false, cmdline_credentials
, wks_creds
)) {
1303 d_printf("join failed\n");
1307 cli_credentials_set_domain(
1308 cmdline_credentials
, cli_credentials_get_domain(wks_creds
),
1311 for (i
=0; i
<2; i
++) {
1313 /* Do this more than once, the routine "schan" changes
1314 * the workstation password using the netlogon
1315 * password change routine */
1319 if (!auth2(cli
, torture
->lp_ctx
, wks_creds
)) {
1320 d_printf("auth2 failed\n");
1324 for (j
=0; j
<2; j
++) {
1325 if (!schan(cli
, torture
->lp_ctx
, wks_creds
, cmdline_credentials
)) {
1326 d_printf("schan failed\n");
1332 if (!leave(cli
, torture
->lp_ctx
, cmdline_credentials
, wks_creds
)) {
1333 d_printf("leave failed\n");
1340 talloc_free(mem_ctx
);
1345 * Do a simple join, testjoin and leave using specified smb and samr
1349 static bool test_join3(struct torture_context
*tctx
,
1351 struct cli_credentials
*smb_creds
,
1352 struct cli_credentials
*samr_creds
,
1353 const char *wks_name
)
1357 struct smbcli_state
*cli
;
1358 struct cli_credentials
*wks_creds
;
1359 struct smbcli_options options
;
1360 struct smbcli_session_options session_options
;
1362 lp_smbcli_options(tctx
->lp_ctx
, &options
);
1363 lp_smbcli_session_options(tctx
->lp_ctx
, &session_options
);
1365 status
= smbcli_full_connection(tctx
, &cli
,
1366 torture_setting_string(tctx
, "host", NULL
),
1367 lp_smb_ports(tctx
->lp_ctx
),
1368 "IPC$", NULL
, lp_socket_options(tctx
->lp_ctx
),
1369 smb_creds
, lp_resolve_context(tctx
->lp_ctx
),
1370 tctx
->ev
, &options
, &session_options
,
1371 lp_iconv_convenience(tctx
->lp_ctx
),
1372 lp_gensec_settings(tctx
, tctx
->lp_ctx
));
1373 if (!NT_STATUS_IS_OK(status
)) {
1374 d_printf("smbcli_full_connection failed: %s\n",
1379 wks_creds
= cli_credentials_init(cli
);
1380 if (wks_creds
== NULL
) {
1381 d_printf("cli_credentials_init failed\n");
1385 cli_credentials_set_conf(wks_creds
, tctx
->lp_ctx
);
1386 cli_credentials_set_secure_channel_type(wks_creds
, SEC_CHAN_WKSTA
);
1387 cli_credentials_set_username(wks_creds
, wks_name
, CRED_SPECIFIED
);
1388 cli_credentials_set_workstation(wks_creds
, wks_name
, CRED_SPECIFIED
);
1389 cli_credentials_set_password(wks_creds
,
1390 generate_random_str(wks_creds
, 8),
1393 if (!join3(cli
, tctx
->lp_ctx
, use_level25
, samr_creds
, wks_creds
)) {
1394 d_printf("join failed\n");
1398 cli_credentials_set_domain(
1399 cmdline_credentials
, cli_credentials_get_domain(wks_creds
),
1402 if (!auth2(cli
, tctx
->lp_ctx
, wks_creds
)) {
1403 d_printf("auth2 failed\n");
1407 if (!leave(cli
, tctx
->lp_ctx
, samr_creds
, wks_creds
)) {
1408 d_printf("leave failed\n");
1421 * Test the different session key variants. Do it by joining, this uses the
1422 * session key in the setpassword routine. Test the join by doing the auth2.
1425 bool torture_samba3_sessionkey(struct torture_context
*torture
)
1428 struct cli_credentials
*anon_creds
;
1429 const char *wks_name
;
1431 wks_name
= torture_setting_string(torture
, "wksname", get_myname(torture
));
1433 if (!(anon_creds
= cli_credentials_init_anon(torture
))) {
1434 d_printf("create_anon_creds failed\n");
1438 cli_credentials_set_workstation(anon_creds
, wks_name
, CRED_SPECIFIED
);
1442 if (!torture_setting_bool(torture
, "samba3", false)) {
1444 /* Samba3 in the build farm right now does this happily. Need
1447 if (test_join3(torture
, false, anon_creds
, NULL
, wks_name
)) {
1448 d_printf("join using anonymous bind on an anonymous smb "
1449 "connection succeeded -- HUH??\n");
1454 if (!test_join3(torture
, false, anon_creds
, cmdline_credentials
,
1456 d_printf("join using ntlmssp bind on an anonymous smb "
1457 "connection failed\n");
1461 if (!test_join3(torture
, false, cmdline_credentials
, NULL
, wks_name
)) {
1462 d_printf("join using anonymous bind on an authenticated smb "
1463 "connection failed\n");
1467 if (!test_join3(torture
, false, cmdline_credentials
,
1468 cmdline_credentials
,
1470 d_printf("join using ntlmssp bind on an authenticated smb "
1471 "connection failed\n");
1476 * The following two are tests for setuserinfolevel 25
1479 if (!test_join3(torture
, true, anon_creds
, cmdline_credentials
,
1481 d_printf("join using ntlmssp bind on an anonymous smb "
1482 "connection failed\n");
1486 if (!test_join3(torture
, true, cmdline_credentials
, NULL
, wks_name
)) {
1487 d_printf("join using anonymous bind on an authenticated smb "
1488 "connection failed\n");
1498 * open pipe and bind, given an IPC$ context
1501 static NTSTATUS
pipe_bind_smb(TALLOC_CTX
*mem_ctx
,
1502 struct loadparm_context
*lp_ctx
,
1503 struct smbcli_tree
*tree
,
1504 const char *pipe_name
,
1505 const struct ndr_interface_table
*iface
,
1506 struct dcerpc_pipe
**p
)
1508 struct dcerpc_pipe
*result
;
1511 if (!(result
= dcerpc_pipe_init(
1512 mem_ctx
, tree
->session
->transport
->socket
->event
.ctx
,
1513 lp_iconv_convenience(lp_ctx
)))) {
1514 return NT_STATUS_NO_MEMORY
;
1517 status
= dcerpc_pipe_open_smb(result
, tree
, pipe_name
);
1518 if (!NT_STATUS_IS_OK(status
)) {
1519 d_printf("dcerpc_pipe_open_smb failed: %s\n",
1521 talloc_free(result
);
1525 status
= dcerpc_bind_auth_none(result
, iface
);
1526 if (!NT_STATUS_IS_OK(status
)) {
1527 d_printf("schannel bind failed: %s\n", nt_errstr(status
));
1528 talloc_free(result
);
1533 return NT_STATUS_OK
;
1537 * Sane wrapper around lsa_LookupNames
1540 static struct dom_sid
*name2sid(TALLOC_CTX
*mem_ctx
,
1541 struct dcerpc_pipe
*p
,
1545 struct lsa_ObjectAttribute attr
;
1546 struct lsa_QosInfo qos
;
1547 struct lsa_OpenPolicy2 r
;
1550 struct policy_handle handle
;
1551 struct lsa_LookupNames l
;
1552 struct lsa_TransSidArray sids
;
1553 struct lsa_RefDomainList
*domains
= NULL
;
1554 struct lsa_String lsa_name
;
1556 struct dom_sid
*result
;
1557 TALLOC_CTX
*tmp_ctx
;
1559 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
1564 qos
.impersonation_level
= 2;
1565 qos
.context_mode
= 1;
1566 qos
.effective_only
= 0;
1569 attr
.root_dir
= NULL
;
1570 attr
.object_name
= NULL
;
1571 attr
.attributes
= 0;
1572 attr
.sec_desc
= NULL
;
1573 attr
.sec_qos
= &qos
;
1575 r
.in
.system_name
= "\\";
1577 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1578 r
.out
.handle
= &handle
;
1580 status
= dcerpc_lsa_OpenPolicy2(p
, tmp_ctx
, &r
);
1581 if (!NT_STATUS_IS_OK(status
)) {
1582 printf("OpenPolicy2 failed - %s\n", nt_errstr(status
));
1583 talloc_free(tmp_ctx
);
1590 lsa_name
.string
= talloc_asprintf(tmp_ctx
, "%s\\%s", domain
, name
);
1592 l
.in
.handle
= &handle
;
1594 l
.in
.names
= &lsa_name
;
1597 l
.in
.count
= &count
;
1598 l
.out
.count
= &count
;
1600 l
.out
.domains
= &domains
;
1602 status
= dcerpc_lsa_LookupNames(p
, tmp_ctx
, &l
);
1603 if (!NT_STATUS_IS_OK(status
)) {
1604 printf("LookupNames of %s failed - %s\n", lsa_name
.string
,
1606 talloc_free(tmp_ctx
);
1610 result
= dom_sid_add_rid(mem_ctx
, domains
->domains
[0].sid
,
1611 l
.out
.sids
->sids
[0].rid
);
1613 c
.in
.handle
= &handle
;
1614 c
.out
.handle
= &handle
;
1616 status
= dcerpc_lsa_Close(p
, tmp_ctx
, &c
);
1617 if (!NT_STATUS_IS_OK(status
)) {
1618 printf("dcerpc_lsa_Close failed - %s\n", nt_errstr(status
));
1619 talloc_free(tmp_ctx
);
1623 talloc_free(tmp_ctx
);
1628 * Find out the user SID on this connection
1631 static struct dom_sid
*whoami(TALLOC_CTX
*mem_ctx
,
1632 struct loadparm_context
*lp_ctx
,
1633 struct smbcli_tree
*tree
)
1635 struct dcerpc_pipe
*lsa
;
1636 struct lsa_GetUserName r
;
1638 struct lsa_String
*authority_name_p
= NULL
;
1639 struct lsa_String
*account_name_p
= NULL
;
1640 struct dom_sid
*result
;
1642 status
= pipe_bind_smb(mem_ctx
, lp_ctx
, tree
, "\\pipe\\lsarpc",
1643 &ndr_table_lsarpc
, &lsa
);
1644 if (!NT_STATUS_IS_OK(status
)) {
1645 d_printf("(%s) Could not bind to LSA: %s\n",
1646 __location__
, nt_errstr(status
));
1650 r
.in
.system_name
= "\\";
1651 r
.in
.account_name
= &account_name_p
;
1652 r
.in
.authority_name
= &authority_name_p
;
1653 r
.out
.account_name
= &account_name_p
;
1655 status
= dcerpc_lsa_GetUserName(lsa
, mem_ctx
, &r
);
1657 authority_name_p
= *r
.out
.authority_name
;
1659 if (!NT_STATUS_IS_OK(status
)) {
1660 printf("(%s) GetUserName failed - %s\n",
1661 __location__
, nt_errstr(status
));
1666 result
= name2sid(mem_ctx
, lsa
, account_name_p
->string
,
1667 authority_name_p
->string
);
1673 static int destroy_tree(struct smbcli_tree
*tree
)
1675 smb_tree_disconnect(tree
);
1680 * Do a tcon, given a session
1683 NTSTATUS
secondary_tcon(TALLOC_CTX
*mem_ctx
,
1684 struct smbcli_session
*session
,
1685 const char *sharename
,
1686 struct smbcli_tree
**res
)
1688 struct smbcli_tree
*result
;
1689 TALLOC_CTX
*tmp_ctx
;
1690 union smb_tcon tcon
;
1693 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
1694 return NT_STATUS_NO_MEMORY
;
1697 if (!(result
= smbcli_tree_init(session
, mem_ctx
, false))) {
1698 talloc_free(tmp_ctx
);
1699 return NT_STATUS_NO_MEMORY
;
1702 tcon
.generic
.level
= RAW_TCON_TCONX
;
1703 tcon
.tconx
.in
.flags
= 0;
1704 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
1705 tcon
.tconx
.in
.path
= sharename
;
1706 tcon
.tconx
.in
.device
= "?????";
1708 status
= smb_raw_tcon(result
, tmp_ctx
, &tcon
);
1709 if (!NT_STATUS_IS_OK(status
)) {
1710 d_printf("(%s) smb_raw_tcon failed: %s\n", __location__
,
1712 talloc_free(tmp_ctx
);
1716 result
->tid
= tcon
.tconx
.out
.tid
;
1717 result
= talloc_steal(mem_ctx
, result
);
1718 talloc_set_destructor(result
, destroy_tree
);
1719 talloc_free(tmp_ctx
);
1721 return NT_STATUS_OK
;
1725 * Test the getusername behaviour
1728 bool torture_samba3_rpc_getusername(struct torture_context
*torture
)
1731 struct smbcli_state
*cli
;
1732 TALLOC_CTX
*mem_ctx
;
1734 struct dom_sid
*user_sid
;
1735 struct dom_sid
*created_sid
;
1736 struct cli_credentials
*anon_creds
;
1737 struct cli_credentials
*user_creds
;
1739 struct smbcli_options options
;
1740 struct smbcli_session_options session_options
;
1742 if (!(mem_ctx
= talloc_new(torture
))) {
1746 lp_smbcli_options(torture
->lp_ctx
, &options
);
1747 lp_smbcli_session_options(torture
->lp_ctx
, &session_options
);
1749 status
= smbcli_full_connection(
1750 mem_ctx
, &cli
, torture_setting_string(torture
, "host", NULL
),
1751 lp_smb_ports(torture
->lp_ctx
),
1752 "IPC$", NULL
, lp_socket_options(torture
->lp_ctx
), cmdline_credentials
,
1753 lp_resolve_context(torture
->lp_ctx
),
1754 torture
->ev
, &options
, &session_options
,
1755 lp_iconv_convenience(torture
->lp_ctx
),
1756 lp_gensec_settings(torture
, torture
->lp_ctx
));
1757 if (!NT_STATUS_IS_OK(status
)) {
1758 d_printf("(%s) smbcli_full_connection failed: %s\n",
1759 __location__
, nt_errstr(status
));
1764 if (!(user_sid
= whoami(mem_ctx
, torture
->lp_ctx
, cli
->tree
))) {
1765 d_printf("(%s) whoami on auth'ed connection failed\n",
1772 if (!(anon_creds
= cli_credentials_init_anon(mem_ctx
))) {
1773 d_printf("(%s) create_anon_creds failed\n", __location__
);
1778 status
= smbcli_full_connection(
1779 mem_ctx
, &cli
, torture_setting_string(torture
, "host", NULL
),
1780 lp_smb_ports(torture
->lp_ctx
), "IPC$", NULL
,
1781 lp_socket_options(torture
->lp_ctx
), anon_creds
,
1782 lp_resolve_context(torture
->lp_ctx
),
1783 torture
->ev
, &options
, &session_options
,
1784 lp_iconv_convenience(torture
->lp_ctx
),
1785 lp_gensec_settings(torture
, torture
->lp_ctx
));
1786 if (!NT_STATUS_IS_OK(status
)) {
1787 d_printf("(%s) anon smbcli_full_connection failed: %s\n",
1788 __location__
, nt_errstr(status
));
1793 if (!(user_sid
= whoami(mem_ctx
, torture
->lp_ctx
, cli
->tree
))) {
1794 d_printf("(%s) whoami on anon connection failed\n",
1800 if (!dom_sid_equal(user_sid
,
1801 dom_sid_parse_talloc(mem_ctx
, "s-1-5-7"))) {
1802 d_printf("(%s) Anon lsa_GetUserName returned %s, expected "
1803 "S-1-5-7", __location__
,
1804 dom_sid_string(mem_ctx
, user_sid
));
1808 if (!(user_creds
= cli_credentials_init(mem_ctx
))) {
1809 d_printf("(%s) cli_credentials_init failed\n", __location__
);
1814 cli_credentials_set_conf(user_creds
, torture
->lp_ctx
);
1815 cli_credentials_set_username(user_creds
, "torture_username",
1817 cli_credentials_set_password(user_creds
,
1818 generate_random_str(user_creds
, 8),
1821 if (!create_user(mem_ctx
, cli
, torture
->lp_ctx
, cmdline_credentials
,
1822 cli_credentials_get_username(user_creds
),
1823 cli_credentials_get_password(user_creds
),
1824 &domain_name
, &created_sid
)) {
1825 d_printf("(%s) create_user failed\n", __location__
);
1830 cli_credentials_set_domain(user_creds
, domain_name
,
1834 struct smbcli_session
*session2
;
1835 struct smb_composite_sesssetup setup
;
1836 struct smbcli_tree
*tree
;
1838 session2
= smbcli_session_init(cli
->transport
, mem_ctx
, false, session_options
);
1839 if (session2
== NULL
) {
1840 d_printf("(%s) smbcli_session_init failed\n",
1845 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
1846 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
1847 setup
.in
.workgroup
= "";
1848 setup
.in
.credentials
= user_creds
;
1849 setup
.in
.gensec_settings
= lp_gensec_settings(torture
, torture
->lp_ctx
);
1851 status
= smb_composite_sesssetup(session2
, &setup
);
1852 if (!NT_STATUS_IS_OK(status
)) {
1853 d_printf("(%s) session setup with new user failed: "
1854 "%s\n", __location__
, nt_errstr(status
));
1858 session2
->vuid
= setup
.out
.vuid
;
1860 if (!NT_STATUS_IS_OK(secondary_tcon(mem_ctx
, session2
,
1862 d_printf("(%s) secondary_tcon failed\n",
1868 if (!(user_sid
= whoami(mem_ctx
, torture
->lp_ctx
, tree
))) {
1869 d_printf("(%s) whoami on user connection failed\n",
1878 d_printf("Created %s, found %s\n",
1879 dom_sid_string(mem_ctx
, created_sid
),
1880 dom_sid_string(mem_ctx
, user_sid
));
1882 if (!dom_sid_equal(created_sid
, user_sid
)) {
1887 if (!delete_user(cli
, torture
->lp_ctx
,
1888 cmdline_credentials
,
1889 cli_credentials_get_username(user_creds
))) {
1890 d_printf("(%s) delete_user failed\n", __location__
);
1895 talloc_free(mem_ctx
);
1899 static bool test_NetShareGetInfo(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
1900 const char *sharename
)
1903 struct srvsvc_NetShareGetInfo r
;
1904 union srvsvc_NetShareInfo info
;
1905 uint32_t levels
[] = { 0, 1, 2, 501, 502, 1004, 1005, 1006, 1007, 1501 };
1909 r
.in
.server_unc
= talloc_asprintf(mem_ctx
, "\\\\%s",
1910 dcerpc_server_name(p
));
1911 r
.in
.share_name
= sharename
;
1914 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1915 r
.in
.level
= levels
[i
];
1917 printf("testing NetShareGetInfo level %u on share '%s'\n",
1918 r
.in
.level
, r
.in
.share_name
);
1920 status
= dcerpc_srvsvc_NetShareGetInfo(p
, mem_ctx
, &r
);
1921 if (!NT_STATUS_IS_OK(status
)) {
1922 printf("NetShareGetInfo level %u on share '%s' failed"
1923 " - %s\n", r
.in
.level
, r
.in
.share_name
,
1928 if (!W_ERROR_IS_OK(r
.out
.result
)) {
1929 printf("NetShareGetInfo level %u on share '%s' failed "
1930 "- %s\n", r
.in
.level
, r
.in
.share_name
,
1931 win_errstr(r
.out
.result
));
1940 static bool test_NetShareEnum(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
1941 const char **one_sharename
)
1944 struct srvsvc_NetShareEnum r
;
1945 struct srvsvc_NetShareInfoCtr info_ctr
;
1946 struct srvsvc_NetShareCtr0 c0
;
1947 struct srvsvc_NetShareCtr1 c1
;
1948 struct srvsvc_NetShareCtr2 c2
;
1949 struct srvsvc_NetShareCtr501 c501
;
1950 struct srvsvc_NetShareCtr502 c502
;
1951 struct srvsvc_NetShareCtr1004 c1004
;
1952 struct srvsvc_NetShareCtr1005 c1005
;
1953 struct srvsvc_NetShareCtr1006 c1006
;
1954 struct srvsvc_NetShareCtr1007 c1007
;
1955 uint32_t totalentries
= 0;
1956 uint32_t levels
[] = { 0, 1, 2, 501, 502, 1004, 1005, 1006, 1007 };
1960 ZERO_STRUCT(info_ctr
);
1962 r
.in
.server_unc
= talloc_asprintf(mem_ctx
,"\\\\%s",dcerpc_server_name(p
));
1963 r
.in
.info_ctr
= &info_ctr
;
1964 r
.in
.max_buffer
= (uint32_t)-1;
1965 r
.in
.resume_handle
= NULL
;
1966 r
.out
.totalentries
= &totalentries
;
1967 r
.out
.info_ctr
= &info_ctr
;
1969 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1970 info_ctr
.level
= levels
[i
];
1972 switch (info_ctr
.level
) {
1975 info_ctr
.ctr
.ctr0
= &c0
;
1979 info_ctr
.ctr
.ctr1
= &c1
;
1983 info_ctr
.ctr
.ctr2
= &c2
;
1987 info_ctr
.ctr
.ctr501
= &c501
;
1991 info_ctr
.ctr
.ctr502
= &c502
;
1995 info_ctr
.ctr
.ctr1004
= &c1004
;
1999 info_ctr
.ctr
.ctr1005
= &c1005
;
2003 info_ctr
.ctr
.ctr1006
= &c1006
;
2007 info_ctr
.ctr
.ctr1007
= &c1007
;
2011 printf("testing NetShareEnum level %u\n", info_ctr
.level
);
2012 status
= dcerpc_srvsvc_NetShareEnum(p
, mem_ctx
, &r
);
2013 if (!NT_STATUS_IS_OK(status
)) {
2014 printf("NetShareEnum level %u failed - %s\n",
2015 info_ctr
.level
, nt_errstr(status
));
2019 if (!W_ERROR_IS_OK(r
.out
.result
)) {
2020 printf("NetShareEnum level %u failed - %s\n",
2021 info_ctr
.level
, win_errstr(r
.out
.result
));
2024 if (info_ctr
.level
== 0) {
2025 struct srvsvc_NetShareCtr0
*ctr
= r
.out
.info_ctr
->ctr
.ctr0
;
2026 if (ctr
->count
> 0) {
2027 *one_sharename
= ctr
->array
[0].name
;
2035 bool torture_samba3_rpc_srvsvc(struct torture_context
*torture
)
2037 struct dcerpc_pipe
*p
;
2038 TALLOC_CTX
*mem_ctx
;
2040 const char *sharename
= NULL
;
2041 struct smbcli_state
*cli
;
2044 if (!(mem_ctx
= talloc_new(torture
))) {
2048 if (!(torture_open_connection_share(
2049 mem_ctx
, &cli
, torture
, torture_setting_string(torture
, "host", NULL
),
2050 "IPC$", torture
->ev
))) {
2051 talloc_free(mem_ctx
);
2055 status
= pipe_bind_smb(mem_ctx
, torture
->lp_ctx
, cli
->tree
,
2056 "\\pipe\\srvsvc", &ndr_table_srvsvc
, &p
);
2057 if (!NT_STATUS_IS_OK(status
)) {
2058 d_printf("(%s) could not bind to srvsvc pipe: %s\n",
2059 __location__
, nt_errstr(status
));
2064 ret
&= test_NetShareEnum(p
, mem_ctx
, &sharename
);
2065 if (sharename
== NULL
) {
2066 printf("did not get sharename\n");
2068 ret
&= test_NetShareGetInfo(p
, mem_ctx
, sharename
);
2072 talloc_free(mem_ctx
);
2077 * Do a ReqChallenge/Auth2 with a random wks name, make sure it returns
2078 * NT_STATUS_NO_SAM_ACCOUNT
2081 bool torture_samba3_rpc_randomauth2(struct torture_context
*torture
)
2083 TALLOC_CTX
*mem_ctx
;
2084 struct dcerpc_pipe
*net_pipe
;
2086 bool result
= false;
2088 struct netr_ServerReqChallenge r
;
2089 struct netr_Credential netr_cli_creds
;
2090 struct netr_Credential netr_srv_creds
;
2091 uint32_t negotiate_flags
;
2092 struct netr_ServerAuthenticate2 a
;
2093 struct netlogon_creds_CredentialState
*creds_state
;
2094 struct netr_Credential netr_cred
;
2095 struct samr_Password mach_pw
;
2096 struct smbcli_state
*cli
;
2098 if (!(mem_ctx
= talloc_new(torture
))) {
2099 d_printf("talloc_new failed\n");
2103 if (!(wksname
= generate_random_str_list(
2104 mem_ctx
, 14, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"))) {
2105 d_printf("generate_random_str_list failed\n");
2109 if (!(torture_open_connection_share(
2111 torture
, torture_setting_string(torture
, "host", NULL
),
2112 "IPC$", torture
->ev
))) {
2113 d_printf("IPC$ connection failed\n");
2117 if (!(net_pipe
= dcerpc_pipe_init(
2118 mem_ctx
, cli
->transport
->socket
->event
.ctx
,
2119 lp_iconv_convenience(torture
->lp_ctx
)))) {
2120 d_printf("dcerpc_pipe_init failed\n");
2124 status
= dcerpc_pipe_open_smb(net_pipe
, cli
->tree
, "\\netlogon");
2125 if (!NT_STATUS_IS_OK(status
)) {
2126 d_printf("dcerpc_pipe_open_smb failed: %s\n",
2131 status
= dcerpc_bind_auth_none(net_pipe
, &ndr_table_netlogon
);
2132 if (!NT_STATUS_IS_OK(status
)) {
2133 d_printf("dcerpc_bind_auth_none failed: %s\n",
2138 r
.in
.computer_name
= wksname
;
2139 r
.in
.server_name
= talloc_asprintf(
2140 mem_ctx
, "\\\\%s", dcerpc_server_name(net_pipe
));
2141 if (r
.in
.server_name
== NULL
) {
2142 d_printf("talloc_asprintf failed\n");
2145 generate_random_buffer(netr_cli_creds
.data
,
2146 sizeof(netr_cli_creds
.data
));
2147 r
.in
.credentials
= &netr_cli_creds
;
2148 r
.out
.return_credentials
= &netr_srv_creds
;
2150 status
= dcerpc_netr_ServerReqChallenge(net_pipe
, mem_ctx
, &r
);
2151 if (!NT_STATUS_IS_OK(status
)) {
2152 d_printf("netr_ServerReqChallenge failed: %s\n",
2157 negotiate_flags
= NETLOGON_NEG_AUTH2_FLAGS
;
2158 E_md4hash("foobar", mach_pw
.hash
);
2160 a
.in
.server_name
= talloc_asprintf(
2161 mem_ctx
, "\\\\%s", dcerpc_server_name(net_pipe
));
2162 a
.in
.account_name
= talloc_asprintf(
2163 mem_ctx
, "%s$", wksname
);
2164 a
.in
.computer_name
= wksname
;
2165 a
.in
.secure_channel_type
= SEC_CHAN_WKSTA
;
2166 a
.in
.negotiate_flags
= &negotiate_flags
;
2167 a
.out
.negotiate_flags
= &negotiate_flags
;
2168 a
.in
.credentials
= &netr_cred
;
2169 a
.out
.return_credentials
= &netr_cred
;
2171 creds_state
= netlogon_creds_client_init(mem_ctx
,
2175 r
.out
.return_credentials
, &mach_pw
,
2176 &netr_cred
, negotiate_flags
);
2179 status
= dcerpc_netr_ServerAuthenticate2(net_pipe
, mem_ctx
, &a
);
2181 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NO_TRUST_SAM_ACCOUNT
)) {
2182 d_printf("dcerpc_netr_ServerAuthenticate2 returned %s, "
2183 "expected NT_STATUS_NO_TRUST_SAM_ACCOUNT\n",
2190 talloc_free(mem_ctx
);
2194 static struct security_descriptor
*get_sharesec(TALLOC_CTX
*mem_ctx
,
2195 struct loadparm_context
*lp_ctx
,
2196 struct smbcli_session
*sess
,
2197 const char *sharename
)
2199 struct smbcli_tree
*tree
;
2200 TALLOC_CTX
*tmp_ctx
;
2201 struct dcerpc_pipe
*p
;
2203 struct srvsvc_NetShareGetInfo r
;
2204 union srvsvc_NetShareInfo info
;
2205 struct security_descriptor
*result
;
2207 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
2208 d_printf("talloc_new failed\n");
2212 if (!NT_STATUS_IS_OK(secondary_tcon(tmp_ctx
, sess
, "IPC$", &tree
))) {
2213 d_printf("secondary_tcon failed\n");
2214 talloc_free(tmp_ctx
);
2218 status
= pipe_bind_smb(mem_ctx
, lp_ctx
, tree
, "\\pipe\\srvsvc",
2219 &ndr_table_srvsvc
, &p
);
2220 if (!NT_STATUS_IS_OK(status
)) {
2221 d_printf("(%s) could not bind to srvsvc pipe: %s\n",
2222 __location__
, nt_errstr(status
));
2223 talloc_free(tmp_ctx
);
2228 p
->conn
->flags
|= DCERPC_DEBUG_PRINT_IN
| DCERPC_DEBUG_PRINT_OUT
;
2231 r
.in
.server_unc
= talloc_asprintf(tmp_ctx
, "\\\\%s",
2232 dcerpc_server_name(p
));
2233 r
.in
.share_name
= sharename
;
2237 status
= dcerpc_srvsvc_NetShareGetInfo(p
, tmp_ctx
, &r
);
2238 if (!NT_STATUS_IS_OK(status
)) {
2239 d_printf("srvsvc_NetShareGetInfo failed: %s\n",
2241 talloc_free(tmp_ctx
);
2245 result
= talloc_steal(mem_ctx
, info
.info502
->sd_buf
.sd
);
2246 talloc_free(tmp_ctx
);
2250 static NTSTATUS
set_sharesec(TALLOC_CTX
*mem_ctx
,
2251 struct loadparm_context
*lp_ctx
,
2252 struct smbcli_session
*sess
,
2253 const char *sharename
,
2254 struct security_descriptor
*sd
)
2256 struct smbcli_tree
*tree
;
2257 TALLOC_CTX
*tmp_ctx
;
2258 struct dcerpc_pipe
*p
;
2260 struct sec_desc_buf i
;
2261 struct srvsvc_NetShareSetInfo r
;
2262 union srvsvc_NetShareInfo info
;
2265 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
2266 d_printf("talloc_new failed\n");
2267 return NT_STATUS_NO_MEMORY
;
2270 if (!NT_STATUS_IS_OK(secondary_tcon(tmp_ctx
, sess
, "IPC$", &tree
))) {
2271 d_printf("secondary_tcon failed\n");
2272 talloc_free(tmp_ctx
);
2273 return NT_STATUS_UNSUCCESSFUL
;
2276 status
= pipe_bind_smb(mem_ctx
, lp_ctx
, tree
, "\\pipe\\srvsvc",
2277 &ndr_table_srvsvc
, &p
);
2278 if (!NT_STATUS_IS_OK(status
)) {
2279 d_printf("(%s) could not bind to srvsvc pipe: %s\n",
2280 __location__
, nt_errstr(status
));
2281 talloc_free(tmp_ctx
);
2282 return NT_STATUS_UNSUCCESSFUL
;
2286 p
->conn
->flags
|= DCERPC_DEBUG_PRINT_IN
| DCERPC_DEBUG_PRINT_OUT
;
2289 r
.in
.server_unc
= talloc_asprintf(tmp_ctx
, "\\\\%s",
2290 dcerpc_server_name(p
));
2291 r
.in
.share_name
= sharename
;
2296 r
.in
.parm_error
= &error
;
2298 status
= dcerpc_srvsvc_NetShareSetInfo(p
, tmp_ctx
, &r
);
2299 if (!NT_STATUS_IS_OK(status
)) {
2300 d_printf("srvsvc_NetShareSetInfo failed: %s\n",
2304 talloc_free(tmp_ctx
);
2308 bool try_tcon(TALLOC_CTX
*mem_ctx
,
2309 struct loadparm_context
*lp_ctx
,
2310 struct security_descriptor
*orig_sd
,
2311 struct smbcli_session
*session
,
2312 const char *sharename
, const struct dom_sid
*user_sid
,
2313 unsigned int access_mask
, NTSTATUS expected_tcon
,
2314 NTSTATUS expected_mkdir
)
2316 TALLOC_CTX
*tmp_ctx
;
2317 struct smbcli_tree
*rmdir_tree
, *tree
;
2318 struct dom_sid
*domain_sid
;
2320 struct security_descriptor
*sd
;
2324 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
2325 d_printf("talloc_new failed\n");
2329 status
= secondary_tcon(tmp_ctx
, session
, sharename
, &rmdir_tree
);
2330 if (!NT_STATUS_IS_OK(status
)) {
2331 d_printf("first tcon to delete dir failed\n");
2332 talloc_free(tmp_ctx
);
2336 smbcli_rmdir(rmdir_tree
, "sharesec_testdir");
2338 if (!NT_STATUS_IS_OK(dom_sid_split_rid(tmp_ctx
, user_sid
,
2339 &domain_sid
, &rid
))) {
2340 d_printf("dom_sid_split_rid failed\n");
2341 talloc_free(tmp_ctx
);
2345 sd
= security_descriptor_dacl_create(
2346 tmp_ctx
, 0, "S-1-5-32-544",
2347 dom_sid_string(mem_ctx
, dom_sid_add_rid(mem_ctx
, domain_sid
,
2349 dom_sid_string(mem_ctx
, user_sid
),
2350 SEC_ACE_TYPE_ACCESS_ALLOWED
, access_mask
, 0, NULL
);
2352 d_printf("security_descriptor_dacl_create failed\n");
2353 talloc_free(tmp_ctx
);
2357 status
= set_sharesec(mem_ctx
, lp_ctx
, session
, sharename
, sd
);
2358 if (!NT_STATUS_IS_OK(status
)) {
2359 d_printf("custom set_sharesec failed: %s\n",
2361 talloc_free(tmp_ctx
);
2365 status
= secondary_tcon(tmp_ctx
, session
, sharename
, &tree
);
2366 if (!NT_STATUS_EQUAL(status
, expected_tcon
)) {
2367 d_printf("Expected %s, got %s\n", nt_errstr(expected_tcon
),
2373 if (!NT_STATUS_IS_OK(status
)) {
2374 /* An expected non-access, no point in trying to write */
2378 status
= smbcli_mkdir(tree
, "sharesec_testdir");
2379 if (!NT_STATUS_EQUAL(status
, expected_mkdir
)) {
2380 d_printf("(%s) Expected %s, got %s\n", __location__
,
2381 nt_errstr(expected_mkdir
), nt_errstr(status
));
2386 smbcli_rmdir(rmdir_tree
, "sharesec_testdir");
2388 status
= set_sharesec(mem_ctx
, lp_ctx
, session
, sharename
, orig_sd
);
2389 if (!NT_STATUS_IS_OK(status
)) {
2390 d_printf("custom set_sharesec failed: %s\n",
2392 talloc_free(tmp_ctx
);
2396 talloc_free(tmp_ctx
);
2400 bool torture_samba3_rpc_sharesec(struct torture_context
*torture
)
2402 TALLOC_CTX
*mem_ctx
;
2404 struct smbcli_state
*cli
;
2405 struct security_descriptor
*sd
;
2406 struct dom_sid
*user_sid
;
2408 if (!(mem_ctx
= talloc_new(torture
))) {
2412 if (!(torture_open_connection_share(
2413 mem_ctx
, &cli
, torture
, torture_setting_string(torture
, "host", NULL
),
2414 "IPC$", torture
->ev
))) {
2415 d_printf("IPC$ connection failed\n");
2416 talloc_free(mem_ctx
);
2420 if (!(user_sid
= whoami(mem_ctx
, torture
->lp_ctx
, cli
->tree
))) {
2421 d_printf("whoami failed\n");
2422 talloc_free(mem_ctx
);
2426 sd
= get_sharesec(mem_ctx
, torture
->lp_ctx
, cli
->session
,
2427 torture_setting_string(torture
, "share", NULL
));
2429 ret
&= try_tcon(mem_ctx
, torture
->lp_ctx
, sd
, cli
->session
,
2430 torture_setting_string(torture
, "share", NULL
),
2431 user_sid
, 0, NT_STATUS_ACCESS_DENIED
, NT_STATUS_OK
);
2433 ret
&= try_tcon(mem_ctx
, torture
->lp_ctx
, sd
, cli
->session
,
2434 torture_setting_string(torture
, "share", NULL
),
2435 user_sid
, SEC_FILE_READ_DATA
, NT_STATUS_OK
,
2436 NT_STATUS_MEDIA_WRITE_PROTECTED
);
2438 ret
&= try_tcon(mem_ctx
, torture
->lp_ctx
, sd
, cli
->session
,
2439 torture_setting_string(torture
, "share", NULL
),
2440 user_sid
, SEC_FILE_ALL
, NT_STATUS_OK
, NT_STATUS_OK
);
2442 talloc_free(mem_ctx
);
2446 bool torture_samba3_rpc_lsa(struct torture_context
*torture
)
2448 TALLOC_CTX
*mem_ctx
;
2450 struct smbcli_state
*cli
;
2451 struct dcerpc_pipe
*p
;
2452 struct policy_handle lsa_handle
;
2454 struct dom_sid
*domain_sid
;
2456 if (!(mem_ctx
= talloc_new(torture
))) {
2460 if (!(torture_open_connection_share(
2461 mem_ctx
, &cli
, torture
, torture_setting_string(torture
, "host", NULL
),
2462 "IPC$", torture
->ev
))) {
2463 d_printf("IPC$ connection failed\n");
2464 talloc_free(mem_ctx
);
2468 status
= pipe_bind_smb(mem_ctx
, torture
->lp_ctx
, cli
->tree
, "\\lsarpc",
2469 &ndr_table_lsarpc
, &p
);
2470 if (!NT_STATUS_IS_OK(status
)) {
2471 d_printf("(%s) pipe_bind_smb failed: %s\n", __location__
,
2473 talloc_free(mem_ctx
);
2478 struct lsa_ObjectAttribute attr
;
2479 struct lsa_OpenPolicy2 o
;
2480 o
.in
.system_name
= talloc_asprintf(
2481 mem_ctx
, "\\\\%s", dcerpc_server_name(p
));
2484 o
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2485 o
.out
.handle
= &lsa_handle
;
2486 status
= dcerpc_lsa_OpenPolicy2(p
, mem_ctx
, &o
);
2487 if (!NT_STATUS_IS_OK(status
)) {
2488 d_printf("(%s) dcerpc_lsa_OpenPolicy2 failed: %s\n",
2489 __location__
, nt_errstr(status
));
2490 talloc_free(mem_ctx
);
2496 p
->conn
->flags
|= DCERPC_DEBUG_PRINT_IN
| DCERPC_DEBUG_PRINT_OUT
;
2501 int levels
[] = { 2,3,5,6 };
2503 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
2504 struct lsa_QueryInfoPolicy r
;
2505 union lsa_PolicyInformation
*info
= NULL
;
2506 r
.in
.handle
= &lsa_handle
;
2507 r
.in
.level
= levels
[i
];
2509 status
= dcerpc_lsa_QueryInfoPolicy(p
, mem_ctx
, &r
);
2510 if (!NT_STATUS_IS_OK(status
)) {
2511 d_printf("(%s) dcerpc_lsa_QueryInfoPolicy %d "
2512 "failed: %s\n", __location__
,
2513 levels
[i
], nt_errstr(status
));
2514 talloc_free(mem_ctx
);
2517 if (levels
[i
] == 5) {
2518 domain_sid
= info
->account_domain
.sid
;
2526 static NTSTATUS
get_servername(TALLOC_CTX
*mem_ctx
, struct smbcli_tree
*tree
,
2527 struct smb_iconv_convenience
*iconv_convenience
,
2530 struct rap_WserverGetInfo r
;
2532 char servername
[17];
2535 r
.in
.bufsize
= 0xffff;
2537 status
= smbcli_rap_netservergetinfo(tree
, iconv_convenience
, mem_ctx
, &r
);
2538 if (!NT_STATUS_IS_OK(status
)) {
2542 memcpy(servername
, r
.out
.info
.info0
.name
, 16);
2543 servername
[16] = '\0';
2545 if (!pull_ascii_talloc(mem_ctx
, name
, servername
, NULL
)) {
2546 return NT_STATUS_NO_MEMORY
;
2549 return NT_STATUS_OK
;
2553 static NTSTATUS
find_printers(TALLOC_CTX
*ctx
, struct loadparm_context
*lp_ctx
,
2554 struct smbcli_tree
*tree
,
2555 const char ***printers
, int *num_printers
)
2557 TALLOC_CTX
*mem_ctx
;
2559 struct dcerpc_pipe
*p
;
2560 struct srvsvc_NetShareEnum r
;
2561 struct srvsvc_NetShareInfoCtr info_ctr
;
2562 struct srvsvc_NetShareCtr1 c1_in
;
2563 struct srvsvc_NetShareCtr1
*c1
;
2564 uint32_t totalentries
= 0;
2567 mem_ctx
= talloc_new(ctx
);
2568 if (mem_ctx
== NULL
) {
2569 return NT_STATUS_NO_MEMORY
;
2572 status
= pipe_bind_smb(mem_ctx
, lp_ctx
,
2573 tree
, "\\srvsvc", &ndr_table_srvsvc
,
2575 if (!NT_STATUS_IS_OK(status
)) {
2576 d_printf("could not bind to srvsvc pipe\n");
2577 talloc_free(mem_ctx
);
2583 info_ctr
.ctr
.ctr1
= &c1_in
;
2585 r
.in
.server_unc
= talloc_asprintf(
2586 mem_ctx
, "\\\\%s", dcerpc_server_name(p
));
2587 r
.in
.info_ctr
= &info_ctr
;
2588 r
.in
.max_buffer
= (uint32_t)-1;
2589 r
.in
.resume_handle
= NULL
;
2590 r
.out
.totalentries
= &totalentries
;
2591 r
.out
.info_ctr
= &info_ctr
;
2593 status
= dcerpc_srvsvc_NetShareEnum(p
, mem_ctx
, &r
);
2594 if (!NT_STATUS_IS_OK(status
)) {
2595 d_printf("NetShareEnum level %u failed - %s\n",
2596 info_ctr
.level
, nt_errstr(status
));
2597 talloc_free(mem_ctx
);
2603 c1
= r
.out
.info_ctr
->ctr
.ctr1
;
2604 for (i
=0; i
<c1
->count
; i
++) {
2605 if (c1
->array
[i
].type
!= STYPE_PRINTQ
) {
2608 if (!add_string_to_array(ctx
, c1
->array
[i
].name
,
2609 printers
, num_printers
)) {
2611 return NT_STATUS_NO_MEMORY
;
2615 talloc_free(mem_ctx
);
2616 return NT_STATUS_OK
;
2619 static bool enumprinters(TALLOC_CTX
*mem_ctx
, struct dcerpc_pipe
*pipe
,
2620 const char *servername
, int level
, int *num_printers
)
2622 struct spoolss_EnumPrinters r
;
2627 union spoolss_PrinterInfo
*info
;
2629 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
2630 r
.in
.server
= talloc_asprintf(mem_ctx
, "\\\\%s", servername
);
2634 r
.out
.needed
= &needed
;
2635 r
.out
.count
= &count
;
2638 status
= dcerpc_spoolss_EnumPrinters(pipe
, mem_ctx
, &r
);
2639 if (!NT_STATUS_IS_OK(status
)) {
2640 d_printf("(%s) dcerpc_spoolss_EnumPrinters failed: %s\n",
2641 __location__
, nt_errstr(status
));
2645 if (!W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2646 d_printf("(%s) EnumPrinters unexpected return code %s, should "
2647 "be WERR_INSUFFICIENT_BUFFER\n", __location__
,
2648 win_errstr(r
.out
.result
));
2652 blob
= data_blob_talloc_zero(mem_ctx
, needed
);
2653 if (blob
.data
== NULL
) {
2654 d_printf("(%s) data_blob_talloc failed\n", __location__
);
2658 r
.in
.buffer
= &blob
;
2659 r
.in
.offered
= needed
;
2661 status
= dcerpc_spoolss_EnumPrinters(pipe
, mem_ctx
, &r
);
2662 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2663 d_printf("(%s) dcerpc_spoolss_EnumPrinters failed: %s, "
2664 "%s\n", __location__
, nt_errstr(status
),
2665 win_errstr(r
.out
.result
));
2669 *num_printers
= count
;
2674 static NTSTATUS
getprinterinfo(TALLOC_CTX
*ctx
, struct dcerpc_pipe
*pipe
,
2675 struct policy_handle
*handle
, int level
,
2676 union spoolss_PrinterInfo
**res
)
2678 TALLOC_CTX
*mem_ctx
;
2679 struct spoolss_GetPrinter r
;
2684 mem_ctx
= talloc_new(ctx
);
2685 if (mem_ctx
== NULL
) {
2686 return NT_STATUS_NO_MEMORY
;
2689 r
.in
.handle
= handle
;
2693 r
.out
.needed
= &needed
;
2695 status
= dcerpc_spoolss_GetPrinter(pipe
, mem_ctx
, &r
);
2696 if (!NT_STATUS_IS_OK(status
)) {
2697 d_printf("(%s) dcerpc_spoolss_GetPrinter failed: %s\n",
2698 __location__
, nt_errstr(status
));
2699 talloc_free(mem_ctx
);
2703 if (!W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2704 printf("GetPrinter unexpected return code %s, should "
2705 "be WERR_INSUFFICIENT_BUFFER\n",
2706 win_errstr(r
.out
.result
));
2707 talloc_free(mem_ctx
);
2708 return NT_STATUS_UNSUCCESSFUL
;
2711 r
.in
.handle
= handle
;
2713 blob
= data_blob_talloc(mem_ctx
, NULL
, needed
);
2714 if (blob
.data
== NULL
) {
2715 talloc_free(mem_ctx
);
2716 return NT_STATUS_NO_MEMORY
;
2718 memset(blob
.data
, 0, blob
.length
);
2719 r
.in
.buffer
= &blob
;
2720 r
.in
.offered
= needed
;
2722 status
= dcerpc_spoolss_GetPrinter(pipe
, mem_ctx
, &r
);
2723 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2724 d_printf("(%s) dcerpc_spoolss_GetPrinter failed: %s, "
2725 "%s\n", __location__
, nt_errstr(status
),
2726 win_errstr(r
.out
.result
));
2727 talloc_free(mem_ctx
);
2728 return NT_STATUS_IS_OK(status
) ?
2729 NT_STATUS_UNSUCCESSFUL
: status
;
2733 *res
= talloc_steal(ctx
, r
.out
.info
);
2736 talloc_free(mem_ctx
);
2737 return NT_STATUS_OK
;
2740 bool torture_samba3_rpc_spoolss(struct torture_context
*torture
)
2742 TALLOC_CTX
*mem_ctx
;
2744 struct smbcli_state
*cli
;
2745 struct dcerpc_pipe
*p
;
2747 struct policy_handle server_handle
, printer_handle
;
2748 const char **printers
;
2750 struct spoolss_UserLevel1 userlevel1
;
2753 if (!(mem_ctx
= talloc_new(torture
))) {
2757 if (!(torture_open_connection_share(
2758 mem_ctx
, &cli
, torture
, torture_setting_string(torture
, "host", NULL
),
2759 "IPC$", torture
->ev
))) {
2760 d_printf("IPC$ connection failed\n");
2761 talloc_free(mem_ctx
);
2765 status
= get_servername(mem_ctx
, cli
->tree
, lp_iconv_convenience(torture
->lp_ctx
), &servername
);
2766 if (!NT_STATUS_IS_OK(status
)) {
2767 d_fprintf(stderr
, "(%s) get_servername returned %s\n",
2768 __location__
, nt_errstr(status
));
2769 talloc_free(mem_ctx
);
2773 if (!NT_STATUS_IS_OK(find_printers(mem_ctx
, torture
->lp_ctx
, cli
->tree
,
2774 &printers
, &num_printers
))) {
2775 talloc_free(mem_ctx
);
2779 if (num_printers
== 0) {
2780 d_printf("Did not find printers\n");
2781 talloc_free(mem_ctx
);
2785 status
= pipe_bind_smb(mem_ctx
, torture
->lp_ctx
, cli
->tree
, "\\spoolss",
2786 &ndr_table_spoolss
, &p
);
2787 if (!NT_STATUS_IS_OK(status
)) {
2788 d_printf("(%s) pipe_bind_smb failed: %s\n", __location__
,
2790 talloc_free(mem_ctx
);
2794 ZERO_STRUCT(userlevel1
);
2795 userlevel1
.client
= talloc_asprintf(
2796 mem_ctx
, "\\\\%s", lp_netbios_name(torture
->lp_ctx
));
2797 userlevel1
.user
= cli_credentials_get_username(cmdline_credentials
);
2798 userlevel1
.build
= 2600;
2799 userlevel1
.major
= 3;
2800 userlevel1
.minor
= 0;
2801 userlevel1
.processor
= 0;
2804 struct spoolss_OpenPrinterEx r
;
2807 r
.in
.printername
= talloc_asprintf(mem_ctx
, "\\\\%s",
2809 r
.in
.datatype
= NULL
;
2810 r
.in
.access_mask
= 0;
2812 r
.in
.userlevel
.level1
= &userlevel1
;
2813 r
.out
.handle
= &server_handle
;
2815 status
= dcerpc_spoolss_OpenPrinterEx(p
, mem_ctx
, &r
);
2816 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2817 d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
2818 "%s, %s\n", __location__
, nt_errstr(status
),
2819 win_errstr(r
.out
.result
));
2820 talloc_free(mem_ctx
);
2826 struct spoolss_ClosePrinter r
;
2828 r
.in
.handle
= &server_handle
;
2829 r
.out
.handle
= &server_handle
;
2831 status
= dcerpc_spoolss_ClosePrinter(p
, mem_ctx
, &r
);
2832 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2833 d_printf("(%s) dcerpc_spoolss_ClosePrinter failed: "
2834 "%s, %s\n", __location__
, nt_errstr(status
),
2835 win_errstr(r
.out
.result
));
2836 talloc_free(mem_ctx
);
2842 struct spoolss_OpenPrinterEx r
;
2845 r
.in
.printername
= talloc_asprintf(
2846 mem_ctx
, "\\\\%s\\%s", servername
, printers
[0]);
2847 r
.in
.datatype
= NULL
;
2848 r
.in
.access_mask
= 0;
2850 r
.in
.userlevel
.level1
= &userlevel1
;
2851 r
.out
.handle
= &printer_handle
;
2853 status
= dcerpc_spoolss_OpenPrinterEx(p
, mem_ctx
, &r
);
2854 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2855 d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
2856 "%s, %s\n", __location__
, nt_errstr(status
),
2857 win_errstr(r
.out
.result
));
2858 talloc_free(mem_ctx
);
2866 for (i
=0; i
<8; i
++) {
2867 status
= getprinterinfo(mem_ctx
, p
, &printer_handle
,
2869 if (!NT_STATUS_IS_OK(status
)) {
2870 d_printf("(%s) getprinterinfo %d failed: %s\n",
2871 __location__
, i
, nt_errstr(status
));
2878 struct spoolss_ClosePrinter r
;
2880 r
.in
.handle
= &printer_handle
;
2881 r
.out
.handle
= &printer_handle
;
2883 status
= dcerpc_spoolss_ClosePrinter(p
, mem_ctx
, &r
);
2884 if (!NT_STATUS_IS_OK(status
)) {
2885 d_printf("(%s) dcerpc_spoolss_ClosePrinter failed: "
2886 "%s\n", __location__
, nt_errstr(status
));
2887 talloc_free(mem_ctx
);
2894 if (!enumprinters(mem_ctx
, p
, servername
, 1,
2896 d_printf("(%s) enumprinters failed\n", __location__
);
2897 talloc_free(mem_ctx
);
2900 if (num_printers
!= num_enumerated
) {
2901 d_printf("(%s) netshareenum gave %d printers, "
2902 "enumprinters lvl 1 gave %d\n", __location__
,
2903 num_printers
, num_enumerated
);
2904 talloc_free(mem_ctx
);
2911 if (!enumprinters(mem_ctx
, p
, servername
, 2,
2913 d_printf("(%s) enumprinters failed\n", __location__
);
2914 talloc_free(mem_ctx
);
2917 if (num_printers
!= num_enumerated
) {
2918 d_printf("(%s) netshareenum gave %d printers, "
2919 "enumprinters lvl 2 gave %d\n", __location__
,
2920 num_printers
, num_enumerated
);
2921 talloc_free(mem_ctx
);
2926 talloc_free(mem_ctx
);
2931 bool torture_samba3_rpc_wkssvc(struct torture_context
*torture
)
2933 TALLOC_CTX
*mem_ctx
;
2934 struct smbcli_state
*cli
;
2935 struct dcerpc_pipe
*p
;
2939 if (!(mem_ctx
= talloc_new(torture
))) {
2943 if (!(torture_open_connection_share(
2944 mem_ctx
, &cli
, torture
, torture_setting_string(torture
, "host", NULL
),
2945 "IPC$", torture
->ev
))) {
2946 d_printf("IPC$ connection failed\n");
2947 talloc_free(mem_ctx
);
2951 status
= get_servername(mem_ctx
, cli
->tree
, lp_iconv_convenience(torture
->lp_ctx
), &servername
);
2952 if (!NT_STATUS_IS_OK(status
)) {
2953 d_fprintf(stderr
, "(%s) get_servername returned %s\n",
2954 __location__
, nt_errstr(status
));
2955 talloc_free(mem_ctx
);
2959 status
= pipe_bind_smb(mem_ctx
, torture
->lp_ctx
, cli
->tree
, "\\wkssvc",
2960 &ndr_table_wkssvc
, &p
);
2961 if (!NT_STATUS_IS_OK(status
)) {
2962 d_printf("(%s) pipe_bind_smb failed: %s\n", __location__
,
2964 talloc_free(mem_ctx
);
2969 struct wkssvc_NetWkstaInfo100 wks100
;
2970 union wkssvc_NetWkstaInfo info
;
2971 struct wkssvc_NetWkstaGetInfo r
;
2973 r
.in
.server_name
= "\\foo";
2975 info
.info100
= &wks100
;
2978 status
= dcerpc_wkssvc_NetWkstaGetInfo(p
, mem_ctx
, &r
);
2979 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
2980 d_printf("(%s) dcerpc_wkssvc_NetWksGetInfo failed: "
2981 "%s, %s\n", __location__
, nt_errstr(status
),
2982 win_errstr(r
.out
.result
));
2983 talloc_free(mem_ctx
);
2987 if (strcmp(servername
,
2988 r
.out
.info
->info100
->server_name
) != 0) {
2989 d_printf("(%s) servername inconsistency: RAP=%s, "
2990 "dcerpc_wkssvc_NetWksGetInfo=%s",
2991 __location__
, servername
,
2992 r
.out
.info
->info100
->server_name
);
2993 talloc_free(mem_ctx
);
2998 talloc_free(mem_ctx
);
3002 static NTSTATUS
winreg_close(struct dcerpc_pipe
*p
,
3003 struct policy_handle
*handle
)
3005 struct winreg_CloseKey c
;
3007 TALLOC_CTX
*mem_ctx
;
3009 c
.in
.handle
= c
.out
.handle
= handle
;
3011 if (!(mem_ctx
= talloc_new(p
))) {
3012 return NT_STATUS_NO_MEMORY
;
3015 status
= dcerpc_winreg_CloseKey(p
, mem_ctx
, &c
);
3016 talloc_free(mem_ctx
);
3018 if (!NT_STATUS_IS_OK(status
)) {
3022 if (!W_ERROR_IS_OK(c
.out
.result
)) {
3023 return werror_to_ntstatus(c
.out
.result
);
3026 return NT_STATUS_OK
;
3029 static NTSTATUS
enumvalues(struct dcerpc_pipe
*p
, struct policy_handle
*handle
,
3030 TALLOC_CTX
*mem_ctx
)
3032 uint32_t enum_index
= 0;
3035 struct winreg_EnumValue r
;
3036 struct winreg_ValNameBuf name
;
3037 enum winreg_Type type
= 0;
3040 uint32_t size
, length
;
3042 r
.in
.handle
= handle
;
3043 r
.in
.enum_index
= enum_index
;
3046 r
.in
.name
= r
.out
.name
= &name
;
3052 r
.in
.length
= &length
;
3054 status
= dcerpc_winreg_EnumValue(p
, mem_ctx
, &r
);
3055 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
3056 return NT_STATUS_OK
;
3062 static NTSTATUS
enumkeys(struct dcerpc_pipe
*p
, struct policy_handle
*handle
,
3063 TALLOC_CTX
*mem_ctx
, int depth
)
3065 struct winreg_EnumKey r
;
3066 struct winreg_StringBuf kclass
, name
;
3071 return NT_STATUS_OK
;
3077 r
.in
.handle
= handle
;
3078 r
.in
.enum_index
= 0;
3080 r
.in
.keyclass
= &kclass
;
3082 r
.in
.last_changed_time
= &t
;
3085 TALLOC_CTX
*tmp_ctx
;
3086 struct winreg_OpenKey o
;
3087 struct policy_handle key_handle
;
3090 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
3091 return NT_STATUS_NO_MEMORY
;
3097 status
= dcerpc_winreg_EnumKey(p
, tmp_ctx
, &r
);
3098 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
3099 /* We're done enumerating */
3100 talloc_free(tmp_ctx
);
3101 return NT_STATUS_OK
;
3104 for (i
=0; i
<10-depth
; i
++)
3106 printf("%s\n", r
.out
.name
->name
);
3109 o
.in
.parent_handle
= handle
;
3110 o
.in
.keyname
.name
= r
.out
.name
->name
;
3112 o
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3113 o
.out
.handle
= &key_handle
;
3115 status
= dcerpc_winreg_OpenKey(p
, tmp_ctx
, &o
);
3116 if (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(o
.out
.result
)) {
3117 enumkeys(p
, &key_handle
, tmp_ctx
, depth
-1);
3118 enumvalues(p
, &key_handle
, tmp_ctx
);
3119 status
= winreg_close(p
, &key_handle
);
3120 if (!NT_STATUS_IS_OK(status
)) {
3125 talloc_free(tmp_ctx
);
3127 r
.in
.enum_index
+= 1;
3130 return NT_STATUS_OK
;
3133 typedef NTSTATUS (*winreg_open_fn
)(struct dcerpc_pipe
*, TALLOC_CTX
*, void *);
3135 static bool test_Open3(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
3136 const char *name
, winreg_open_fn open_fn
)
3138 struct policy_handle handle
;
3139 struct winreg_OpenHKLM r
;
3142 r
.in
.system_name
= 0;
3143 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3144 r
.out
.handle
= &handle
;
3146 status
= open_fn(p
, mem_ctx
, &r
);
3147 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
3148 d_printf("(%s) %s failed: %s, %s\n", __location__
, name
,
3149 nt_errstr(status
), win_errstr(r
.out
.result
));
3153 enumkeys(p
, &handle
, mem_ctx
, 4);
3155 status
= winreg_close(p
, &handle
);
3156 if (!NT_STATUS_IS_OK(status
)) {
3157 d_printf("(%s) dcerpc_CloseKey failed: %s\n",
3158 __location__
, nt_errstr(status
));
3165 bool torture_samba3_rpc_winreg(struct torture_context
*torture
)
3168 struct dcerpc_pipe
*p
;
3169 TALLOC_CTX
*mem_ctx
;
3175 {"OpenHKLM", (winreg_open_fn
)dcerpc_winreg_OpenHKLM
},
3176 {"OpenHKU", (winreg_open_fn
)dcerpc_winreg_OpenHKU
},
3177 {"OpenHKPD", (winreg_open_fn
)dcerpc_winreg_OpenHKPD
},
3178 {"OpenHKPT", (winreg_open_fn
)dcerpc_winreg_OpenHKPT
},
3179 {"OpenHKCR", (winreg_open_fn
)dcerpc_winreg_OpenHKCR
}};
3184 mem_ctx
= talloc_init("torture_rpc_winreg");
3186 status
= torture_rpc_connection(torture
, &p
, &ndr_table_winreg
);
3188 if (!NT_STATUS_IS_OK(status
)) {
3189 talloc_free(mem_ctx
);
3194 ret
= test_Open3(p
, mem_ctx
, open_fns
[0].name
, open_fns
[0].fn
);
3196 for (i
= 0; i
< ARRAY_SIZE(open_fns
); i
++) {
3197 if (!test_Open3(p
, mem_ctx
, open_fns
[i
].name
, open_fns
[i
].fn
))
3202 talloc_free(mem_ctx
);
3207 static NTSTATUS
get_shareinfo(TALLOC_CTX
*mem_ctx
,
3208 struct loadparm_context
*lp_ctx
,
3209 struct smbcli_state
*cli
,
3211 struct srvsvc_NetShareInfo502
**info502
)
3213 struct smbcli_tree
*ipc
;
3214 struct dcerpc_pipe
*p
;
3215 struct srvsvc_NetShareGetInfo r
;
3216 union srvsvc_NetShareInfo info
;
3219 if (!(p
= dcerpc_pipe_init(cli
,
3220 cli
->transport
->socket
->event
.ctx
,
3221 lp_iconv_convenience(lp_ctx
)))) {
3222 status
= NT_STATUS_NO_MEMORY
;
3226 status
= secondary_tcon(p
, cli
->session
, "IPC$", &ipc
);
3227 if (!NT_STATUS_IS_OK(status
)) {
3231 status
= dcerpc_pipe_open_smb(p
, ipc
, "\\pipe\\srvsvc");
3232 if (!NT_STATUS_IS_OK(status
)) {
3233 d_printf("dcerpc_pipe_open_smb failed: %s\n",
3238 status
= dcerpc_bind_auth_none(p
, &ndr_table_srvsvc
);
3239 if (!NT_STATUS_IS_OK(status
)) {
3240 d_printf("dcerpc_bind_auth_none failed: %s\n",
3245 r
.in
.server_unc
= talloc_asprintf(mem_ctx
, "\\\\%s",
3246 dcerpc_server_name(p
));
3247 r
.in
.share_name
= share
;
3251 status
= dcerpc_srvsvc_NetShareGetInfo(p
, p
, &r
);
3252 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
3253 d_printf("(%s) srvsvc_NetShareGetInfo failed: %s, %s\n", __location__
,
3254 nt_errstr(status
), win_errstr(r
.out
.result
));
3255 status
= NT_STATUS_IS_OK(status
) ? werror_to_ntstatus(r
.out
.result
) : status
;
3259 *info502
= talloc_move(mem_ctx
, &info
.info502
);
3260 return NT_STATUS_OK
;
3268 * Get us a handle on HKLM\
3271 static NTSTATUS
get_hklm_handle(TALLOC_CTX
*mem_ctx
,
3272 struct smbcli_state
*cli
,
3273 struct smb_iconv_convenience
*iconv_convenience
,
3274 struct dcerpc_pipe
**pipe_p
,
3275 struct policy_handle
**handle
)
3277 struct smbcli_tree
*ipc
;
3278 struct dcerpc_pipe
*p
;
3279 struct winreg_OpenHKLM r
;
3281 struct policy_handle
*result
;
3283 result
= talloc(mem_ctx
, struct policy_handle
);
3285 if (result
== NULL
) {
3286 return NT_STATUS_NO_MEMORY
;
3289 if (!(p
= dcerpc_pipe_init(result
,
3290 cli
->transport
->socket
->event
.ctx
,
3291 iconv_convenience
))) {
3292 status
= NT_STATUS_NO_MEMORY
;
3296 status
= secondary_tcon(p
, cli
->session
, "IPC$", &ipc
);
3297 if (!NT_STATUS_IS_OK(status
)) {
3301 status
= dcerpc_pipe_open_smb(p
, ipc
, "\\winreg");
3302 if (!NT_STATUS_IS_OK(status
)) {
3303 d_printf("dcerpc_pipe_open_smb failed: %s\n",
3308 status
= dcerpc_bind_auth_none(p
, &ndr_table_winreg
);
3309 if (!NT_STATUS_IS_OK(status
)) {
3310 d_printf("dcerpc_bind_auth_none failed: %s\n",
3315 r
.in
.system_name
= 0;
3316 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3317 r
.out
.handle
= result
;
3319 status
= dcerpc_winreg_OpenHKLM(p
, p
, &r
);
3320 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(r
.out
.result
)) {
3321 d_printf("(%s) OpenHKLM failed: %s, %s\n", __location__
,
3322 nt_errstr(status
), win_errstr(r
.out
.result
));
3323 status
= NT_STATUS_IS_OK(status
) ? werror_to_ntstatus(r
.out
.result
) : status
;
3329 return NT_STATUS_OK
;
3332 talloc_free(result
);
3336 static NTSTATUS
torture_samba3_createshare(struct smbcli_state
*cli
,
3337 struct smb_iconv_convenience
*iconv_convenience
,
3338 const char *sharename
)
3340 struct dcerpc_pipe
*p
;
3341 struct policy_handle
*hklm
= NULL
;
3342 struct policy_handle new_handle
;
3343 struct winreg_CreateKey c
;
3344 struct winreg_CloseKey cl
;
3345 enum winreg_CreateAction action_taken
;
3347 TALLOC_CTX
*mem_ctx
;
3349 mem_ctx
= talloc_new(cli
);
3350 NT_STATUS_HAVE_NO_MEMORY(mem_ctx
);
3352 status
= get_hklm_handle(mem_ctx
, cli
, iconv_convenience
, &p
, &hklm
);
3353 if (!NT_STATUS_IS_OK(status
)) {
3354 d_printf("get_hklm_handle failed: %s\n", nt_errstr(status
));
3359 c
.in
.name
.name
= talloc_asprintf(
3360 mem_ctx
, "software\\samba\\smbconf\\%s", sharename
);
3361 if (c
.in
.name
.name
== NULL
) {
3362 d_printf("talloc_asprintf failed\n");
3363 status
= NT_STATUS_NO_MEMORY
;
3366 c
.in
.keyclass
.name
= "";
3368 c
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3369 c
.in
.secdesc
= NULL
;
3370 c
.in
.action_taken
= &action_taken
;
3371 c
.out
.new_handle
= &new_handle
;
3372 c
.out
.action_taken
= &action_taken
;
3374 status
= dcerpc_winreg_CreateKey(p
, p
, &c
);
3375 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(c
.out
.result
)) {
3376 d_printf("(%s) OpenKey failed: %s, %s\n", __location__
,
3377 nt_errstr(status
), win_errstr(c
.out
.result
));
3378 status
= NT_STATUS_IS_OK(status
) ? werror_to_ntstatus(c
.out
.result
) : status
;
3382 cl
.in
.handle
= &new_handle
;
3383 cl
.out
.handle
= &new_handle
;
3384 status
= dcerpc_winreg_CloseKey(p
, p
, &cl
);
3385 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(cl
.out
.result
)) {
3386 d_printf("(%s) OpenKey failed: %s, %s\n", __location__
,
3387 nt_errstr(status
), win_errstr(cl
.out
.result
));
3388 status
= NT_STATUS_IS_OK(status
) ? werror_to_ntstatus(cl
.out
.result
) : status
;
3394 talloc_free(mem_ctx
);
3398 static NTSTATUS
torture_samba3_deleteshare(struct torture_context
*torture
,
3399 struct smbcli_state
*cli
,
3400 const char *sharename
)
3402 struct dcerpc_pipe
*p
;
3403 struct policy_handle
*hklm
= NULL
;
3404 struct winreg_DeleteKey d
;
3406 TALLOC_CTX
*mem_ctx
;
3408 mem_ctx
= talloc_new(cli
);
3409 NT_STATUS_HAVE_NO_MEMORY(mem_ctx
);
3411 status
= get_hklm_handle(cli
, cli
, lp_iconv_convenience(torture
->lp_ctx
),
3413 if (!NT_STATUS_IS_OK(status
)) {
3414 d_printf("get_hklm_handle failed: %s\n", nt_errstr(status
));
3419 d
.in
.key
.name
= talloc_asprintf(
3420 mem_ctx
, "software\\samba\\smbconf\\%s", sharename
);
3421 if (d
.in
.key
.name
== NULL
) {
3422 d_printf("talloc_asprintf failed\n");
3423 status
= NT_STATUS_NO_MEMORY
;
3426 status
= dcerpc_winreg_DeleteKey(p
, p
, &d
);
3427 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(d
.out
.result
)) {
3428 d_printf("(%s) OpenKey failed: %s, %s\n", __location__
,
3429 nt_errstr(status
), win_errstr(d
.out
.result
));
3430 status
= NT_STATUS_IS_OK(status
) ? werror_to_ntstatus(d
.out
.result
) : status
;
3435 talloc_free(mem_ctx
);
3439 static NTSTATUS
torture_samba3_setconfig(struct smbcli_state
*cli
,
3440 struct loadparm_context
*lp_ctx
,
3441 const char *sharename
,
3442 const char *parameter
,
3445 struct dcerpc_pipe
*p
= NULL
;
3446 struct policy_handle
*hklm
= NULL
, key_handle
;
3447 struct winreg_OpenKey o
;
3448 struct winreg_SetValue s
;
3453 status
= get_hklm_handle(cli
, cli
, lp_iconv_convenience(lp_ctx
), &p
, &hklm
);
3454 if (!NT_STATUS_IS_OK(status
)) {
3455 d_printf("get_hklm_handle failed: %s\n", nt_errstr(status
));
3459 o
.in
.parent_handle
= hklm
;
3460 o
.in
.keyname
.name
= talloc_asprintf(
3461 hklm
, "software\\samba\\smbconf\\%s", sharename
);
3462 if (o
.in
.keyname
.name
== NULL
) {
3463 d_printf("talloc_asprintf failed\n");
3464 status
= NT_STATUS_NO_MEMORY
;
3468 o
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3469 o
.out
.handle
= &key_handle
;
3471 status
= dcerpc_winreg_OpenKey(p
, p
, &o
);
3472 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(o
.out
.result
)) {
3473 d_printf("(%s) OpenKey failed: %s, %s\n", __location__
,
3474 nt_errstr(status
), win_errstr(o
.out
.result
));
3475 status
= NT_STATUS_IS_OK(status
) ? werror_to_ntstatus(o
.out
.result
) : status
;
3479 if (!reg_string_to_val(hklm
, lp_iconv_convenience(lp_ctx
), "REG_SZ",
3480 value
, &type
, &val
)) {
3481 d_printf("(%s) reg_string_to_val failed\n", __location__
);
3485 s
.in
.handle
= &key_handle
;
3486 s
.in
.name
.name
= parameter
;
3488 s
.in
.data
= val
.data
;
3489 s
.in
.size
= val
.length
;
3491 status
= dcerpc_winreg_SetValue(p
, p
, &s
);
3492 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(s
.out
.result
)) {
3493 d_printf("(%s) SetValue failed: %s, %s\n", __location__
,
3494 nt_errstr(status
), win_errstr(s
.out
.result
));
3495 status
= NT_STATUS_IS_OK(status
) ? werror_to_ntstatus(s
.out
.result
) : status
;
3504 bool torture_samba3_regconfig(struct torture_context
*torture
)
3506 struct smbcli_state
*cli
;
3507 struct srvsvc_NetShareInfo502
*i
= NULL
;
3510 const char *comment
= "Dummer Kommentar";
3512 if (!(torture_open_connection(&cli
, torture
, 0))) {
3516 status
= torture_samba3_createshare(cli
, lp_iconv_convenience(torture
->lp_ctx
), "blubber");
3517 if (!NT_STATUS_IS_OK(status
)) {
3518 torture_warning(torture
, "torture_samba3_createshare failed: "
3519 "%s\n", nt_errstr(status
));
3523 status
= torture_samba3_setconfig(cli
, torture
->lp_ctx
, "blubber", "comment", comment
);
3524 if (!NT_STATUS_IS_OK(status
)) {
3525 torture_warning(torture
, "torture_samba3_setconfig failed: "
3526 "%s\n", nt_errstr(status
));
3530 status
= get_shareinfo(torture
, torture
->lp_ctx
, cli
, "blubber", &i
);
3531 if (!NT_STATUS_IS_OK(status
)) {
3532 torture_warning(torture
, "get_shareinfo failed: "
3533 "%s\n", nt_errstr(status
));
3537 if (strcmp(comment
, i
->comment
) != 0) {
3538 torture_warning(torture
, "Expected comment [%s], got [%s]\n",
3539 comment
, i
->comment
);
3543 status
= torture_samba3_deleteshare(torture
, cli
, "blubber");
3544 if (!NT_STATUS_IS_OK(status
)) {
3545 torture_warning(torture
, "torture_samba3_deleteshare failed: "
3546 "%s\n", nt_errstr(status
));