ECLIPSE + PyDev Project
[Samba/kamenim.git] / source4 / torture / libnet / libnet_user.c
blob3bb962c2fadfde96e888b44cb3443ecc204c6b29
1 /*
2 Unix SMB/CIFS implementation.
3 Test suite for libnet calls.
5 Copyright (C) Rafal Szczesniak 2005
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.
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.
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/>.
21 #include "includes.h"
22 #include "system/time.h"
23 #include "lib/cmdline/popt_common.h"
24 #include "libnet/libnet.h"
25 #include "librpc/gen_ndr/ndr_samr_c.h"
26 #include "librpc/gen_ndr/ndr_lsa_c.h"
27 #include "torture/rpc/rpc.h"
28 #include "torture/libnet/usertest.h"
29 #include "param/param.h"
32 static bool test_cleanup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
33 struct policy_handle *domain_handle, const char *username)
35 NTSTATUS status;
36 struct samr_LookupNames r1;
37 struct samr_OpenUser r2;
38 struct samr_DeleteUser r3;
39 struct lsa_String names[2];
40 uint32_t rid;
41 struct policy_handle user_handle;
42 struct samr_Ids rids, types;
44 names[0].string = username;
46 r1.in.domain_handle = domain_handle;
47 r1.in.num_names = 1;
48 r1.in.names = names;
49 r1.out.rids = &rids;
50 r1.out.types = &types;
52 printf("user account lookup '%s'\n", username);
54 status = dcerpc_samr_LookupNames(p, mem_ctx, &r1);
55 if (!NT_STATUS_IS_OK(status)) {
56 printf("LookupNames failed - %s\n", nt_errstr(status));
57 return false;
60 rid = r1.out.rids->ids[0];
62 r2.in.domain_handle = domain_handle;
63 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
64 r2.in.rid = rid;
65 r2.out.user_handle = &user_handle;
67 printf("opening user account\n");
69 status = dcerpc_samr_OpenUser(p, mem_ctx, &r2);
70 if (!NT_STATUS_IS_OK(status)) {
71 printf("OpenUser failed - %s\n", nt_errstr(status));
72 return false;
75 r3.in.user_handle = &user_handle;
76 r3.out.user_handle = &user_handle;
78 printf("deleting user account\n");
80 status = dcerpc_samr_DeleteUser(p, mem_ctx, &r3);
81 if (!NT_STATUS_IS_OK(status)) {
82 printf("DeleteUser failed - %s\n", nt_errstr(status));
83 return false;
86 return true;
90 static bool test_opendomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
91 struct policy_handle *handle, struct lsa_String *domname)
93 NTSTATUS status;
94 struct policy_handle h, domain_handle;
95 struct samr_Connect r1;
96 struct samr_LookupDomain r2;
97 struct dom_sid2 *sid = NULL;
98 struct samr_OpenDomain r3;
100 printf("connecting\n");
102 r1.in.system_name = 0;
103 r1.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
104 r1.out.connect_handle = &h;
106 status = dcerpc_samr_Connect(p, mem_ctx, &r1);
107 if (!NT_STATUS_IS_OK(status)) {
108 printf("Connect failed - %s\n", nt_errstr(status));
109 return false;
112 r2.in.connect_handle = &h;
113 r2.in.domain_name = domname;
114 r2.out.sid = &sid;
116 printf("domain lookup on %s\n", domname->string);
118 status = dcerpc_samr_LookupDomain(p, mem_ctx, &r2);
119 if (!NT_STATUS_IS_OK(status)) {
120 printf("LookupDomain failed - %s\n", nt_errstr(status));
121 return false;
124 r3.in.connect_handle = &h;
125 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
126 r3.in.sid = *r2.out.sid;
127 r3.out.domain_handle = &domain_handle;
129 printf("opening domain\n");
131 status = dcerpc_samr_OpenDomain(p, mem_ctx, &r3);
132 if (!NT_STATUS_IS_OK(status)) {
133 printf("OpenDomain failed - %s\n", nt_errstr(status));
134 return false;
135 } else {
136 *handle = domain_handle;
139 return true;
143 static bool test_samr_close(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
144 struct policy_handle *domain_handle)
146 NTSTATUS status;
147 struct samr_Close r;
149 r.in.handle = domain_handle;
150 r.out.handle = domain_handle;
152 status = dcerpc_samr_Close(p, mem_ctx, &r);
153 if (!NT_STATUS_IS_OK(status)) {
154 printf("Close samr domain failed - %s\n", nt_errstr(status));
155 return false;
158 return true;
162 static bool test_lsa_close(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
163 struct policy_handle *domain_handle)
165 NTSTATUS status;
166 struct lsa_Close r;
168 r.in.handle = domain_handle;
169 r.out.handle = domain_handle;
171 status = dcerpc_lsa_Close(p, mem_ctx, &r);
172 if (!NT_STATUS_IS_OK(status)) {
173 printf("Close lsa domain failed - %s\n", nt_errstr(status));
174 return false;
177 return true;
181 static bool test_createuser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
182 struct policy_handle *handle, const char* user)
184 NTSTATUS status;
185 struct policy_handle user_handle;
186 struct lsa_String username;
187 struct samr_CreateUser r1;
188 struct samr_Close r2;
189 uint32_t user_rid;
191 username.string = user;
193 r1.in.domain_handle = handle;
194 r1.in.account_name = &username;
195 r1.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
196 r1.out.user_handle = &user_handle;
197 r1.out.rid = &user_rid;
199 printf("creating user '%s'\n", username.string);
201 status = dcerpc_samr_CreateUser(p, mem_ctx, &r1);
202 if (!NT_STATUS_IS_OK(status)) {
203 printf("CreateUser failed - %s\n", nt_errstr(status));
205 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
206 printf("User (%s) already exists - attempting to delete and recreate account again\n", user);
207 if (!test_cleanup(p, mem_ctx, handle, TEST_USERNAME)) {
208 return false;
211 printf("creating user account\n");
213 status = dcerpc_samr_CreateUser(p, mem_ctx, &r1);
214 if (!NT_STATUS_IS_OK(status)) {
215 printf("CreateUser failed - %s\n", nt_errstr(status));
216 return false;
218 return true;
220 return false;
223 r2.in.handle = &user_handle;
224 r2.out.handle = &user_handle;
226 printf("closing user '%s'\n", username.string);
228 status = dcerpc_samr_Close(p, mem_ctx, &r2);
229 if (!NT_STATUS_IS_OK(status)) {
230 printf("Close failed - %s\n", nt_errstr(status));
231 return false;
234 return true;
238 bool torture_createuser(struct torture_context *torture)
240 NTSTATUS status;
241 TALLOC_CTX *mem_ctx;
242 struct libnet_context *ctx;
243 struct libnet_CreateUser req;
244 bool ret = true;
246 mem_ctx = talloc_init("test_createuser");
248 ctx = libnet_context_init(torture->ev, torture->lp_ctx);
249 ctx->cred = cmdline_credentials;
251 req.in.user_name = TEST_USERNAME;
252 req.in.domain_name = lp_workgroup(torture->lp_ctx);
253 req.out.error_string = NULL;
255 status = libnet_CreateUser(ctx, mem_ctx, &req);
256 if (!NT_STATUS_IS_OK(status)) {
257 printf("libnet_CreateUser call failed: %s\n", nt_errstr(status));
258 ret = false;
259 goto done;
262 if (!test_cleanup(ctx->samr.pipe, mem_ctx, &ctx->samr.handle, TEST_USERNAME)) {
263 printf("cleanup failed\n");
264 ret = false;
265 goto done;
268 if (!test_samr_close(ctx->samr.pipe, mem_ctx, &ctx->samr.handle)) {
269 printf("domain close failed\n");
270 ret = false;
273 done:
274 talloc_free(ctx);
275 talloc_free(mem_ctx);
276 return ret;
280 bool torture_deleteuser(struct torture_context *torture)
282 NTSTATUS status;
283 struct dcerpc_pipe *p;
284 TALLOC_CTX *prep_mem_ctx, *mem_ctx;
285 struct policy_handle h;
286 struct lsa_String domain_name;
287 const char *name = TEST_USERNAME;
288 struct libnet_context *ctx;
289 struct libnet_DeleteUser req;
290 bool ret = true;
292 prep_mem_ctx = talloc_init("prepare test_deleteuser");
294 ctx = libnet_context_init(torture->ev, torture->lp_ctx);
295 ctx->cred = cmdline_credentials;
297 req.in.user_name = TEST_USERNAME;
298 req.in.domain_name = lp_workgroup(torture->lp_ctx);
300 status = torture_rpc_connection(torture,
302 &ndr_table_samr);
303 if (!NT_STATUS_IS_OK(status)) {
304 ret = false;
305 goto done;
308 domain_name.string = lp_workgroup(torture->lp_ctx);
309 if (!test_opendomain(p, prep_mem_ctx, &h, &domain_name)) {
310 ret = false;
311 goto done;
314 if (!test_createuser(p, prep_mem_ctx, &h, name)) {
315 ret = false;
316 goto done;
319 mem_ctx = talloc_init("test_deleteuser");
321 status = libnet_DeleteUser(ctx, mem_ctx, &req);
322 if (!NT_STATUS_IS_OK(status)) {
323 printf("libnet_DeleteUser call failed: %s\n", nt_errstr(status));
324 ret = false;
327 talloc_free(mem_ctx);
329 done:
330 talloc_free(ctx);
331 talloc_free(prep_mem_ctx);
332 return ret;
337 Generate testing set of random changes
340 static void set_test_changes(TALLOC_CTX *mem_ctx, struct libnet_ModifyUser *r,
341 int num_changes, char **user_name, enum test_fields req_change)
343 const char* logon_scripts[] = { "start_login.cmd", "login.bat", "start.cmd" };
344 const char* home_dirs[] = { "\\\\srv\\home", "\\\\homesrv\\home\\user", "\\\\pdcsrv\\domain" };
345 const char* home_drives[] = { "H:", "z:", "I:", "J:", "n:" };
346 const uint32_t flags[] = { (ACB_DISABLED | ACB_NORMAL | ACB_PW_EXPIRED),
347 (ACB_NORMAL | ACB_PWNOEXP),
348 (ACB_NORMAL | ACB_PW_EXPIRED) };
349 const char *homedir, *homedrive, *logonscript;
350 struct timeval now;
351 int i, testfld;
353 printf("Fields to change: [");
355 for (i = 0; i < num_changes && i < FIELDS_NUM; i++) {
356 const char *fldname;
358 testfld = (req_change == none) ? (random() % FIELDS_NUM) : req_change;
360 /* get one in case we hit time field this time */
361 gettimeofday(&now, NULL);
363 switch (testfld) {
364 case account_name:
365 continue_if_field_set(r->in.account_name);
366 r->in.account_name = talloc_asprintf(mem_ctx, TEST_CHG_ACCOUNTNAME,
367 (int)(random() % 100));
368 fldname = "account_name";
370 /* update the test's user name in case it's about to change */
371 *user_name = talloc_strdup(mem_ctx, r->in.account_name);
372 break;
374 case full_name:
375 continue_if_field_set(r->in.full_name);
376 r->in.full_name = talloc_asprintf(mem_ctx, TEST_CHG_FULLNAME,
377 (unsigned int)random(), (unsigned int)random());
378 fldname = "full_name";
379 break;
381 case description:
382 continue_if_field_set(r->in.description);
383 r->in.description = talloc_asprintf(mem_ctx, TEST_CHG_DESCRIPTION,
384 (long)random());
385 fldname = "description";
386 break;
388 case home_directory:
389 continue_if_field_set(r->in.home_directory);
390 homedir = home_dirs[random() % ARRAY_SIZE(home_dirs)];
391 r->in.home_directory = talloc_strdup(mem_ctx, homedir);
392 fldname = "home_dir";
393 break;
395 case home_drive:
396 continue_if_field_set(r->in.home_drive);
397 homedrive = home_drives[random() % ARRAY_SIZE(home_drives)];
398 r->in.home_drive = talloc_strdup(mem_ctx, homedrive);
399 fldname = "home_drive";
400 break;
402 case comment:
403 continue_if_field_set(r->in.comment);
404 r->in.comment = talloc_asprintf(mem_ctx, TEST_CHG_COMMENT,
405 (unsigned long)random(), (unsigned long)random());
406 fldname = "comment";
407 break;
409 case logon_script:
410 continue_if_field_set(r->in.logon_script);
411 logonscript = logon_scripts[random() % ARRAY_SIZE(logon_scripts)];
412 r->in.logon_script = talloc_strdup(mem_ctx, logonscript);
413 fldname = "logon_script";
414 break;
416 case profile_path:
417 continue_if_field_set(r->in.profile_path);
418 r->in.profile_path = talloc_asprintf(mem_ctx, TEST_CHG_PROFILEPATH,
419 (unsigned long)random(), (unsigned int)random());
420 fldname = "profile_path";
421 break;
423 case acct_expiry:
424 continue_if_field_set(r->in.acct_expiry);
425 now = timeval_add(&now, (random() % (31*24*60*60)), 0);
426 r->in.acct_expiry = (struct timeval *)talloc_memdup(mem_ctx, &now, sizeof(now));
427 fldname = "acct_expiry";
428 break;
430 case acct_flags:
431 continue_if_field_set(r->in.acct_flags);
432 r->in.acct_flags = flags[random() % ARRAY_SIZE(flags)];
433 fldname = "acct_flags";
434 break;
436 default:
437 fldname = "unknown_field";
440 printf(((i < num_changes - 1) ? "%s," : "%s"), fldname);
442 /* disable requested field (it's supposed to be the only one used) */
443 if (req_change != none) req_change = none;
446 printf("]\n");
450 #define TEST_STR_FLD(fld) \
451 if (!strequal(req.in.fld, user_req.out.fld)) { \
452 printf("failed to change '%s'\n", #fld); \
453 ret = false; \
454 goto cleanup; \
457 #define TEST_TIME_FLD(fld) \
458 if (timeval_compare(req.in.fld, user_req.out.fld)) { \
459 printf("failed to change '%s'\n", #fld); \
460 ret = false; \
461 goto cleanup; \
464 #define TEST_NUM_FLD(fld) \
465 if (req.in.fld != user_req.out.fld) { \
466 printf("failed to change '%s'\n", #fld); \
467 ret = false; \
468 goto cleanup; \
472 bool torture_modifyuser(struct torture_context *torture)
474 NTSTATUS status;
475 struct dcerpc_binding *binding;
476 struct dcerpc_pipe *p;
477 TALLOC_CTX *prep_mem_ctx;
478 struct policy_handle h;
479 struct lsa_String domain_name;
480 char *name;
481 struct libnet_context *ctx;
482 struct libnet_ModifyUser req;
483 struct libnet_UserInfo user_req;
484 int fld;
485 bool ret = true;
487 prep_mem_ctx = talloc_init("prepare test_deleteuser");
489 ctx = libnet_context_init(torture->ev, torture->lp_ctx);
490 ctx->cred = cmdline_credentials;
492 status = torture_rpc_connection(torture,
494 &ndr_table_samr);
495 if (!NT_STATUS_IS_OK(status)) {
496 ret = false;
497 goto done;
500 name = talloc_strdup(prep_mem_ctx, TEST_USERNAME);
502 domain_name.string = lp_workgroup(torture->lp_ctx);
503 if (!test_opendomain(p, prep_mem_ctx, &h, &domain_name)) {
504 ret = false;
505 goto done;
508 if (!test_createuser(p, prep_mem_ctx, &h, name)) {
509 ret = false;
510 goto done;
513 status = torture_rpc_binding(torture, &binding);
514 if (!NT_STATUS_IS_OK(status)) {
515 ret = false;
516 goto done;
519 printf("Testing change of all fields - each single one in turn\n");
521 for (fld = 1; fld < FIELDS_NUM - 1; fld++) {
522 ZERO_STRUCT(req);
523 req.in.domain_name = lp_workgroup(torture->lp_ctx);
524 req.in.user_name = name;
526 set_test_changes(torture, &req, 1, &name, fld);
528 status = libnet_ModifyUser(ctx, torture, &req);
529 if (!NT_STATUS_IS_OK(status)) {
530 printf("libnet_ModifyUser call failed: %s\n", nt_errstr(status));
531 ret = false;
532 continue;
535 ZERO_STRUCT(user_req);
536 user_req.in.domain_name = lp_workgroup(torture->lp_ctx);
537 user_req.in.data.user_name = name;
538 user_req.in.level = USER_INFO_BY_NAME;
540 status = libnet_UserInfo(ctx, torture, &user_req);
541 if (!NT_STATUS_IS_OK(status)) {
542 printf("libnet_UserInfo call failed: %s\n", nt_errstr(status));
543 ret = false;
544 continue;
547 switch (fld) {
548 case account_name: TEST_STR_FLD(account_name);
549 break;
550 case full_name: TEST_STR_FLD(full_name);
551 break;
552 case comment: TEST_STR_FLD(comment);
553 break;
554 case description: TEST_STR_FLD(description);
555 break;
556 case home_directory: TEST_STR_FLD(home_directory);
557 break;
558 case home_drive: TEST_STR_FLD(home_drive);
559 break;
560 case logon_script: TEST_STR_FLD(logon_script);
561 break;
562 case profile_path: TEST_STR_FLD(profile_path);
563 break;
564 case acct_expiry: TEST_TIME_FLD(acct_expiry);
565 break;
566 case acct_flags: TEST_NUM_FLD(acct_flags);
567 break;
568 default:
569 break;
572 if (fld == account_name) {
573 /* restore original testing username - it's useful when test fails
574 because it prevents from problems with recreating account */
575 ZERO_STRUCT(req);
576 req.in.domain_name = lp_workgroup(torture->lp_ctx);
577 req.in.user_name = name;
578 req.in.account_name = TEST_USERNAME;
580 status = libnet_ModifyUser(ctx, torture, &req);
581 if (!NT_STATUS_IS_OK(status)) {
582 printf("libnet_ModifyUser call failed: %s\n", nt_errstr(status));
583 ret = false;
584 goto done;
587 name = talloc_strdup(torture, TEST_USERNAME);
591 cleanup:
592 if (!test_cleanup(ctx->samr.pipe, torture, &ctx->samr.handle, name)) {
593 printf("cleanup failed\n");
594 ret = false;
595 goto done;
598 if (!test_samr_close(ctx->samr.pipe, torture, &ctx->samr.handle)) {
599 printf("domain close failed\n");
600 ret = false;
603 done:
604 talloc_free(ctx);
605 talloc_free(prep_mem_ctx);
606 return ret;
610 bool torture_userinfo_api(struct torture_context *torture)
612 const char *name = TEST_USERNAME;
613 bool ret = true;
614 NTSTATUS status;
615 TALLOC_CTX *mem_ctx = NULL, *prep_mem_ctx;
616 struct libnet_context *ctx;
617 struct dcerpc_pipe *p;
618 struct policy_handle h;
619 struct lsa_String domain_name;
620 struct libnet_UserInfo req;
622 prep_mem_ctx = talloc_init("prepare torture user info");
624 ctx = libnet_context_init(torture->ev, torture->lp_ctx);
625 ctx->cred = cmdline_credentials;
627 status = torture_rpc_connection(torture,
629 &ndr_table_samr);
630 if (!NT_STATUS_IS_OK(status)) {
631 return false;
634 domain_name.string = lp_workgroup(torture->lp_ctx);
635 if (!test_opendomain(p, prep_mem_ctx, &h, &domain_name)) {
636 ret = false;
637 goto done;
640 if (!test_createuser(p, prep_mem_ctx, &h, name)) {
641 ret = false;
642 goto done;
645 mem_ctx = talloc_init("torture user info");
647 ZERO_STRUCT(req);
649 req.in.domain_name = domain_name.string;
650 req.in.data.user_name = name;
651 req.in.level = USER_INFO_BY_NAME;
653 status = libnet_UserInfo(ctx, mem_ctx, &req);
654 if (!NT_STATUS_IS_OK(status)) {
655 printf("libnet_UserInfo call failed: %s\n", nt_errstr(status));
656 ret = false;
657 talloc_free(mem_ctx);
658 goto done;
661 if (!test_cleanup(ctx->samr.pipe, mem_ctx, &ctx->samr.handle, TEST_USERNAME)) {
662 printf("cleanup failed\n");
663 ret = false;
664 goto done;
667 if (!test_samr_close(ctx->samr.pipe, mem_ctx, &ctx->samr.handle)) {
668 printf("domain close failed\n");
669 ret = false;
672 talloc_free(ctx);
674 done:
675 talloc_free(mem_ctx);
676 return ret;
680 bool torture_userlist(struct torture_context *torture)
682 bool ret = true;
683 NTSTATUS status;
684 TALLOC_CTX *mem_ctx = NULL;
685 struct libnet_context *ctx;
686 struct lsa_String domain_name;
687 struct libnet_UserList req;
688 int i;
690 ctx = libnet_context_init(torture->ev, torture->lp_ctx);
691 ctx->cred = cmdline_credentials;
693 domain_name.string = lp_workgroup(torture->lp_ctx);
694 mem_ctx = talloc_init("torture user list");
696 ZERO_STRUCT(req);
698 printf("listing user accounts:\n");
700 do {
702 req.in.domain_name = domain_name.string;
703 req.in.page_size = 128;
704 req.in.resume_index = req.out.resume_index;
706 status = libnet_UserList(ctx, mem_ctx, &req);
707 if (!NT_STATUS_IS_OK(status) &&
708 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) break;
710 for (i = 0; i < req.out.count; i++) {
711 printf("\tuser: %s, sid=%s\n",
712 req.out.users[i].username, req.out.users[i].sid);
715 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
717 if (!(NT_STATUS_IS_OK(status) ||
718 NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES))) {
719 printf("libnet_UserList call failed: %s\n", nt_errstr(status));
720 ret = false;
721 goto done;
724 if (!test_samr_close(ctx->samr.pipe, mem_ctx, &ctx->samr.handle)) {
725 printf("samr domain close failed\n");
726 ret = false;
727 goto done;
730 if (!test_lsa_close(ctx->lsa.pipe, mem_ctx, &ctx->lsa.handle)) {
731 printf("lsa domain close failed\n");
732 ret = false;
735 talloc_free(ctx);
737 done:
738 talloc_free(mem_ctx);
739 return ret;