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
);