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 "torture/torture.h"
24 #include "librpc/gen_ndr/ndr_samr_c.h"
25 #include "torture/rpc/rpc.h"
26 #include "param/param.h"
27 #include "libcli/security/security.h"
28 #include "librpc/gen_ndr/ndr_security.h"
31 /* test user created to test the ACLs associated to SAMR objects */
32 #define TEST_USER_NAME "samr_testuser"
33 #define TEST_MACHINENAME "samrtestmach"
35 static NTSTATUS
torture_samr_Close(struct torture_context
*tctx
,
36 struct dcerpc_pipe
*p
,
37 struct policy_handle
*h
)
44 status
= dcerpc_samr_Close(p
, tctx
, &cl
);
49 static NTSTATUS
torture_samr_Connect5(struct torture_context
*tctx
,
50 struct dcerpc_pipe
*p
,
51 uint32_t mask
, struct policy_handle
*h
)
54 struct samr_Connect5 r5
;
55 union samr_ConnectInfo info
;
56 uint32_t level_out
= 0;
58 info
.info1
.client_version
= 0;
59 info
.info1
.unknown2
= 0;
60 r5
.in
.system_name
= "";
62 r5
.in
.info_in
= &info
;
63 r5
.out
.info_out
= &info
;
64 r5
.out
.level_out
= &level_out
;
65 r5
.out
.connect_handle
= h
;
66 r5
.in
.access_mask
= mask
;
68 status
= dcerpc_samr_Connect5(p
, tctx
, &r5
);
73 /* check which bits in accessmask allows us to connect to the server */
74 static bool test_samr_accessmask_Connect5(struct torture_context
*tctx
,
75 struct dcerpc_pipe
*p
)
78 struct policy_handle h
;
82 printf("testing which bits in accessmask allows us to connect\n");
85 printf("testing Connect5 with access mask 0x%08x", mask
);
86 status
= torture_samr_Connect5(tctx
, p
, mask
, &h
);
106 printf(" expecting to fail");
107 /* of only one of these bits are set we expect to
110 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED
, status
)) {
111 printf("Connect5 failed - %s\n", nt_errstr(status
));
116 /* these bits set are expected to succeed by default */
117 if (!NT_STATUS_IS_OK(status
)) {
118 printf("Connect5 failed - %s\n", nt_errstr(status
));
122 status
= torture_samr_Close(tctx
, p
, &h
);
123 if (!NT_STATUS_IS_OK(status
)) {
124 printf("Close failed - %s\n", nt_errstr(status
));
135 /* check which bits in accessmask allows us to EnumDomains()
136 by default we must specify at least one of :
141 in the access mask to Connect5() in order to be allowed to perform
142 EnumDomains() on the policy handle returned from Connect5()
144 static bool test_samr_accessmask_EnumDomains(struct torture_context
*tctx
,
145 struct dcerpc_pipe
*p
)
148 struct samr_EnumDomains ed
;
149 struct policy_handle ch
;
152 uint32_t resume_handle
= 0;
153 struct samr_SamArray
*sam
= NULL
;
154 uint32_t num_entries
= 0;
156 printf("testing which bits in Connect5 accessmask allows us to EnumDomains\n");
159 printf("testing Connect5/EnumDomains with access mask 0x%08x", mask
);
160 status
= torture_samr_Connect5(tctx
, p
, mask
, &ch
);
164 case 4: /* SAMR/EnumDomains */
165 case 25: /* Maximum */
166 case 28: /* GenericAll */
167 case 31: /* GenericRead */
168 /* these bits set are expected to succeed by default */
169 if (!NT_STATUS_IS_OK(status
)) {
170 printf("Connect5 failed - %s\n", nt_errstr(status
));
174 ed
.in
.connect_handle
= &ch
;
175 ed
.in
.resume_handle
= &resume_handle
;
176 ed
.in
.buf_size
= (uint32_t)-1;
177 ed
.out
.resume_handle
= &resume_handle
;
178 ed
.out
.num_entries
= &num_entries
;
181 status
= dcerpc_samr_EnumDomains(p
, tctx
, &ed
);
182 if (!NT_STATUS_IS_OK(status
)) {
183 printf("EnumDomains failed - %s\n", nt_errstr(status
));
187 status
= torture_samr_Close(tctx
, p
, &ch
);
188 if (!NT_STATUS_IS_OK(status
)) {
189 printf("Close failed - %s\n", nt_errstr(status
));
194 printf(" expecting to fail");
196 if (!NT_STATUS_IS_OK(status
)) {
201 ed
.in
.connect_handle
= &ch
;
202 ed
.in
.resume_handle
= &resume_handle
;
203 ed
.in
.buf_size
= (uint32_t)-1;
204 ed
.out
.resume_handle
= &resume_handle
;
205 ed
.out
.num_entries
= &num_entries
;
208 status
= dcerpc_samr_EnumDomains(p
, tctx
, &ed
);
209 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED
, status
)) {
210 printf("EnumDomains failed - %s\n", nt_errstr(status
));
214 status
= torture_samr_Close(tctx
, p
, &ch
);
215 if (!NT_STATUS_IS_OK(status
)) {
216 printf("Close failed - %s\n", nt_errstr(status
));
229 * test how ACLs affect how/if a user can connect to the SAMR service
231 * samr_SetSecurity() returns SUCCESS when changing the ACL for
232 * a policy handle got from Connect5() but the ACL is not changed on
235 static bool test_samr_connect_user_acl(struct torture_context
*tctx
,
236 struct dcerpc_pipe
*p
,
237 struct cli_credentials
*test_credentials
,
238 const struct dom_sid
*test_sid
)
242 struct policy_handle ch
;
243 struct policy_handle uch
;
244 struct samr_QuerySecurity qs
;
245 struct samr_SetSecurity ss
;
246 struct security_ace ace
;
247 struct security_descriptor
*sd
;
248 struct sec_desc_buf sdb
, *sdbuf
= NULL
;
251 struct dcerpc_pipe
*test_p
;
252 const char *binding
= torture_setting_string(tctx
, "binding", NULL
);
254 printf("testing ACLs to allow/prevent users to connect to SAMR");
256 /* connect to SAMR */
257 status
= torture_samr_Connect5(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
, &ch
);
258 if (!NT_STATUS_IS_OK(status
)) {
259 printf("Connect5 failed - %s\n", nt_errstr(status
));
264 /* get the current ACL for the SAMR policy handle */
266 qs
.in
.sec_info
= SECINFO_DACL
;
267 qs
.out
.sdbuf
= &sdbuf
;
268 status
= dcerpc_samr_QuerySecurity(p
, tctx
, &qs
);
269 if (!NT_STATUS_IS_OK(status
)) {
270 printf("QuerySecurity failed - %s\n", nt_errstr(status
));
274 /* how big is the security descriptor? */
275 sd_size
= sdbuf
->sd_size
;
278 /* add an ACE to the security descriptor to deny the user the
279 * 'connect to server' right
282 ace
.type
= SEC_ACE_TYPE_ACCESS_DENIED
;
284 ace
.access_mask
= SAMR_ACCESS_CONNECT_TO_SERVER
;
285 ace
.trustee
= *test_sid
;
286 status
= security_descriptor_dacl_add(sd
, &ace
);
287 if (!NT_STATUS_IS_OK(status
)) {
288 printf("Failed to add ACE to security descriptor\n");
292 ss
.in
.sec_info
= SECINFO_DACL
;
295 status
= dcerpc_samr_SetSecurity(p
, tctx
, &ss
);
296 if (!NT_STATUS_IS_OK(status
)) {
297 printf("SetSecurity failed - %s\n", nt_errstr(status
));
302 /* Try to connect as the test user */
303 status
= dcerpc_pipe_connect(tctx
,
304 &test_p
, binding
, &ndr_table_samr
,
305 test_credentials
, tctx
->ev
, tctx
->lp_ctx
);
306 if (!NT_STATUS_IS_OK(status
)) {
307 printf("dcerpc_pipe_connect failed: %s\n", nt_errstr(status
));
311 /* connect to SAMR as the user */
312 status
= torture_samr_Connect5(tctx
, test_p
, SEC_FLAG_MAXIMUM_ALLOWED
, &uch
);
313 if (!NT_STATUS_IS_OK(status
)) {
314 printf("Connect5 failed - %s\n", nt_errstr(status
));
317 /* disconnec the user */
321 /* read the sequrity descriptor back. it should not have changed
322 * eventhough samr_SetSecurity returned SUCCESS
324 status
= dcerpc_samr_QuerySecurity(p
, tctx
, &qs
);
325 if (!NT_STATUS_IS_OK(status
)) {
326 printf("QuerySecurity failed - %s\n", nt_errstr(status
));
329 if (sd_size
!= sdbuf
->sd_size
) {
330 printf("security descriptor changed\n");
335 status
= torture_samr_Close(tctx
, p
, &ch
);
336 if (!NT_STATUS_IS_OK(status
)) {
337 printf("Close failed - %s\n", nt_errstr(status
));
348 * test if the ACLs are enforced for users.
349 * a normal testuser only gets the rights provided in hte ACL for
350 * Everyone which does not include the SAMR_ACCESS_SHUTDOWN_SERVER
351 * right. If the ACLs are checked when a user connects
352 * a testuser that requests the accessmask with only this bit set
353 * the connect should fail.
355 static bool test_samr_connect_user_acl_enforced(struct torture_context
*tctx
,
356 struct dcerpc_pipe
*p
,
357 struct cli_credentials
*test_credentials
,
358 const struct dom_sid
*test_sid
)
362 struct policy_handle uch
;
364 struct dcerpc_pipe
*test_p
;
365 const char *binding
= torture_setting_string(tctx
, "binding", NULL
);
367 printf("testing if ACLs are enforced for non domain admin users when connecting to SAMR");
370 status
= dcerpc_pipe_connect(tctx
,
371 &test_p
, binding
, &ndr_table_samr
,
372 test_credentials
, tctx
->ev
, tctx
->lp_ctx
);
373 if (!NT_STATUS_IS_OK(status
)) {
374 printf("dcerpc_pipe_connect failed: %s\n", nt_errstr(status
));
378 /* connect to SAMR as the user */
379 status
= torture_samr_Connect5(tctx
, test_p
, SAMR_ACCESS_SHUTDOWN_SERVER
, &uch
);
380 if (NT_STATUS_IS_OK(status
)) {
381 printf("Connect5 failed - %s\n", nt_errstr(status
));
386 /* disconnec the user */
392 /* check which bits in accessmask allows us to LookupDomain()
393 by default we must specify at least one of :
394 in the access mask to Connect5() in order to be allowed to perform
395 case 5: samr/opendomain
398 case 29: GenericExecute
399 LookupDomain() on the policy handle returned from Connect5()
401 static bool test_samr_accessmask_LookupDomain(struct torture_context
*tctx
,
402 struct dcerpc_pipe
*p
)
405 struct samr_LookupDomain ld
;
406 struct dom_sid2
*sid
= NULL
;
407 struct policy_handle ch
;
408 struct lsa_String dn
;
412 printf("testing which bits in Connect5 accessmask allows us to LookupDomain\n");
415 printf("testing Connect5/LookupDomain with access mask 0x%08x", mask
);
416 status
= torture_samr_Connect5(tctx
, p
, mask
, &ch
);
421 case 25: /* Maximum */
422 case 28: /* GenericAll */
423 case 29: /* GenericExecute */
424 /* these bits set are expected to succeed by default */
425 if (!NT_STATUS_IS_OK(status
)) {
426 printf("Connect5 failed - %s\n", nt_errstr(status
));
430 ld
.in
.connect_handle
= &ch
;
431 ld
.in
.domain_name
= &dn
;
433 dn
.string
= lp_workgroup(tctx
->lp_ctx
);
435 status
= dcerpc_samr_LookupDomain(p
, tctx
, &ld
);
436 if (!NT_STATUS_IS_OK(status
)) {
437 printf("LookupDomain failed - %s\n", nt_errstr(status
));
441 status
= torture_samr_Close(tctx
, p
, &ch
);
442 if (!NT_STATUS_IS_OK(status
)) {
443 printf("Close failed - %s\n", nt_errstr(status
));
448 printf(" expecting to fail");
450 if (!NT_STATUS_IS_OK(status
)) {
455 ld
.in
.connect_handle
= &ch
;
456 ld
.in
.domain_name
= &dn
;
458 dn
.string
= lp_workgroup(tctx
->lp_ctx
);
460 status
= dcerpc_samr_LookupDomain(p
, tctx
, &ld
);
461 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED
, status
)) {
462 printf("LookupDomain failed - %s\n", nt_errstr(status
));
466 status
= torture_samr_Close(tctx
, p
, &ch
);
467 if (!NT_STATUS_IS_OK(status
)) {
468 printf("Close failed - %s\n", nt_errstr(status
));
479 /* check which bits in accessmask allows us to OpenDomain()
480 by default we must specify at least one of :
485 in the access mask to Connect5() in order to be allowed to perform
486 OpenDomain() on the policy handle returned from Connect5()
488 static bool test_samr_accessmask_OpenDomain(struct torture_context
*tctx
,
489 struct dcerpc_pipe
*p
)
492 struct samr_LookupDomain ld
;
493 struct dom_sid2
*sid
= NULL
;
494 struct samr_OpenDomain od
;
495 struct policy_handle ch
;
496 struct policy_handle dh
;
497 struct lsa_String dn
;
502 /* first we must grab the sid of the domain */
503 status
= torture_samr_Connect5(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
, &ch
);
504 if (!NT_STATUS_IS_OK(status
)) {
505 printf("Connect5 failed - %s\n", nt_errstr(status
));
509 ld
.in
.connect_handle
= &ch
;
510 ld
.in
.domain_name
= &dn
;
512 dn
.string
= lp_workgroup(tctx
->lp_ctx
);
513 status
= dcerpc_samr_LookupDomain(p
, tctx
, &ld
);
514 if (!NT_STATUS_IS_OK(status
)) {
515 printf("LookupDomain failed - %s\n", nt_errstr(status
));
521 printf("testing which bits in Connect5 accessmask allows us to OpenDomain\n");
524 printf("testing Connect5/OpenDomain with access mask 0x%08x", mask
);
525 status
= torture_samr_Connect5(tctx
, p
, mask
, &ch
);
530 case 25: /* Maximum */
531 case 28: /* GenericAll */
532 case 29: /* GenericExecute */
533 /* these bits set are expected to succeed by default */
534 if (!NT_STATUS_IS_OK(status
)) {
535 printf("Connect5 failed - %s\n", nt_errstr(status
));
539 od
.in
.connect_handle
= &ch
;
540 od
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
542 od
.out
.domain_handle
= &dh
;
544 status
= dcerpc_samr_OpenDomain(p
, tctx
, &od
);
545 if (!NT_STATUS_IS_OK(status
)) {
546 printf("OpenDomain failed - %s\n", nt_errstr(status
));
550 status
= torture_samr_Close(tctx
, p
, &dh
);
551 if (!NT_STATUS_IS_OK(status
)) {
552 printf("Close failed - %s\n", nt_errstr(status
));
556 status
= torture_samr_Close(tctx
, p
, &ch
);
557 if (!NT_STATUS_IS_OK(status
)) {
558 printf("Close failed - %s\n", nt_errstr(status
));
563 printf(" expecting to fail");
565 if (!NT_STATUS_IS_OK(status
)) {
570 status
= torture_samr_Close(tctx
, p
, &ch
);
571 if (!NT_STATUS_IS_OK(status
)) {
572 printf("Close failed - %s\n", nt_errstr(status
));
583 static bool test_samr_connect(struct torture_context
*tctx
,
584 struct dcerpc_pipe
*p
)
587 const char *testuser_passwd
;
588 struct cli_credentials
*test_credentials
;
590 const struct dom_sid
*test_sid
;
592 if (torture_setting_bool(tctx
, "samba3", false)) {
593 torture_skip(tctx
, "Skipping test against Samba 3");
596 /* create a test user */
597 testuser
= torture_create_testuser(tctx
, TEST_USER_NAME
, lp_workgroup(tctx
->lp_ctx
),
598 ACB_NORMAL
, &testuser_passwd
);
600 printf("Failed to create test user\n");
603 test_credentials
= cli_credentials_init(tctx
);
604 cli_credentials_set_workstation(test_credentials
, "localhost", CRED_SPECIFIED
);
605 cli_credentials_set_domain(test_credentials
, lp_workgroup(tctx
->lp_ctx
),
607 cli_credentials_set_username(test_credentials
, TEST_USER_NAME
, CRED_SPECIFIED
);
608 cli_credentials_set_password(test_credentials
, testuser_passwd
, CRED_SPECIFIED
);
609 test_sid
= torture_join_user_sid(testuser
);
612 /* test if ACLs can be changed for the policy handle
613 * returned by Connect5
615 if (!test_samr_connect_user_acl(tctx
, p
, test_credentials
, test_sid
)) {
619 /* test if the ACLs that are reported from the Connect5
620 * policy handle is enforced.
621 * i.e. an ordinary user only has the same rights as Everybody
625 * Samr/ConnectToServer
626 * is granted and should therefore not be able to connect when
627 * requesting SAMR_ACCESS_SHUTDOWN_SERVER
629 if (!test_samr_connect_user_acl_enforced(tctx
, p
, test_credentials
, test_sid
)) {
633 /* remove the test user */
634 torture_leave_domain(tctx
, testuser
);
639 struct torture_suite
*torture_rpc_samr_accessmask(TALLOC_CTX
*mem_ctx
)
641 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SAMR-ACCESSMASK");
642 struct torture_rpc_tcase
*tcase
;
644 tcase
= torture_suite_add_rpc_iface_tcase(suite
, "samr",
647 torture_rpc_tcase_add_test(tcase
, "CONNECT", test_samr_connect
);
649 /* test which bits in the accessmask to Connect5 will allow
650 * us to call OpenDomain() */
651 torture_rpc_tcase_add_test(tcase
, "OpenDomain",
652 test_samr_accessmask_OpenDomain
);
654 /* test which bits in the accessmask to Connect5 will allow
655 * us to call LookupDomain() */
656 torture_rpc_tcase_add_test(tcase
, "LookupDomain",
657 test_samr_accessmask_LookupDomain
);
659 /* test which bits in the accessmask to Connect5 will allow
660 * us to call EnumDomains() */
661 torture_rpc_tcase_add_test(tcase
, "EnumDomains",
662 test_samr_accessmask_EnumDomains
);
664 /* test which bits in the accessmask to Connect5
665 will allow us to connect to the server */
666 torture_rpc_tcase_add_test(tcase
, "Connect5",
667 test_samr_accessmask_Connect5
);
672 static bool test_LookupRids(struct torture_context
*tctx
,
673 struct dcerpc_pipe
*p
,
674 struct policy_handle
*domain_handle
,
677 struct samr_LookupRids r
;
678 struct lsa_Strings names
;
679 struct samr_Ids types
;
681 torture_comment(tctx
, "testing LookupRids %d\n", rid
);
683 r
.in
.domain_handle
= domain_handle
;
686 r
.out
.names
= &names
;
687 r
.out
.types
= &types
;
689 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_LookupRids(p
, tctx
, &r
),
690 "failed to call samr_LookupRids");
696 static bool test_user(struct torture_context
*tctx
,
697 struct dcerpc_pipe
*p
,
698 struct policy_handle
*domain_handle
,
699 uint32_t access_mask
,
700 struct samr_DispEntryGeneral
*u
)
702 struct policy_handle user_handle
;
704 torture_comment(tctx
, "testing user %s (%d)\n", u
->account_name
.string
, u
->rid
);
706 torture_assert(tctx
, test_LookupRids(tctx
, p
, domain_handle
, u
->rid
),
707 "failed to call lookuprids");
710 struct samr_OpenUser r
;
712 r
.in
.domain_handle
= domain_handle
;
713 r
.in
.access_mask
= access_mask
;
715 r
.out
.user_handle
= &user_handle
;
717 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_OpenUser(p
, tctx
, &r
),
718 "failed to open user");
721 struct samr_QueryUserInfo r
;
722 union samr_UserInfo
*info
;
723 uint32_t levels
[] = { 16, 21 };
726 r
.in
.user_handle
= &user_handle
;
729 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
731 r
.in
.level
= levels
[i
];
733 torture_comment(tctx
, "testing QueryUserInfo rid: %d level: %d\n",
736 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_QueryUserInfo(p
, tctx
, &r
),
737 talloc_asprintf(tctx
, "failed to query user info level %d", r
.in
.level
));
741 struct samr_GetGroupsForUser r
;
742 struct samr_RidWithAttributeArray
*rids
;
744 r
.in
.user_handle
= &user_handle
;
747 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_GetGroupsForUser(p
, tctx
, &r
),
748 "failed to query groups for user");
751 torture_assert_ntstatus_ok(tctx
,
752 torture_samr_Close(tctx
, p
, &user_handle
),
753 "failed to close user handle");
758 static bool test_samr_group(struct torture_context
*tctx
,
759 struct dcerpc_pipe
*p
,
760 struct policy_handle
*domain_handle
,
761 uint32_t access_mask
,
762 struct samr_SamEntry
*g
)
764 struct policy_handle group_handle
;
766 torture_comment(tctx
, "testing group %s (%d)\n", g
->name
.string
, g
->idx
);
768 torture_assert(tctx
, test_LookupRids(tctx
, p
, domain_handle
, g
->idx
),
769 "failed to call lookuprids");
771 struct samr_OpenGroup r
;
773 r
.in
.domain_handle
= domain_handle
;
774 r
.in
.access_mask
= access_mask
;
776 r
.out
.group_handle
= &group_handle
;
778 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_OpenGroup(p
, tctx
, &r
),
779 "failed to open group");
782 struct samr_QueryGroupMember r
;
783 struct samr_RidTypeArray
*rids
;
785 r
.in
.group_handle
= &group_handle
;
788 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_QueryGroupMember(p
, tctx
, &r
),
789 "failed to query group member");
792 torture_assert_ntstatus_ok(tctx
,
793 torture_samr_Close(tctx
, p
, &group_handle
),
794 "failed to close group handle");
799 static bool test_samr_alias(struct torture_context
*tctx
,
800 struct dcerpc_pipe
*p
,
801 struct policy_handle
*domain_handle
,
802 struct samr_SamEntry
*a
)
804 torture_comment(tctx
, "testing alias %s (%d)\n", a
->name
.string
, a
->idx
);
806 torture_assert(tctx
, test_LookupRids(tctx
, p
, domain_handle
, a
->idx
),
807 "failed to call lookuprids");
810 struct samr_GetAliasMembership r
;
811 struct lsa_SidArray sids
;
812 struct samr_Ids rids
;
816 r
.in
.domain_handle
= domain_handle
;
820 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_GetAliasMembership(p
, tctx
, &r
),
821 "failed to get alias membership");
828 static bool test_samr_domain(struct torture_context
*tctx
,
829 struct dcerpc_pipe
*p
,
830 uint32_t access_mask
,
831 const char *domain_name
,
832 struct policy_handle
*connect_handle
,
833 struct policy_handle
*domain_handle_p
)
835 struct policy_handle domain_handle
;
836 struct dom_sid
*domain_sid
;
839 struct samr_EnumDomains r
;
840 uint32_t resume_handle
;
841 struct samr_SamArray
*sam
;
842 uint32_t num_entries
;
845 r
.in
.connect_handle
= connect_handle
;
846 r
.in
.buf_size
= 0xffff;
847 r
.in
.resume_handle
= &resume_handle
;
849 r
.out
.num_entries
= &num_entries
;
850 r
.out
.resume_handle
= &resume_handle
;
852 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_EnumDomains(p
, tctx
, &r
),
853 "failed to enum domains");
855 torture_assert_int_equal(tctx
, num_entries
, 2,
856 "unexpected number of domains");
858 torture_assert(tctx
, sam
,
859 "no domain pointer returned");
861 for (i
=0; i
< sam
->count
; i
++) {
862 if (!strequal(sam
->entries
[i
].name
.string
, "builtin")) {
863 domain_name
= sam
->entries
[i
].name
.string
;
868 torture_assert(tctx
, domain_name
,
869 "no domain found other than builtin found");
873 struct samr_LookupDomain r
;
874 struct dom_sid2
*sid
;
875 struct lsa_String name
;
877 name
.string
= talloc_strdup(tctx
, domain_name
);
879 r
.in
.connect_handle
= connect_handle
;
880 r
.in
.domain_name
= &name
;
883 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_LookupDomain(p
, tctx
, &r
),
884 "failed to lookup domain");
886 domain_sid
= dom_sid_dup(tctx
, sid
);
890 struct samr_OpenDomain r
;
892 r
.in
.connect_handle
= connect_handle
;
893 r
.in
.access_mask
= access_mask
;
894 r
.in
.sid
= domain_sid
;
895 r
.out
.domain_handle
= &domain_handle
;
897 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_OpenDomain(p
, tctx
, &r
),
898 "failed to open domain");
902 struct samr_QueryDomainInfo r
;
903 union samr_DomainInfo
*info
;
904 uint32_t levels
[] = { 1, 2, 8, 12 };
907 r
.in
.domain_handle
= &domain_handle
;
910 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
912 r
.in
.level
= levels
[i
];
914 torture_assert_ntstatus_ok(tctx
, dcerpc_samr_QueryDomainInfo(p
, tctx
, &r
),
915 talloc_asprintf(tctx
, "failed to query domain info level %d", r
.in
.level
));
920 *domain_handle_p
= domain_handle
;
925 static void get_query_dispinfo_params(int loop_count
,
926 uint32_t *max_entries
,
946 default: /* loop_count >= 4 */
954 static bool test_samr_users(struct torture_context
*tctx
,
955 struct dcerpc_pipe
*p
,
956 uint32_t access_mask
,
957 struct policy_handle
*domain_handle
)
962 struct samr_QueryDisplayInfo r
;
964 uint32_t returned_size
;
965 union samr_DispInfo info
;
968 r
.in
.domain_handle
= domain_handle
;
972 r
.out
.total_size
= &total_size
;
973 r
.out
.returned_size
= &returned_size
;
979 r
.in
.max_entries
= 0xffff;
980 r
.in
.buf_size
= 0xffff;
982 get_query_dispinfo_params(loop_count
,
986 status
= dcerpc_samr_QueryDisplayInfo(p
, tctx
, &r
);
987 if (NT_STATUS_IS_ERR(status
)) {
988 torture_assert_ntstatus_ok(tctx
, status
,
989 "failed to call QueryDisplayInfo");
992 for (i
=0; i
< info
.info1
.count
; i
++) {
994 test_user(tctx
, p
, domain_handle
, access_mask
, &info
.info1
.entries
[i
]),
995 "failed to test user");
998 r
.in
.start_idx
+= info
.info1
.count
;
1000 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
1006 static bool test_samr_groups(struct torture_context
*tctx
,
1007 struct dcerpc_pipe
*p
,
1008 uint32_t access_mask
,
1009 struct policy_handle
*domain_handle
)
1014 struct samr_EnumDomainGroups r
;
1015 uint32_t resume_handle
= 0;
1016 struct samr_SamArray
*sam
;
1017 uint32_t num_entries
;
1019 r
.in
.domain_handle
= domain_handle
;
1020 r
.in
.resume_handle
= &resume_handle
;
1021 r
.in
.max_size
= 0xFFFF;
1024 r
.out
.num_entries
= &num_entries
;
1025 r
.out
.resume_handle
= &resume_handle
;
1030 status
= dcerpc_samr_EnumDomainGroups(p
, tctx
, &r
);
1031 if (NT_STATUS_IS_ERR(status
)) {
1032 torture_assert_ntstatus_ok(tctx
, status
,
1033 "failed to call EnumDomainGroups");
1036 for (i
=0; i
< num_entries
; i
++) {
1037 torture_assert(tctx
,
1038 test_samr_group(tctx
, p
, domain_handle
, access_mask
, &sam
->entries
[i
]),
1039 "failed to test group");
1042 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
1048 static bool test_samr_aliases(struct torture_context
*tctx
,
1049 struct dcerpc_pipe
*p
,
1050 uint32_t access_mask
,
1051 struct policy_handle
*domain_handle
)
1056 struct samr_EnumDomainAliases r
;
1057 uint32_t resume_handle
= 0;
1058 struct samr_SamArray
*sam
;
1059 uint32_t num_entries
;
1061 r
.in
.domain_handle
= domain_handle
;
1062 r
.in
.resume_handle
= &resume_handle
;
1063 r
.in
.max_size
= 0xFFFF;
1066 r
.out
.num_entries
= &num_entries
;
1067 r
.out
.resume_handle
= &resume_handle
;
1072 status
= dcerpc_samr_EnumDomainAliases(p
, tctx
, &r
);
1073 if (NT_STATUS_IS_ERR(status
)) {
1074 torture_assert_ntstatus_ok(tctx
, status
,
1075 "failed to call EnumDomainAliases");
1078 for (i
=0; i
< num_entries
; i
++) {
1079 torture_assert(tctx
,
1080 test_samr_alias(tctx
, p
, domain_handle
, &sam
->entries
[i
]),
1081 "failed to test alias");
1084 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
1090 static bool torture_rpc_samr_workstation_query(struct torture_context
*tctx
,
1091 struct dcerpc_pipe
*p
,
1092 struct cli_credentials
*machine_credentials
)
1094 struct policy_handle connect_handle
;
1095 struct policy_handle domain_handle
;
1097 torture_assert_ntstatus_ok(tctx
,
1098 torture_samr_Connect5(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
,
1100 "failed to connect to samr server");
1102 torture_assert(tctx
,
1103 test_samr_domain(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
,
1104 lp_workgroup(tctx
->lp_ctx
),
1105 &connect_handle
, &domain_handle
),
1106 "failed to test domain");
1108 torture_assert(tctx
,
1109 test_samr_users(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
,
1111 "failed to test users");
1113 torture_assert(tctx
,
1114 test_samr_groups(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
,
1116 "failed to test groups");
1118 torture_assert(tctx
,
1119 test_samr_aliases(tctx
, p
, SEC_FLAG_MAXIMUM_ALLOWED
,
1121 "failed to test aliases");
1123 torture_assert_ntstatus_ok(tctx
,
1124 torture_samr_Close(tctx
, p
, &domain_handle
),
1125 "failed to close domain handle");
1127 torture_assert_ntstatus_ok(tctx
,
1128 torture_samr_Close(tctx
, p
, &connect_handle
),
1129 "failed to close connect handle");
1134 /* The purpose of this test is to verify that an account authenticated as a
1135 * domain member workstation can query a DC for various remote read calls all
1136 * opening objects while requesting SEC_FLAG_MAXIMUM_ALLOWED access rights on
1137 * the object open calls. This is the behavior of winbind (and most of samba's
1138 * client code) - gd */
1140 struct torture_suite
*torture_rpc_samr_workstation_auth(TALLOC_CTX
*mem_ctx
)
1142 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SAMR-MACHINE-AUTH");
1143 struct torture_rpc_tcase
*tcase
;
1145 tcase
= torture_suite_add_machine_workstation_rpc_iface_tcase(suite
, "samr",
1149 torture_rpc_tcase_add_test_creds(tcase
, "workstation_query",
1150 torture_rpc_samr_workstation_query
);