s4-torture: Add a user creation check.
[samba.git] / source4 / torture / rpc / samr_priv.c
1 /*
2  * Unix SMB/CIFS implementation.
3  * test suite for samr rpc operations
4  *
5  * Copyright (c) 2011      Andreas Schneider
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "includes.h"
22 #include "param/param.h"
23 #include "torture/torture.h"
24 #include "librpc/gen_ndr/ndr_samr_c.h"
25 #include "librpc/rpc/dcerpc_proto.h"
26 #include "libcli/security/security.h"
27 #include "torture/rpc/torture_rpc.h"
28
29 #define TEST_ACCOUNT_NAME "guru"
30
31 struct torture_user {
32         const char *username;
33         const char *password;
34         const char *domain;
35         uint32_t *builtin_memberships;
36         uint32_t num_builtin_memberships;
37         bool admin_rights;
38 };
39
40 struct torture_access_context {
41         struct dcerpc_pipe *pipe;
42         struct torture_user user;
43         struct test_join *join;
44 };
45
46 static void init_lsa_String(struct lsa_String *name, const char *s)
47 {
48         name->string = s;
49 }
50
51 static bool test_samr_queryUserInfo(struct torture_context *tctx,
52                                     struct dcerpc_binding_handle *b,
53                                     struct policy_handle *user_handle)
54 {
55         struct samr_QueryUserInfo r;
56         union samr_UserInfo *info;
57         NTSTATUS status;
58
59         r.in.level = UserGeneralInformation;
60         r.in.user_handle = user_handle;
61         r.out.info = &info;
62
63         status = dcerpc_samr_QueryUserInfo_r(b,
64                                              tctx,
65                                              &r);
66         torture_assert_ntstatus_ok(tctx, status, "queryUserInfo failed");
67         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_OK)) {
68                 torture_comment(tctx, "queryUserInfo failed");
69                 return false;
70         }
71
72         return true;
73 }
74
75 static bool test_LookupName(struct dcerpc_binding_handle *b,
76                             struct torture_context *tctx,
77                             struct policy_handle *domain_handle,
78                             const char *name,
79                             uint32_t *rid)
80 {
81         NTSTATUS status;
82         struct samr_LookupNames n;
83         struct lsa_String sname[1];
84         struct samr_Ids rids, types;
85
86         init_lsa_String(&sname[0], name);
87
88         n.in.domain_handle = domain_handle;
89         n.in.num_names = 1;
90         n.in.names = sname;
91         n.out.rids = &rids;
92         n.out.types = &types;
93
94         status = dcerpc_samr_LookupNames_r(b, tctx, &n);
95         if (!NT_STATUS_IS_OK(status)) {
96                 return false;
97         }
98         if (!NT_STATUS_IS_OK(n.out.result)) {
99                 return false;
100         }
101
102         *rid = n.out.rids->ids[0];
103         return true;
104 }
105
106 static bool test_samr_CreateUser(struct torture_context *tctx,
107                                  struct dcerpc_binding_handle *b,
108                                  struct policy_handle *domain_handle,
109                                  const char *name,
110                                  struct policy_handle *user_handle)
111 {
112         struct lsa_String username;
113         struct samr_CreateUser r;
114         uint32_t rid = 0;
115         NTSTATUS status;
116
117         init_lsa_String(&username, name);
118
119         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
120         r.in.domain_handle = domain_handle;
121         r.in.account_name = &username;
122         r.out.user_handle = user_handle;
123         r.out.rid = &rid;
124
125         status = dcerpc_samr_CreateUser_r(b, tctx, &r);
126         torture_assert_ntstatus_ok(tctx, status, "CreateUser failed");
127         if (!NT_STATUS_IS_OK(r.out.result)) {
128                 torture_comment(tctx, "CreateUser failed");
129                 return false;
130         }
131
132         return true;
133 }
134
135 static bool test_samr_OpenUser(struct torture_context *tctx,
136                                struct dcerpc_binding_handle *b,
137                                struct policy_handle *domain_handle,
138                                const char *name,
139                                struct policy_handle *user_handle,
140                                bool expected)
141 {
142         struct samr_OpenUser r;
143         uint32_t rid = 0;
144         NTSTATUS status;
145         bool ok;
146
147         ok = test_LookupName(b, tctx, domain_handle, name, &rid);
148         if (!ok && expected) {
149                 torture_comment(tctx, " - lookup name for %s failed\n", name);
150                 return true;
151         } else if (!ok) {
152                 return false;
153         }
154
155         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
156         r.in.domain_handle = domain_handle;
157         r.in.rid = rid;
158         r.out.user_handle = user_handle;
159
160         status = dcerpc_samr_OpenUser_r(b, tctx, &r);
161         torture_assert_ntstatus_ok(tctx, status, "CreateUser failed");
162         if (!NT_STATUS_IS_OK(r.out.result)) {
163                 torture_comment(tctx, "CreateUser failed");
164                 return false;
165         }
166
167         return true;
168 }
169
170 static bool test_samr_openDomain(struct torture_context *tctx,
171                                  struct dcerpc_binding_handle *b,
172                                  struct policy_handle *connect_handle,
173                                  const char *domain,
174                                  struct policy_handle *domain_handle)
175 {
176         struct samr_LookupDomain r;
177         struct samr_OpenDomain r2;
178         struct lsa_String n;
179         struct dom_sid *sid;
180         NTSTATUS status;
181
182         r.in.connect_handle = connect_handle;
183         init_lsa_String(&n, domain);
184         r.in.domain_name = &n;
185         r.out.sid = &sid;
186
187         status = dcerpc_samr_LookupDomain_r(b, tctx, &r);
188         torture_assert_ntstatus_ok(tctx, status, "LookupDomain failed");
189         if (!NT_STATUS_IS_OK(r.out.result)) {
190                 torture_comment(tctx, "LookupDomain failed - %s\n", nt_errstr(r.out.result));
191                 return false;
192         }
193
194         r2.in.connect_handle = connect_handle;
195         r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
196         r2.in.sid = sid;
197         r2.out.domain_handle = domain_handle;
198
199         status = dcerpc_samr_OpenDomain_r(b, tctx, &r2);
200         torture_assert_ntstatus_ok(tctx, status, "OpenDomain failed");
201         if (!NT_STATUS_IS_OK(r2.out.result)) {
202                 torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(r.out.result));
203                 return false;
204         }
205
206         return true;
207 }
208
209 static bool test_samr_Connect(struct torture_context *tctx,
210                               struct dcerpc_binding_handle *b,
211                               struct policy_handle *connect_handle)
212 {
213         struct samr_Connect r;
214         NTSTATUS status;
215
216         r.in.system_name = 0;
217         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
218         r.out.connect_handle = connect_handle;
219
220         status = dcerpc_samr_Connect_r(b, tctx, &r);
221         torture_assert_ntstatus_ok(tctx, status, "SAMR connect failed");
222         if (!NT_STATUS_IS_OK(r.out.result)) {
223                 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
224                 return false;
225         }
226
227         return true;
228 }
229
230 static bool test_samr_create_user(struct torture_context *tctx,
231                                   struct torture_access_context *t,
232                                   const char *name)
233 {
234         struct dcerpc_binding_handle *b = t->pipe->binding_handle;
235         struct policy_handle connect_handle;
236         struct policy_handle domain_handle;
237         struct policy_handle user_handle;
238         bool ok = false;
239
240         torture_comment(tctx, "Connecting to SAMR\n");
241         ZERO_STRUCT(connect_handle);
242         ok = test_samr_Connect(tctx, b, &connect_handle);
243         torture_assert(tctx, ok, "Unable to connect to domain");
244
245         torture_comment(tctx, "Opening domain %s\n", t->user.domain);
246         ZERO_STRUCT(domain_handle);
247         ok = test_samr_openDomain(tctx,
248                                   b,
249                                   &connect_handle,
250                                   t->user.domain,
251                                   &domain_handle);
252         torture_assert(tctx, ok, "Unable to open to domain");
253
254         torture_comment(tctx, "Creating account %s\n", name);
255         ZERO_STRUCT(user_handle);
256         ok = test_samr_CreateUser(tctx,
257                                   b,
258                                   &domain_handle,
259                                   name,
260                                   &user_handle);
261
262         test_samr_handle_Close(b, tctx, &domain_handle);
263         test_samr_handle_Close(b, tctx, &connect_handle);
264
265         return ok;
266 }
267
268 static bool test_samr_userinfo_getinfo(struct torture_context *tctx,
269                                        struct dcerpc_pipe *p,
270                                        bool expected)
271 {
272         const char *name;
273         struct dcerpc_pipe *p2 = NULL;
274         struct dcerpc_binding_handle *b;
275         struct policy_handle connect_handle;
276         struct policy_handle domain_handle;
277         struct policy_handle user_handle;
278         NTSTATUS status;
279         uint32_t i = 0;
280         bool ok;
281
282         status = torture_rpc_connection(tctx, &p2, &ndr_table_samr);
283         torture_assert_ntstatus_ok(tctx, status,
284                         "Creating secondary connection failed");
285         b = p2->binding_handle;
286
287         torture_comment(tctx, " - 2nd connect\n");
288         /* connect */
289         ZERO_STRUCT(connect_handle);
290         ok = test_samr_Connect(tctx, b, &connect_handle);
291         torture_assert(tctx, ok, "Unable to connect to domain");
292
293         torture_comment(tctx, " - 2nd open domain\n");
294         /* open domain */
295         ZERO_STRUCT(domain_handle);
296         ok = test_samr_openDomain(tctx,
297                                   b,
298                                   &connect_handle,
299                                   torture_setting_string(tctx, "workgroup",
300                                                          lpcfg_workgroup(tctx->lp_ctx)),
301                                   &domain_handle);
302         torture_assert(tctx, ok, "Unable to open to domain");
303
304         /* create user */
305         name = talloc_asprintf(tctx,
306                                "%s%04d",
307                                TEST_ACCOUNT_NAME,
308                                i);
309
310         torture_comment(tctx, " - 2nd open user\n");
311         ZERO_STRUCT(user_handle);
312         ok = test_samr_OpenUser(tctx,
313                                 b,
314                                 &domain_handle,
315                                 name,
316                                 &user_handle,
317                                 expected);
318         torture_assert(tctx, ok, "Unable to open user");
319
320         if (!expected) {
321                 torture_comment(tctx, " - 2nd query user\n");
322                 ok = test_samr_queryUserInfo(tctx, b, &user_handle);
323                 torture_assert(tctx, ok, "Unable to query user");
324
325                 test_samr_handle_Close(b, tctx, &user_handle);
326         }
327
328         test_samr_handle_Close(b, tctx, &domain_handle);
329         test_samr_handle_Close(b, tctx, &connect_handle);
330
331         talloc_free(p2);
332
333         return true;
334 }
335
336 #define NUM_RUNS 20
337 static bool torture_rpc_samr_caching(struct torture_context *tctx,
338                                      struct dcerpc_pipe *p)
339 {
340         struct test_join *join;
341         const char *password = NULL;
342         const char *name;
343         NTSTATUS status;
344         uint32_t i = 0;
345         bool ok;
346
347         torture_comment(tctx, ">>> Testing User Info Caching\n");
348
349         /* create user */
350         name = talloc_asprintf(tctx,
351                                "%s%04d",
352                                TEST_ACCOUNT_NAME,
353                                i);
354
355         torture_comment(tctx, "- Creating user %s\n", name);
356
357         join = torture_create_testuser(tctx,
358                                        name,
359                                        torture_setting_string(tctx, "workgroup",
360                                                               lpcfg_workgroup(tctx->lp_ctx)),
361                                        ACB_NORMAL,
362                                        &password);
363         if (join == NULL) {
364                 return false;
365         }
366
367         torture_comment(tctx, "- Query user information\n");
368         for (i = 0; i < NUM_RUNS; i++) {
369                 ok = test_samr_userinfo_getinfo(tctx, p, false);
370                 torture_assert(tctx, ok, "test_samr_userinfo_getinfo failed");
371         }
372
373         torture_comment(tctx, "- Delete user\n");
374         status = torture_delete_testuser(tctx,
375                                          join,
376                                          name);
377         if (!NT_STATUS_IS_OK(status)) {
378                 torture_comment(tctx, "DeleteUser failed - %s\n",
379                                       nt_errstr(status));
380                 return false;
381         }
382
383         torture_comment(tctx, "- Try to query user information again (should fail)\n");
384         for (i = 0; i < NUM_RUNS; i++) {
385                 ok = test_samr_userinfo_getinfo(tctx,
386                                                 p,
387                                                 true);
388                 torture_assert(tctx, ok, "test_samr_userinfo_getinfo failed");
389         }
390
391         return true;
392 }
393 #undef NUM_RUNS
394
395 static bool torture_rpc_samr_access_setup_membership(struct torture_context *tctx,
396                                                      struct dcerpc_pipe *p,
397                                                      uint32_t num_members,
398                                                      uint32_t *members,
399                                                      struct dom_sid *user_sid)
400 {
401         struct dcerpc_binding_handle *b = p->binding_handle;
402         struct policy_handle connect_handle, domain_handle;
403         int i;
404
405         torture_comment(tctx,
406                 "Setting up BUILTIN membership for %s\n",
407                 dom_sid_string(tctx, user_sid));
408
409         for (i=0; i < num_members; i++) {
410                 torture_comment(tctx, "adding user to S-1-5-32-%d\n", members[i]);
411         }
412
413         /* connect */
414         {
415                 struct samr_Connect2 r;
416                 r.in.system_name = "";
417                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
418                 ZERO_STRUCT(connect_handle);
419                 r.out.connect_handle = &connect_handle;
420
421                 torture_assert_ntstatus_ok(tctx,
422                         dcerpc_samr_Connect2_r(b, tctx, &r),
423                         "samr_Connect2 failed");
424                 torture_assert_ntstatus_ok(tctx, r.out.result,
425                         "samr_Connect2 failed");
426         }
427
428         /* open domain */
429         {
430                 struct samr_OpenDomain r;
431                 r.in.connect_handle = &connect_handle;
432                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
433                 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32");
434                 ZERO_STRUCT(domain_handle);
435                 r.out.domain_handle = &domain_handle;
436
437                 torture_assert_ntstatus_ok(tctx,
438                         dcerpc_samr_OpenDomain_r(b, tctx, &r),
439                         "samr_OpenDomain failed");
440                 torture_assert_ntstatus_ok(tctx, r.out.result,
441                         "samr_OpenDomain failed");
442         }
443
444         for (i = 0; i < num_members; i++) {
445
446                 struct policy_handle alias_handle;
447
448                 /* open alias */
449                 {
450                         struct samr_OpenAlias r;
451                         r.in.domain_handle = &domain_handle;
452                         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
453                         r.in.rid = members[i];
454                         ZERO_STRUCT(alias_handle);
455                         r.out.alias_handle = &alias_handle;
456
457                         torture_assert_ntstatus_ok(tctx,
458                                         dcerpc_samr_OpenAlias_r(b, tctx, &r),
459                                         "samr_OpenAlias failed");
460                         torture_assert_ntstatus_ok(tctx, r.out.result,
461                                         "samr_OpenAlias failed");
462                 }
463
464                 /* add alias member */
465                 {
466                         struct samr_AddAliasMember r;
467                         ZERO_STRUCT(alias_handle);
468                         r.in.alias_handle = &alias_handle;
469                         r.in.sid = user_sid;
470
471                         torture_assert_ntstatus_ok(tctx,
472                                         dcerpc_samr_AddAliasMember_r(b, tctx, &r),
473                                         "samr_AddAliasMember failed");
474                         torture_assert_ntstatus_ok(tctx, r.out.result,
475                                         "samr_AddAliasMember failed");
476                 }
477
478                 test_samr_handle_Close(b, tctx, &alias_handle);
479         }
480
481         test_samr_handle_Close(b, tctx, &domain_handle);
482         test_samr_handle_Close(b, tctx, &connect_handle);
483
484         return true;
485 }
486
487 static bool torture_rpc_samr_access_setup(struct torture_context *tctx,
488                                           struct dcerpc_pipe *p,
489                                           struct torture_access_context *t)
490 {
491         const char *binding = torture_setting_string(tctx, "binding", NULL);
492         struct cli_credentials *test_credentials;
493         struct test_join *join;
494         struct dom_sid *test_sid;
495         struct dcerpc_pipe *samr_pipe;
496
497         t->user.domain = torture_setting_string(tctx, "workgroup",
498                                                 lpcfg_workgroup(tctx->lp_ctx)),
499
500         join = torture_create_testuser(tctx,
501                                        t->user.username,
502                                        t->user.domain,
503                                        ACB_NORMAL,
504                                        &t->user.password);
505         if (join == NULL) {
506                 return false;
507         }
508         t->join = join;
509
510         test_credentials = cli_credentials_init(tctx);
511
512         cli_credentials_set_workstation(test_credentials,
513                                         "localhost",
514                                         CRED_SPECIFIED);
515         cli_credentials_set_domain(test_credentials,
516                                    torture_setting_string(tctx, "workgroup",
517                                                           lpcfg_workgroup(tctx->lp_ctx)),
518                                    CRED_SPECIFIED);
519         cli_credentials_set_username(test_credentials,
520                                      t->user.username,
521                                      CRED_SPECIFIED);
522         cli_credentials_set_password(test_credentials,
523                                      t->user.password,
524                                      CRED_SPECIFIED);
525         test_sid = discard_const_p(struct dom_sid,
526                                    torture_join_user_sid(t->join));
527
528         if (t->user.num_builtin_memberships) {
529                 torture_assert(tctx,
530                         torture_rpc_samr_access_setup_membership(tctx,
531                                                                  p,
532                                                                  t->user.num_builtin_memberships,
533                                                                  t->user.builtin_memberships,
534                                                                  test_sid),
535                         "failed to setup membership");
536         }
537
538         torture_assert_ntstatus_ok(tctx,
539                 dcerpc_pipe_connect(tctx,
540                                     &samr_pipe,
541                                     binding,
542                                     &ndr_table_samr,
543                                     test_credentials,
544                                     tctx->ev,
545                                     tctx->lp_ctx),
546                 "Error connecting to server");
547
548         t->pipe = samr_pipe;
549
550         return true;
551 }
552
553 static bool torture_rpc_samr_access(struct torture_context *tctx,
554                                     struct dcerpc_pipe *p)
555 {
556         struct torture_access_context *t;
557         const char *testuser;
558         bool ok;
559
560         torture_comment(tctx, "Testing non-privileged user access\n");
561
562         t = talloc_zero(tctx, struct torture_access_context);
563         if (t == NULL) {
564                 return false;
565         }
566
567         t->user.username = talloc_asprintf(t, "%s%04d", TEST_ACCOUNT_NAME, 100);
568
569         torture_comment(tctx, "*** Setting up non-privleged user\n"
570                               "***\n");
571
572         ok = torture_rpc_samr_access_setup(tctx, p, t);
573         if (!ok) {
574                 return false;
575         }
576
577         testuser = talloc_asprintf(t, "%s%04d", TEST_ACCOUNT_NAME, 200);
578
579         torture_comment(tctx, "*** Try to create user (%s) as non-privileged "
580                               "user - should fail\n"
581                               "***\n", testuser);
582
583         ok = test_samr_create_user(tctx, t, testuser);
584         if (!ok) {
585                 torture_comment(tctx, "*** Creating user (%s) failed, which is "
586                                       "correct!\n", testuser);
587                 return true;
588         }
589
590         torture_comment(tctx, "*** Creating user (%s) was successful, but "
591                               "should fail!\n", testuser);
592
593         return false;
594 }
595
596 struct torture_suite *torture_rpc_samr_priv(TALLOC_CTX *mem_ctx)
597 {
598         struct torture_suite *suite =
599                 torture_suite_create(mem_ctx, "samr.priv");
600         struct torture_rpc_tcase *tcase;
601
602         tcase = torture_suite_add_rpc_iface_tcase(suite,
603                                                   "samr",
604                                                   &ndr_table_samr);
605
606         torture_rpc_tcase_add_test(tcase,
607                                    "caching",
608                                    torture_rpc_samr_caching);
609
610         torture_rpc_tcase_add_test(tcase,
611                                    "access",
612                                    torture_rpc_samr_access);
613
614         return suite;
615 }