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/rap/rap.h"
25 #include "torture/torture.h"
26 #include "torture/util.h"
27 #include "torture/rap/proto.h"
28 #include "librpc/gen_ndr/ndr_lsa.h"
29 #include "librpc/gen_ndr/ndr_lsa_c.h"
30 #include "librpc/gen_ndr/ndr_samr.h"
31 #include "librpc/gen_ndr/ndr_samr_c.h"
32 #include "librpc/gen_ndr/ndr_netlogon.h"
33 #include "librpc/gen_ndr/ndr_netlogon_c.h"
34 #include "librpc/gen_ndr/ndr_srvsvc.h"
35 #include "librpc/gen_ndr/ndr_srvsvc_c.h"
36 #include "librpc/gen_ndr/ndr_spoolss.h"
37 #include "librpc/gen_ndr/ndr_spoolss_c.h"
38 #include "librpc/gen_ndr/ndr_winreg.h"
39 #include "librpc/gen_ndr/ndr_winreg_c.h"
40 #include "librpc/gen_ndr/ndr_wkssvc.h"
41 #include "librpc/gen_ndr/ndr_wkssvc_c.h"
42 #include "lib/cmdline/popt_common.h"
43 #include "librpc/rpc/dcerpc.h"
44 #include "torture/rpc/rpc.h"
45 #include "libcli/libcli.h"
46 #include "libcli/composite/composite.h"
47 #include "libcli/smb_composite/smb_composite.h"
48 #include "libcli/auth/libcli_auth.h"
49 #include "lib/crypto/crypto.h"
50 #include "libcli/security/proto.h"
52 static struct cli_credentials *create_anon_creds(TALLOC_CTX *mem_ctx)
54 struct cli_credentials *result;
56 if (!(result = cli_credentials_init(mem_ctx))) {
60 cli_credentials_set_conf(result);
61 cli_credentials_set_anonymous(result);
67 * This tests a RPC call using an invalid vuid
70 BOOL torture_bind_authcontext(struct torture_context *torture)
75 struct lsa_ObjectAttribute objectattr;
76 struct lsa_OpenPolicy2 openpolicy;
77 struct policy_handle handle;
78 struct lsa_Close close_handle;
79 struct smbcli_session *tmp;
80 struct smbcli_session *session2;
81 struct smbcli_state *cli;
82 struct dcerpc_pipe *lsa_pipe;
83 struct cli_credentials *anon_creds;
84 struct smb_composite_sesssetup setup;
86 mem_ctx = talloc_init("torture_bind_authcontext");
88 if (mem_ctx == NULL) {
89 d_printf("talloc_init failed\n");
93 status = smbcli_full_connection(mem_ctx, &cli,
94 torture_setting_string(torture, "host", NULL),
95 "IPC$", NULL, cmdline_credentials,
97 if (!NT_STATUS_IS_OK(status)) {
98 d_printf("smbcli_full_connection failed: %s\n",
103 lsa_pipe = dcerpc_pipe_init(mem_ctx, cli->transport->socket->event.ctx);
104 if (lsa_pipe == NULL) {
105 d_printf("dcerpc_pipe_init failed\n");
109 status = dcerpc_pipe_open_smb(lsa_pipe, cli->tree, "\\lsarpc");
110 if (!NT_STATUS_IS_OK(status)) {
111 d_printf("dcerpc_pipe_open_smb failed: %s\n",
116 status = dcerpc_bind_auth_none(lsa_pipe, &ndr_table_lsarpc);
117 if (!NT_STATUS_IS_OK(status)) {
118 d_printf("dcerpc_bind_auth_none failed: %s\n",
123 openpolicy.in.system_name =talloc_asprintf(
124 mem_ctx, "\\\\%s", dcerpc_server_name(lsa_pipe));
125 ZERO_STRUCT(objectattr);
126 openpolicy.in.attr = &objectattr;
127 openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
128 openpolicy.out.handle = &handle;
130 status = dcerpc_lsa_OpenPolicy2(lsa_pipe, mem_ctx, &openpolicy);
132 if (!NT_STATUS_IS_OK(status)) {
133 d_printf("dcerpc_lsa_OpenPolicy2 failed: %s\n",
138 close_handle.in.handle = &handle;
139 close_handle.out.handle = &handle;
141 status = dcerpc_lsa_Close(lsa_pipe, mem_ctx, &close_handle);
142 if (!NT_STATUS_IS_OK(status)) {
143 d_printf("dcerpc_lsa_Close failed: %s\n",
148 session2 = smbcli_session_init(cli->transport, mem_ctx, False);
149 if (session2 == NULL) {
150 d_printf("smbcli_session_init failed\n");
154 if (!(anon_creds = create_anon_creds(mem_ctx))) {
155 d_printf("create_anon_creds failed\n");
159 setup.in.sesskey = cli->transport->negotiate.sesskey;
160 setup.in.capabilities = cli->transport->negotiate.capabilities;
161 setup.in.workgroup = "";
162 setup.in.credentials = anon_creds;
164 status = smb_composite_sesssetup(session2, &setup);
165 if (!NT_STATUS_IS_OK(status)) {
166 d_printf("anon session setup failed: %s\n",
170 session2->vuid = setup.out.vuid;
172 tmp = cli->tree->session;
173 cli->tree->session = session2;
175 status = dcerpc_lsa_OpenPolicy2(lsa_pipe, mem_ctx, &openpolicy);
177 cli->tree->session = tmp;
178 talloc_free(lsa_pipe);
181 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
182 d_printf("dcerpc_lsa_OpenPolicy2 with wrong vuid gave %s, "
183 "expected NT_STATUS_INVALID_HANDLE\n",
190 talloc_free(mem_ctx);
195 * Bind to lsa using a specific auth method
198 static BOOL bindtest(struct smbcli_state *cli,
199 struct cli_credentials *credentials,
200 uint8_t auth_type, uint8_t auth_level)
206 struct dcerpc_pipe *lsa_pipe;
207 struct lsa_ObjectAttribute objectattr;
208 struct lsa_OpenPolicy2 openpolicy;
209 struct lsa_QueryInfoPolicy query;
210 struct policy_handle handle;
211 struct lsa_Close close_handle;
213 if ((mem_ctx = talloc_init("bindtest")) == NULL) {
214 d_printf("talloc_init failed\n");
218 lsa_pipe = dcerpc_pipe_init(mem_ctx,
219 cli->transport->socket->event.ctx);
220 if (lsa_pipe == NULL) {
221 d_printf("dcerpc_pipe_init failed\n");
225 status = dcerpc_pipe_open_smb(lsa_pipe, cli->tree, "\\lsarpc");
226 if (!NT_STATUS_IS_OK(status)) {
227 d_printf("dcerpc_pipe_open_smb failed: %s\n",
232 status = dcerpc_bind_auth(lsa_pipe, &ndr_table_lsarpc,
233 credentials, auth_type, auth_level,
235 if (!NT_STATUS_IS_OK(status)) {
236 d_printf("dcerpc_bind_auth failed: %s\n", nt_errstr(status));
240 openpolicy.in.system_name =talloc_asprintf(
241 mem_ctx, "\\\\%s", dcerpc_server_name(lsa_pipe));
242 ZERO_STRUCT(objectattr);
243 openpolicy.in.attr = &objectattr;
244 openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
245 openpolicy.out.handle = &handle;
247 status = dcerpc_lsa_OpenPolicy2(lsa_pipe, mem_ctx, &openpolicy);
249 if (!NT_STATUS_IS_OK(status)) {
250 d_printf("dcerpc_lsa_OpenPolicy2 failed: %s\n",
255 query.in.handle = &handle;
256 query.in.level = LSA_POLICY_INFO_DOMAIN;
258 status = dcerpc_lsa_QueryInfoPolicy(lsa_pipe, mem_ctx, &query);
259 if (!NT_STATUS_IS_OK(status)) {
260 d_printf("dcerpc_lsa_QueryInfoPolicy failed: %s\n",
265 close_handle.in.handle = &handle;
266 close_handle.out.handle = &handle;
268 status = dcerpc_lsa_Close(lsa_pipe, mem_ctx, &close_handle);
269 if (!NT_STATUS_IS_OK(status)) {
270 d_printf("dcerpc_lsa_Close failed: %s\n",
277 talloc_free(mem_ctx);
282 * test authenticated RPC binds with the variants Samba3 does support
285 BOOL torture_bind_samba3(struct torture_context *torture)
290 struct smbcli_state *cli;
292 mem_ctx = talloc_init("torture_bind_authcontext");
294 if (mem_ctx == NULL) {
295 d_printf("talloc_init failed\n");
299 status = smbcli_full_connection(mem_ctx, &cli,
300 torture_setting_string(torture, "host", NULL),
301 "IPC$", NULL, cmdline_credentials,
303 if (!NT_STATUS_IS_OK(status)) {
304 d_printf("smbcli_full_connection failed: %s\n",
311 ret &= bindtest(cli, cmdline_credentials, DCERPC_AUTH_TYPE_NTLMSSP,
312 DCERPC_AUTH_LEVEL_INTEGRITY);
313 ret &= bindtest(cli, cmdline_credentials, DCERPC_AUTH_TYPE_NTLMSSP,
314 DCERPC_AUTH_LEVEL_PRIVACY);
315 ret &= bindtest(cli, cmdline_credentials, DCERPC_AUTH_TYPE_SPNEGO,
316 DCERPC_AUTH_LEVEL_INTEGRITY);
317 ret &= bindtest(cli, cmdline_credentials, DCERPC_AUTH_TYPE_SPNEGO,
318 DCERPC_AUTH_LEVEL_PRIVACY);
321 talloc_free(mem_ctx);
326 * Lookup or create a user and return all necessary info
329 static NTSTATUS get_usr_handle(struct smbcli_state *cli,
331 struct cli_credentials *admin_creds,
334 const char *username,
336 struct dcerpc_pipe **result_pipe,
337 struct policy_handle **result_handle,
338 struct dom_sid **sid)
340 struct dcerpc_pipe *samr_pipe;
342 struct policy_handle conn_handle;
343 struct policy_handle domain_handle;
344 struct policy_handle *user_handle;
345 struct samr_Connect2 conn;
346 struct samr_EnumDomains enumdom;
347 uint32_t resume_handle = 0;
348 struct samr_LookupDomain l;
350 struct lsa_String domain_name;
351 struct lsa_String user_name;
352 struct samr_OpenDomain o;
353 struct samr_CreateUser2 c;
354 uint32_t user_rid,access_granted;
356 samr_pipe = dcerpc_pipe_init(mem_ctx,
357 cli->transport->socket->event.ctx);
358 if (samr_pipe == NULL) {
359 d_printf("dcerpc_pipe_init failed\n");
360 status = NT_STATUS_NO_MEMORY;
364 status = dcerpc_pipe_open_smb(samr_pipe, cli->tree, "\\samr");
365 if (!NT_STATUS_IS_OK(status)) {
366 d_printf("dcerpc_pipe_open_smb failed: %s\n",
371 if (admin_creds != NULL) {
372 status = dcerpc_bind_auth(samr_pipe, &ndr_table_samr,
373 admin_creds, auth_type, auth_level,
375 if (!NT_STATUS_IS_OK(status)) {
376 d_printf("dcerpc_bind_auth failed: %s\n",
381 /* We must have an authenticated SMB connection */
382 status = dcerpc_bind_auth_none(samr_pipe, &ndr_table_samr);
383 if (!NT_STATUS_IS_OK(status)) {
384 d_printf("dcerpc_bind_auth_none failed: %s\n",
390 conn.in.system_name = talloc_asprintf(
391 mem_ctx, "\\\\%s", dcerpc_server_name(samr_pipe));
392 conn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
393 conn.out.connect_handle = &conn_handle;
395 status = dcerpc_samr_Connect2(samr_pipe, mem_ctx, &conn);
396 if (!NT_STATUS_IS_OK(status)) {
397 d_printf("samr_Connect2 failed: %s\n", nt_errstr(status));
401 enumdom.in.connect_handle = &conn_handle;
402 enumdom.in.resume_handle = &resume_handle;
403 enumdom.in.buf_size = (uint32_t)-1;
404 enumdom.out.resume_handle = &resume_handle;
406 status = dcerpc_samr_EnumDomains(samr_pipe, mem_ctx, &enumdom);
407 if (!NT_STATUS_IS_OK(status)) {
408 d_printf("samr_EnumDomains failed: %s\n", nt_errstr(status));
412 if (enumdom.out.num_entries != 2) {
413 d_printf("samr_EnumDomains returned %d entries, expected 2\n",
414 enumdom.out.num_entries);
415 status = NT_STATUS_UNSUCCESSFUL;
419 dom_idx = strequal(enumdom.out.sam->entries[0].name.string,
422 l.in.connect_handle = &conn_handle;
423 domain_name.string = enumdom.out.sam->entries[0].name.string;
424 *domain = talloc_strdup(mem_ctx, domain_name.string);
425 l.in.domain_name = &domain_name;
427 status = dcerpc_samr_LookupDomain(samr_pipe, mem_ctx, &l);
428 if (!NT_STATUS_IS_OK(status)) {
429 d_printf("samr_LookupDomain failed: %s\n", nt_errstr(status));
433 o.in.connect_handle = &conn_handle;
434 o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
435 o.in.sid = l.out.sid;
436 o.out.domain_handle = &domain_handle;
438 status = dcerpc_samr_OpenDomain(samr_pipe, mem_ctx, &o);
439 if (!NT_STATUS_IS_OK(status)) {
440 d_printf("samr_OpenDomain failed: %s\n", nt_errstr(status));
444 c.in.domain_handle = &domain_handle;
445 user_name.string = username;
446 c.in.account_name = &user_name;
447 c.in.acct_flags = ACB_NORMAL;
448 c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
449 user_handle = talloc(mem_ctx, struct policy_handle);
450 c.out.user_handle = user_handle;
451 c.out.access_granted = &access_granted;
452 c.out.rid = &user_rid;
454 status = dcerpc_samr_CreateUser2(samr_pipe, mem_ctx, &c);
456 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
457 struct samr_LookupNames ln;
458 struct samr_OpenUser ou;
460 ln.in.domain_handle = &domain_handle;
462 ln.in.names = &user_name;
464 status = dcerpc_samr_LookupNames(samr_pipe, mem_ctx, &ln);
465 if (!NT_STATUS_IS_OK(status)) {
466 d_printf("samr_LookupNames failed: %s\n",
471 ou.in.domain_handle = &domain_handle;
472 ou.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
473 user_rid = ou.in.rid = ln.out.rids.ids[0];
474 ou.out.user_handle = user_handle;
476 status = dcerpc_samr_OpenUser(samr_pipe, mem_ctx, &ou);
477 if (!NT_STATUS_IS_OK(status)) {
478 d_printf("samr_OpenUser failed: %s\n",
484 if (!NT_STATUS_IS_OK(status)) {
485 d_printf("samr_CreateUser failed: %s\n", nt_errstr(status));
489 *result_pipe = samr_pipe;
490 *result_handle = user_handle;
492 *sid = dom_sid_add_rid(mem_ctx, l.out.sid, user_rid);
504 static BOOL create_user(TALLOC_CTX *mem_ctx, struct smbcli_state *cli,
505 struct cli_credentials *admin_creds,
506 const char *username, const char *password,
508 struct dom_sid **user_sid)
512 struct dcerpc_pipe *samr_pipe;
513 struct policy_handle *wks_handle;
516 if (!(tmp_ctx = talloc_new(mem_ctx))) {
517 d_printf("talloc_init failed\n");
521 status = get_usr_handle(cli, tmp_ctx, admin_creds,
522 DCERPC_AUTH_TYPE_NTLMSSP,
523 DCERPC_AUTH_LEVEL_INTEGRITY,
524 username, domain_name, &samr_pipe, &wks_handle,
526 if (!NT_STATUS_IS_OK(status)) {
527 d_printf("get_wks_handle failed: %s\n", nt_errstr(status));
532 struct samr_SetUserInfo2 sui2;
533 struct samr_SetUserInfo sui;
534 struct samr_QueryUserInfo qui;
535 union samr_UserInfo u_info;
536 DATA_BLOB session_key;
540 encode_pw_buffer(u_info.info23.password.data, password,
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.info23.password.data, 516,
550 u_info.info23.info.password_expired = 0;
551 u_info.info23.info.fields_present = SAMR_FIELD_PASSWORD |
552 SAMR_FIELD_PASSWORD2 |
553 SAMR_FIELD_EXPIRED_FLAG;
554 sui2.in.user_handle = wks_handle;
555 sui2.in.info = &u_info;
558 status = dcerpc_samr_SetUserInfo2(samr_pipe, tmp_ctx, &sui2);
559 if (!NT_STATUS_IS_OK(status)) {
560 d_printf("samr_SetUserInfo(23) failed: %s\n",
565 u_info.info16.acct_flags = ACB_NORMAL;
566 sui.in.user_handle = wks_handle;
567 sui.in.info = &u_info;
570 status = dcerpc_samr_SetUserInfo(samr_pipe, tmp_ctx, &sui);
571 if (!NT_STATUS_IS_OK(status)) {
572 d_printf("samr_SetUserInfo(16) failed\n");
576 qui.in.user_handle = wks_handle;
579 status = dcerpc_samr_QueryUserInfo(samr_pipe, tmp_ctx, &qui);
580 if (!NT_STATUS_IS_OK(status)) {
581 d_printf("samr_QueryUserInfo(21) failed\n");
585 qui.out.info->info21.allow_password_change = 0;
586 qui.out.info->info21.force_password_change = 0;
587 qui.out.info->info21.account_name.string = NULL;
588 qui.out.info->info21.rid = 0;
589 qui.out.info->info21.acct_expiry = 0;
590 qui.out.info->info21.fields_present = 0x81827fa; /* copy usrmgr.exe */
592 u_info.info21 = qui.out.info->info21;
593 sui.in.user_handle = wks_handle;
594 sui.in.info = &u_info;
597 status = dcerpc_samr_SetUserInfo(samr_pipe, tmp_ctx, &sui);
598 if (!NT_STATUS_IS_OK(status)) {
599 d_printf("samr_SetUserInfo(21) failed\n");
604 *domain_name= talloc_steal(mem_ctx, *domain_name);
605 *user_sid = talloc_steal(mem_ctx, *user_sid);
608 talloc_free(tmp_ctx);
616 static BOOL delete_user(struct smbcli_state *cli,
617 struct cli_credentials *admin_creds,
618 const char *username)
623 struct dcerpc_pipe *samr_pipe;
624 struct policy_handle *user_handle;
627 if ((mem_ctx = talloc_init("leave")) == NULL) {
628 d_printf("talloc_init failed\n");
632 status = get_usr_handle(cli, mem_ctx, admin_creds,
633 DCERPC_AUTH_TYPE_NTLMSSP,
634 DCERPC_AUTH_LEVEL_INTEGRITY,
635 username, &dom_name, &samr_pipe,
638 if (!NT_STATUS_IS_OK(status)) {
639 d_printf("get_wks_handle failed: %s\n", nt_errstr(status));
644 struct samr_DeleteUser d;
646 d.in.user_handle = user_handle;
647 d.out.user_handle = user_handle;
649 status = dcerpc_samr_DeleteUser(samr_pipe, mem_ctx, &d);
650 if (!NT_STATUS_IS_OK(status)) {
651 d_printf("samr_DeleteUser failed\n");
659 talloc_free(mem_ctx);
664 * Do a Samba3-style join
667 static BOOL join3(struct smbcli_state *cli,
669 struct cli_credentials *admin_creds,
670 struct cli_credentials *wks_creds)
675 struct dcerpc_pipe *samr_pipe;
676 struct policy_handle *wks_handle;
679 if ((mem_ctx = talloc_init("join3")) == NULL) {
680 d_printf("talloc_init failed\n");
684 status = get_usr_handle(
685 cli, mem_ctx, admin_creds,
686 DCERPC_AUTH_TYPE_NTLMSSP,
687 DCERPC_AUTH_LEVEL_PRIVACY,
688 talloc_asprintf(mem_ctx, "%s$",
689 cli_credentials_get_workstation(wks_creds)),
690 &dom_name, &samr_pipe, &wks_handle, NULL);
692 if (!NT_STATUS_IS_OK(status)) {
693 d_printf("get_wks_handle failed: %s\n", nt_errstr(status));
697 cli_credentials_set_domain(wks_creds, dom_name, CRED_SPECIFIED);
700 struct samr_SetUserInfo2 sui2;
701 union samr_UserInfo u_info;
702 struct samr_UserInfo21 *i21 = &u_info.info25.info;
703 DATA_BLOB session_key;
704 DATA_BLOB confounded_session_key = data_blob_talloc(
706 struct MD5Context ctx;
707 uint8_t confounder[16];
711 i21->full_name.string = talloc_asprintf(
713 cli_credentials_get_workstation(wks_creds));
714 i21->acct_flags = ACB_WSTRUST;
715 i21->fields_present = SAMR_FIELD_FULL_NAME |
716 SAMR_FIELD_ACCT_FLAGS | SAMR_FIELD_PASSWORD;
718 encode_pw_buffer(u_info.info25.password.data,
719 cli_credentials_get_password(wks_creds),
721 status = dcerpc_fetch_session_key(samr_pipe, &session_key);
722 if (!NT_STATUS_IS_OK(status)) {
723 d_printf("dcerpc_fetch_session_key failed: %s\n",
727 generate_random_buffer((uint8_t *)confounder, 16);
730 MD5Update(&ctx, confounder, 16);
731 MD5Update(&ctx, session_key.data, session_key.length);
732 MD5Final(confounded_session_key.data, &ctx);
734 arcfour_crypt_blob(u_info.info25.password.data, 516,
735 &confounded_session_key);
736 memcpy(&u_info.info25.password.data[516], confounder, 16);
738 sui2.in.user_handle = wks_handle;
740 sui2.in.info = &u_info;
742 status = dcerpc_samr_SetUserInfo2(samr_pipe, mem_ctx, &sui2);
743 if (!NT_STATUS_IS_OK(status)) {
744 d_printf("samr_SetUserInfo2(25) failed: %s\n",
749 struct samr_SetUserInfo2 sui2;
750 struct samr_SetUserInfo sui;
751 union samr_UserInfo u_info;
752 DATA_BLOB session_key;
754 encode_pw_buffer(u_info.info24.password.data,
755 cli_credentials_get_password(wks_creds),
757 u_info.info24.pw_len =
758 strlen_m(cli_credentials_get_password(wks_creds))*2;
760 status = dcerpc_fetch_session_key(samr_pipe, &session_key);
761 if (!NT_STATUS_IS_OK(status)) {
762 d_printf("dcerpc_fetch_session_key failed\n");
765 arcfour_crypt_blob(u_info.info24.password.data, 516,
767 sui2.in.user_handle = wks_handle;
768 sui2.in.info = &u_info;
771 status = dcerpc_samr_SetUserInfo2(samr_pipe, mem_ctx, &sui2);
772 if (!NT_STATUS_IS_OK(status)) {
773 d_printf("samr_SetUserInfo(24) failed: %s\n",
778 u_info.info16.acct_flags = ACB_WSTRUST;
779 sui.in.user_handle = wks_handle;
780 sui.in.info = &u_info;
783 status = dcerpc_samr_SetUserInfo(samr_pipe, mem_ctx, &sui);
784 if (!NT_STATUS_IS_OK(status)) {
785 d_printf("samr_SetUserInfo(16) failed\n");
793 talloc_free(mem_ctx);
798 * Do a ReqChallenge/Auth2 and get the wks creds
801 static BOOL auth2(struct smbcli_state *cli,
802 struct cli_credentials *wks_cred)
805 struct dcerpc_pipe *net_pipe;
808 struct netr_ServerReqChallenge r;
809 struct netr_Credential netr_cli_creds;
810 struct netr_Credential netr_srv_creds;
811 uint32_t negotiate_flags;
812 struct netr_ServerAuthenticate2 a;
813 struct creds_CredentialState *creds_state;
814 struct netr_Credential netr_cred;
815 struct samr_Password mach_pw;
817 mem_ctx = talloc_new(NULL);
818 if (mem_ctx == NULL) {
819 d_printf("talloc_new failed\n");
823 net_pipe = dcerpc_pipe_init(mem_ctx,
824 cli->transport->socket->event.ctx);
825 if (net_pipe == NULL) {
826 d_printf("dcerpc_pipe_init failed\n");
830 status = dcerpc_pipe_open_smb(net_pipe, cli->tree, "\\netlogon");
831 if (!NT_STATUS_IS_OK(status)) {
832 d_printf("dcerpc_pipe_open_smb failed: %s\n",
837 status = dcerpc_bind_auth_none(net_pipe, &ndr_table_netlogon);
838 if (!NT_STATUS_IS_OK(status)) {
839 d_printf("dcerpc_bind_auth_none failed: %s\n",
844 r.in.computer_name = cli_credentials_get_workstation(wks_cred);
845 r.in.server_name = talloc_asprintf(
846 mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
847 if (r.in.server_name == NULL) {
848 d_printf("talloc_asprintf failed\n");
851 generate_random_buffer(netr_cli_creds.data,
852 sizeof(netr_cli_creds.data));
853 r.in.credentials = &netr_cli_creds;
854 r.out.credentials = &netr_srv_creds;
856 status = dcerpc_netr_ServerReqChallenge(net_pipe, mem_ctx, &r);
857 if (!NT_STATUS_IS_OK(status)) {
858 d_printf("netr_ServerReqChallenge failed: %s\n",
863 negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
864 E_md4hash(cli_credentials_get_password(wks_cred), mach_pw.hash);
866 creds_state = talloc(mem_ctx, struct creds_CredentialState);
867 creds_client_init(creds_state, r.in.credentials,
868 r.out.credentials, &mach_pw,
869 &netr_cred, negotiate_flags);
871 a.in.server_name = talloc_asprintf(
872 mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
873 a.in.account_name = talloc_asprintf(
874 mem_ctx, "%s$", cli_credentials_get_workstation(wks_cred));
875 a.in.computer_name = cli_credentials_get_workstation(wks_cred);
876 a.in.secure_channel_type = SEC_CHAN_WKSTA;
877 a.in.negotiate_flags = &negotiate_flags;
878 a.out.negotiate_flags = &negotiate_flags;
879 a.in.credentials = &netr_cred;
880 a.out.credentials = &netr_cred;
882 status = dcerpc_netr_ServerAuthenticate2(net_pipe, mem_ctx, &a);
883 if (!NT_STATUS_IS_OK(status)) {
884 d_printf("netr_ServerServerAuthenticate2 failed: %s\n",
889 if (!creds_client_check(creds_state, a.out.credentials)) {
890 d_printf("creds_client_check failed\n");
894 cli_credentials_set_netlogon_creds(wks_cred, creds_state);
899 talloc_free(mem_ctx);
904 * Do a couple of schannel protected Netlogon ops: Interactive and Network
905 * login, and change the wks password
908 static BOOL schan(struct smbcli_state *cli,
909 struct cli_credentials *wks_creds,
910 struct cli_credentials *user_creds)
915 struct dcerpc_pipe *net_pipe;
918 mem_ctx = talloc_new(NULL);
919 if (mem_ctx == NULL) {
920 d_printf("talloc_new failed\n");
924 net_pipe = dcerpc_pipe_init(mem_ctx,
925 cli->transport->socket->event.ctx);
926 if (net_pipe == NULL) {
927 d_printf("dcerpc_pipe_init failed\n");
931 status = dcerpc_pipe_open_smb(net_pipe, cli->tree, "\\netlogon");
932 if (!NT_STATUS_IS_OK(status)) {
933 d_printf("dcerpc_pipe_open_smb failed: %s\n",
939 net_pipe->conn->flags |= DCERPC_DEBUG_PRINT_IN |
940 DCERPC_DEBUG_PRINT_OUT;
943 net_pipe->conn->flags |= (DCERPC_SIGN | DCERPC_SEAL);
944 status = dcerpc_bind_auth(net_pipe, &ndr_table_netlogon,
945 wks_creds, DCERPC_AUTH_TYPE_SCHANNEL,
946 DCERPC_AUTH_LEVEL_PRIVACY,
949 status = dcerpc_bind_auth_none(net_pipe, &ndr_table_netlogon);
951 if (!NT_STATUS_IS_OK(status)) {
952 d_printf("schannel bind failed: %s\n", nt_errstr(status));
957 for (i=2; i<4; i++) {
959 DATA_BLOB chal, nt_resp, lm_resp, names_blob, session_key;
960 struct creds_CredentialState *creds_state;
961 struct netr_Authenticator netr_auth, netr_auth2;
962 struct netr_NetworkInfo ninfo;
963 struct netr_PasswordInfo pinfo;
964 struct netr_LogonSamLogon r;
966 flags = CLI_CRED_LANMAN_AUTH | CLI_CRED_NTLM_AUTH |
967 CLI_CRED_NTLMv2_AUTH;
969 chal = data_blob_talloc(mem_ctx, NULL, 8);
970 if (chal.data == NULL) {
971 d_printf("data_blob_talloc failed\n");
975 generate_random_buffer(chal.data, chal.length);
976 names_blob = NTLMv2_generate_names_blob(
977 mem_ctx, cli_credentials_get_workstation(user_creds),
978 cli_credentials_get_domain(user_creds));
979 status = cli_credentials_get_ntlm_response(
980 user_creds, mem_ctx, &flags, chal, names_blob,
981 &lm_resp, &nt_resp, NULL, NULL);
982 if (!NT_STATUS_IS_OK(status)) {
983 d_printf("cli_credentials_get_ntlm_response failed:"
984 " %s\n", nt_errstr(status));
988 creds_state = cli_credentials_get_netlogon_creds(wks_creds);
989 creds_client_authenticator(creds_state, &netr_auth);
991 ninfo.identity_info.account_name.string =
992 cli_credentials_get_username(user_creds);
993 ninfo.identity_info.domain_name.string =
994 cli_credentials_get_domain(user_creds);
995 ninfo.identity_info.parameter_control = 0;
996 ninfo.identity_info.logon_id_low = 0;
997 ninfo.identity_info.logon_id_high = 0;
998 ninfo.identity_info.workstation.string =
999 cli_credentials_get_workstation(user_creds);
1000 memcpy(ninfo.challenge, chal.data, sizeof(ninfo.challenge));
1001 ninfo.nt.length = nt_resp.length;
1002 ninfo.nt.data = nt_resp.data;
1003 ninfo.lm.length = lm_resp.length;
1004 ninfo.lm.data = lm_resp.data;
1006 r.in.server_name = talloc_asprintf(
1007 mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
1008 ZERO_STRUCT(netr_auth2);
1009 r.in.computer_name =
1010 cli_credentials_get_workstation(wks_creds);
1011 r.in.credential = &netr_auth;
1012 r.in.return_authenticator = &netr_auth2;
1013 r.in.logon_level = 2;
1014 r.in.validation_level = i;
1015 r.in.logon.network = &ninfo;
1016 r.out.return_authenticator = NULL;
1018 status = dcerpc_netr_LogonSamLogon(net_pipe, mem_ctx, &r);
1019 if (!NT_STATUS_IS_OK(status)) {
1020 d_printf("netr_LogonSamLogon failed: %s\n",
1025 if ((r.out.return_authenticator == NULL) ||
1026 (!creds_client_check(creds_state,
1027 &r.out.return_authenticator->cred))) {
1028 d_printf("Credentials check failed!\n");
1032 creds_client_authenticator(creds_state, &netr_auth);
1034 pinfo.identity_info = ninfo.identity_info;
1035 ZERO_STRUCT(pinfo.lmpassword.hash);
1036 E_md4hash(cli_credentials_get_password(user_creds),
1037 pinfo.ntpassword.hash);
1038 session_key = data_blob_talloc(mem_ctx,
1039 creds_state->session_key, 16);
1040 arcfour_crypt_blob(pinfo.ntpassword.hash,
1041 sizeof(pinfo.ntpassword.hash),
1044 r.in.logon_level = 1;
1045 r.in.logon.password = &pinfo;
1046 r.out.return_authenticator = NULL;
1048 status = dcerpc_netr_LogonSamLogon(net_pipe, mem_ctx, &r);
1049 if (!NT_STATUS_IS_OK(status)) {
1050 d_printf("netr_LogonSamLogon failed: %s\n",
1055 if ((r.out.return_authenticator == NULL) ||
1056 (!creds_client_check(creds_state,
1057 &r.out.return_authenticator->cred))) {
1058 d_printf("Credentials check failed!\n");
1064 struct netr_ServerPasswordSet s;
1065 char *password = generate_random_str(wks_creds, 8);
1066 struct creds_CredentialState *creds_state;
1068 s.in.server_name = talloc_asprintf(
1069 mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
1070 s.in.computer_name = cli_credentials_get_workstation(wks_creds);
1071 s.in.account_name = talloc_asprintf(
1072 mem_ctx, "%s$", s.in.computer_name);
1073 s.in.secure_channel_type = SEC_CHAN_WKSTA;
1074 E_md4hash(password, s.in.new_password.hash);
1076 creds_state = cli_credentials_get_netlogon_creds(wks_creds);
1077 creds_des_encrypt(creds_state, &s.in.new_password);
1078 creds_client_authenticator(creds_state, &s.in.credential);
1080 status = dcerpc_netr_ServerPasswordSet(net_pipe, mem_ctx, &s);
1081 if (!NT_STATUS_IS_OK(status)) {
1082 printf("ServerPasswordSet - %s\n", nt_errstr(status));
1086 if (!creds_client_check(creds_state,
1087 &s.out.return_authenticator.cred)) {
1088 printf("Credential chaining failed\n");
1091 cli_credentials_set_password(wks_creds, password,
1097 talloc_free(mem_ctx);
1102 * Delete the wks account again
1105 static BOOL leave(struct smbcli_state *cli,
1106 struct cli_credentials *admin_creds,
1107 struct cli_credentials *wks_creds)
1109 char *wks_name = talloc_asprintf(
1110 NULL, "%s$", cli_credentials_get_workstation(wks_creds));
1113 ret = delete_user(cli, admin_creds, wks_name);
1114 talloc_free(wks_name);
1119 * Test the Samba3 DC code a bit. Join, do some schan netlogon ops, leave
1122 BOOL torture_netlogon_samba3(struct torture_context *torture)
1124 TALLOC_CTX *mem_ctx;
1127 struct smbcli_state *cli;
1128 struct cli_credentials *anon_creds;
1129 struct cli_credentials *wks_creds;
1130 const char *wks_name;
1133 wks_name = torture_setting_string(torture, "wksname", NULL);
1134 if (wks_name == NULL) {
1135 wks_name = get_myname();
1138 mem_ctx = talloc_init("torture_netlogon_samba3");
1140 if (mem_ctx == NULL) {
1141 d_printf("talloc_init failed\n");
1145 if (!(anon_creds = create_anon_creds(mem_ctx))) {
1146 d_printf("create_anon_creds failed\n");
1150 status = smbcli_full_connection(mem_ctx, &cli,
1151 torture_setting_string(torture, "host", NULL),
1152 "IPC$", NULL, anon_creds, NULL);
1153 if (!NT_STATUS_IS_OK(status)) {
1154 d_printf("smbcli_full_connection failed: %s\n",
1159 wks_creds = cli_credentials_init(mem_ctx);
1160 if (wks_creds == NULL) {
1161 d_printf("cli_credentials_init failed\n");
1165 cli_credentials_set_conf(wks_creds);
1166 cli_credentials_set_secure_channel_type(wks_creds, SEC_CHAN_WKSTA);
1167 cli_credentials_set_username(wks_creds, wks_name, CRED_SPECIFIED);
1168 cli_credentials_set_workstation(wks_creds, wks_name, CRED_SPECIFIED);
1169 cli_credentials_set_password(wks_creds,
1170 generate_random_str(wks_creds, 8),
1173 if (!join3(cli, False, cmdline_credentials, wks_creds)) {
1174 d_printf("join failed\n");
1178 cli_credentials_set_domain(
1179 cmdline_credentials, cli_credentials_get_domain(wks_creds),
1182 for (i=0; i<2; i++) {
1184 /* Do this more than once, the routine "schan" changes
1185 * the workstation password using the netlogon
1186 * password change routine */
1190 if (!auth2(cli, wks_creds)) {
1191 d_printf("auth2 failed\n");
1195 for (j=0; j<2; j++) {
1196 if (!schan(cli, wks_creds, cmdline_credentials)) {
1197 d_printf("schan failed\n");
1203 if (!leave(cli, cmdline_credentials, wks_creds)) {
1204 d_printf("leave failed\n");
1211 talloc_free(mem_ctx);
1216 * Do a simple join, testjoin and leave using specified smb and samr
1220 static BOOL test_join3(TALLOC_CTX *mem_ctx,
1222 struct cli_credentials *smb_creds,
1223 struct cli_credentials *samr_creds,
1224 const char *wks_name)
1228 struct smbcli_state *cli;
1229 struct cli_credentials *wks_creds;
1231 status = smbcli_full_connection(mem_ctx, &cli,
1232 lp_parm_string(-1, "torture", "host"),
1233 "IPC$", NULL, smb_creds, NULL);
1234 if (!NT_STATUS_IS_OK(status)) {
1235 d_printf("smbcli_full_connection failed: %s\n",
1240 wks_creds = cli_credentials_init(cli);
1241 if (wks_creds == NULL) {
1242 d_printf("cli_credentials_init failed\n");
1246 cli_credentials_set_conf(wks_creds);
1247 cli_credentials_set_secure_channel_type(wks_creds, SEC_CHAN_WKSTA);
1248 cli_credentials_set_username(wks_creds, wks_name, CRED_SPECIFIED);
1249 cli_credentials_set_workstation(wks_creds, wks_name, CRED_SPECIFIED);
1250 cli_credentials_set_password(wks_creds,
1251 generate_random_str(wks_creds, 8),
1254 if (!join3(cli, use_level25, samr_creds, wks_creds)) {
1255 d_printf("join failed\n");
1259 cli_credentials_set_domain(
1260 cmdline_credentials, cli_credentials_get_domain(wks_creds),
1263 if (!auth2(cli, wks_creds)) {
1264 d_printf("auth2 failed\n");
1268 if (!leave(cli, samr_creds, wks_creds)) {
1269 d_printf("leave failed\n");
1282 * Test the different session key variants. Do it by joining, this uses the
1283 * session key in the setpassword routine. Test the join by doing the auth2.
1286 BOOL torture_samba3_sessionkey(struct torture_context *torture)
1288 TALLOC_CTX *mem_ctx;
1290 struct cli_credentials *anon_creds;
1291 const char *wks_name;
1293 wks_name = torture_setting_string(torture, "wksname", get_myname());
1295 mem_ctx = talloc_init("torture_samba3_sessionkey");
1297 if (mem_ctx == NULL) {
1298 d_printf("talloc_init failed\n");
1302 if (!(anon_creds = create_anon_creds(mem_ctx))) {
1303 d_printf("create_anon_creds failed\n");
1309 if (!torture_setting_bool(torture, "samba3", False)) {
1311 /* Samba3 in the build farm right now does this happily. Need
1314 if (test_join3(mem_ctx, False, anon_creds, NULL, wks_name)) {
1315 d_printf("join using anonymous bind on an anonymous smb "
1316 "connection succeeded -- HUH??\n");
1321 if (!test_join3(mem_ctx, False, anon_creds, cmdline_credentials,
1323 d_printf("join using ntlmssp bind on an anonymous smb "
1324 "connection failed\n");
1328 if (!test_join3(mem_ctx, False, cmdline_credentials, NULL, wks_name)) {
1329 d_printf("join using anonymous bind on an authenticated smb "
1330 "connection failed\n");
1334 if (!test_join3(mem_ctx, False, cmdline_credentials,
1335 cmdline_credentials,
1337 d_printf("join using ntlmssp bind on an authenticated smb "
1338 "connection failed\n");
1343 * The following two are tests for setuserinfolevel 25
1346 if (!test_join3(mem_ctx, True, anon_creds, cmdline_credentials,
1348 d_printf("join using ntlmssp bind on an anonymous smb "
1349 "connection failed\n");
1353 if (!test_join3(mem_ctx, True, cmdline_credentials, NULL, wks_name)) {
1354 d_printf("join using anonymous bind on an authenticated smb "
1355 "connection failed\n");
1365 * open pipe and bind, given an IPC$ context
1368 static NTSTATUS pipe_bind_smb(TALLOC_CTX *mem_ctx,
1369 struct smbcli_tree *tree,
1370 const char *pipe_name,
1371 const struct ndr_interface_table *iface,
1372 struct dcerpc_pipe **p)
1374 struct dcerpc_pipe *result;
1377 if (!(result = dcerpc_pipe_init(
1378 mem_ctx, tree->session->transport->socket->event.ctx))) {
1379 return NT_STATUS_NO_MEMORY;
1382 status = dcerpc_pipe_open_smb(result, tree, pipe_name);
1383 if (!NT_STATUS_IS_OK(status)) {
1384 d_printf("dcerpc_pipe_open_smb failed: %s\n",
1386 talloc_free(result);
1390 status = dcerpc_bind_auth_none(result, iface);
1391 if (!NT_STATUS_IS_OK(status)) {
1392 d_printf("schannel bind failed: %s\n", nt_errstr(status));
1393 talloc_free(result);
1398 return NT_STATUS_OK;
1402 * Sane wrapper around lsa_LookupNames
1405 static struct dom_sid *name2sid(TALLOC_CTX *mem_ctx,
1406 struct dcerpc_pipe *p,
1410 struct lsa_ObjectAttribute attr;
1411 struct lsa_QosInfo qos;
1412 struct lsa_OpenPolicy2 r;
1415 struct policy_handle handle;
1416 struct lsa_LookupNames l;
1417 struct lsa_TransSidArray sids;
1418 struct lsa_String lsa_name;
1420 struct dom_sid *result;
1421 TALLOC_CTX *tmp_ctx;
1423 if (!(tmp_ctx = talloc_new(mem_ctx))) {
1428 qos.impersonation_level = 2;
1429 qos.context_mode = 1;
1430 qos.effective_only = 0;
1433 attr.root_dir = NULL;
1434 attr.object_name = NULL;
1435 attr.attributes = 0;
1436 attr.sec_desc = NULL;
1437 attr.sec_qos = &qos;
1439 r.in.system_name = "\\";
1441 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1442 r.out.handle = &handle;
1444 status = dcerpc_lsa_OpenPolicy2(p, tmp_ctx, &r);
1445 if (!NT_STATUS_IS_OK(status)) {
1446 printf("OpenPolicy2 failed - %s\n", nt_errstr(status));
1447 talloc_free(tmp_ctx);
1454 lsa_name.string = talloc_asprintf(tmp_ctx, "%s\\%s", domain, name);
1456 l.in.handle = &handle;
1458 l.in.names = &lsa_name;
1461 l.in.count = &count;
1462 l.out.count = &count;
1465 status = dcerpc_lsa_LookupNames(p, tmp_ctx, &l);
1466 if (!NT_STATUS_IS_OK(status)) {
1467 printf("LookupNames of %s failed - %s\n", lsa_name.string,
1469 talloc_free(tmp_ctx);
1473 result = dom_sid_add_rid(mem_ctx, l.out.domains->domains[0].sid,
1474 l.out.sids->sids[0].rid);
1476 c.in.handle = &handle;
1477 c.out.handle = &handle;
1479 status = dcerpc_lsa_Close(p, tmp_ctx, &c);
1480 if (!NT_STATUS_IS_OK(status)) {
1481 printf("dcerpc_lsa_Close failed - %s\n", nt_errstr(status));
1482 talloc_free(tmp_ctx);
1486 talloc_free(tmp_ctx);
1491 * Find out the user SID on this connection
1494 static struct dom_sid *whoami(TALLOC_CTX *mem_ctx, struct smbcli_tree *tree)
1496 struct dcerpc_pipe *lsa;
1497 struct lsa_GetUserName r;
1499 struct lsa_StringPointer authority_name_p;
1500 struct dom_sid *result;
1502 status = pipe_bind_smb(mem_ctx, tree, "\\pipe\\lsarpc",
1503 &ndr_table_lsarpc, &lsa);
1504 if (!NT_STATUS_IS_OK(status)) {
1505 d_printf("(%s) Could not bind to LSA: %s\n",
1506 __location__, nt_errstr(status));
1510 r.in.system_name = "\\";
1511 r.in.account_name = NULL;
1512 authority_name_p.string = NULL;
1513 r.in.authority_name = &authority_name_p;
1515 status = dcerpc_lsa_GetUserName(lsa, mem_ctx, &r);
1517 if (!NT_STATUS_IS_OK(status)) {
1518 printf("(%s) GetUserName failed - %s\n",
1519 __location__, nt_errstr(status));
1524 result = name2sid(mem_ctx, lsa, r.out.account_name->string,
1525 r.out.authority_name->string->string);
1532 * Do a tcon, given a session
1535 NTSTATUS secondary_tcon(TALLOC_CTX *mem_ctx,
1536 struct smbcli_session *session,
1537 const char *sharename,
1538 struct smbcli_tree **res)
1540 struct smbcli_tree *result;
1541 TALLOC_CTX *tmp_ctx;
1542 union smb_tcon tcon;
1545 if (!(tmp_ctx = talloc_new(mem_ctx))) {
1546 return NT_STATUS_NO_MEMORY;
1549 if (!(result = smbcli_tree_init(session, mem_ctx, False))) {
1550 talloc_free(tmp_ctx);
1551 return NT_STATUS_NO_MEMORY;
1554 tcon.generic.level = RAW_TCON_TCONX;
1555 tcon.tconx.in.flags = 0;
1556 tcon.tconx.in.password = data_blob(NULL, 0);
1557 tcon.tconx.in.path = sharename;
1558 tcon.tconx.in.device = "?????";
1560 status = smb_raw_tcon(result, tmp_ctx, &tcon);
1561 if (!NT_STATUS_IS_OK(status)) {
1562 d_printf("(%s) smb_raw_tcon failed: %s\n", __location__,
1564 talloc_free(tmp_ctx);
1568 result->tid = tcon.tconx.out.tid;
1569 result = talloc_steal(mem_ctx, result);
1570 talloc_free(tmp_ctx);
1572 return NT_STATUS_OK;
1576 * Test the getusername behaviour
1579 BOOL torture_samba3_rpc_getusername(struct torture_context *torture)
1582 struct smbcli_state *cli;
1583 TALLOC_CTX *mem_ctx;
1585 struct dom_sid *user_sid;
1586 struct dom_sid *created_sid;
1587 struct cli_credentials *anon_creds;
1588 struct cli_credentials *user_creds;
1591 if (!(mem_ctx = talloc_new(torture))) {
1595 status = smbcli_full_connection(
1596 mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
1597 "IPC$", NULL, cmdline_credentials, NULL);
1598 if (!NT_STATUS_IS_OK(status)) {
1599 d_printf("(%s) smbcli_full_connection failed: %s\n",
1600 __location__, nt_errstr(status));
1605 if (!(user_sid = whoami(mem_ctx, cli->tree))) {
1606 d_printf("(%s) whoami on auth'ed connection failed\n",
1613 if (!(anon_creds = create_anon_creds(mem_ctx))) {
1614 d_printf("(%s) create_anon_creds failed\n", __location__);
1619 status = smbcli_full_connection(
1620 mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
1621 "IPC$", NULL, anon_creds, NULL);
1622 if (!NT_STATUS_IS_OK(status)) {
1623 d_printf("(%s) anon smbcli_full_connection failed: %s\n",
1624 __location__, nt_errstr(status));
1629 if (!(user_sid = whoami(mem_ctx, cli->tree))) {
1630 d_printf("(%s) whoami on anon connection failed\n",
1636 if (!dom_sid_equal(user_sid,
1637 dom_sid_parse_talloc(mem_ctx, "s-1-5-7"))) {
1638 d_printf("(%s) Anon lsa_GetUserName returned %s, expected "
1639 "S-1-5-7", __location__,
1640 dom_sid_string(mem_ctx, user_sid));
1644 if (!(user_creds = cli_credentials_init(mem_ctx))) {
1645 d_printf("(%s) cli_credentials_init failed\n", __location__);
1650 cli_credentials_set_conf(user_creds);
1651 cli_credentials_set_username(user_creds, "torture_username",
1653 cli_credentials_set_password(user_creds,
1654 generate_random_str(user_creds, 8),
1657 if (!create_user(mem_ctx, cli, cmdline_credentials,
1658 cli_credentials_get_username(user_creds),
1659 cli_credentials_get_password(user_creds),
1660 &domain_name, &created_sid)) {
1661 d_printf("(%s) create_user failed\n", __location__);
1666 cli_credentials_set_domain(user_creds, domain_name,
1670 struct smbcli_session *session2;
1671 struct smb_composite_sesssetup setup;
1672 struct smbcli_tree *tree;
1674 session2 = smbcli_session_init(cli->transport, mem_ctx, False);
1675 if (session2 == NULL) {
1676 d_printf("(%s) smbcli_session_init failed\n",
1681 setup.in.sesskey = cli->transport->negotiate.sesskey;
1682 setup.in.capabilities = cli->transport->negotiate.capabilities;
1683 setup.in.workgroup = "";
1684 setup.in.credentials = user_creds;
1686 status = smb_composite_sesssetup(session2, &setup);
1687 if (!NT_STATUS_IS_OK(status)) {
1688 d_printf("(%s) session setup with new user failed: "
1689 "%s\n", __location__, nt_errstr(status));
1693 session2->vuid = setup.out.vuid;
1695 if (!NT_STATUS_IS_OK(secondary_tcon(mem_ctx, session2,
1697 d_printf("(%s) secondary_tcon failed\n",
1703 if (!(user_sid = whoami(mem_ctx, tree))) {
1704 d_printf("(%s) whoami on user connection failed\n",
1713 d_printf("Created %s, found %s\n",
1714 dom_sid_string(mem_ctx, created_sid),
1715 dom_sid_string(mem_ctx, user_sid));
1717 if (!dom_sid_equal(created_sid, user_sid)) {
1722 if (!delete_user(cli, cmdline_credentials,
1723 cli_credentials_get_username(user_creds))) {
1724 d_printf("(%s) delete_user failed\n", __location__);
1729 talloc_free(mem_ctx);
1733 static BOOL test_NetShareGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1734 const char *sharename)
1737 struct srvsvc_NetShareGetInfo r;
1738 uint32_t levels[] = { 0, 1, 2, 501, 502, 1004, 1005, 1006, 1007, 1501 };
1742 r.in.server_unc = talloc_asprintf(mem_ctx, "\\\\%s",
1743 dcerpc_server_name(p));
1744 r.in.share_name = sharename;
1746 for (i=0;i<ARRAY_SIZE(levels);i++) {
1747 r.in.level = levels[i];
1751 printf("testing NetShareGetInfo level %u on share '%s'\n",
1752 r.in.level, r.in.share_name);
1754 status = dcerpc_srvsvc_NetShareGetInfo(p, mem_ctx, &r);
1755 if (!NT_STATUS_IS_OK(status)) {
1756 printf("NetShareGetInfo level %u on share '%s' failed"
1757 " - %s\n", r.in.level, r.in.share_name,
1762 if (!W_ERROR_IS_OK(r.out.result)) {
1763 printf("NetShareGetInfo level %u on share '%s' failed "
1764 "- %s\n", r.in.level, r.in.share_name,
1765 win_errstr(r.out.result));
1774 static BOOL test_NetShareEnum(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1775 const char **one_sharename)
1778 struct srvsvc_NetShareEnum r;
1779 struct srvsvc_NetShareCtr0 c0;
1780 uint32_t levels[] = { 0, 1, 2, 501, 502, 1004, 1005, 1006, 1007 };
1784 r.in.server_unc = talloc_asprintf(mem_ctx,"\\\\%s",dcerpc_server_name(p));
1785 r.in.ctr.ctr0 = &c0;
1786 r.in.ctr.ctr0->count = 0;
1787 r.in.ctr.ctr0->array = NULL;
1788 r.in.max_buffer = (uint32_t)-1;
1789 r.in.resume_handle = NULL;
1791 for (i=0;i<ARRAY_SIZE(levels);i++) {
1792 r.in.level = levels[i];
1796 printf("testing NetShareEnum level %u\n", r.in.level);
1797 status = dcerpc_srvsvc_NetShareEnum(p, mem_ctx, &r);
1798 if (!NT_STATUS_IS_OK(status)) {
1799 printf("NetShareEnum level %u failed - %s\n",
1800 r.in.level, nt_errstr(status));
1804 if (!W_ERROR_IS_OK(r.out.result)) {
1805 printf("NetShareEnum level %u failed - %s\n",
1806 r.in.level, win_errstr(r.out.result));
1809 if (r.in.level == 0) {
1810 struct srvsvc_NetShareCtr0 *ctr = r.out.ctr.ctr0;
1811 if (ctr->count > 0) {
1812 *one_sharename = ctr->array[0].name;
1820 BOOL torture_samba3_rpc_srvsvc(struct torture_context *torture)
1822 struct dcerpc_pipe *p;
1823 TALLOC_CTX *mem_ctx;
1825 const char *sharename = NULL;
1826 struct smbcli_state *cli;
1829 if (!(mem_ctx = talloc_new(torture))) {
1833 if (!(torture_open_connection_share(
1834 mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
1836 talloc_free(mem_ctx);
1840 status = pipe_bind_smb(mem_ctx, cli->tree, "\\pipe\\srvsvc",
1841 &ndr_table_srvsvc, &p);
1842 if (!NT_STATUS_IS_OK(status)) {
1843 d_printf("(%s) could not bind to srvsvc pipe: %s\n",
1844 __location__, nt_errstr(status));
1849 ret &= test_NetShareEnum(p, mem_ctx, &sharename);
1850 if (sharename == NULL) {
1851 printf("did not get sharename\n");
1853 ret &= test_NetShareGetInfo(p, mem_ctx, sharename);
1857 talloc_free(mem_ctx);
1861 static struct security_descriptor *get_sharesec(TALLOC_CTX *mem_ctx,
1862 struct smbcli_session *sess,
1863 const char *sharename)
1865 struct smbcli_tree *tree;
1866 TALLOC_CTX *tmp_ctx;
1867 struct dcerpc_pipe *p;
1869 struct srvsvc_NetShareGetInfo r;
1870 struct security_descriptor *result;
1872 if (!(tmp_ctx = talloc_new(mem_ctx))) {
1873 d_printf("talloc_new failed\n");
1877 if (!NT_STATUS_IS_OK(secondary_tcon(tmp_ctx, sess, "IPC$", &tree))) {
1878 d_printf("secondary_tcon failed\n");
1879 talloc_free(tmp_ctx);
1883 status = pipe_bind_smb(mem_ctx, tree, "\\pipe\\srvsvc",
1884 &ndr_table_srvsvc, &p);
1885 if (!NT_STATUS_IS_OK(status)) {
1886 d_printf("(%s) could not bind to srvsvc pipe: %s\n",
1887 __location__, nt_errstr(status));
1888 talloc_free(tmp_ctx);
1893 p->conn->flags |= DCERPC_DEBUG_PRINT_IN | DCERPC_DEBUG_PRINT_OUT;
1896 r.in.server_unc = talloc_asprintf(tmp_ctx, "\\\\%s",
1897 dcerpc_server_name(p));
1898 r.in.share_name = sharename;
1901 status = dcerpc_srvsvc_NetShareGetInfo(p, tmp_ctx, &r);
1902 if (!NT_STATUS_IS_OK(status)) {
1903 d_printf("srvsvc_NetShareGetInfo failed: %s\n",
1905 talloc_free(tmp_ctx);
1909 result = talloc_steal(mem_ctx, r.out.info.info502->sd);
1910 talloc_free(tmp_ctx);
1914 static NTSTATUS set_sharesec(TALLOC_CTX *mem_ctx,
1915 struct smbcli_session *sess,
1916 const char *sharename,
1917 struct security_descriptor *sd)
1919 struct smbcli_tree *tree;
1920 TALLOC_CTX *tmp_ctx;
1921 struct dcerpc_pipe *p;
1923 struct sec_desc_buf i;
1924 struct srvsvc_NetShareSetInfo r;
1927 if (!(tmp_ctx = talloc_new(mem_ctx))) {
1928 d_printf("talloc_new failed\n");
1929 return NT_STATUS_NO_MEMORY;
1932 if (!NT_STATUS_IS_OK(secondary_tcon(tmp_ctx, sess, "IPC$", &tree))) {
1933 d_printf("secondary_tcon failed\n");
1934 talloc_free(tmp_ctx);
1935 return NT_STATUS_UNSUCCESSFUL;
1938 status = pipe_bind_smb(mem_ctx, tree, "\\pipe\\srvsvc",
1939 &ndr_table_srvsvc, &p);
1940 if (!NT_STATUS_IS_OK(status)) {
1941 d_printf("(%s) could not bind to srvsvc pipe: %s\n",
1942 __location__, nt_errstr(status));
1943 talloc_free(tmp_ctx);
1944 return NT_STATUS_UNSUCCESSFUL;
1948 p->conn->flags |= DCERPC_DEBUG_PRINT_IN | DCERPC_DEBUG_PRINT_OUT;
1951 r.in.server_unc = talloc_asprintf(tmp_ctx, "\\\\%s",
1952 dcerpc_server_name(p));
1953 r.in.share_name = sharename;
1956 r.in.info.info1501 = &i;
1957 r.in.parm_error = &error;
1959 status = dcerpc_srvsvc_NetShareSetInfo(p, tmp_ctx, &r);
1960 if (!NT_STATUS_IS_OK(status)) {
1961 d_printf("srvsvc_NetShareGetInfo failed: %s\n",
1965 talloc_free(tmp_ctx);
1969 BOOL try_tcon(TALLOC_CTX *mem_ctx,
1970 struct security_descriptor *orig_sd,
1971 struct smbcli_session *session,
1972 const char *sharename, const struct dom_sid *user_sid,
1973 unsigned int access_mask, NTSTATUS expected_tcon,
1974 NTSTATUS expected_mkdir)
1976 TALLOC_CTX *tmp_ctx;
1977 struct smbcli_tree *rmdir_tree, *tree;
1978 struct dom_sid *domain_sid;
1980 struct security_descriptor *sd;
1984 if (!(tmp_ctx = talloc_new(mem_ctx))) {
1985 d_printf("talloc_new failed\n");
1989 status = secondary_tcon(tmp_ctx, session, sharename, &rmdir_tree);
1990 if (!NT_STATUS_IS_OK(status)) {
1991 d_printf("first tcon to delete dir failed\n");
1992 talloc_free(tmp_ctx);
1996 smbcli_rmdir(rmdir_tree, "sharesec_testdir");
1998 if (!NT_STATUS_IS_OK(dom_sid_split_rid(tmp_ctx, user_sid,
1999 &domain_sid, &rid))) {
2000 d_printf("dom_sid_split_rid failed\n");
2001 talloc_free(tmp_ctx);
2005 sd = security_descriptor_create(
2006 tmp_ctx, "S-1-5-32-544",
2007 dom_sid_string(mem_ctx, dom_sid_add_rid(mem_ctx, domain_sid,
2009 dom_sid_string(mem_ctx, user_sid),
2010 SEC_ACE_TYPE_ACCESS_ALLOWED, access_mask, 0, NULL);
2012 d_printf("security_descriptor_create failed\n");
2013 talloc_free(tmp_ctx);
2017 status = set_sharesec(mem_ctx, session, sharename, sd);
2018 if (!NT_STATUS_IS_OK(status)) {
2019 d_printf("custom set_sharesec failed: %s\n",
2021 talloc_free(tmp_ctx);
2025 status = secondary_tcon(tmp_ctx, session, sharename, &tree);
2026 if (!NT_STATUS_EQUAL(status, expected_tcon)) {
2027 d_printf("Expected %s, got %s\n", nt_errstr(expected_tcon),
2033 if (!NT_STATUS_IS_OK(status)) {
2034 /* An expected non-access, no point in trying to write */
2038 status = smbcli_mkdir(tree, "sharesec_testdir");
2039 if (!NT_STATUS_EQUAL(status, expected_mkdir)) {
2040 d_printf("(%s) Expected %s, got %s\n", __location__,
2041 nt_errstr(expected_mkdir), nt_errstr(status));
2046 smbcli_rmdir(rmdir_tree, "sharesec_testdir");
2048 status = set_sharesec(mem_ctx, session, sharename, orig_sd);
2049 if (!NT_STATUS_IS_OK(status)) {
2050 d_printf("custom set_sharesec failed: %s\n",
2052 talloc_free(tmp_ctx);
2056 talloc_free(tmp_ctx);
2060 BOOL torture_samba3_rpc_sharesec(struct torture_context *torture)
2062 TALLOC_CTX *mem_ctx;
2064 struct smbcli_state *cli;
2065 struct security_descriptor *sd;
2066 struct dom_sid *user_sid;
2068 if (!(mem_ctx = talloc_new(torture))) {
2072 if (!(torture_open_connection_share(
2073 mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
2075 d_printf("IPC$ connection failed\n");
2076 talloc_free(mem_ctx);
2080 if (!(user_sid = whoami(mem_ctx, cli->tree))) {
2081 d_printf("whoami failed\n");
2082 talloc_free(mem_ctx);
2086 sd = get_sharesec(mem_ctx, cli->session, torture_setting_string(torture,
2089 ret &= try_tcon(mem_ctx, sd, cli->session,
2090 torture_setting_string(torture, "share", NULL),
2091 user_sid, 0, NT_STATUS_ACCESS_DENIED, NT_STATUS_OK);
2093 ret &= try_tcon(mem_ctx, sd, cli->session,
2094 torture_setting_string(torture, "share", NULL),
2095 user_sid, SEC_FILE_READ_DATA, NT_STATUS_OK,
2096 NT_STATUS_MEDIA_WRITE_PROTECTED);
2098 ret &= try_tcon(mem_ctx, sd, cli->session,
2099 torture_setting_string(torture, "share", NULL),
2100 user_sid, SEC_FILE_ALL, NT_STATUS_OK, NT_STATUS_OK);
2102 talloc_free(mem_ctx);
2106 BOOL torture_samba3_rpc_lsa(struct torture_context *torture)
2108 TALLOC_CTX *mem_ctx;
2110 struct smbcli_state *cli;
2111 struct dcerpc_pipe *p;
2112 struct policy_handle lsa_handle;
2114 struct dom_sid *domain_sid;
2116 if (!(mem_ctx = talloc_new(torture))) {
2120 if (!(torture_open_connection_share(
2121 mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
2123 d_printf("IPC$ connection failed\n");
2124 talloc_free(mem_ctx);
2128 status = pipe_bind_smb(mem_ctx, cli->tree, "\\lsarpc",
2129 &ndr_table_lsarpc, &p);
2130 if (!NT_STATUS_IS_OK(status)) {
2131 d_printf("(%s) pipe_bind_smb failed: %s\n", __location__,
2133 talloc_free(mem_ctx);
2138 struct lsa_ObjectAttribute attr;
2139 struct lsa_OpenPolicy2 o;
2140 o.in.system_name = talloc_asprintf(
2141 mem_ctx, "\\\\%s", dcerpc_server_name(p));
2144 o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2145 o.out.handle = &lsa_handle;
2146 status = dcerpc_lsa_OpenPolicy2(p, mem_ctx, &o);
2147 if (!NT_STATUS_IS_OK(status)) {
2148 d_printf("(%s) dcerpc_lsa_OpenPolicy2 failed: %s\n",
2149 __location__, nt_errstr(status));
2150 talloc_free(mem_ctx);
2156 p->conn->flags |= DCERPC_DEBUG_PRINT_IN | DCERPC_DEBUG_PRINT_OUT;
2161 int levels[] = { 2,3,5,6 };
2163 for (i=0; i<ARRAY_SIZE(levels); i++) {
2164 struct lsa_QueryInfoPolicy r;
2165 r.in.handle = &lsa_handle;
2166 r.in.level = levels[i];
2167 status = dcerpc_lsa_QueryInfoPolicy(p, mem_ctx, &r);
2168 if (!NT_STATUS_IS_OK(status)) {
2169 d_printf("(%s) dcerpc_lsa_QueryInfoPolicy %d "
2170 "failed: %s\n", __location__,
2171 levels[i], nt_errstr(status));
2172 talloc_free(mem_ctx);
2175 if (levels[i] == 5) {
2176 domain_sid = r.out.info->account_domain.sid;
2184 static NTSTATUS get_servername(TALLOC_CTX *mem_ctx, struct smbcli_tree *tree,
2187 struct rap_WserverGetInfo r;
2189 char servername[17];
2192 r.in.bufsize = 0xffff;
2194 status = smbcli_rap_netservergetinfo(tree, mem_ctx, &r);
2195 if (!NT_STATUS_IS_OK(status)) {
2199 memcpy(servername, r.out.info.info0.name, 16);
2200 servername[16] = '\0';
2202 if (pull_ascii_talloc(mem_ctx, name, servername) < 0) {
2203 return NT_STATUS_NO_MEMORY;
2206 return NT_STATUS_OK;
2210 static NTSTATUS find_printers(TALLOC_CTX *ctx, struct smbcli_tree *tree,
2211 const char ***printers, int *num_printers)
2213 TALLOC_CTX *mem_ctx;
2215 struct dcerpc_pipe *p;
2216 struct srvsvc_NetShareEnum r;
2217 struct srvsvc_NetShareCtr1 c1_in;
2218 struct srvsvc_NetShareCtr1 *c1;
2221 mem_ctx = talloc_new(ctx);
2222 if (mem_ctx == NULL) {
2223 return NT_STATUS_NO_MEMORY;
2226 status = pipe_bind_smb(mem_ctx, tree, "\\srvsvc", &ndr_table_srvsvc,
2228 if (!NT_STATUS_IS_OK(status)) {
2229 d_printf("could not bind to srvsvc pipe\n");
2230 talloc_free(mem_ctx);
2234 r.in.server_unc = talloc_asprintf(
2235 mem_ctx, "\\\\%s", dcerpc_server_name(p));
2238 r.in.ctr.ctr1 = &c1_in;
2239 r.in.max_buffer = (uint32_t)-1;
2240 r.in.resume_handle = NULL;
2242 status = dcerpc_srvsvc_NetShareEnum(p, mem_ctx, &r);
2243 if (!NT_STATUS_IS_OK(status)) {
2244 d_printf("NetShareEnum level %u failed - %s\n",
2245 r.in.level, nt_errstr(status));
2246 talloc_free(mem_ctx);
2252 c1 = r.out.ctr.ctr1;
2253 for (i=0; i<c1->count; i++) {
2254 if (c1->array[i].type != STYPE_PRINTQ) {
2257 if (!add_string_to_array(ctx, c1->array[i].name,
2258 printers, num_printers)) {
2260 return NT_STATUS_NO_MEMORY;
2264 talloc_free(mem_ctx);
2265 return NT_STATUS_OK;
2268 static BOOL enumprinters(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *pipe,
2269 const char *servername, int level, int *num_printers)
2271 struct spoolss_EnumPrinters r;
2275 r.in.flags = PRINTER_ENUM_LOCAL;
2276 r.in.server = talloc_asprintf(mem_ctx, "\\\\%s", servername);
2281 status = dcerpc_spoolss_EnumPrinters(pipe, mem_ctx, &r);
2282 if (!NT_STATUS_IS_OK(status)) {
2283 d_printf("(%s) dcerpc_spoolss_EnumPrinters failed: %s\n",
2284 __location__, nt_errstr(status));
2288 if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2289 d_printf("(%s) EnumPrinters unexpected return code %s, should "
2290 "be WERR_INSUFFICIENT_BUFFER\n", __location__,
2291 win_errstr(r.out.result));
2295 blob = data_blob_talloc_zero(mem_ctx, r.out.needed);
2296 if (blob.data == NULL) {
2297 d_printf("(%s) data_blob_talloc failed\n", __location__);
2301 r.in.buffer = &blob;
2302 r.in.offered = r.out.needed;
2304 status = dcerpc_spoolss_EnumPrinters(pipe, mem_ctx, &r);
2305 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
2306 d_printf("(%s) dcerpc_spoolss_EnumPrinters failed: %s, "
2307 "%s\n", __location__, nt_errstr(status),
2308 win_errstr(r.out.result));
2312 *num_printers = r.out.count;
2317 static NTSTATUS getprinterinfo(TALLOC_CTX *ctx, struct dcerpc_pipe *pipe,
2318 struct policy_handle *handle, int level,
2319 union spoolss_PrinterInfo **res)
2321 TALLOC_CTX *mem_ctx;
2322 struct spoolss_GetPrinter r;
2326 mem_ctx = talloc_new(ctx);
2327 if (mem_ctx == NULL) {
2328 return NT_STATUS_NO_MEMORY;
2331 r.in.handle = handle;
2336 status = dcerpc_spoolss_GetPrinter(pipe, mem_ctx, &r);
2337 if (!NT_STATUS_IS_OK(status)) {
2338 d_printf("(%s) dcerpc_spoolss_GetPrinter failed: %s\n",
2339 __location__, nt_errstr(status));
2340 talloc_free(mem_ctx);
2344 if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2345 printf("GetPrinter unexpected return code %s, should "
2346 "be WERR_INSUFFICIENT_BUFFER\n",
2347 win_errstr(r.out.result));
2348 talloc_free(mem_ctx);
2349 return NT_STATUS_UNSUCCESSFUL;
2352 r.in.handle = handle;
2354 blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
2355 if (blob.data == NULL) {
2356 talloc_free(mem_ctx);
2357 return NT_STATUS_NO_MEMORY;
2359 memset(blob.data, 0, blob.length);
2360 r.in.buffer = &blob;
2361 r.in.offered = r.out.needed;
2363 status = dcerpc_spoolss_GetPrinter(pipe, mem_ctx, &r);
2364 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
2365 d_printf("(%s) dcerpc_spoolss_GetPrinter failed: %s, "
2366 "%s\n", __location__, nt_errstr(status),
2367 win_errstr(r.out.result));
2368 talloc_free(mem_ctx);
2369 return NT_STATUS_IS_OK(status) ?
2370 NT_STATUS_UNSUCCESSFUL : status;
2374 *res = talloc_steal(ctx, r.out.info);
2377 talloc_free(mem_ctx);
2378 return NT_STATUS_OK;
2381 BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
2383 TALLOC_CTX *mem_ctx;
2385 struct smbcli_state *cli;
2386 struct dcerpc_pipe *p;
2388 struct policy_handle server_handle, printer_handle;
2389 const char **printers;
2391 struct spoolss_UserLevel1 userlevel1;
2394 if (!(mem_ctx = talloc_new(torture))) {
2398 if (!(torture_open_connection_share(
2399 mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
2401 d_printf("IPC$ connection failed\n");
2402 talloc_free(mem_ctx);
2406 status = get_servername(mem_ctx, cli->tree, &servername);
2407 if (!NT_STATUS_IS_OK(status)) {
2408 d_fprintf(stderr, "(%s) get_servername returned %s\n",
2409 __location__, nt_errstr(status));
2410 talloc_free(mem_ctx);
2414 if (!NT_STATUS_IS_OK(find_printers(mem_ctx, cli->tree,
2415 &printers, &num_printers))) {
2416 talloc_free(mem_ctx);
2420 if (num_printers == 0) {
2421 d_printf("Did not find printers\n");
2422 talloc_free(mem_ctx);
2426 status = pipe_bind_smb(mem_ctx, cli->tree, "\\spoolss",
2427 &ndr_table_spoolss, &p);
2428 if (!NT_STATUS_IS_OK(status)) {
2429 d_printf("(%s) pipe_bind_smb failed: %s\n", __location__,
2431 talloc_free(mem_ctx);
2435 ZERO_STRUCT(userlevel1);
2436 userlevel1.client = talloc_asprintf(
2437 mem_ctx, "\\\\%s", lp_netbios_name());
2438 userlevel1.user = cli_credentials_get_username(cmdline_credentials);
2439 userlevel1.build = 2600;
2440 userlevel1.major = 3;
2441 userlevel1.minor = 0;
2442 userlevel1.processor = 0;
2445 struct spoolss_OpenPrinterEx r;
2448 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s",
2450 r.in.datatype = NULL;
2451 r.in.access_mask = 0;
2453 r.in.userlevel.level1 = &userlevel1;
2454 r.out.handle = &server_handle;
2456 status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
2457 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
2458 d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
2459 "%s, %s\n", __location__, nt_errstr(status),
2460 win_errstr(r.out.result));
2461 talloc_free(mem_ctx);
2467 struct spoolss_ClosePrinter r;
2469 r.in.handle = &server_handle;
2470 r.out.handle = &server_handle;
2472 status = dcerpc_spoolss_ClosePrinter(p, mem_ctx, &r);
2473 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
2474 d_printf("(%s) dcerpc_spoolss_ClosePrinter failed: "
2475 "%s, %s\n", __location__, nt_errstr(status),
2476 win_errstr(r.out.result));
2477 talloc_free(mem_ctx);
2483 struct spoolss_OpenPrinterEx r;
2486 r.in.printername = talloc_asprintf(
2487 mem_ctx, "\\\\%s\\%s", servername, printers[0]);
2488 r.in.datatype = NULL;
2489 r.in.access_mask = 0;
2491 r.in.userlevel.level1 = &userlevel1;
2492 r.out.handle = &printer_handle;
2494 status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
2495 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
2496 d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
2497 "%s, %s\n", __location__, nt_errstr(status),
2498 win_errstr(r.out.result));
2499 talloc_free(mem_ctx);
2507 for (i=0; i<8; i++) {
2508 status = getprinterinfo(mem_ctx, p, &printer_handle,
2510 if (!NT_STATUS_IS_OK(status)) {
2511 d_printf("(%s) getprinterinfo %d failed: %s\n",
2512 __location__, i, nt_errstr(status));
2519 struct spoolss_ClosePrinter r;
2521 r.in.handle = &printer_handle;
2522 r.out.handle = &printer_handle;
2524 status = dcerpc_spoolss_ClosePrinter(p, mem_ctx, &r);
2525 if (!NT_STATUS_IS_OK(status)) {
2526 d_printf("(%s) dcerpc_spoolss_ClosePrinter failed: "
2527 "%s\n", __location__, nt_errstr(status));
2528 talloc_free(mem_ctx);
2535 if (!enumprinters(mem_ctx, p, servername, 1,
2537 d_printf("(%s) enumprinters failed\n", __location__);
2538 talloc_free(mem_ctx);
2541 if (num_printers != num_enumerated) {
2542 d_printf("(%s) netshareenum gave %d printers, "
2543 "enumprinters lvl 1 gave %d\n", __location__,
2544 num_printers, num_enumerated);
2545 talloc_free(mem_ctx);
2552 if (!enumprinters(mem_ctx, p, servername, 2,
2554 d_printf("(%s) enumprinters failed\n", __location__);
2555 talloc_free(mem_ctx);
2558 if (num_printers != num_enumerated) {
2559 d_printf("(%s) netshareenum gave %d printers, "
2560 "enumprinters lvl 2 gave %d\n", __location__,
2561 num_printers, num_enumerated);
2562 talloc_free(mem_ctx);
2567 talloc_free(mem_ctx);
2572 BOOL torture_samba3_rpc_wkssvc(struct torture_context *torture)
2574 TALLOC_CTX *mem_ctx;
2575 struct smbcli_state *cli;
2576 struct dcerpc_pipe *p;
2580 if (!(mem_ctx = talloc_new(torture))) {
2584 if (!(torture_open_connection_share(
2585 mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
2587 d_printf("IPC$ connection failed\n");
2588 talloc_free(mem_ctx);
2592 status = get_servername(mem_ctx, cli->tree, &servername);
2593 if (!NT_STATUS_IS_OK(status)) {
2594 d_fprintf(stderr, "(%s) get_servername returned %s\n",
2595 __location__, nt_errstr(status));
2596 talloc_free(mem_ctx);
2600 status = pipe_bind_smb(mem_ctx, cli->tree, "\\wkssvc",
2601 &ndr_table_wkssvc, &p);
2602 if (!NT_STATUS_IS_OK(status)) {
2603 d_printf("(%s) pipe_bind_smb failed: %s\n", __location__,
2605 talloc_free(mem_ctx);
2610 struct wkssvc_NetWkstaInfo100 wks100;
2611 union wkssvc_NetWkstaInfo info;
2612 struct wkssvc_NetWkstaGetInfo r;
2614 r.in.server_name = "\\foo";
2616 info.info100 = &wks100;
2619 status = dcerpc_wkssvc_NetWkstaGetInfo(p, mem_ctx, &r);
2620 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
2621 d_printf("(%s) dcerpc_wkssvc_NetWksGetInfo failed: "
2622 "%s, %s\n", __location__, nt_errstr(status),
2623 win_errstr(r.out.result));
2624 talloc_free(mem_ctx);
2628 if (strcmp(servername,
2629 r.out.info->info100->server_name) != 0) {
2630 d_printf("(%s) servername inconsistency: RAP=%s, "
2631 "dcerpc_wkssvc_NetWksGetInfo=%s",
2632 __location__, servername,
2633 r.out.info->info100->server_name);
2634 talloc_free(mem_ctx);
2639 talloc_free(mem_ctx);
2643 static NTSTATUS winreg_close(struct dcerpc_pipe *p,
2644 struct policy_handle *handle)
2646 struct winreg_CloseKey c;
2648 TALLOC_CTX *mem_ctx;
2650 c.in.handle = c.out.handle = handle;
2652 if (!(mem_ctx = talloc_new(p))) {
2653 return NT_STATUS_NO_MEMORY;
2656 status = dcerpc_winreg_CloseKey(p, mem_ctx, &c);
2657 talloc_free(mem_ctx);
2659 if (!NT_STATUS_IS_OK(status)) {
2663 if (!W_ERROR_IS_OK(c.out.result)) {
2664 return werror_to_ntstatus(c.out.result);
2667 return NT_STATUS_OK;
2670 static NTSTATUS enumvalues(struct dcerpc_pipe *p, struct policy_handle *handle,
2671 TALLOC_CTX *mem_ctx)
2673 uint32_t enum_index = 0;
2676 struct winreg_EnumValue r;
2677 struct winreg_StringBuf name;
2678 enum winreg_Type type = 0;
2681 uint32_t size, length;
2683 r.in.handle = handle;
2684 r.in.enum_index = enum_index;
2687 r.in.name = r.out.name = &name;
2693 r.in.length = &length;
2695 status = dcerpc_winreg_EnumValue(p, mem_ctx, &r);
2696 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
2697 return NT_STATUS_OK;
2703 static NTSTATUS enumkeys(struct dcerpc_pipe *p, struct policy_handle *handle,
2704 TALLOC_CTX *mem_ctx, int depth)
2706 struct winreg_EnumKey r;
2707 struct winreg_StringBuf class, name;
2712 return NT_STATUS_OK;
2718 r.in.handle = handle;
2719 r.in.enum_index = 0;
2721 r.in.keyclass = &class;
2723 r.in.last_changed_time = &t;
2726 TALLOC_CTX *tmp_ctx;
2727 struct winreg_OpenKey o;
2728 struct policy_handle key_handle;
2731 if (!(tmp_ctx = talloc_new(mem_ctx))) {
2732 return NT_STATUS_NO_MEMORY;
2738 status = dcerpc_winreg_EnumKey(p, tmp_ctx, &r);
2739 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
2740 /* We're done enumerating */
2741 talloc_free(tmp_ctx);
2742 return NT_STATUS_OK;
2745 for (i=0; i<10-depth; i++)
2747 printf("%s\n", r.out.name->name);
2750 o.in.parent_handle = handle;
2751 o.in.keyname.name = r.out.name->name;
2753 o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2754 o.out.handle = &key_handle;
2756 status = dcerpc_winreg_OpenKey(p, tmp_ctx, &o);
2757 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(o.out.result)) {
2758 enumkeys(p, &key_handle, tmp_ctx, depth-1);
2759 enumvalues(p, &key_handle, tmp_ctx);
2760 status = winreg_close(p, &key_handle);
2761 if (!NT_STATUS_IS_OK(status)) {
2766 talloc_free(tmp_ctx);
2768 r.in.enum_index += 1;
2771 return NT_STATUS_OK;
2774 typedef NTSTATUS (*winreg_open_fn)(struct dcerpc_pipe *, TALLOC_CTX *, void *);
2776 static BOOL test_Open3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2777 const char *name, winreg_open_fn open_fn)
2779 struct policy_handle handle;
2780 struct winreg_OpenHKLM r;
2783 r.in.system_name = 0;
2784 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2785 r.out.handle = &handle;
2787 status = open_fn(p, mem_ctx, &r);
2788 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
2789 d_printf("(%s) %s failed: %s, %s\n", __location__, name,
2790 nt_errstr(status), win_errstr(r.out.result));
2794 enumkeys(p, &handle, mem_ctx, 4);
2796 status = winreg_close(p, &handle);
2797 if (!NT_STATUS_IS_OK(status)) {
2798 d_printf("(%s) dcerpc_CloseKey failed: %s\n",
2799 __location__, nt_errstr(status));
2806 BOOL torture_samba3_rpc_winreg(struct torture_context *torture)
2809 struct dcerpc_pipe *p;
2810 TALLOC_CTX *mem_ctx;
2816 {"OpenHKLM", (winreg_open_fn)dcerpc_winreg_OpenHKLM },
2817 {"OpenHKU", (winreg_open_fn)dcerpc_winreg_OpenHKU },
2818 {"OpenHKPD", (winreg_open_fn)dcerpc_winreg_OpenHKPD },
2819 {"OpenHKPT", (winreg_open_fn)dcerpc_winreg_OpenHKPT },
2820 {"OpenHKCR", (winreg_open_fn)dcerpc_winreg_OpenHKCR }};
2825 mem_ctx = talloc_init("torture_rpc_winreg");
2827 status = torture_rpc_connection(mem_ctx, &p, &ndr_table_winreg);
2829 if (!NT_STATUS_IS_OK(status)) {
2830 talloc_free(mem_ctx);
2835 ret = test_Open3(p, mem_ctx, open_fns[0].name, open_fns[0].fn);
2837 for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
2838 if (!test_Open3(p, mem_ctx, open_fns[i].name, open_fns[i].fn))
2843 talloc_free(mem_ctx);