2 Unix SMB/CIFS implementation.
3 test suite for accessmasks on the SAMR pipe
5 Copyright (C) Ronnie Sahlberg 2007
6 Copyright (C) Guenther Deschner 2009
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 "librpc/gen_ndr/ndr_samr_c.h"
24 #include "torture/rpc/torture_rpc.h"
25 #include "param/param.h"
26 #include "libcli/security/security.h"
29 /* test user created to test the ACLs associated to SAMR objects */
30 #define TEST_USER_NAME "samr_testuser"
31 #define TEST_MACHINENAME "samrtestmach"
33 static NTSTATUS torture_samr_Close(struct torture_context *tctx,
34 struct dcerpc_binding_handle *b,
35 struct policy_handle *h)
42 status = dcerpc_samr_Close_r(b, tctx, &cl);
43 if (!NT_STATUS_IS_OK(status)) {
50 static NTSTATUS torture_samr_Connect5(struct torture_context *tctx,
51 struct dcerpc_binding_handle *b,
52 uint32_t mask, struct policy_handle *h)
55 struct samr_Connect5 r5;
56 union samr_ConnectInfo info;
57 uint32_t level_out = 0;
59 info.info1.client_version = 0;
60 info.info1.unknown2 = 0;
61 r5.in.system_name = "";
63 r5.in.info_in = &info;
64 r5.out.info_out = &info;
65 r5.out.level_out = &level_out;
66 r5.out.connect_handle = h;
67 r5.in.access_mask = mask;
69 status = dcerpc_samr_Connect5_r(b, tctx, &r5);
70 if (!NT_STATUS_IS_OK(status)) {
77 /* check which bits in accessmask allows us to connect to the server */
78 static bool test_samr_accessmask_Connect5(struct torture_context *tctx,
79 struct dcerpc_pipe *p)
82 struct policy_handle h;
85 struct dcerpc_binding_handle *b = p->binding_handle;
87 printf("Testing which bits in accessmask allows us to connect\n");
90 printf("Testing Connect5 with access mask 0x%08x", mask);
91 status = torture_samr_Connect5(tctx, b, mask, &h);
111 printf(" expecting to fail");
112 /* of only one of these bits are set we expect to
115 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, status)) {
116 printf("Connect5 failed - %s\n", nt_errstr(status));
121 /* these bits set are expected to succeed by default */
122 if (!NT_STATUS_IS_OK(status)) {
123 printf("Connect5 failed - %s\n", nt_errstr(status));
127 status = torture_samr_Close(tctx, b, &h);
128 if (!NT_STATUS_IS_OK(status)) {
129 printf("Close failed - %s\n", nt_errstr(status));
140 /* check which bits in accessmask allows us to EnumDomains()
141 by default we must specify at least one of :
146 in the access mask to Connect5() in order to be allowed to perform
147 EnumDomains() on the policy handle returned from Connect5()
149 static bool test_samr_accessmask_EnumDomains(struct torture_context *tctx,
150 struct dcerpc_pipe *p)
153 struct samr_EnumDomains ed;
154 struct policy_handle ch;
157 uint32_t resume_handle = 0;
158 struct samr_SamArray *sam = NULL;
159 uint32_t num_entries = 0;
160 struct dcerpc_binding_handle *b = p->binding_handle;
162 printf("Testing which bits in Connect5 accessmask allows us to EnumDomains\n");
165 printf("Testing Connect5/EnumDomains with access mask 0x%08x", mask);
166 status = torture_samr_Connect5(tctx, b, mask, &ch);
170 case 4: /* SAMR/EnumDomains */
171 case 25: /* Maximum */
172 case 28: /* GenericAll */
173 case 31: /* GenericRead */
174 /* these bits set are expected to succeed by default */
175 if (!NT_STATUS_IS_OK(status)) {
176 printf("Connect5 failed - %s\n", nt_errstr(status));
180 ed.in.connect_handle = &ch;
181 ed.in.resume_handle = &resume_handle;
182 ed.in.buf_size = (uint32_t)-1;
183 ed.out.resume_handle = &resume_handle;
184 ed.out.num_entries = &num_entries;
187 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &ed),
188 "EnumDomains failed");
189 if (!NT_STATUS_IS_OK(ed.out.result)) {
190 printf("EnumDomains failed - %s\n", nt_errstr(ed.out.result));
194 status = torture_samr_Close(tctx, b, &ch);
195 if (!NT_STATUS_IS_OK(status)) {
196 printf("Close failed - %s\n", nt_errstr(status));
201 printf(" expecting to fail");
203 if (!NT_STATUS_IS_OK(status)) {
208 ed.in.connect_handle = &ch;
209 ed.in.resume_handle = &resume_handle;
210 ed.in.buf_size = (uint32_t)-1;
211 ed.out.resume_handle = &resume_handle;
212 ed.out.num_entries = &num_entries;
215 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &ed),
216 "EnumDomains failed");
217 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, ed.out.result)) {
218 printf("EnumDomains failed - %s\n", nt_errstr(ed.out.result));
222 status = torture_samr_Close(tctx, b, &ch);
223 if (!NT_STATUS_IS_OK(status)) {
224 printf("Close failed - %s\n", nt_errstr(status));
237 * test how ACLs affect how/if a user can connect to the SAMR service
239 * samr_SetSecurity() returns SUCCESS when changing the ACL for
240 * a policy handle got from Connect5() but the ACL is not changed on
243 static bool test_samr_connect_user_acl(struct torture_context *tctx,
244 struct dcerpc_binding_handle *b,
245 struct cli_credentials *test_credentials,
246 const struct dom_sid *test_sid)
250 struct policy_handle ch;
251 struct policy_handle uch;
252 struct samr_QuerySecurity qs;
253 struct samr_SetSecurity ss;
254 struct security_ace ace;
255 struct security_descriptor *sd;
256 struct sec_desc_buf sdb, *sdbuf = NULL;
259 struct dcerpc_pipe *test_p;
260 struct dcerpc_binding_handle *test_b;
261 const char *binding = torture_setting_string(tctx, "binding", NULL);
263 printf("Testing ACLs to allow/prevent users to connect to SAMR");
265 /* connect to SAMR */
266 status = torture_samr_Connect5(tctx, b, SEC_FLAG_MAXIMUM_ALLOWED, &ch);
267 if (!NT_STATUS_IS_OK(status)) {
268 printf("Connect5 failed - %s\n", nt_errstr(status));
273 /* get the current ACL for the SAMR policy handle */
275 qs.in.sec_info = SECINFO_DACL;
276 qs.out.sdbuf = &sdbuf;
277 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &qs),
278 "QuerySecurity failed");
279 if (!NT_STATUS_IS_OK(qs.out.result)) {
280 printf("QuerySecurity failed - %s\n", nt_errstr(qs.out.result));
284 /* how big is the security descriptor? */
285 sd_size = sdbuf->sd_size;
288 /* add an ACE to the security descriptor to deny the user the
289 * 'connect to server' right
292 ace.type = SEC_ACE_TYPE_ACCESS_DENIED;
294 ace.access_mask = SAMR_ACCESS_CONNECT_TO_SERVER;
295 ace.trustee = *test_sid;
296 status = security_descriptor_dacl_add(sd, &ace);
297 if (!NT_STATUS_IS_OK(status)) {
298 printf("Failed to add ACE to security descriptor\n");
302 ss.in.sec_info = SECINFO_DACL;
305 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetSecurity_r(b, tctx, &ss),
306 "SetSecurity failed");
307 if (!NT_STATUS_IS_OK(ss.out.result)) {
308 printf("SetSecurity failed - %s\n", nt_errstr(ss.out.result));
313 /* Try to connect as the test user */
314 status = dcerpc_pipe_connect(tctx,
315 &test_p, binding, &ndr_table_samr,
316 test_credentials, tctx->ev, tctx->lp_ctx);
317 if (!NT_STATUS_IS_OK(status)) {
318 printf("dcerpc_pipe_connect failed: %s\n", nt_errstr(status));
321 test_b = test_p->binding_handle;
323 /* connect to SAMR as the user */
324 status = torture_samr_Connect5(tctx, test_b, SEC_FLAG_MAXIMUM_ALLOWED, &uch);
325 if (!NT_STATUS_IS_OK(status)) {
326 printf("Connect5 failed - %s\n", nt_errstr(status));
329 /* disconnec the user */
333 /* read the sequrity descriptor back. it should not have changed
334 * eventhough samr_SetSecurity returned SUCCESS
336 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &qs),
337 "QuerySecurity failed");
338 if (!NT_STATUS_IS_OK(qs.out.result)) {
339 printf("QuerySecurity failed - %s\n", nt_errstr(qs.out.result));
342 if (sd_size != sdbuf->sd_size) {
343 printf("security descriptor changed\n");
348 status = torture_samr_Close(tctx, b, &ch);
349 if (!NT_STATUS_IS_OK(status)) {
350 printf("Close failed - %s\n", nt_errstr(status));
361 * test if the ACLs are enforced for users.
362 * a normal testuser only gets the rights provided in hte ACL for
363 * Everyone which does not include the SAMR_ACCESS_SHUTDOWN_SERVER
364 * right. If the ACLs are checked when a user connects
365 * a testuser that requests the accessmask with only this bit set
366 * the connect should fail.
368 static bool test_samr_connect_user_acl_enforced(struct torture_context *tctx,
369 struct dcerpc_binding_handle *b,
370 struct cli_credentials *test_credentials,
371 const struct dom_sid *test_sid)
375 struct policy_handle uch;
377 struct dcerpc_pipe *test_p;
378 struct dcerpc_binding_handle *test_b;
379 const char *binding = torture_setting_string(tctx, "binding", NULL);
381 printf("Testing if ACLs are enforced for non domain admin users when connecting to SAMR");
384 status = dcerpc_pipe_connect(tctx,
385 &test_p, binding, &ndr_table_samr,
386 test_credentials, tctx->ev, tctx->lp_ctx);
387 if (!NT_STATUS_IS_OK(status)) {
388 printf("dcerpc_pipe_connect failed: %s\n", nt_errstr(status));
391 test_b = test_p->binding_handle;
393 /* connect to SAMR as the user */
394 status = torture_samr_Connect5(tctx, test_b, SAMR_ACCESS_SHUTDOWN_SERVER, &uch);
395 if (NT_STATUS_IS_OK(status)) {
396 printf("Connect5 failed - %s\n", nt_errstr(status));
401 /* disconnec the user */
407 /* check which bits in accessmask allows us to LookupDomain()
408 by default we must specify at least one of :
409 in the access mask to Connect5() in order to be allowed to perform
410 case 5: samr/opendomain
413 case 29: GenericExecute
414 LookupDomain() on the policy handle returned from Connect5()
416 static bool test_samr_accessmask_LookupDomain(struct torture_context *tctx,
417 struct dcerpc_pipe *p)
420 struct samr_LookupDomain ld;
421 struct dom_sid2 *sid = NULL;
422 struct policy_handle ch;
423 struct lsa_String dn;
426 struct dcerpc_binding_handle *b = p->binding_handle;
428 printf("Testing which bits in Connect5 accessmask allows us to LookupDomain\n");
431 printf("Testing Connect5/LookupDomain with access mask 0x%08x", mask);
432 status = torture_samr_Connect5(tctx, b, mask, &ch);
437 case 25: /* Maximum */
438 case 28: /* GenericAll */
439 case 29: /* GenericExecute */
440 /* these bits set are expected to succeed by default */
441 if (!NT_STATUS_IS_OK(status)) {
442 printf("Connect5 failed - %s\n", nt_errstr(status));
446 ld.in.connect_handle = &ch;
447 ld.in.domain_name = &dn;
449 dn.string = lpcfg_workgroup(tctx->lp_ctx);
451 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &ld),
452 "LookupDomain failed");
453 if (!NT_STATUS_IS_OK(ld.out.result)) {
454 printf("LookupDomain failed - %s\n", nt_errstr(ld.out.result));
458 status = torture_samr_Close(tctx, b, &ch);
459 if (!NT_STATUS_IS_OK(status)) {
460 printf("Close failed - %s\n", nt_errstr(status));
465 printf(" expecting to fail");
467 if (!NT_STATUS_IS_OK(status)) {
472 ld.in.connect_handle = &ch;
473 ld.in.domain_name = &dn;
475 dn.string = lpcfg_workgroup(tctx->lp_ctx);
477 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &ld),
478 "LookupDomain failed");
479 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, ld.out.result)) {
480 printf("LookupDomain failed - %s\n", nt_errstr(ld.out.result));
484 status = torture_samr_Close(tctx, b, &ch);
485 if (!NT_STATUS_IS_OK(status)) {
486 printf("Close failed - %s\n", nt_errstr(status));
497 /* check which bits in accessmask allows us to OpenDomain()
498 by default we must specify at least one of :
503 in the access mask to Connect5() in order to be allowed to perform
504 OpenDomain() on the policy handle returned from Connect5()
506 static bool test_samr_accessmask_OpenDomain(struct torture_context *tctx,
507 struct dcerpc_pipe *p)
510 struct samr_LookupDomain ld;
511 struct dom_sid2 *sid = NULL;
512 struct samr_OpenDomain od;
513 struct policy_handle ch;
514 struct policy_handle dh;
515 struct lsa_String dn;
518 struct dcerpc_binding_handle *b = p->binding_handle;
521 /* first we must grab the sid of the domain */
522 status = torture_samr_Connect5(tctx, b, SEC_FLAG_MAXIMUM_ALLOWED, &ch);
523 if (!NT_STATUS_IS_OK(status)) {
524 printf("Connect5 failed - %s\n", nt_errstr(status));
528 ld.in.connect_handle = &ch;
529 ld.in.domain_name = &dn;
531 dn.string = lpcfg_workgroup(tctx->lp_ctx);
532 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &ld),
533 "LookupDomain failed");
534 if (!NT_STATUS_IS_OK(ld.out.result)) {
535 printf("LookupDomain failed - %s\n", nt_errstr(ld.out.result));
541 printf("Testing which bits in Connect5 accessmask allows us to OpenDomain\n");
544 printf("Testing Connect5/OpenDomain with access mask 0x%08x", mask);
545 status = torture_samr_Connect5(tctx, b, mask, &ch);
550 case 25: /* Maximum */
551 case 28: /* GenericAll */
552 case 29: /* GenericExecute */
553 /* these bits set are expected to succeed by default */
554 if (!NT_STATUS_IS_OK(status)) {
555 printf("Connect5 failed - %s\n", nt_errstr(status));
559 od.in.connect_handle = &ch;
560 od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
562 od.out.domain_handle = &dh;
564 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &od),
565 "OpenDomain failed");
566 if (!NT_STATUS_IS_OK(od.out.result)) {
567 printf("OpenDomain failed - %s\n", nt_errstr(od.out.result));
571 status = torture_samr_Close(tctx, b, &dh);
572 if (!NT_STATUS_IS_OK(status)) {
573 printf("Close failed - %s\n", nt_errstr(status));
577 status = torture_samr_Close(tctx, b, &ch);
578 if (!NT_STATUS_IS_OK(status)) {
579 printf("Close failed - %s\n", nt_errstr(status));
584 printf(" expecting to fail");
586 if (!NT_STATUS_IS_OK(status)) {
591 status = torture_samr_Close(tctx, b, &ch);
592 if (!NT_STATUS_IS_OK(status)) {
593 printf("Close failed - %s\n", nt_errstr(status));
604 static bool test_samr_connect(struct torture_context *tctx,
605 struct dcerpc_pipe *p)
608 const char *testuser_passwd;
609 struct cli_credentials *test_credentials;
611 const struct dom_sid *test_sid;
612 struct dcerpc_binding_handle *b = p->binding_handle;
614 if (torture_setting_bool(tctx, "samba3", false)) {
615 torture_skip(tctx, "Skipping test against Samba 3");
618 /* create a test user */
619 testuser = torture_create_testuser(tctx, TEST_USER_NAME, lpcfg_workgroup(tctx->lp_ctx),
620 ACB_NORMAL, &testuser_passwd);
622 printf("Failed to create test user\n");
625 test_credentials = cli_credentials_init(tctx);
626 cli_credentials_set_workstation(test_credentials, "localhost", CRED_SPECIFIED);
627 cli_credentials_set_domain(test_credentials, lpcfg_workgroup(tctx->lp_ctx),
629 cli_credentials_set_username(test_credentials, TEST_USER_NAME, CRED_SPECIFIED);
630 cli_credentials_set_password(test_credentials, testuser_passwd, CRED_SPECIFIED);
631 test_sid = torture_join_user_sid(testuser);
634 /* test if ACLs can be changed for the policy handle
635 * returned by Connect5
637 if (!test_samr_connect_user_acl(tctx, b, test_credentials, test_sid)) {
641 /* test if the ACLs that are reported from the Connect5
642 * policy handle is enforced.
643 * i.e. an ordinary user only has the same rights as Everybody
647 * Samr/ConnectToServer
648 * is granted and should therefore not be able to connect when
649 * requesting SAMR_ACCESS_SHUTDOWN_SERVER
651 if (!test_samr_connect_user_acl_enforced(tctx, b, test_credentials, test_sid)) {
655 /* remove the test user */
656 torture_leave_domain(tctx, testuser);
661 struct torture_suite *torture_rpc_samr_accessmask(TALLOC_CTX *mem_ctx)
663 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-ACCESSMASK");
664 struct torture_rpc_tcase *tcase;
666 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr",
669 torture_rpc_tcase_add_test(tcase, "CONNECT", test_samr_connect);
671 /* test which bits in the accessmask to Connect5 will allow
672 * us to call OpenDomain() */
673 torture_rpc_tcase_add_test(tcase, "OpenDomain",
674 test_samr_accessmask_OpenDomain);
676 /* test which bits in the accessmask to Connect5 will allow
677 * us to call LookupDomain() */
678 torture_rpc_tcase_add_test(tcase, "LookupDomain",
679 test_samr_accessmask_LookupDomain);
681 /* test which bits in the accessmask to Connect5 will allow
682 * us to call EnumDomains() */
683 torture_rpc_tcase_add_test(tcase, "EnumDomains",
684 test_samr_accessmask_EnumDomains);
686 /* test which bits in the accessmask to Connect5
687 will allow us to connect to the server */
688 torture_rpc_tcase_add_test(tcase, "Connect5",
689 test_samr_accessmask_Connect5);
694 static bool test_LookupRids(struct torture_context *tctx,
695 struct dcerpc_binding_handle *b,
696 struct policy_handle *domain_handle,
699 struct samr_LookupRids r;
700 struct lsa_Strings names;
701 struct samr_Ids types;
703 torture_comment(tctx, "Testing LookupRids %d\n", rid);
705 r.in.domain_handle = domain_handle;
708 r.out.names = &names;
709 r.out.types = &types;
711 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &r),
712 "failed to call samr_LookupRids");
713 torture_assert_ntstatus_ok(tctx, r.out.result,
714 "failed to call samr_LookupRids");
720 static bool test_user(struct torture_context *tctx,
721 struct dcerpc_binding_handle *b,
722 struct policy_handle *domain_handle,
723 uint32_t access_mask,
724 struct samr_DispEntryGeneral *u)
726 struct policy_handle user_handle;
728 torture_comment(tctx, "Testing user %s (%d)\n", u->account_name.string, u->rid);
730 torture_assert(tctx, test_LookupRids(tctx, b, domain_handle, u->rid),
731 "failed to call lookuprids");
734 struct samr_OpenUser r;
736 r.in.domain_handle = domain_handle;
737 r.in.access_mask = access_mask;
739 r.out.user_handle = &user_handle;
741 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
742 "failed to open user");
743 torture_assert_ntstatus_ok(tctx, r.out.result,
744 "failed to open user");
747 struct samr_QueryUserInfo r;
748 union samr_UserInfo *info;
749 uint32_t levels[] = { 16, 21 };
752 r.in.user_handle = &user_handle;
755 for (i=0; i < ARRAY_SIZE(levels); i++) {
757 r.in.level = levels[i];
759 torture_comment(tctx, "Testing QueryUserInfo rid: %d level: %d\n",
762 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
763 talloc_asprintf(tctx, "failed to query user info level %d", r.in.level));
764 torture_assert_ntstatus_ok(tctx, r.out.result,
765 talloc_asprintf(tctx, "failed to query user info level %d", r.in.level));
769 struct samr_GetGroupsForUser r;
770 struct samr_RidWithAttributeArray *rids;
772 r.in.user_handle = &user_handle;
775 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetGroupsForUser_r(b, tctx, &r),
776 "failed to query groups for user");
777 torture_assert_ntstatus_ok(tctx, r.out.result,
778 "failed to query groups for user");
781 torture_assert_ntstatus_ok(tctx,
782 torture_samr_Close(tctx, b, &user_handle),
783 "failed to close user handle");
788 static bool test_samr_group(struct torture_context *tctx,
789 struct dcerpc_binding_handle *b,
790 struct policy_handle *domain_handle,
791 uint32_t access_mask,
792 struct samr_SamEntry *g)
794 struct policy_handle group_handle;
796 torture_comment(tctx, "Testing group %s (%d)\n", g->name.string, g->idx);
798 torture_assert(tctx, test_LookupRids(tctx, b, domain_handle, g->idx),
799 "failed to call lookuprids");
801 struct samr_OpenGroup r;
803 r.in.domain_handle = domain_handle;
804 r.in.access_mask = access_mask;
806 r.out.group_handle = &group_handle;
808 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
809 "failed to open group");
810 torture_assert_ntstatus_ok(tctx, r.out.result,
811 "failed to open group");
814 struct samr_QueryGroupMember r;
815 struct samr_RidAttrArray *rids;
817 r.in.group_handle = &group_handle;
820 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
821 "failed to query group member");
822 torture_assert_ntstatus_ok(tctx, r.out.result,
823 "failed to query group member");
827 torture_assert_ntstatus_ok(tctx,
828 torture_samr_Close(tctx, b, &group_handle),
829 "failed to close group handle");
834 static bool test_samr_alias(struct torture_context *tctx,
835 struct dcerpc_binding_handle *b,
836 struct policy_handle *domain_handle,
837 struct samr_SamEntry *a)
839 torture_comment(tctx, "Testing alias %s (%d)\n", a->name.string, a->idx);
841 torture_assert(tctx, test_LookupRids(tctx, b, domain_handle, a->idx),
842 "failed to call lookuprids");
845 struct samr_GetAliasMembership r;
846 struct lsa_SidArray sids;
847 struct samr_Ids rids;
851 r.in.domain_handle = domain_handle;
855 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
856 "failed to get alias membership");
857 torture_assert_ntstatus_ok(tctx, r.out.result,
858 "failed to get alias membership");
865 static bool test_samr_domain(struct torture_context *tctx,
866 struct dcerpc_binding_handle *b,
867 uint32_t access_mask,
868 const char *domain_name,
869 struct policy_handle *connect_handle,
870 struct policy_handle *domain_handle_p)
872 struct policy_handle domain_handle;
873 struct dom_sid *domain_sid;
876 struct samr_EnumDomains r;
877 uint32_t resume_handle;
878 struct samr_SamArray *sam;
879 uint32_t num_entries;
882 r.in.connect_handle = connect_handle;
883 r.in.buf_size = 0xffff;
884 r.in.resume_handle = &resume_handle;
886 r.out.num_entries = &num_entries;
887 r.out.resume_handle = &resume_handle;
889 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
890 "failed to enum domains");
891 torture_assert_ntstatus_ok(tctx, r.out.result,
892 "failed to enum domains");
894 torture_assert_int_equal(tctx, num_entries, 2,
895 "unexpected number of domains");
897 torture_assert(tctx, sam,
898 "no domain pointer returned");
900 for (i=0; i < sam->count; i++) {
901 if (!strequal(sam->entries[i].name.string, "builtin")) {
902 domain_name = sam->entries[i].name.string;
907 torture_assert(tctx, domain_name,
908 "no domain found other than builtin found");
912 struct samr_LookupDomain r;
913 struct dom_sid2 *sid;
914 struct lsa_String name;
916 name.string = talloc_strdup(tctx, domain_name);
918 r.in.connect_handle = connect_handle;
919 r.in.domain_name = &name;
922 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
923 "failed to lookup domain");
924 torture_assert_ntstatus_ok(tctx, r.out.result,
925 "failed to lookup domain");
927 domain_sid = dom_sid_dup(tctx, sid);
931 struct samr_OpenDomain r;
933 r.in.connect_handle = connect_handle;
934 r.in.access_mask = access_mask;
935 r.in.sid = domain_sid;
936 r.out.domain_handle = &domain_handle;
938 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
939 "failed to open domain");
940 torture_assert_ntstatus_ok(tctx, r.out.result,
941 "failed to open domain");
946 struct samr_QueryDomainInfo r;
947 union samr_DomainInfo *info;
948 uint32_t levels[] = { 1, 2, 8, 12 };
951 r.in.domain_handle = &domain_handle;
954 for (i=0; i < ARRAY_SIZE(levels); i++) {
956 r.in.level = levels[i];
958 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
959 talloc_asprintf(tctx, "failed to query domain info level %d", r.in.level));
960 torture_assert_ntstatus_ok(tctx, r.out.result,
961 talloc_asprintf(tctx, "failed to query domain info level %d", r.in.level));
966 *domain_handle_p = domain_handle;
971 static void get_query_dispinfo_params(int loop_count,
972 uint32_t *max_entries,
992 default: /* loop_count >= 4 */
1000 static bool test_samr_users(struct torture_context *tctx,
1001 struct dcerpc_binding_handle *b,
1002 uint32_t access_mask,
1003 struct policy_handle *domain_handle)
1006 struct samr_QueryDisplayInfo r;
1007 uint32_t total_size;
1008 uint32_t returned_size;
1009 union samr_DispInfo info;
1012 r.in.domain_handle = domain_handle;
1016 r.out.total_size = &total_size;
1017 r.out.returned_size = &returned_size;
1023 r.in.max_entries = 0xffff;
1024 r.in.buf_size = 0xffff;
1026 get_query_dispinfo_params(loop_count,
1030 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
1031 "QueryDisplayInfo failed");
1032 if (NT_STATUS_IS_ERR(r.out.result)) {
1033 torture_assert_ntstatus_ok(tctx, r.out.result,
1034 "failed to call QueryDisplayInfo");
1037 for (i=0; i < info.info1.count; i++) {
1038 torture_assert(tctx,
1039 test_user(tctx, b, domain_handle, access_mask, &info.info1.entries[i]),
1040 "failed to test user");
1043 r.in.start_idx += info.info1.count;
1045 } while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES));
1051 static bool test_samr_groups(struct torture_context *tctx,
1052 struct dcerpc_binding_handle *b,
1053 uint32_t access_mask,
1054 struct policy_handle *domain_handle)
1057 struct samr_EnumDomainGroups r;
1058 uint32_t resume_handle = 0;
1059 struct samr_SamArray *sam;
1060 uint32_t num_entries;
1062 r.in.domain_handle = domain_handle;
1063 r.in.resume_handle = &resume_handle;
1064 r.in.max_size = 0xFFFF;
1067 r.out.num_entries = &num_entries;
1068 r.out.resume_handle = &resume_handle;
1073 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
1074 "EnumDomainGroups failed");
1075 if (NT_STATUS_IS_ERR(r.out.result)) {
1076 torture_assert_ntstatus_ok(tctx, r.out.result,
1077 "failed to call EnumDomainGroups");
1080 for (i=0; i < num_entries; i++) {
1081 torture_assert(tctx,
1082 test_samr_group(tctx, b, domain_handle, access_mask, &sam->entries[i]),
1083 "failed to test group");
1086 } while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES));
1092 static bool test_samr_aliases(struct torture_context *tctx,
1093 struct dcerpc_binding_handle *b,
1094 uint32_t access_mask,
1095 struct policy_handle *domain_handle)
1098 struct samr_EnumDomainAliases r;
1099 uint32_t resume_handle = 0;
1100 struct samr_SamArray *sam;
1101 uint32_t num_entries;
1103 r.in.domain_handle = domain_handle;
1104 r.in.resume_handle = &resume_handle;
1105 r.in.max_size = 0xFFFF;
1108 r.out.num_entries = &num_entries;
1109 r.out.resume_handle = &resume_handle;
1114 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
1115 "EnumDomainAliases failed");
1116 if (NT_STATUS_IS_ERR(r.out.result)) {
1117 torture_assert_ntstatus_ok(tctx, r.out.result,
1118 "failed to call EnumDomainAliases");
1121 for (i=0; i < num_entries; i++) {
1122 torture_assert(tctx,
1123 test_samr_alias(tctx, b, domain_handle, &sam->entries[i]),
1124 "failed to test alias");
1127 } while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES));
1133 static bool torture_rpc_samr_workstation_query(struct torture_context *tctx,
1134 struct dcerpc_pipe *p,
1135 struct cli_credentials *machine_credentials)
1137 struct policy_handle connect_handle;
1138 struct policy_handle domain_handle;
1139 struct dcerpc_binding_handle *b = p->binding_handle;
1141 torture_assert_ntstatus_ok(tctx,
1142 torture_samr_Connect5(tctx, b, SEC_FLAG_MAXIMUM_ALLOWED,
1144 "failed to connect to samr server");
1146 torture_assert(tctx,
1147 test_samr_domain(tctx, b, SEC_FLAG_MAXIMUM_ALLOWED,
1148 lpcfg_workgroup(tctx->lp_ctx),
1149 &connect_handle, &domain_handle),
1150 "failed to test domain");
1152 torture_assert(tctx,
1153 test_samr_users(tctx, b, SEC_FLAG_MAXIMUM_ALLOWED,
1155 "failed to test users");
1157 torture_assert(tctx,
1158 test_samr_groups(tctx, b, SEC_FLAG_MAXIMUM_ALLOWED,
1160 "failed to test groups");
1162 torture_assert(tctx,
1163 test_samr_aliases(tctx, b, SEC_FLAG_MAXIMUM_ALLOWED,
1165 "failed to test aliases");
1167 torture_assert_ntstatus_ok(tctx,
1168 torture_samr_Close(tctx, b, &domain_handle),
1169 "failed to close domain handle");
1171 torture_assert_ntstatus_ok(tctx,
1172 torture_samr_Close(tctx, b, &connect_handle),
1173 "failed to close connect handle");
1178 /* The purpose of this test is to verify that an account authenticated as a
1179 * domain member workstation can query a DC for various remote read calls all
1180 * opening objects while requesting SEC_FLAG_MAXIMUM_ALLOWED access rights on
1181 * the object open calls. This is the behavior of winbind (and most of samba's
1182 * client code) - gd */
1184 struct torture_suite *torture_rpc_samr_workstation_auth(TALLOC_CTX *mem_ctx)
1186 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-MACHINE-AUTH");
1187 struct torture_rpc_tcase *tcase;
1189 tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "samr",
1193 torture_rpc_tcase_add_test_creds(tcase, "workstation_query",
1194 torture_rpc_samr_workstation_query);