s3-schannel: use NL_AUTH_SIGNATURE for schannel sign & seal (client & server).
[Samba/aatanasov.git] / source4 / torture / rpc / samr_accessmask.c
blob1af9fac6721ef64442be92eae1f2d4dbd10362f1
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 "torture/torture.h"
24 #include "librpc/gen_ndr/ndr_samr_c.h"
25 #include "torture/rpc/rpc.h"
26 #include "param/param.h"
27 #include "libcli/security/security.h"
28 #include "librpc/gen_ndr/ndr_security.h"
31 /* test user created to test the ACLs associated to SAMR objects */
32 #define TEST_USER_NAME "samr_testuser"
33 #define TEST_MACHINENAME "samrtestmach"
35 static NTSTATUS torture_samr_Close(struct torture_context *tctx,
36 struct dcerpc_pipe *p,
37 struct policy_handle *h)
39 NTSTATUS status;
40 struct samr_Close cl;
42 cl.in.handle = h;
43 cl.out.handle = h;
44 status = dcerpc_samr_Close(p, tctx, &cl);
46 return status;
49 static NTSTATUS torture_samr_Connect5(struct torture_context *tctx,
50 struct dcerpc_pipe *p,
51 uint32_t mask, struct policy_handle *h)
53 NTSTATUS status;
54 struct samr_Connect5 r5;
55 union samr_ConnectInfo info;
56 uint32_t level_out = 0;
58 info.info1.client_version = 0;
59 info.info1.unknown2 = 0;
60 r5.in.system_name = "";
61 r5.in.level_in = 1;
62 r5.in.info_in = &info;
63 r5.out.info_out = &info;
64 r5.out.level_out = &level_out;
65 r5.out.connect_handle = h;
66 r5.in.access_mask = mask;
68 status = dcerpc_samr_Connect5(p, tctx, &r5);
70 return status;
73 /* check which bits in accessmask allows us to connect to the server */
74 static bool test_samr_accessmask_Connect5(struct torture_context *tctx,
75 struct dcerpc_pipe *p)
77 NTSTATUS status;
78 struct policy_handle h;
79 int i;
80 uint32_t mask;
82 printf("testing which bits in accessmask allows us to connect\n");
83 mask = 1;
84 for (i=0;i<33;i++) {
85 printf("testing Connect5 with access mask 0x%08x", mask);
86 status = torture_samr_Connect5(tctx, p, mask, &h);
87 mask <<= 1;
89 switch (i) {
90 case 6:
91 case 7:
92 case 8:
93 case 9:
94 case 10:
95 case 11:
96 case 12:
97 case 13:
98 case 14:
99 case 15:
100 case 20:
101 case 21:
102 case 22:
103 case 23:
104 case 26:
105 case 27:
106 printf(" expecting to fail");
107 /* of only one of these bits are set we expect to
108 fail by default
110 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, status)) {
111 printf("Connect5 failed - %s\n", nt_errstr(status));
112 return false;
114 break;
115 default:
116 /* these bits set are expected to succeed by default */
117 if (!NT_STATUS_IS_OK(status)) {
118 printf("Connect5 failed - %s\n", nt_errstr(status));
119 return false;
122 status = torture_samr_Close(tctx, p, &h);
123 if (!NT_STATUS_IS_OK(status)) {
124 printf("Close failed - %s\n", nt_errstr(status));
125 return false;
127 break;
129 printf(" OK\n");
132 return true;
135 /* check which bits in accessmask allows us to EnumDomains()
136 by default we must specify at least one of :
137 SAMR/EnumDomains
138 Maximum
139 GenericAll
140 GenericRead
141 in the access mask to Connect5() in order to be allowed to perform
142 EnumDomains() on the policy handle returned from Connect5()
144 static bool test_samr_accessmask_EnumDomains(struct torture_context *tctx,
145 struct dcerpc_pipe *p)
147 NTSTATUS status;
148 struct samr_EnumDomains ed;
149 struct policy_handle ch;
150 int i;
151 uint32_t mask;
152 uint32_t resume_handle = 0;
153 struct samr_SamArray *sam = NULL;
154 uint32_t num_entries = 0;
156 printf("testing which bits in Connect5 accessmask allows us to EnumDomains\n");
157 mask = 1;
158 for (i=0;i<33;i++) {
159 printf("testing Connect5/EnumDomains with access mask 0x%08x", mask);
160 status = torture_samr_Connect5(tctx, p, mask, &ch);
161 mask <<= 1;
163 switch (i) {
164 case 4: /* SAMR/EnumDomains */
165 case 25: /* Maximum */
166 case 28: /* GenericAll */
167 case 31: /* GenericRead */
168 /* these bits set are expected to succeed by default */
169 if (!NT_STATUS_IS_OK(status)) {
170 printf("Connect5 failed - %s\n", nt_errstr(status));
171 return false;
174 ed.in.connect_handle = &ch;
175 ed.in.resume_handle = &resume_handle;
176 ed.in.buf_size = (uint32_t)-1;
177 ed.out.resume_handle = &resume_handle;
178 ed.out.num_entries = &num_entries;
179 ed.out.sam = &sam;
181 status = dcerpc_samr_EnumDomains(p, tctx, &ed);
182 if (!NT_STATUS_IS_OK(status)) {
183 printf("EnumDomains failed - %s\n", nt_errstr(status));
184 return false;
187 status = torture_samr_Close(tctx, p, &ch);
188 if (!NT_STATUS_IS_OK(status)) {
189 printf("Close failed - %s\n", nt_errstr(status));
190 return false;
192 break;
193 default:
194 printf(" expecting to fail");
196 if (!NT_STATUS_IS_OK(status)) {
197 printf(" OK\n");
198 continue;
201 ed.in.connect_handle = &ch;
202 ed.in.resume_handle = &resume_handle;
203 ed.in.buf_size = (uint32_t)-1;
204 ed.out.resume_handle = &resume_handle;
205 ed.out.num_entries = &num_entries;
206 ed.out.sam = &sam;
208 status = dcerpc_samr_EnumDomains(p, tctx, &ed);
209 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, status)) {
210 printf("EnumDomains failed - %s\n", nt_errstr(status));
211 return false;
214 status = torture_samr_Close(tctx, p, &ch);
215 if (!NT_STATUS_IS_OK(status)) {
216 printf("Close failed - %s\n", nt_errstr(status));
217 return false;
219 break;
221 printf(" OK\n");
224 return true;
229 * test how ACLs affect how/if a user can connect to the SAMR service
231 * samr_SetSecurity() returns SUCCESS when changing the ACL for
232 * a policy handle got from Connect5() but the ACL is not changed on
233 * the server
235 static bool test_samr_connect_user_acl(struct torture_context *tctx,
236 struct dcerpc_pipe *p,
237 struct cli_credentials *test_credentials,
238 const struct dom_sid *test_sid)
241 NTSTATUS status;
242 struct policy_handle ch;
243 struct policy_handle uch;
244 struct samr_QuerySecurity qs;
245 struct samr_SetSecurity ss;
246 struct security_ace ace;
247 struct security_descriptor *sd;
248 struct sec_desc_buf sdb, *sdbuf = NULL;
249 bool ret = true;
250 int sd_size;
251 struct dcerpc_pipe *test_p;
252 const char *binding = torture_setting_string(tctx, "binding", NULL);
254 printf("testing ACLs to allow/prevent users to connect to SAMR");
256 /* connect to SAMR */
257 status = torture_samr_Connect5(tctx, p, SEC_FLAG_MAXIMUM_ALLOWED, &ch);
258 if (!NT_STATUS_IS_OK(status)) {
259 printf("Connect5 failed - %s\n", nt_errstr(status));
260 return false;
264 /* get the current ACL for the SAMR policy handle */
265 qs.in.handle = &ch;
266 qs.in.sec_info = SECINFO_DACL;
267 qs.out.sdbuf = &sdbuf;
268 status = dcerpc_samr_QuerySecurity(p, tctx, &qs);
269 if (!NT_STATUS_IS_OK(status)) {
270 printf("QuerySecurity failed - %s\n", nt_errstr(status));
271 ret = false;
274 /* how big is the security descriptor? */
275 sd_size = sdbuf->sd_size;
278 /* add an ACE to the security descriptor to deny the user the
279 * 'connect to server' right
281 sd = sdbuf->sd;
282 ace.type = SEC_ACE_TYPE_ACCESS_DENIED;
283 ace.flags = 0;
284 ace.access_mask = SAMR_ACCESS_CONNECT_TO_SERVER;
285 ace.trustee = *test_sid;
286 status = security_descriptor_dacl_add(sd, &ace);
287 if (!NT_STATUS_IS_OK(status)) {
288 printf("Failed to add ACE to security descriptor\n");
289 ret = false;
291 ss.in.handle = &ch;
292 ss.in.sec_info = SECINFO_DACL;
293 ss.in.sdbuf = &sdb;
294 sdb.sd = sd;
295 status = dcerpc_samr_SetSecurity(p, tctx, &ss);
296 if (!NT_STATUS_IS_OK(status)) {
297 printf("SetSecurity failed - %s\n", nt_errstr(status));
298 ret = false;
302 /* Try to connect as the test user */
303 status = dcerpc_pipe_connect(tctx,
304 &test_p, binding, &ndr_table_samr,
305 test_credentials, tctx->ev, tctx->lp_ctx);
306 if (!NT_STATUS_IS_OK(status)) {
307 printf("dcerpc_pipe_connect failed: %s\n", nt_errstr(status));
308 return false;
311 /* connect to SAMR as the user */
312 status = torture_samr_Connect5(tctx, test_p, SEC_FLAG_MAXIMUM_ALLOWED, &uch);
313 if (!NT_STATUS_IS_OK(status)) {
314 printf("Connect5 failed - %s\n", nt_errstr(status));
315 return false;
317 /* disconnec the user */
318 talloc_free(test_p);
321 /* read the sequrity descriptor back. it should not have changed
322 * eventhough samr_SetSecurity returned SUCCESS
324 status = dcerpc_samr_QuerySecurity(p, tctx, &qs);
325 if (!NT_STATUS_IS_OK(status)) {
326 printf("QuerySecurity failed - %s\n", nt_errstr(status));
327 ret = false;
329 if (sd_size != sdbuf->sd_size) {
330 printf("security descriptor changed\n");
331 ret = false;
335 status = torture_samr_Close(tctx, p, &ch);
336 if (!NT_STATUS_IS_OK(status)) {
337 printf("Close failed - %s\n", nt_errstr(status));
338 ret = false;
341 if (ret == true) {
342 printf(" OK\n");
344 return ret;
348 * test if the ACLs are enforced for users.
349 * a normal testuser only gets the rights provided in hte ACL for
350 * Everyone which does not include the SAMR_ACCESS_SHUTDOWN_SERVER
351 * right. If the ACLs are checked when a user connects
352 * a testuser that requests the accessmask with only this bit set
353 * the connect should fail.
355 static bool test_samr_connect_user_acl_enforced(struct torture_context *tctx,
356 struct dcerpc_pipe *p,
357 struct cli_credentials *test_credentials,
358 const struct dom_sid *test_sid)
361 NTSTATUS status;
362 struct policy_handle uch;
363 bool ret = true;
364 struct dcerpc_pipe *test_p;
365 const char *binding = torture_setting_string(tctx, "binding", NULL);
367 printf("testing if ACLs are enforced for non domain admin users when connecting to SAMR");
370 status = dcerpc_pipe_connect(tctx,
371 &test_p, binding, &ndr_table_samr,
372 test_credentials, tctx->ev, tctx->lp_ctx);
373 if (!NT_STATUS_IS_OK(status)) {
374 printf("dcerpc_pipe_connect failed: %s\n", nt_errstr(status));
375 return false;
378 /* connect to SAMR as the user */
379 status = torture_samr_Connect5(tctx, test_p, SAMR_ACCESS_SHUTDOWN_SERVER, &uch);
380 if (NT_STATUS_IS_OK(status)) {
381 printf("Connect5 failed - %s\n", nt_errstr(status));
382 return false;
384 printf(" OK\n");
386 /* disconnec the user */
387 talloc_free(test_p);
389 return ret;
392 /* check which bits in accessmask allows us to LookupDomain()
393 by default we must specify at least one of :
394 in the access mask to Connect5() in order to be allowed to perform
395 case 5: samr/opendomain
396 case 25: Maximum
397 case 28: GenericAll
398 case 29: GenericExecute
399 LookupDomain() on the policy handle returned from Connect5()
401 static bool test_samr_accessmask_LookupDomain(struct torture_context *tctx,
402 struct dcerpc_pipe *p)
404 NTSTATUS status;
405 struct samr_LookupDomain ld;
406 struct dom_sid2 *sid = NULL;
407 struct policy_handle ch;
408 struct lsa_String dn;
409 int i;
410 uint32_t mask;
412 printf("testing which bits in Connect5 accessmask allows us to LookupDomain\n");
413 mask = 1;
414 for (i=0;i<33;i++) {
415 printf("testing Connect5/LookupDomain with access mask 0x%08x", mask);
416 status = torture_samr_Connect5(tctx, p, mask, &ch);
417 mask <<= 1;
419 switch (i) {
420 case 5:
421 case 25: /* Maximum */
422 case 28: /* GenericAll */
423 case 29: /* GenericExecute */
424 /* these bits set are expected to succeed by default */
425 if (!NT_STATUS_IS_OK(status)) {
426 printf("Connect5 failed - %s\n", nt_errstr(status));
427 return false;
430 ld.in.connect_handle = &ch;
431 ld.in.domain_name = &dn;
432 ld.out.sid = &sid;
433 dn.string = lp_workgroup(tctx->lp_ctx);
435 status = dcerpc_samr_LookupDomain(p, tctx, &ld);
436 if (!NT_STATUS_IS_OK(status)) {
437 printf("LookupDomain failed - %s\n", nt_errstr(status));
438 return false;
441 status = torture_samr_Close(tctx, p, &ch);
442 if (!NT_STATUS_IS_OK(status)) {
443 printf("Close failed - %s\n", nt_errstr(status));
444 return false;
446 break;
447 default:
448 printf(" expecting to fail");
450 if (!NT_STATUS_IS_OK(status)) {
451 printf(" OK\n");
452 continue;
455 ld.in.connect_handle = &ch;
456 ld.in.domain_name = &dn;
457 ld.out.sid = &sid;
458 dn.string = lp_workgroup(tctx->lp_ctx);
460 status = dcerpc_samr_LookupDomain(p, tctx, &ld);
461 if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, status)) {
462 printf("LookupDomain failed - %s\n", nt_errstr(status));
463 return false;
466 status = torture_samr_Close(tctx, p, &ch);
467 if (!NT_STATUS_IS_OK(status)) {
468 printf("Close failed - %s\n", nt_errstr(status));
469 return false;
471 break;
473 printf(" OK\n");
476 return true;
479 /* check which bits in accessmask allows us to OpenDomain()
480 by default we must specify at least one of :
481 samr/opendomain
482 Maximum
483 GenericAll
484 GenericExecute
485 in the access mask to Connect5() in order to be allowed to perform
486 OpenDomain() on the policy handle returned from Connect5()
488 static bool test_samr_accessmask_OpenDomain(struct torture_context *tctx,
489 struct dcerpc_pipe *p)
491 NTSTATUS status;
492 struct samr_LookupDomain ld;
493 struct dom_sid2 *sid = NULL;
494 struct samr_OpenDomain od;
495 struct policy_handle ch;
496 struct policy_handle dh;
497 struct lsa_String dn;
498 int i;
499 uint32_t mask;
502 /* first we must grab the sid of the domain */
503 status = torture_samr_Connect5(tctx, p, SEC_FLAG_MAXIMUM_ALLOWED, &ch);
504 if (!NT_STATUS_IS_OK(status)) {
505 printf("Connect5 failed - %s\n", nt_errstr(status));
506 return false;
509 ld.in.connect_handle = &ch;
510 ld.in.domain_name = &dn;
511 ld.out.sid = &sid;
512 dn.string = lp_workgroup(tctx->lp_ctx);
513 status = dcerpc_samr_LookupDomain(p, tctx, &ld);
514 if (!NT_STATUS_IS_OK(status)) {
515 printf("LookupDomain failed - %s\n", nt_errstr(status));
516 return false;
521 printf("testing which bits in Connect5 accessmask allows us to OpenDomain\n");
522 mask = 1;
523 for (i=0;i<33;i++) {
524 printf("testing Connect5/OpenDomain with access mask 0x%08x", mask);
525 status = torture_samr_Connect5(tctx, p, mask, &ch);
526 mask <<= 1;
528 switch (i) {
529 case 5:
530 case 25: /* Maximum */
531 case 28: /* GenericAll */
532 case 29: /* GenericExecute */
533 /* these bits set are expected to succeed by default */
534 if (!NT_STATUS_IS_OK(status)) {
535 printf("Connect5 failed - %s\n", nt_errstr(status));
536 return false;
539 od.in.connect_handle = &ch;
540 od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
541 od.in.sid = sid;
542 od.out.domain_handle = &dh;
544 status = dcerpc_samr_OpenDomain(p, tctx, &od);
545 if (!NT_STATUS_IS_OK(status)) {
546 printf("OpenDomain failed - %s\n", nt_errstr(status));
547 return false;
550 status = torture_samr_Close(tctx, p, &dh);
551 if (!NT_STATUS_IS_OK(status)) {
552 printf("Close failed - %s\n", nt_errstr(status));
553 return false;
556 status = torture_samr_Close(tctx, p, &ch);
557 if (!NT_STATUS_IS_OK(status)) {
558 printf("Close failed - %s\n", nt_errstr(status));
559 return false;
561 break;
562 default:
563 printf(" expecting to fail");
565 if (!NT_STATUS_IS_OK(status)) {
566 printf(" OK\n");
567 continue;
570 status = torture_samr_Close(tctx, p, &ch);
571 if (!NT_STATUS_IS_OK(status)) {
572 printf("Close failed - %s\n", nt_errstr(status));
573 return false;
575 break;
577 printf(" OK\n");
580 return true;
583 static bool test_samr_connect(struct torture_context *tctx,
584 struct dcerpc_pipe *p)
586 void *testuser;
587 const char *testuser_passwd;
588 struct cli_credentials *test_credentials;
589 bool ret = true;
590 const struct dom_sid *test_sid;
592 if (torture_setting_bool(tctx, "samba3", false)) {
593 torture_skip(tctx, "Skipping test against Samba 3");
596 /* create a test user */
597 testuser = torture_create_testuser(tctx, TEST_USER_NAME, lp_workgroup(tctx->lp_ctx),
598 ACB_NORMAL, &testuser_passwd);
599 if (!testuser) {
600 printf("Failed to create test user\n");
601 return false;
603 test_credentials = cli_credentials_init(tctx);
604 cli_credentials_set_workstation(test_credentials, "localhost", CRED_SPECIFIED);
605 cli_credentials_set_domain(test_credentials, lp_workgroup(tctx->lp_ctx),
606 CRED_SPECIFIED);
607 cli_credentials_set_username(test_credentials, TEST_USER_NAME, CRED_SPECIFIED);
608 cli_credentials_set_password(test_credentials, testuser_passwd, CRED_SPECIFIED);
609 test_sid = torture_join_user_sid(testuser);
612 /* test if ACLs can be changed for the policy handle
613 * returned by Connect5
615 if (!test_samr_connect_user_acl(tctx, p, test_credentials, test_sid)) {
616 ret = false;
619 /* test if the ACLs that are reported from the Connect5
620 * policy handle is enforced.
621 * i.e. an ordinary user only has the same rights as Everybody
622 * ReadControl
623 * Samr/OpenDomain
624 * Samr/EnumDomains
625 * Samr/ConnectToServer
626 * is granted and should therefore not be able to connect when
627 * requesting SAMR_ACCESS_SHUTDOWN_SERVER
629 if (!test_samr_connect_user_acl_enforced(tctx, p, test_credentials, test_sid)) {
630 ret = false;
633 /* remove the test user */
634 torture_leave_domain(tctx, testuser);
636 return ret;
639 struct torture_suite *torture_rpc_samr_accessmask(TALLOC_CTX *mem_ctx)
641 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-ACCESSMASK");
642 struct torture_rpc_tcase *tcase;
644 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr",
645 &ndr_table_samr);
647 torture_rpc_tcase_add_test(tcase, "CONNECT", test_samr_connect);
649 /* test which bits in the accessmask to Connect5 will allow
650 * us to call OpenDomain() */
651 torture_rpc_tcase_add_test(tcase, "OpenDomain",
652 test_samr_accessmask_OpenDomain);
654 /* test which bits in the accessmask to Connect5 will allow
655 * us to call LookupDomain() */
656 torture_rpc_tcase_add_test(tcase, "LookupDomain",
657 test_samr_accessmask_LookupDomain);
659 /* test which bits in the accessmask to Connect5 will allow
660 * us to call EnumDomains() */
661 torture_rpc_tcase_add_test(tcase, "EnumDomains",
662 test_samr_accessmask_EnumDomains);
664 /* test which bits in the accessmask to Connect5
665 will allow us to connect to the server */
666 torture_rpc_tcase_add_test(tcase, "Connect5",
667 test_samr_accessmask_Connect5);
669 return suite;
672 static bool test_LookupRids(struct torture_context *tctx,
673 struct dcerpc_pipe *p,
674 struct policy_handle *domain_handle,
675 uint32_t rid)
677 struct samr_LookupRids r;
678 struct lsa_Strings names;
679 struct samr_Ids types;
681 torture_comment(tctx, "testing LookupRids %d\n", rid);
683 r.in.domain_handle = domain_handle;
684 r.in.num_rids = 1;
685 r.in.rids = &rid;
686 r.out.names = &names;
687 r.out.types = &types;
689 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids(p, tctx, &r),
690 "failed to call samr_LookupRids");
692 return true;
696 static bool test_user(struct torture_context *tctx,
697 struct dcerpc_pipe *p,
698 struct policy_handle *domain_handle,
699 uint32_t access_mask,
700 struct samr_DispEntryGeneral *u)
702 struct policy_handle user_handle;
704 torture_comment(tctx, "testing user %s (%d)\n", u->account_name.string, u->rid);
706 torture_assert(tctx, test_LookupRids(tctx, p, domain_handle, u->rid),
707 "failed to call lookuprids");
710 struct samr_OpenUser r;
712 r.in.domain_handle = domain_handle;
713 r.in.access_mask = access_mask;
714 r.in.rid = u->rid;
715 r.out.user_handle = &user_handle;
717 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser(p, tctx, &r),
718 "failed to open user");
721 struct samr_QueryUserInfo r;
722 union samr_UserInfo *info;
723 uint32_t levels[] = { 16, 21 };
724 int i;
726 r.in.user_handle = &user_handle;
727 r.out.info = &info;
729 for (i=0; i < ARRAY_SIZE(levels); i++) {
731 r.in.level = levels[i];
733 torture_comment(tctx, "testing QueryUserInfo rid: %d level: %d\n",
734 u->rid, r.in.level);
736 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo(p, tctx, &r),
737 talloc_asprintf(tctx, "failed to query user info level %d", r.in.level));
741 struct samr_GetGroupsForUser r;
742 struct samr_RidWithAttributeArray *rids;
744 r.in.user_handle = &user_handle;
745 r.out.rids = &rids;
747 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetGroupsForUser(p, tctx, &r),
748 "failed to query groups for user");
751 torture_assert_ntstatus_ok(tctx,
752 torture_samr_Close(tctx, p, &user_handle),
753 "failed to close user handle");
755 return true;
758 static bool test_samr_group(struct torture_context *tctx,
759 struct dcerpc_pipe *p,
760 struct policy_handle *domain_handle,
761 uint32_t access_mask,
762 struct samr_SamEntry *g)
764 struct policy_handle group_handle;
766 torture_comment(tctx, "testing group %s (%d)\n", g->name.string, g->idx);
768 torture_assert(tctx, test_LookupRids(tctx, p, domain_handle, g->idx),
769 "failed to call lookuprids");
771 struct samr_OpenGroup r;
773 r.in.domain_handle = domain_handle;
774 r.in.access_mask = access_mask;
775 r.in.rid = g->idx;
776 r.out.group_handle = &group_handle;
778 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup(p, tctx, &r),
779 "failed to open group");
782 struct samr_QueryGroupMember r;
783 struct samr_RidTypeArray *rids;
785 r.in.group_handle = &group_handle;
786 r.out.rids = &rids;
788 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember(p, tctx, &r),
789 "failed to query group member");
792 torture_assert_ntstatus_ok(tctx,
793 torture_samr_Close(tctx, p, &group_handle),
794 "failed to close group handle");
796 return true;
799 static bool test_samr_alias(struct torture_context *tctx,
800 struct dcerpc_pipe *p,
801 struct policy_handle *domain_handle,
802 struct samr_SamEntry *a)
804 torture_comment(tctx, "testing alias %s (%d)\n", a->name.string, a->idx);
806 torture_assert(tctx, test_LookupRids(tctx, p, domain_handle, a->idx),
807 "failed to call lookuprids");
810 struct samr_GetAliasMembership r;
811 struct lsa_SidArray sids;
812 struct samr_Ids rids;
814 ZERO_STRUCT(sids);
816 r.in.domain_handle = domain_handle;
817 r.in.sids = &sids;
818 r.out.rids = &rids;
820 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership(p, tctx, &r),
821 "failed to get alias membership");
825 return true;
828 static bool test_samr_domain(struct torture_context *tctx,
829 struct dcerpc_pipe *p,
830 uint32_t access_mask,
831 const char *domain_name,
832 struct policy_handle *connect_handle,
833 struct policy_handle *domain_handle_p)
835 struct policy_handle domain_handle;
836 struct dom_sid *domain_sid;
838 if (!domain_name) {
839 struct samr_EnumDomains r;
840 uint32_t resume_handle;
841 struct samr_SamArray *sam;
842 uint32_t num_entries;
843 int i;
845 r.in.connect_handle = connect_handle;
846 r.in.buf_size = 0xffff;
847 r.in.resume_handle = &resume_handle;
848 r.out.sam = &sam;
849 r.out.num_entries = &num_entries;
850 r.out.resume_handle = &resume_handle;
852 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains(p, tctx, &r),
853 "failed to enum domains");
855 torture_assert_int_equal(tctx, num_entries, 2,
856 "unexpected number of domains");
858 torture_assert(tctx, sam,
859 "no domain pointer returned");
861 for (i=0; i < sam->count; i++) {
862 if (!strequal(sam->entries[i].name.string, "builtin")) {
863 domain_name = sam->entries[i].name.string;
864 break;
868 torture_assert(tctx, domain_name,
869 "no domain found other than builtin found");
873 struct samr_LookupDomain r;
874 struct dom_sid2 *sid;
875 struct lsa_String name;
877 name.string = talloc_strdup(tctx, domain_name);
879 r.in.connect_handle = connect_handle;
880 r.in.domain_name = &name;
881 r.out.sid = &sid;
883 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain(p, tctx, &r),
884 "failed to lookup domain");
886 domain_sid = dom_sid_dup(tctx, sid);
890 struct samr_OpenDomain r;
892 r.in.connect_handle = connect_handle;
893 r.in.access_mask = access_mask;
894 r.in.sid = domain_sid;
895 r.out.domain_handle = &domain_handle;
897 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain(p, tctx, &r),
898 "failed to open domain");
902 struct samr_QueryDomainInfo r;
903 union samr_DomainInfo *info;
904 uint32_t levels[] = { 1, 2, 8, 12 };
905 int i;
907 r.in.domain_handle = &domain_handle;
908 r.out.info = &info;
910 for (i=0; i < ARRAY_SIZE(levels); i++) {
912 r.in.level = levels[i];
914 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo(p, tctx, &r),
915 talloc_asprintf(tctx, "failed to query domain info level %d", r.in.level));
920 *domain_handle_p = domain_handle;
922 return true;
925 static void get_query_dispinfo_params(int loop_count,
926 uint32_t *max_entries,
927 uint32_t *buf_size)
929 switch(loop_count) {
930 case 0:
931 *max_entries = 512;
932 *buf_size = 16383;
933 break;
934 case 1:
935 *max_entries = 1024;
936 *buf_size = 32766;
937 break;
938 case 2:
939 *max_entries = 2048;
940 *buf_size = 65532;
941 break;
942 case 3:
943 *max_entries = 4096;
944 *buf_size = 131064;
945 break;
946 default: /* loop_count >= 4 */
947 *max_entries = 4096;
948 *buf_size = 131071;
949 break;
954 static bool test_samr_users(struct torture_context *tctx,
955 struct dcerpc_pipe *p,
956 uint32_t access_mask,
957 struct policy_handle *domain_handle)
959 NTSTATUS status;
962 struct samr_QueryDisplayInfo r;
963 uint32_t total_size;
964 uint32_t returned_size;
965 union samr_DispInfo info;
966 int loop_count = 0;
968 r.in.domain_handle = domain_handle;
969 r.in.level = 1;
970 r.in.start_idx = 0;
972 r.out.total_size = &total_size;
973 r.out.returned_size = &returned_size;
974 r.out.info = &info;
976 do {
977 int i;
979 r.in.max_entries = 0xffff;
980 r.in.buf_size = 0xffff;
982 get_query_dispinfo_params(loop_count,
983 &r.in.max_entries,
984 &r.in.buf_size);
986 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
987 if (NT_STATUS_IS_ERR(status)) {
988 torture_assert_ntstatus_ok(tctx, status,
989 "failed to call QueryDisplayInfo");
992 for (i=0; i < info.info1.count; i++) {
993 torture_assert(tctx,
994 test_user(tctx, p, domain_handle, access_mask, &info.info1.entries[i]),
995 "failed to test user");
997 loop_count++;
998 r.in.start_idx += info.info1.count;
1000 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1003 return true;
1006 static bool test_samr_groups(struct torture_context *tctx,
1007 struct dcerpc_pipe *p,
1008 uint32_t access_mask,
1009 struct policy_handle *domain_handle)
1011 NTSTATUS status;
1014 struct samr_EnumDomainGroups r;
1015 uint32_t resume_handle = 0;
1016 struct samr_SamArray *sam;
1017 uint32_t num_entries;
1019 r.in.domain_handle = domain_handle;
1020 r.in.resume_handle = &resume_handle;
1021 r.in.max_size = 0xFFFF;
1023 r.out.sam = &sam;
1024 r.out.num_entries = &num_entries;
1025 r.out.resume_handle = &resume_handle;
1027 do {
1028 int i;
1030 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
1031 if (NT_STATUS_IS_ERR(status)) {
1032 torture_assert_ntstatus_ok(tctx, status,
1033 "failed to call EnumDomainGroups");
1036 for (i=0; i < num_entries; i++) {
1037 torture_assert(tctx,
1038 test_samr_group(tctx, p, domain_handle, access_mask, &sam->entries[i]),
1039 "failed to test group");
1042 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1045 return true;
1048 static bool test_samr_aliases(struct torture_context *tctx,
1049 struct dcerpc_pipe *p,
1050 uint32_t access_mask,
1051 struct policy_handle *domain_handle)
1053 NTSTATUS status;
1056 struct samr_EnumDomainAliases r;
1057 uint32_t resume_handle = 0;
1058 struct samr_SamArray *sam;
1059 uint32_t num_entries;
1061 r.in.domain_handle = domain_handle;
1062 r.in.resume_handle = &resume_handle;
1063 r.in.max_size = 0xFFFF;
1065 r.out.sam = &sam;
1066 r.out.num_entries = &num_entries;
1067 r.out.resume_handle = &resume_handle;
1069 do {
1070 int i;
1072 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
1073 if (NT_STATUS_IS_ERR(status)) {
1074 torture_assert_ntstatus_ok(tctx, status,
1075 "failed to call EnumDomainAliases");
1078 for (i=0; i < num_entries; i++) {
1079 torture_assert(tctx,
1080 test_samr_alias(tctx, p, domain_handle, &sam->entries[i]),
1081 "failed to test alias");
1084 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
1087 return true;
1090 static bool torture_rpc_samr_workstation_query(struct torture_context *tctx,
1091 struct dcerpc_pipe *p,
1092 struct cli_credentials *machine_credentials)
1094 struct policy_handle connect_handle;
1095 struct policy_handle domain_handle;
1097 torture_assert_ntstatus_ok(tctx,
1098 torture_samr_Connect5(tctx, p, SEC_FLAG_MAXIMUM_ALLOWED,
1099 &connect_handle),
1100 "failed to connect to samr server");
1102 torture_assert(tctx,
1103 test_samr_domain(tctx, p, SEC_FLAG_MAXIMUM_ALLOWED,
1104 lp_workgroup(tctx->lp_ctx),
1105 &connect_handle, &domain_handle),
1106 "failed to test domain");
1108 torture_assert(tctx,
1109 test_samr_users(tctx, p, SEC_FLAG_MAXIMUM_ALLOWED,
1110 &domain_handle),
1111 "failed to test users");
1113 torture_assert(tctx,
1114 test_samr_groups(tctx, p, SEC_FLAG_MAXIMUM_ALLOWED,
1115 &domain_handle),
1116 "failed to test groups");
1118 torture_assert(tctx,
1119 test_samr_aliases(tctx, p, SEC_FLAG_MAXIMUM_ALLOWED,
1120 &domain_handle),
1121 "failed to test aliases");
1123 torture_assert_ntstatus_ok(tctx,
1124 torture_samr_Close(tctx, p, &domain_handle),
1125 "failed to close domain handle");
1127 torture_assert_ntstatus_ok(tctx,
1128 torture_samr_Close(tctx, p, &connect_handle),
1129 "failed to close connect handle");
1131 return true;
1134 /* The purpose of this test is to verify that an account authenticated as a
1135 * domain member workstation can query a DC for various remote read calls all
1136 * opening objects while requesting SEC_FLAG_MAXIMUM_ALLOWED access rights on
1137 * the object open calls. This is the behavior of winbind (and most of samba's
1138 * client code) - gd */
1140 struct torture_suite *torture_rpc_samr_workstation_auth(TALLOC_CTX *mem_ctx)
1142 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-MACHINE-AUTH");
1143 struct torture_rpc_tcase *tcase;
1145 tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "samr",
1146 &ndr_table_samr,
1147 TEST_MACHINENAME);
1149 torture_rpc_tcase_add_test_creds(tcase, "workstation_query",
1150 torture_rpc_samr_workstation_query);
1152 return suite;