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/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_pipe
*p
,
35 struct policy_handle
*h
)
42 status
= dcerpc_samr_Close(p
, tctx
, &cl
);
47 static NTSTATUS
torture_samr_Connect5(struct torture_context
*tctx
,
48 struct dcerpc_pipe
*p
,
49 uint32_t mask
, struct policy_handle
*h
)
52 struct samr_Connect5 r5
;
53 union samr_ConnectInfo info
;
54 uint32_t level_out
= 0;
56 info
.info1
.client_version
= 0;
57 info
.info1
.unknown2
= 0;
58 r5
.in
.system_name
= "";
60 r5
.in
.info_in
= &info
;
61 r5
.out
.info_out
= &info
;
62 r5
.out
.level_out
= &level_out
;
63 r5
.out
.connect_handle
= h
;
64 r5
.in
.access_mask
= mask
;
66 status
= dcerpc_samr_Connect5(p
, tctx
, &r5
);
71 /* check which bits in accessmask allows us to connect to the server */
72 static bool test_samr_accessmask_Connect5(struct torture_context
*tctx
,
73 struct dcerpc_pipe
*p
)
76 struct policy_handle h
;
80 printf("testing which bits in accessmask allows us to connect\n");
83 printf("testing Connect5 with access mask 0x%08x", mask
);
84 status
= torture_samr_Connect5(tctx
, p
, mask
, &h
);
104 printf(" expecting to fail");
105 /* of only one of these bits are set we expect to
108 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED
, status
)) {
109 printf("Connect5 failed - %s\n", nt_errstr(status
));
114 /* these bits set are expected to succeed by default */
115 if (!NT_STATUS_IS_OK(status
)) {
116 printf("Connect5 failed - %s\n", nt_errstr(status
));
120 status
= torture_samr_Close(tctx
, p
, &h
);
121 if (!NT_STATUS_IS_OK(status
)) {
122 printf("Close failed - %s\n", nt_errstr(status
));
133 /* check which bits in accessmask allows us to EnumDomains()
134 by default we must specify at least one of :
139 in the access mask to Connect5() in order to be allowed to perform
140 EnumDomains() on the policy handle returned from Connect5()
142 static bool test_samr_accessmask_EnumDomains(struct torture_context
*tctx
,
143 struct dcerpc_pipe
*p
)
146 struct samr_EnumDomains ed
;
147 struct policy_handle ch
;
150 uint32_t resume_handle
= 0;
151 struct samr_SamArray
*sam
= NULL
;
152 uint32_t num_entries
= 0;
154 printf("testing which bits in Connect5 accessmask allows us to EnumDomains\n");
157 printf("testing Connect5/EnumDomains with access mask 0x%08x", mask
);
158 status
= torture_samr_Connect5(tctx
, p
, mask
, &ch
);
162 case 4: /* SAMR/EnumDomains */
163 case 25: /* Maximum */
164 case 28: /* GenericAll */
165 case 31: /* GenericRead */
166 /* these bits set are expected to succeed by default */
167 if (!NT_STATUS_IS_OK(status
)) {
168 printf("Connect5 failed - %s\n", nt_errstr(status
));
172 ed
.in
.connect_handle
= &ch
;
173 ed
.in
.resume_handle
= &resume_handle
;
174 ed
.in
.buf_size
= (uint32_t)-1;
175 ed
.out
.resume_handle
= &resume_handle
;
176 ed
.out
.num_entries
= &num_entries
;
179 status
= dcerpc_samr_EnumDomains(p
, tctx
, &ed
);
180 if (!NT_STATUS_IS_OK(status
)) {
181 printf("EnumDomains failed - %s\n", nt_errstr(status
));
185 status
= torture_samr_Close(tctx
, p
, &ch
);
186 if (!NT_STATUS_IS_OK(status
)) {
187 printf("Close failed - %s\n", nt_errstr(status
));
192 printf(" expecting to fail");
194 if (!NT_STATUS_IS_OK(status
)) {
199 ed
.in
.connect_handle
= &ch
;
200 ed
.in
.resume_handle
= &resume_handle
;
201 ed
.in
.buf_size
= (uint32_t)-1;
202 ed
.out
.resume_handle
= &resume_handle
;
203 ed
.out
.num_entries
= &num_entries
;
206 status
= dcerpc_samr_EnumDomains(p
, tctx
, &ed
);
207 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED
, status
)) {
208 printf("EnumDomains failed - %s\n", nt_errstr(status
));
212 status
= torture_samr_Close(tctx
, p
, &ch
);
213 if (!NT_STATUS_IS_OK(status
)) {
214 printf("Close failed - %s\n", nt_errstr(status
));
227 * test how ACLs affect how/if a user can connect to the SAMR service
229 * samr_SetSecurity() returns SUCCESS when changing the ACL for
230 * a policy handle got from Connect5() but the ACL is not changed on
233 static bool test_samr_connect_user_acl(struct torture_context
*tctx
,
234 struct dcerpc_pipe
*p
,
235 struct cli_credentials
*test_credentials
,
236 const struct dom_sid
*test_sid
)
240 struct policy_handle ch
;
241 struct policy_handle uch
;
242 struct samr_QuerySecurity qs
;
243 struct samr_SetSecurity ss
;
244 struct security_ace ace
;
245 struct security_descriptor
*sd
;
246 struct sec_desc_buf sdb
, *sdbuf
= NULL
;
249 struct dcerpc_pipe
*test_p
;
250 const char *binding
= torture_setting_string(tctx
, "binding", NULL
);
252 printf("testing ACLs to allow/prevent users to connect to SAMR");
254 /* connect to SAMR */
255 status
= torture_samr_Connect5(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
, &ch
);
256 if (!NT_STATUS_IS_OK(status
)) {
257 printf("Connect5 failed - %s\n", nt_errstr(status
));
262 /* get the current ACL for the SAMR policy handle */
264 qs
.in
.sec_info
= SECINFO_DACL
;
265 qs
.out
.sdbuf
= &sdbuf
;
266 status
= dcerpc_samr_QuerySecurity(p
, tctx
, &qs
);
267 if (!NT_STATUS_IS_OK(status
)) {
268 printf("QuerySecurity failed - %s\n", nt_errstr(status
));
272 /* how big is the security descriptor? */
273 sd_size
= sdbuf
->sd_size
;
276 /* add an ACE to the security descriptor to deny the user the
277 * 'connect to server' right
280 ace
.type
= SEC_ACE_TYPE_ACCESS_DENIED
;
282 ace
.access_mask
= SAMR_ACCESS_CONNECT_TO_SERVER
;
283 ace
.trustee
= *test_sid
;
284 status
= security_descriptor_dacl_add(sd
, &ace
);
285 if (!NT_STATUS_IS_OK(status
)) {
286 printf("Failed to add ACE to security descriptor\n");
290 ss
.in
.sec_info
= SECINFO_DACL
;
293 status
= dcerpc_samr_SetSecurity(p
, tctx
, &ss
);
294 if (!NT_STATUS_IS_OK(status
)) {
295 printf("SetSecurity failed - %s\n", nt_errstr(status
));
300 /* Try to connect as the test user */
301 status
= dcerpc_pipe_connect(tctx
,
302 &test_p
, binding
, &ndr_table_samr
,
303 test_credentials
, tctx
->ev
, tctx
->lp_ctx
);
304 if (!NT_STATUS_IS_OK(status
)) {
305 printf("dcerpc_pipe_connect failed: %s\n", nt_errstr(status
));
309 /* connect to SAMR as the user */
310 status
= torture_samr_Connect5(tctx
, test_p
, SEC_FLAG_MAXIMUM_ALLOWED
, &uch
);
311 if (!NT_STATUS_IS_OK(status
)) {
312 printf("Connect5 failed - %s\n", nt_errstr(status
));
315 /* disconnec the user */
319 /* read the sequrity descriptor back. it should not have changed
320 * eventhough samr_SetSecurity returned SUCCESS
322 status
= dcerpc_samr_QuerySecurity(p
, tctx
, &qs
);
323 if (!NT_STATUS_IS_OK(status
)) {
324 printf("QuerySecurity failed - %s\n", nt_errstr(status
));
327 if (sd_size
!= sdbuf
->sd_size
) {
328 printf("security descriptor changed\n");
333 status
= torture_samr_Close(tctx
, p
, &ch
);
334 if (!NT_STATUS_IS_OK(status
)) {
335 printf("Close failed - %s\n", nt_errstr(status
));
346 * test if the ACLs are enforced for users.
347 * a normal testuser only gets the rights provided in hte ACL for
348 * Everyone which does not include the SAMR_ACCESS_SHUTDOWN_SERVER
349 * right. If the ACLs are checked when a user connects
350 * a testuser that requests the accessmask with only this bit set
351 * the connect should fail.
353 static bool test_samr_connect_user_acl_enforced(struct torture_context
*tctx
,
354 struct dcerpc_pipe
*p
,
355 struct cli_credentials
*test_credentials
,
356 const struct dom_sid
*test_sid
)
360 struct policy_handle uch
;
362 struct dcerpc_pipe
*test_p
;
363 const char *binding
= torture_setting_string(tctx
, "binding", NULL
);
365 printf("testing if ACLs are enforced for non domain admin users when connecting to SAMR");
368 status
= dcerpc_pipe_connect(tctx
,
369 &test_p
, binding
, &ndr_table_samr
,
370 test_credentials
, tctx
->ev
, tctx
->lp_ctx
);
371 if (!NT_STATUS_IS_OK(status
)) {
372 printf("dcerpc_pipe_connect failed: %s\n", nt_errstr(status
));
376 /* connect to SAMR as the user */
377 status
= torture_samr_Connect5(tctx
, test_p
, SAMR_ACCESS_SHUTDOWN_SERVER
, &uch
);
378 if (NT_STATUS_IS_OK(status
)) {
379 printf("Connect5 failed - %s\n", nt_errstr(status
));
384 /* disconnec the user */
390 /* check which bits in accessmask allows us to LookupDomain()
391 by default we must specify at least one of :
392 in the access mask to Connect5() in order to be allowed to perform
393 case 5: samr/opendomain
396 case 29: GenericExecute
397 LookupDomain() on the policy handle returned from Connect5()
399 static bool test_samr_accessmask_LookupDomain(struct torture_context
*tctx
,
400 struct dcerpc_pipe
*p
)
403 struct samr_LookupDomain ld
;
404 struct dom_sid2
*sid
= NULL
;
405 struct policy_handle ch
;
406 struct lsa_String dn
;
410 printf("testing which bits in Connect5 accessmask allows us to LookupDomain\n");
413 printf("testing Connect5/LookupDomain with access mask 0x%08x", mask
);
414 status
= torture_samr_Connect5(tctx
, p
, mask
, &ch
);
419 case 25: /* Maximum */
420 case 28: /* GenericAll */
421 case 29: /* GenericExecute */
422 /* these bits set are expected to succeed by default */
423 if (!NT_STATUS_IS_OK(status
)) {
424 printf("Connect5 failed - %s\n", nt_errstr(status
));
428 ld
.in
.connect_handle
= &ch
;
429 ld
.in
.domain_name
= &dn
;
431 dn
.string
= lp_workgroup(tctx
->lp_ctx
);
433 status
= dcerpc_samr_LookupDomain(p
, tctx
, &ld
);
434 if (!NT_STATUS_IS_OK(status
)) {
435 printf("LookupDomain failed - %s\n", nt_errstr(status
));
439 status
= torture_samr_Close(tctx
, p
, &ch
);
440 if (!NT_STATUS_IS_OK(status
)) {
441 printf("Close failed - %s\n", nt_errstr(status
));
446 printf(" expecting to fail");
448 if (!NT_STATUS_IS_OK(status
)) {
453 ld
.in
.connect_handle
= &ch
;
454 ld
.in
.domain_name
= &dn
;
456 dn
.string
= lp_workgroup(tctx
->lp_ctx
);
458 status
= dcerpc_samr_LookupDomain(p
, tctx
, &ld
);
459 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED
, status
)) {
460 printf("LookupDomain failed - %s\n", nt_errstr(status
));
464 status
= torture_samr_Close(tctx
, p
, &ch
);
465 if (!NT_STATUS_IS_OK(status
)) {
466 printf("Close failed - %s\n", nt_errstr(status
));
477 /* check which bits in accessmask allows us to OpenDomain()
478 by default we must specify at least one of :
483 in the access mask to Connect5() in order to be allowed to perform
484 OpenDomain() on the policy handle returned from Connect5()
486 static bool test_samr_accessmask_OpenDomain(struct torture_context
*tctx
,
487 struct dcerpc_pipe
*p
)
490 struct samr_LookupDomain ld
;
491 struct dom_sid2
*sid
= NULL
;
492 struct samr_OpenDomain od
;
493 struct policy_handle ch
;
494 struct policy_handle dh
;
495 struct lsa_String dn
;
500 /* first we must grab the sid of the domain */
501 status
= torture_samr_Connect5(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
, &ch
);
502 if (!NT_STATUS_IS_OK(status
)) {
503 printf("Connect5 failed - %s\n", nt_errstr(status
));
507 ld
.in
.connect_handle
= &ch
;
508 ld
.in
.domain_name
= &dn
;
510 dn
.string
= lp_workgroup(tctx
->lp_ctx
);
511 status
= dcerpc_samr_LookupDomain(p
, tctx
, &ld
);
512 if (!NT_STATUS_IS_OK(status
)) {
513 printf("LookupDomain failed - %s\n", nt_errstr(status
));
519 printf("testing which bits in Connect5 accessmask allows us to OpenDomain\n");
522 printf("testing Connect5/OpenDomain with access mask 0x%08x", mask
);
523 status
= torture_samr_Connect5(tctx
, p
, mask
, &ch
);
528 case 25: /* Maximum */
529 case 28: /* GenericAll */
530 case 29: /* GenericExecute */
531 /* these bits set are expected to succeed by default */
532 if (!NT_STATUS_IS_OK(status
)) {
533 printf("Connect5 failed - %s\n", nt_errstr(status
));
537 od
.in
.connect_handle
= &ch
;
538 od
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
540 od
.out
.domain_handle
= &dh
;
542 status
= dcerpc_samr_OpenDomain(p
, tctx
, &od
);
543 if (!NT_STATUS_IS_OK(status
)) {
544 printf("OpenDomain failed - %s\n", nt_errstr(status
));
548 status
= torture_samr_Close(tctx
, p
, &dh
);
549 if (!NT_STATUS_IS_OK(status
)) {
550 printf("Close failed - %s\n", nt_errstr(status
));
554 status
= torture_samr_Close(tctx
, p
, &ch
);
555 if (!NT_STATUS_IS_OK(status
)) {
556 printf("Close failed - %s\n", nt_errstr(status
));
561 printf(" expecting to fail");
563 if (!NT_STATUS_IS_OK(status
)) {
568 status
= torture_samr_Close(tctx
, p
, &ch
);
569 if (!NT_STATUS_IS_OK(status
)) {
570 printf("Close failed - %s\n", nt_errstr(status
));
581 static bool test_samr_connect(struct torture_context
*tctx
,
582 struct dcerpc_pipe
*p
)
585 const char *testuser_passwd
;
586 struct cli_credentials
*test_credentials
;
588 const struct dom_sid
*test_sid
;
590 if (torture_setting_bool(tctx
, "samba3", false)) {
591 torture_skip(tctx
, "Skipping test against Samba 3");
594 /* create a test user */
595 testuser
= torture_create_testuser(tctx
, TEST_USER_NAME
, lp_workgroup(tctx
->lp_ctx
),
596 ACB_NORMAL
, &testuser_passwd
);
598 printf("Failed to create test user\n");
601 test_credentials
= cli_credentials_init(tctx
);
602 cli_credentials_set_workstation(test_credentials
, "localhost", CRED_SPECIFIED
);
603 cli_credentials_set_domain(test_credentials
, lp_workgroup(tctx
->lp_ctx
),
605 cli_credentials_set_username(test_credentials
, TEST_USER_NAME
, CRED_SPECIFIED
);
606 cli_credentials_set_password(test_credentials
, testuser_passwd
, CRED_SPECIFIED
);
607 test_sid
= torture_join_user_sid(testuser
);
610 /* test if ACLs can be changed for the policy handle
611 * returned by Connect5
613 if (!test_samr_connect_user_acl(tctx
, p
, test_credentials
, test_sid
)) {
617 /* test if the ACLs that are reported from the Connect5
618 * policy handle is enforced.
619 * i.e. an ordinary user only has the same rights as Everybody
623 * Samr/ConnectToServer
624 * is granted and should therefore not be able to connect when
625 * requesting SAMR_ACCESS_SHUTDOWN_SERVER
627 if (!test_samr_connect_user_acl_enforced(tctx
, p
, test_credentials
, test_sid
)) {
631 /* remove the test user */
632 torture_leave_domain(tctx
, testuser
);
637 struct torture_suite
*torture_rpc_samr_accessmask(TALLOC_CTX
*mem_ctx
)
639 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SAMR-ACCESSMASK");
640 struct torture_rpc_tcase
*tcase
;
642 tcase
= torture_suite_add_rpc_iface_tcase(suite
, "samr",
645 torture_rpc_tcase_add_test(tcase
, "CONNECT", test_samr_connect
);
647 /* test which bits in the accessmask to Connect5 will allow
648 * us to call OpenDomain() */
649 torture_rpc_tcase_add_test(tcase
, "OpenDomain",
650 test_samr_accessmask_OpenDomain
);
652 /* test which bits in the accessmask to Connect5 will allow
653 * us to call LookupDomain() */
654 torture_rpc_tcase_add_test(tcase
, "LookupDomain",
655 test_samr_accessmask_LookupDomain
);
657 /* test which bits in the accessmask to Connect5 will allow
658 * us to call EnumDomains() */
659 torture_rpc_tcase_add_test(tcase
, "EnumDomains",
660 test_samr_accessmask_EnumDomains
);
662 /* test which bits in the accessmask to Connect5
663 will allow us to connect to the server */
664 torture_rpc_tcase_add_test(tcase
, "Connect5",
665 test_samr_accessmask_Connect5
);
670 static bool test_LookupRids(struct torture_context
*tctx
,
671 struct dcerpc_pipe
*p
,
672 struct policy_handle
*domain_handle
,
675 struct samr_LookupRids r
;
676 struct lsa_Strings names
;
677 struct samr_Ids types
;
679 torture_comment(tctx
, "testing LookupRids %d\n", rid
);
681 r
.in
.domain_handle
= domain_handle
;
684 r
.out
.names
= &names
;
685 r
.out
.types
= &types
;
687 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_LookupRids(p
, tctx
, &r
),
688 "failed to call samr_LookupRids");
694 static bool test_user(struct torture_context
*tctx
,
695 struct dcerpc_pipe
*p
,
696 struct policy_handle
*domain_handle
,
697 uint32_t access_mask
,
698 struct samr_DispEntryGeneral
*u
)
700 struct policy_handle user_handle
;
702 torture_comment(tctx
, "testing user %s (%d)\n", u
->account_name
.string
, u
->rid
);
704 torture_assert(tctx
, test_LookupRids(tctx
, p
, domain_handle
, u
->rid
),
705 "failed to call lookuprids");
708 struct samr_OpenUser r
;
710 r
.in
.domain_handle
= domain_handle
;
711 r
.in
.access_mask
= access_mask
;
713 r
.out
.user_handle
= &user_handle
;
715 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_OpenUser(p
, tctx
, &r
),
716 "failed to open user");
719 struct samr_QueryUserInfo r
;
720 union samr_UserInfo
*info
;
721 uint32_t levels
[] = { 16, 21 };
724 r
.in
.user_handle
= &user_handle
;
727 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
729 r
.in
.level
= levels
[i
];
731 torture_comment(tctx
, "testing QueryUserInfo rid: %d level: %d\n",
734 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_QueryUserInfo(p
, tctx
, &r
),
735 talloc_asprintf(tctx
, "failed to query user info level %d", r
.in
.level
));
739 struct samr_GetGroupsForUser r
;
740 struct samr_RidWithAttributeArray
*rids
;
742 r
.in
.user_handle
= &user_handle
;
745 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_GetGroupsForUser(p
, tctx
, &r
),
746 "failed to query groups for user");
749 torture_assert_ntstatus_ok(tctx
,
750 torture_samr_Close(tctx
, p
, &user_handle
),
751 "failed to close user handle");
756 static bool test_samr_group(struct torture_context
*tctx
,
757 struct dcerpc_pipe
*p
,
758 struct policy_handle
*domain_handle
,
759 uint32_t access_mask
,
760 struct samr_SamEntry
*g
)
762 struct policy_handle group_handle
;
764 torture_comment(tctx
, "testing group %s (%d)\n", g
->name
.string
, g
->idx
);
766 torture_assert(tctx
, test_LookupRids(tctx
, p
, domain_handle
, g
->idx
),
767 "failed to call lookuprids");
769 struct samr_OpenGroup r
;
771 r
.in
.domain_handle
= domain_handle
;
772 r
.in
.access_mask
= access_mask
;
774 r
.out
.group_handle
= &group_handle
;
776 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_OpenGroup(p
, tctx
, &r
),
777 "failed to open group");
780 struct samr_QueryGroupMember r
;
781 struct samr_RidTypeArray
*rids
;
783 r
.in
.group_handle
= &group_handle
;
786 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_QueryGroupMember(p
, tctx
, &r
),
787 "failed to query group member");
790 torture_assert_ntstatus_ok(tctx
,
791 torture_samr_Close(tctx
, p
, &group_handle
),
792 "failed to close group handle");
797 static bool test_samr_alias(struct torture_context
*tctx
,
798 struct dcerpc_pipe
*p
,
799 struct policy_handle
*domain_handle
,
800 struct samr_SamEntry
*a
)
802 torture_comment(tctx
, "testing alias %s (%d)\n", a
->name
.string
, a
->idx
);
804 torture_assert(tctx
, test_LookupRids(tctx
, p
, domain_handle
, a
->idx
),
805 "failed to call lookuprids");
808 struct samr_GetAliasMembership r
;
809 struct lsa_SidArray sids
;
810 struct samr_Ids rids
;
814 r
.in
.domain_handle
= domain_handle
;
818 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_GetAliasMembership(p
, tctx
, &r
),
819 "failed to get alias membership");
826 static bool test_samr_domain(struct torture_context
*tctx
,
827 struct dcerpc_pipe
*p
,
828 uint32_t access_mask
,
829 const char *domain_name
,
830 struct policy_handle
*connect_handle
,
831 struct policy_handle
*domain_handle_p
)
833 struct policy_handle domain_handle
;
834 struct dom_sid
*domain_sid
;
837 struct samr_EnumDomains r
;
838 uint32_t resume_handle
;
839 struct samr_SamArray
*sam
;
840 uint32_t num_entries
;
843 r
.in
.connect_handle
= connect_handle
;
844 r
.in
.buf_size
= 0xffff;
845 r
.in
.resume_handle
= &resume_handle
;
847 r
.out
.num_entries
= &num_entries
;
848 r
.out
.resume_handle
= &resume_handle
;
850 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_EnumDomains(p
, tctx
, &r
),
851 "failed to enum domains");
853 torture_assert_int_equal(tctx
, num_entries
, 2,
854 "unexpected number of domains");
856 torture_assert(tctx
, sam
,
857 "no domain pointer returned");
859 for (i
=0; i
< sam
->count
; i
++) {
860 if (!strequal(sam
->entries
[i
].name
.string
, "builtin")) {
861 domain_name
= sam
->entries
[i
].name
.string
;
866 torture_assert(tctx
, domain_name
,
867 "no domain found other than builtin found");
871 struct samr_LookupDomain r
;
872 struct dom_sid2
*sid
;
873 struct lsa_String name
;
875 name
.string
= talloc_strdup(tctx
, domain_name
);
877 r
.in
.connect_handle
= connect_handle
;
878 r
.in
.domain_name
= &name
;
881 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_LookupDomain(p
, tctx
, &r
),
882 "failed to lookup domain");
884 domain_sid
= dom_sid_dup(tctx
, sid
);
888 struct samr_OpenDomain r
;
890 r
.in
.connect_handle
= connect_handle
;
891 r
.in
.access_mask
= access_mask
;
892 r
.in
.sid
= domain_sid
;
893 r
.out
.domain_handle
= &domain_handle
;
895 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_OpenDomain(p
, tctx
, &r
),
896 "failed to open domain");
900 struct samr_QueryDomainInfo r
;
901 union samr_DomainInfo
*info
;
902 uint32_t levels
[] = { 1, 2, 8, 12 };
905 r
.in
.domain_handle
= &domain_handle
;
908 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
910 r
.in
.level
= levels
[i
];
912 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_QueryDomainInfo(p
, tctx
, &r
),
913 talloc_asprintf(tctx
, "failed to query domain info level %d", r
.in
.level
));
918 *domain_handle_p
= domain_handle
;
923 static void get_query_dispinfo_params(int loop_count
,
924 uint32_t *max_entries
,
944 default: /* loop_count >= 4 */
952 static bool test_samr_users(struct torture_context
*tctx
,
953 struct dcerpc_pipe
*p
,
954 uint32_t access_mask
,
955 struct policy_handle
*domain_handle
)
960 struct samr_QueryDisplayInfo r
;
962 uint32_t returned_size
;
963 union samr_DispInfo info
;
966 r
.in
.domain_handle
= domain_handle
;
970 r
.out
.total_size
= &total_size
;
971 r
.out
.returned_size
= &returned_size
;
977 r
.in
.max_entries
= 0xffff;
978 r
.in
.buf_size
= 0xffff;
980 get_query_dispinfo_params(loop_count
,
984 status
= dcerpc_samr_QueryDisplayInfo(p
, tctx
, &r
);
985 if (NT_STATUS_IS_ERR(status
)) {
986 torture_assert_ntstatus_ok(tctx
, status
,
987 "failed to call QueryDisplayInfo");
990 for (i
=0; i
< info
.info1
.count
; i
++) {
992 test_user(tctx
, p
, domain_handle
, access_mask
, &info
.info1
.entries
[i
]),
993 "failed to test user");
996 r
.in
.start_idx
+= info
.info1
.count
;
998 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
1004 static bool test_samr_groups(struct torture_context
*tctx
,
1005 struct dcerpc_pipe
*p
,
1006 uint32_t access_mask
,
1007 struct policy_handle
*domain_handle
)
1012 struct samr_EnumDomainGroups r
;
1013 uint32_t resume_handle
= 0;
1014 struct samr_SamArray
*sam
;
1015 uint32_t num_entries
;
1017 r
.in
.domain_handle
= domain_handle
;
1018 r
.in
.resume_handle
= &resume_handle
;
1019 r
.in
.max_size
= 0xFFFF;
1022 r
.out
.num_entries
= &num_entries
;
1023 r
.out
.resume_handle
= &resume_handle
;
1028 status
= dcerpc_samr_EnumDomainGroups(p
, tctx
, &r
);
1029 if (NT_STATUS_IS_ERR(status
)) {
1030 torture_assert_ntstatus_ok(tctx
, status
,
1031 "failed to call EnumDomainGroups");
1034 for (i
=0; i
< num_entries
; i
++) {
1035 torture_assert(tctx
,
1036 test_samr_group(tctx
, p
, domain_handle
, access_mask
, &sam
->entries
[i
]),
1037 "failed to test group");
1040 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
1046 static bool test_samr_aliases(struct torture_context
*tctx
,
1047 struct dcerpc_pipe
*p
,
1048 uint32_t access_mask
,
1049 struct policy_handle
*domain_handle
)
1054 struct samr_EnumDomainAliases r
;
1055 uint32_t resume_handle
= 0;
1056 struct samr_SamArray
*sam
;
1057 uint32_t num_entries
;
1059 r
.in
.domain_handle
= domain_handle
;
1060 r
.in
.resume_handle
= &resume_handle
;
1061 r
.in
.max_size
= 0xFFFF;
1064 r
.out
.num_entries
= &num_entries
;
1065 r
.out
.resume_handle
= &resume_handle
;
1070 status
= dcerpc_samr_EnumDomainAliases(p
, tctx
, &r
);
1071 if (NT_STATUS_IS_ERR(status
)) {
1072 torture_assert_ntstatus_ok(tctx
, status
,
1073 "failed to call EnumDomainAliases");
1076 for (i
=0; i
< num_entries
; i
++) {
1077 torture_assert(tctx
,
1078 test_samr_alias(tctx
, p
, domain_handle
, &sam
->entries
[i
]),
1079 "failed to test alias");
1082 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
1088 static bool torture_rpc_samr_workstation_query(struct torture_context
*tctx
,
1089 struct dcerpc_pipe
*p
,
1090 struct cli_credentials
*machine_credentials
)
1092 struct policy_handle connect_handle
;
1093 struct policy_handle domain_handle
;
1095 torture_assert_ntstatus_ok(tctx
,
1096 torture_samr_Connect5(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
,
1098 "failed to connect to samr server");
1100 torture_assert(tctx
,
1101 test_samr_domain(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
,
1102 lp_workgroup(tctx
->lp_ctx
),
1103 &connect_handle
, &domain_handle
),
1104 "failed to test domain");
1106 torture_assert(tctx
,
1107 test_samr_users(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
,
1109 "failed to test users");
1111 torture_assert(tctx
,
1112 test_samr_groups(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
,
1114 "failed to test groups");
1116 torture_assert(tctx
,
1117 test_samr_aliases(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
,
1119 "failed to test aliases");
1121 torture_assert_ntstatus_ok(tctx
,
1122 torture_samr_Close(tctx
, p
, &domain_handle
),
1123 "failed to close domain handle");
1125 torture_assert_ntstatus_ok(tctx
,
1126 torture_samr_Close(tctx
, p
, &connect_handle
),
1127 "failed to close connect handle");
1132 /* The purpose of this test is to verify that an account authenticated as a
1133 * domain member workstation can query a DC for various remote read calls all
1134 * opening objects while requesting SEC_FLAG_MAXIMUM_ALLOWED access rights on
1135 * the object open calls. This is the behavior of winbind (and most of samba's
1136 * client code) - gd */
1138 struct torture_suite
*torture_rpc_samr_workstation_auth(TALLOC_CTX
*mem_ctx
)
1140 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SAMR-MACHINE-AUTH");
1141 struct torture_rpc_tcase
*tcase
;
1143 tcase
= torture_suite_add_machine_workstation_rpc_iface_tcase(suite
, "samr",
1147 torture_rpc_tcase_add_test_creds(tcase
, "workstation_query",
1148 torture_rpc_samr_workstation_query
);