libcli/cldap: make use of samba_tevent_context_init()
[Samba/gebeck_regimport.git] / source4 / torture / rpc / samr_accessmask.c
blob118026f80ffba8689c72677dc494e92876351573
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/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)
37 NTSTATUS status;
38 struct samr_Close cl;
40 cl.in.handle = h;
41 cl.out.handle = h;
42 status = dcerpc_samr_Close_r(b, tctx, &cl);
43 if (!NT_STATUS_IS_OK(status)) {
44 return status;
47 return cl.out.result;
50 static NTSTATUS torture_samr_Connect5(struct torture_context *tctx,
51 struct dcerpc_binding_handle *b,
52 uint32_t mask, struct policy_handle *h)
54 NTSTATUS status;
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 = "";
62 r5.in.level_in = 1;
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)) {
71 return status;
74 return r5.out.result;
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)
81 NTSTATUS status;
82 struct policy_handle h;
83 int i;
84 uint32_t mask;
85 struct dcerpc_binding_handle *b = p->binding_handle;
87 printf("Testing which bits in accessmask allows us to connect\n");
88 mask = 1;
89 for (i=0;i<33;i++) {
90 printf("Testing Connect5 with access mask 0x%08x", mask);
91 status = torture_samr_Connect5(tctx, b, mask, &h);
92 mask <<= 1;
94 switch (i) {
95 case 6:
96 case 7:
97 case 8:
98 case 9:
99 case 10:
100 case 11:
101 case 12:
102 case 13:
103 case 14:
104 case 15:
105 case 20:
106 case 21:
107 case 22:
108 case 23:
109 case 26:
110 case 27:
111 printf(" expecting to fail");
112 /* of only one of these bits are set we expect to
113 fail by default
115 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, status)) {
116 printf("Connect5 failed - %s\n", nt_errstr(status));
117 return false;
119 break;
120 default:
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));
124 return false;
127 status = torture_samr_Close(tctx, b, &h);
128 if (!NT_STATUS_IS_OK(status)) {
129 printf("Close failed - %s\n", nt_errstr(status));
130 return false;
132 break;
134 printf(" OK\n");
137 return true;
140 /* check which bits in accessmask allows us to EnumDomains()
141 by default we must specify at least one of :
142 SAMR/EnumDomains
143 Maximum
144 GenericAll
145 GenericRead
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)
152 NTSTATUS status;
153 struct samr_EnumDomains ed;
154 struct policy_handle ch;
155 int i;
156 uint32_t mask;
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");
163 mask = 1;
164 for (i=0;i<33;i++) {
165 printf("Testing Connect5/EnumDomains with access mask 0x%08x", mask);
166 status = torture_samr_Connect5(tctx, b, mask, &ch);
167 mask <<= 1;
169 switch (i) {
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));
177 return false;
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;
185 ed.out.sam = &sam;
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));
191 return false;
194 status = torture_samr_Close(tctx, b, &ch);
195 if (!NT_STATUS_IS_OK(status)) {
196 printf("Close failed - %s\n", nt_errstr(status));
197 return false;
199 break;
200 default:
201 printf(" expecting to fail");
203 if (!NT_STATUS_IS_OK(status)) {
204 printf(" OK\n");
205 continue;
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;
213 ed.out.sam = &sam;
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));
219 return false;
222 status = torture_samr_Close(tctx, b, &ch);
223 if (!NT_STATUS_IS_OK(status)) {
224 printf("Close failed - %s\n", nt_errstr(status));
225 return false;
227 break;
229 printf(" OK\n");
232 return true;
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
241 * the server
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)
249 NTSTATUS status;
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;
257 bool ret = true;
258 int sd_size;
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));
269 return false;
273 /* get the current ACL for the SAMR policy handle */
274 qs.in.handle = &ch;
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));
281 ret = false;
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
291 sd = sdbuf->sd;
292 ace.type = SEC_ACE_TYPE_ACCESS_DENIED;
293 ace.flags = 0;
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");
299 ret = false;
301 ss.in.handle = &ch;
302 ss.in.sec_info = SECINFO_DACL;
303 ss.in.sdbuf = &sdb;
304 sdb.sd = sd;
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));
309 ret = false;
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));
319 return false;
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));
327 return false;
329 /* disconnec the user */
330 talloc_free(test_p);
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));
340 ret = false;
342 if (sd_size != sdbuf->sd_size) {
343 printf("security descriptor changed\n");
344 ret = false;
348 status = torture_samr_Close(tctx, b, &ch);
349 if (!NT_STATUS_IS_OK(status)) {
350 printf("Close failed - %s\n", nt_errstr(status));
351 ret = false;
354 if (ret == true) {
355 printf(" OK\n");
357 return ret;
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)
374 NTSTATUS status;
375 struct policy_handle uch;
376 bool ret = true;
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));
389 return false;
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));
397 return false;
399 printf(" OK\n");
401 /* disconnec the user */
402 talloc_free(test_p);
404 return ret;
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
411 case 25: Maximum
412 case 28: GenericAll
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)
419 NTSTATUS status;
420 struct samr_LookupDomain ld;
421 struct dom_sid2 *sid = NULL;
422 struct policy_handle ch;
423 struct lsa_String dn;
424 int i;
425 uint32_t mask;
426 struct dcerpc_binding_handle *b = p->binding_handle;
428 printf("Testing which bits in Connect5 accessmask allows us to LookupDomain\n");
429 mask = 1;
430 for (i=0;i<33;i++) {
431 printf("Testing Connect5/LookupDomain with access mask 0x%08x", mask);
432 status = torture_samr_Connect5(tctx, b, mask, &ch);
433 mask <<= 1;
435 switch (i) {
436 case 5:
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));
443 return false;
446 ld.in.connect_handle = &ch;
447 ld.in.domain_name = &dn;
448 ld.out.sid = &sid;
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));
455 return false;
458 status = torture_samr_Close(tctx, b, &ch);
459 if (!NT_STATUS_IS_OK(status)) {
460 printf("Close failed - %s\n", nt_errstr(status));
461 return false;
463 break;
464 default:
465 printf(" expecting to fail");
467 if (!NT_STATUS_IS_OK(status)) {
468 printf(" OK\n");
469 continue;
472 ld.in.connect_handle = &ch;
473 ld.in.domain_name = &dn;
474 ld.out.sid = &sid;
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));
481 return false;
484 status = torture_samr_Close(tctx, b, &ch);
485 if (!NT_STATUS_IS_OK(status)) {
486 printf("Close failed - %s\n", nt_errstr(status));
487 return false;
489 break;
491 printf(" OK\n");
494 return true;
497 /* check which bits in accessmask allows us to OpenDomain()
498 by default we must specify at least one of :
499 samr/opendomain
500 Maximum
501 GenericAll
502 GenericExecute
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)
509 NTSTATUS status;
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;
516 int i;
517 uint32_t mask;
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));
525 return false;
528 ld.in.connect_handle = &ch;
529 ld.in.domain_name = &dn;
530 ld.out.sid = &sid;
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));
536 return false;
541 printf("Testing which bits in Connect5 accessmask allows us to OpenDomain\n");
542 mask = 1;
543 for (i=0;i<33;i++) {
544 printf("Testing Connect5/OpenDomain with access mask 0x%08x", mask);
545 status = torture_samr_Connect5(tctx, b, mask, &ch);
546 mask <<= 1;
548 switch (i) {
549 case 5:
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));
556 return false;
559 od.in.connect_handle = &ch;
560 od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
561 od.in.sid = sid;
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));
568 return false;
571 status = torture_samr_Close(tctx, b, &dh);
572 if (!NT_STATUS_IS_OK(status)) {
573 printf("Close failed - %s\n", nt_errstr(status));
574 return false;
577 status = torture_samr_Close(tctx, b, &ch);
578 if (!NT_STATUS_IS_OK(status)) {
579 printf("Close failed - %s\n", nt_errstr(status));
580 return false;
582 break;
583 default:
584 printf(" expecting to fail");
586 if (!NT_STATUS_IS_OK(status)) {
587 printf(" OK\n");
588 continue;
591 status = torture_samr_Close(tctx, b, &ch);
592 if (!NT_STATUS_IS_OK(status)) {
593 printf("Close failed - %s\n", nt_errstr(status));
594 return false;
596 break;
598 printf(" OK\n");
601 return true;
604 static bool test_samr_connect(struct torture_context *tctx,
605 struct dcerpc_pipe *p)
607 void *testuser;
608 const char *testuser_passwd;
609 struct cli_credentials *test_credentials;
610 bool ret = true;
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);
621 if (!testuser) {
622 printf("Failed to create test user\n");
623 return false;
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),
628 CRED_SPECIFIED);
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)) {
638 ret = false;
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
644 * ReadControl
645 * Samr/OpenDomain
646 * Samr/EnumDomains
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)) {
652 ret = false;
655 /* remove the test user */
656 torture_leave_domain(tctx, testuser);
658 return ret;
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",
667 &ndr_table_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);
691 return suite;
694 static bool test_LookupRids(struct torture_context *tctx,
695 struct dcerpc_binding_handle *b,
696 struct policy_handle *domain_handle,
697 uint32_t rid)
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;
706 r.in.num_rids = 1;
707 r.in.rids = &rid;
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");
716 return true;
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;
738 r.in.rid = u->rid;
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 };
750 int i;
752 r.in.user_handle = &user_handle;
753 r.out.info = &info;
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",
760 u->rid, r.in.level);
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;
773 r.out.rids = &rids;
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");
785 return true;
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;
805 r.in.rid = g->idx;
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;
818 r.out.rids = &rids;
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");
831 return true;
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;
849 ZERO_STRUCT(sids);
851 r.in.domain_handle = domain_handle;
852 r.in.sids = &sids;
853 r.out.rids = &rids;
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");
862 return true;
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;
875 if (!domain_name) {
876 struct samr_EnumDomains r;
877 uint32_t resume_handle;
878 struct samr_SamArray *sam;
879 uint32_t num_entries;
880 int i;
882 r.in.connect_handle = connect_handle;
883 r.in.buf_size = 0xffff;
884 r.in.resume_handle = &resume_handle;
885 r.out.sam = &sam;
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;
903 break;
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;
920 r.out.sid = &sid;
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 };
949 int i;
951 r.in.domain_handle = &domain_handle;
952 r.out.info = &info;
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;
968 return true;
971 static void get_query_dispinfo_params(int loop_count,
972 uint32_t *max_entries,
973 uint32_t *buf_size)
975 switch(loop_count) {
976 case 0:
977 *max_entries = 512;
978 *buf_size = 16383;
979 break;
980 case 1:
981 *max_entries = 1024;
982 *buf_size = 32766;
983 break;
984 case 2:
985 *max_entries = 2048;
986 *buf_size = 65532;
987 break;
988 case 3:
989 *max_entries = 4096;
990 *buf_size = 131064;
991 break;
992 default: /* loop_count >= 4 */
993 *max_entries = 4096;
994 *buf_size = 131071;
995 break;
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;
1010 int loop_count = 0;
1012 r.in.domain_handle = domain_handle;
1013 r.in.level = 1;
1014 r.in.start_idx = 0;
1016 r.out.total_size = &total_size;
1017 r.out.returned_size = &returned_size;
1018 r.out.info = &info;
1020 do {
1021 int i;
1023 r.in.max_entries = 0xffff;
1024 r.in.buf_size = 0xffff;
1026 get_query_dispinfo_params(loop_count,
1027 &r.in.max_entries,
1028 &r.in.buf_size);
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");
1042 loop_count++;
1043 r.in.start_idx += info.info1.count;
1045 } while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES));
1048 return true;
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;
1066 r.out.sam = &sam;
1067 r.out.num_entries = &num_entries;
1068 r.out.resume_handle = &resume_handle;
1070 do {
1071 int i;
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));
1089 return true;
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;
1107 r.out.sam = &sam;
1108 r.out.num_entries = &num_entries;
1109 r.out.resume_handle = &resume_handle;
1111 do {
1112 int i;
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));
1130 return true;
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,
1143 &connect_handle),
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,
1154 &domain_handle),
1155 "failed to test users");
1157 torture_assert(tctx,
1158 test_samr_groups(tctx, b, SEC_FLAG_MAXIMUM_ALLOWED,
1159 &domain_handle),
1160 "failed to test groups");
1162 torture_assert(tctx,
1163 test_samr_aliases(tctx, b, SEC_FLAG_MAXIMUM_ALLOWED,
1164 &domain_handle),
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");
1175 return true;
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",
1190 &ndr_table_samr,
1191 TEST_MACHINENAME);
1193 torture_rpc_tcase_add_test_creds(tcase, "workstation_query",
1194 torture_rpc_samr_workstation_query);
1196 return suite;