s4-smbtorture: fix smbtorture after GetPrinterData{Ex} after IDL changes.
[Samba/cd1.git] / source4 / torture / rpc / samr_accessmask.c
blobebfc069521cf9f9c3993f95b962a151aa145d3bf
1 /*
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/>.
22 #include "includes.h"
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)
37 NTSTATUS status;
38 struct samr_Close cl;
40 cl.in.handle = h;
41 cl.out.handle = h;
42 status = dcerpc_samr_Close(p, tctx, &cl);
44 return status;
47 static NTSTATUS torture_samr_Connect5(struct torture_context *tctx,
48 struct dcerpc_pipe *p,
49 uint32_t mask, struct policy_handle *h)
51 NTSTATUS status;
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 = "";
59 r5.in.level_in = 1;
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);
68 return status;
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)
75 NTSTATUS status;
76 struct policy_handle h;
77 int i;
78 uint32_t mask;
80 printf("testing which bits in accessmask allows us to connect\n");
81 mask = 1;
82 for (i=0;i<33;i++) {
83 printf("testing Connect5 with access mask 0x%08x", mask);
84 status = torture_samr_Connect5(tctx, p, mask, &h);
85 mask <<= 1;
87 switch (i) {
88 case 6:
89 case 7:
90 case 8:
91 case 9:
92 case 10:
93 case 11:
94 case 12:
95 case 13:
96 case 14:
97 case 15:
98 case 20:
99 case 21:
100 case 22:
101 case 23:
102 case 26:
103 case 27:
104 printf(" expecting to fail");
105 /* of only one of these bits are set we expect to
106 fail by default
108 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, status)) {
109 printf("Connect5 failed - %s\n", nt_errstr(status));
110 return false;
112 break;
113 default:
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));
117 return false;
120 status = torture_samr_Close(tctx, p, &h);
121 if (!NT_STATUS_IS_OK(status)) {
122 printf("Close failed - %s\n", nt_errstr(status));
123 return false;
125 break;
127 printf(" OK\n");
130 return true;
133 /* check which bits in accessmask allows us to EnumDomains()
134 by default we must specify at least one of :
135 SAMR/EnumDomains
136 Maximum
137 GenericAll
138 GenericRead
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)
145 NTSTATUS status;
146 struct samr_EnumDomains ed;
147 struct policy_handle ch;
148 int i;
149 uint32_t mask;
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");
155 mask = 1;
156 for (i=0;i<33;i++) {
157 printf("testing Connect5/EnumDomains with access mask 0x%08x", mask);
158 status = torture_samr_Connect5(tctx, p, mask, &ch);
159 mask <<= 1;
161 switch (i) {
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));
169 return false;
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;
177 ed.out.sam = &sam;
179 status = dcerpc_samr_EnumDomains(p, tctx, &ed);
180 if (!NT_STATUS_IS_OK(status)) {
181 printf("EnumDomains failed - %s\n", nt_errstr(status));
182 return false;
185 status = torture_samr_Close(tctx, p, &ch);
186 if (!NT_STATUS_IS_OK(status)) {
187 printf("Close failed - %s\n", nt_errstr(status));
188 return false;
190 break;
191 default:
192 printf(" expecting to fail");
194 if (!NT_STATUS_IS_OK(status)) {
195 printf(" OK\n");
196 continue;
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;
204 ed.out.sam = &sam;
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));
209 return false;
212 status = torture_samr_Close(tctx, p, &ch);
213 if (!NT_STATUS_IS_OK(status)) {
214 printf("Close failed - %s\n", nt_errstr(status));
215 return false;
217 break;
219 printf(" OK\n");
222 return true;
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
231 * the server
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)
239 NTSTATUS status;
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;
247 bool ret = true;
248 int sd_size;
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));
258 return false;
262 /* get the current ACL for the SAMR policy handle */
263 qs.in.handle = &ch;
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));
269 ret = false;
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
279 sd = sdbuf->sd;
280 ace.type = SEC_ACE_TYPE_ACCESS_DENIED;
281 ace.flags = 0;
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");
287 ret = false;
289 ss.in.handle = &ch;
290 ss.in.sec_info = SECINFO_DACL;
291 ss.in.sdbuf = &sdb;
292 sdb.sd = sd;
293 status = dcerpc_samr_SetSecurity(p, tctx, &ss);
294 if (!NT_STATUS_IS_OK(status)) {
295 printf("SetSecurity failed - %s\n", nt_errstr(status));
296 ret = false;
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));
306 return false;
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));
313 return false;
315 /* disconnec the user */
316 talloc_free(test_p);
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));
325 ret = false;
327 if (sd_size != sdbuf->sd_size) {
328 printf("security descriptor changed\n");
329 ret = false;
333 status = torture_samr_Close(tctx, p, &ch);
334 if (!NT_STATUS_IS_OK(status)) {
335 printf("Close failed - %s\n", nt_errstr(status));
336 ret = false;
339 if (ret == true) {
340 printf(" OK\n");
342 return ret;
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)
359 NTSTATUS status;
360 struct policy_handle uch;
361 bool ret = true;
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));
373 return false;
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));
380 return false;
382 printf(" OK\n");
384 /* disconnec the user */
385 talloc_free(test_p);
387 return ret;
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
394 case 25: Maximum
395 case 28: GenericAll
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)
402 NTSTATUS status;
403 struct samr_LookupDomain ld;
404 struct dom_sid2 *sid = NULL;
405 struct policy_handle ch;
406 struct lsa_String dn;
407 int i;
408 uint32_t mask;
410 printf("testing which bits in Connect5 accessmask allows us to LookupDomain\n");
411 mask = 1;
412 for (i=0;i<33;i++) {
413 printf("testing Connect5/LookupDomain with access mask 0x%08x", mask);
414 status = torture_samr_Connect5(tctx, p, mask, &ch);
415 mask <<= 1;
417 switch (i) {
418 case 5:
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));
425 return false;
428 ld.in.connect_handle = &ch;
429 ld.in.domain_name = &dn;
430 ld.out.sid = &sid;
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));
436 return false;
439 status = torture_samr_Close(tctx, p, &ch);
440 if (!NT_STATUS_IS_OK(status)) {
441 printf("Close failed - %s\n", nt_errstr(status));
442 return false;
444 break;
445 default:
446 printf(" expecting to fail");
448 if (!NT_STATUS_IS_OK(status)) {
449 printf(" OK\n");
450 continue;
453 ld.in.connect_handle = &ch;
454 ld.in.domain_name = &dn;
455 ld.out.sid = &sid;
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));
461 return false;
464 status = torture_samr_Close(tctx, p, &ch);
465 if (!NT_STATUS_IS_OK(status)) {
466 printf("Close failed - %s\n", nt_errstr(status));
467 return false;
469 break;
471 printf(" OK\n");
474 return true;
477 /* check which bits in accessmask allows us to OpenDomain()
478 by default we must specify at least one of :
479 samr/opendomain
480 Maximum
481 GenericAll
482 GenericExecute
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)
489 NTSTATUS status;
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;
496 int i;
497 uint32_t mask;
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));
504 return false;
507 ld.in.connect_handle = &ch;
508 ld.in.domain_name = &dn;
509 ld.out.sid = &sid;
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));
514 return false;
519 printf("testing which bits in Connect5 accessmask allows us to OpenDomain\n");
520 mask = 1;
521 for (i=0;i<33;i++) {
522 printf("testing Connect5/OpenDomain with access mask 0x%08x", mask);
523 status = torture_samr_Connect5(tctx, p, mask, &ch);
524 mask <<= 1;
526 switch (i) {
527 case 5:
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));
534 return false;
537 od.in.connect_handle = &ch;
538 od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
539 od.in.sid = sid;
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));
545 return false;
548 status = torture_samr_Close(tctx, p, &dh);
549 if (!NT_STATUS_IS_OK(status)) {
550 printf("Close failed - %s\n", nt_errstr(status));
551 return false;
554 status = torture_samr_Close(tctx, p, &ch);
555 if (!NT_STATUS_IS_OK(status)) {
556 printf("Close failed - %s\n", nt_errstr(status));
557 return false;
559 break;
560 default:
561 printf(" expecting to fail");
563 if (!NT_STATUS_IS_OK(status)) {
564 printf(" OK\n");
565 continue;
568 status = torture_samr_Close(tctx, p, &ch);
569 if (!NT_STATUS_IS_OK(status)) {
570 printf("Close failed - %s\n", nt_errstr(status));
571 return false;
573 break;
575 printf(" OK\n");
578 return true;
581 static bool test_samr_connect(struct torture_context *tctx,
582 struct dcerpc_pipe *p)
584 void *testuser;
585 const char *testuser_passwd;
586 struct cli_credentials *test_credentials;
587 bool ret = true;
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);
597 if (!testuser) {
598 printf("Failed to create test user\n");
599 return false;
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),
604 CRED_SPECIFIED);
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)) {
614 ret = false;
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
620 * ReadControl
621 * Samr/OpenDomain
622 * Samr/EnumDomains
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)) {
628 ret = false;
631 /* remove the test user */
632 torture_leave_domain(tctx, testuser);
634 return ret;
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",
643 &ndr_table_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);
667 return suite;
670 static bool test_LookupRids(struct torture_context *tctx,
671 struct dcerpc_pipe *p,
672 struct policy_handle *domain_handle,
673 uint32_t rid)
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;
682 r.in.num_rids = 1;
683 r.in.rids = &rid;
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");
690 return true;
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;
712 r.in.rid = u->rid;
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 };
722 int i;
724 r.in.user_handle = &user_handle;
725 r.out.info = &info;
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",
732 u->rid, r.in.level);
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;
743 r.out.rids = &rids;
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");
753 return true;
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;
773 r.in.rid = g->idx;
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;
784 r.out.rids = &rids;
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");
794 return true;
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;
812 ZERO_STRUCT(sids);
814 r.in.domain_handle = domain_handle;
815 r.in.sids = &sids;
816 r.out.rids = &rids;
818 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership(p, tctx, &r),
819 "failed to get alias membership");
823 return true;
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;
836 if (!domain_name) {
837 struct samr_EnumDomains r;
838 uint32_t resume_handle;
839 struct samr_SamArray *sam;
840 uint32_t num_entries;
841 int i;
843 r.in.connect_handle = connect_handle;
844 r.in.buf_size = 0xffff;
845 r.in.resume_handle = &resume_handle;
846 r.out.sam = &sam;
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;
862 break;
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;
879 r.out.sid = &sid;
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 };
903 int i;
905 r.in.domain_handle = &domain_handle;
906 r.out.info = &info;
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;
920 return true;
923 static void get_query_dispinfo_params(int loop_count,
924 uint32_t *max_entries,
925 uint32_t *buf_size)
927 switch(loop_count) {
928 case 0:
929 *max_entries = 512;
930 *buf_size = 16383;
931 break;
932 case 1:
933 *max_entries = 1024;
934 *buf_size = 32766;
935 break;
936 case 2:
937 *max_entries = 2048;
938 *buf_size = 65532;
939 break;
940 case 3:
941 *max_entries = 4096;
942 *buf_size = 131064;
943 break;
944 default: /* loop_count >= 4 */
945 *max_entries = 4096;
946 *buf_size = 131071;
947 break;
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)
957 NTSTATUS status;
960 struct samr_QueryDisplayInfo r;
961 uint32_t total_size;
962 uint32_t returned_size;
963 union samr_DispInfo info;
964 int loop_count = 0;
966 r.in.domain_handle = domain_handle;
967 r.in.level = 1;
968 r.in.start_idx = 0;
970 r.out.total_size = &total_size;
971 r.out.returned_size = &returned_size;
972 r.out.info = &info;
974 do {
975 int i;
977 r.in.max_entries = 0xffff;
978 r.in.buf_size = 0xffff;
980 get_query_dispinfo_params(loop_count,
981 &r.in.max_entries,
982 &r.in.buf_size);
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++) {
991 torture_assert(tctx,
992 test_user(tctx, p, domain_handle, access_mask, &info.info1.entries[i]),
993 "failed to test user");
995 loop_count++;
996 r.in.start_idx += info.info1.count;
998 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1001 return true;
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)
1009 NTSTATUS status;
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;
1021 r.out.sam = &sam;
1022 r.out.num_entries = &num_entries;
1023 r.out.resume_handle = &resume_handle;
1025 do {
1026 int i;
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));
1043 return true;
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)
1051 NTSTATUS status;
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;
1063 r.out.sam = &sam;
1064 r.out.num_entries = &num_entries;
1065 r.out.resume_handle = &resume_handle;
1067 do {
1068 int i;
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));
1085 return true;
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,
1097 &connect_handle),
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,
1108 &domain_handle),
1109 "failed to test users");
1111 torture_assert(tctx,
1112 test_samr_groups(tctx, p, SEC_FLAG_MAXIMUM_ALLOWED,
1113 &domain_handle),
1114 "failed to test groups");
1116 torture_assert(tctx,
1117 test_samr_aliases(tctx, p, SEC_FLAG_MAXIMUM_ALLOWED,
1118 &domain_handle),
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");
1129 return true;
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",
1144 &ndr_table_samr,
1145 TEST_MACHINENAME);
1147 torture_rpc_tcase_add_test_creds(tcase, "workstation_query",
1148 torture_rpc_samr_workstation_query);
1150 return suite;