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/>.
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/torture.h"
28 #include "torture/rpc/rpc.h"
29 #include "torture/libnet/usertest.h"
30 #include "param/param.h"
33 static bool test_cleanup(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
34 struct policy_handle
*domain_handle
, const char *username
)
37 struct samr_LookupNames r1
;
38 struct samr_OpenUser r2
;
39 struct samr_DeleteUser r3
;
40 struct lsa_String names
[2];
42 struct policy_handle user_handle
;
43 struct samr_Ids rids
, types
;
45 names
[0].string
= username
;
47 r1
.in
.domain_handle
= domain_handle
;
51 r1
.out
.types
= &types
;
53 printf("user account lookup '%s'\n", username
);
55 status
= dcerpc_samr_LookupNames(p
, mem_ctx
, &r1
);
56 if (!NT_STATUS_IS_OK(status
)) {
57 printf("LookupNames failed - %s\n", nt_errstr(status
));
61 rid
= r1
.out
.rids
->ids
[0];
63 r2
.in
.domain_handle
= domain_handle
;
64 r2
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
66 r2
.out
.user_handle
= &user_handle
;
68 printf("opening user account\n");
70 status
= dcerpc_samr_OpenUser(p
, mem_ctx
, &r2
);
71 if (!NT_STATUS_IS_OK(status
)) {
72 printf("OpenUser failed - %s\n", nt_errstr(status
));
76 r3
.in
.user_handle
= &user_handle
;
77 r3
.out
.user_handle
= &user_handle
;
79 printf("deleting user account\n");
81 status
= dcerpc_samr_DeleteUser(p
, mem_ctx
, &r3
);
82 if (!NT_STATUS_IS_OK(status
)) {
83 printf("DeleteUser failed - %s\n", nt_errstr(status
));
91 static bool test_opendomain(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
92 struct policy_handle
*handle
, struct lsa_String
*domname
)
95 struct policy_handle h
, domain_handle
;
96 struct samr_Connect r1
;
97 struct samr_LookupDomain r2
;
98 struct dom_sid2
*sid
= NULL
;
99 struct samr_OpenDomain r3
;
101 printf("connecting\n");
103 r1
.in
.system_name
= 0;
104 r1
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
105 r1
.out
.connect_handle
= &h
;
107 status
= dcerpc_samr_Connect(p
, mem_ctx
, &r1
);
108 if (!NT_STATUS_IS_OK(status
)) {
109 printf("Connect failed - %s\n", nt_errstr(status
));
113 r2
.in
.connect_handle
= &h
;
114 r2
.in
.domain_name
= domname
;
117 printf("domain lookup on %s\n", domname
->string
);
119 status
= dcerpc_samr_LookupDomain(p
, mem_ctx
, &r2
);
120 if (!NT_STATUS_IS_OK(status
)) {
121 printf("LookupDomain failed - %s\n", nt_errstr(status
));
125 r3
.in
.connect_handle
= &h
;
126 r3
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
127 r3
.in
.sid
= *r2
.out
.sid
;
128 r3
.out
.domain_handle
= &domain_handle
;
130 printf("opening domain\n");
132 status
= dcerpc_samr_OpenDomain(p
, mem_ctx
, &r3
);
133 if (!NT_STATUS_IS_OK(status
)) {
134 printf("OpenDomain failed - %s\n", nt_errstr(status
));
137 *handle
= domain_handle
;
144 static bool test_samr_close(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
145 struct policy_handle
*domain_handle
)
150 r
.in
.handle
= domain_handle
;
151 r
.out
.handle
= domain_handle
;
153 status
= dcerpc_samr_Close(p
, mem_ctx
, &r
);
154 if (!NT_STATUS_IS_OK(status
)) {
155 printf("Close samr domain failed - %s\n", nt_errstr(status
));
163 static bool test_lsa_close(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
164 struct policy_handle
*domain_handle
)
169 r
.in
.handle
= domain_handle
;
170 r
.out
.handle
= domain_handle
;
172 status
= dcerpc_lsa_Close(p
, mem_ctx
, &r
);
173 if (!NT_STATUS_IS_OK(status
)) {
174 printf("Close lsa domain failed - %s\n", nt_errstr(status
));
182 static bool test_createuser(struct dcerpc_pipe
*p
, TALLOC_CTX
*mem_ctx
,
183 struct policy_handle
*handle
, const char* user
)
186 struct policy_handle user_handle
;
187 struct lsa_String username
;
188 struct samr_CreateUser r1
;
189 struct samr_Close r2
;
192 username
.string
= user
;
194 r1
.in
.domain_handle
= handle
;
195 r1
.in
.account_name
= &username
;
196 r1
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
197 r1
.out
.user_handle
= &user_handle
;
198 r1
.out
.rid
= &user_rid
;
200 printf("creating user '%s'\n", username
.string
);
202 status
= dcerpc_samr_CreateUser(p
, mem_ctx
, &r1
);
203 if (!NT_STATUS_IS_OK(status
)) {
204 printf("CreateUser failed - %s\n", nt_errstr(status
));
206 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_EXISTS
)) {
207 printf("User (%s) already exists - attempting to delete and recreate account again\n", user
);
208 if (!test_cleanup(p
, mem_ctx
, handle
, TEST_USERNAME
)) {
212 printf("creating user account\n");
214 status
= dcerpc_samr_CreateUser(p
, mem_ctx
, &r1
);
215 if (!NT_STATUS_IS_OK(status
)) {
216 printf("CreateUser failed - %s\n", nt_errstr(status
));
224 r2
.in
.handle
= &user_handle
;
225 r2
.out
.handle
= &user_handle
;
227 printf("closing user '%s'\n", username
.string
);
229 status
= dcerpc_samr_Close(p
, mem_ctx
, &r2
);
230 if (!NT_STATUS_IS_OK(status
)) {
231 printf("Close failed - %s\n", nt_errstr(status
));
239 bool torture_createuser(struct torture_context
*torture
)
243 struct libnet_context
*ctx
;
244 struct libnet_CreateUser req
;
247 mem_ctx
= talloc_init("test_createuser");
249 ctx
= libnet_context_init(torture
->ev
, torture
->lp_ctx
);
250 ctx
->cred
= cmdline_credentials
;
252 req
.in
.user_name
= TEST_USERNAME
;
253 req
.in
.domain_name
= lp_workgroup(torture
->lp_ctx
);
254 req
.out
.error_string
= NULL
;
256 status
= libnet_CreateUser(ctx
, mem_ctx
, &req
);
257 if (!NT_STATUS_IS_OK(status
)) {
258 printf("libnet_CreateUser call failed: %s\n", nt_errstr(status
));
263 if (!test_cleanup(ctx
->samr
.pipe
, mem_ctx
, &ctx
->samr
.handle
, TEST_USERNAME
)) {
264 printf("cleanup failed\n");
269 if (!test_samr_close(ctx
->samr
.pipe
, mem_ctx
, &ctx
->samr
.handle
)) {
270 printf("domain close failed\n");
276 talloc_free(mem_ctx
);
281 bool torture_deleteuser(struct torture_context
*torture
)
284 struct dcerpc_pipe
*p
;
285 TALLOC_CTX
*prep_mem_ctx
, *mem_ctx
;
286 struct policy_handle h
;
287 struct lsa_String domain_name
;
288 const char *name
= TEST_USERNAME
;
289 struct libnet_context
*ctx
;
290 struct libnet_DeleteUser req
;
293 prep_mem_ctx
= talloc_init("prepare test_deleteuser");
295 ctx
= libnet_context_init(torture
->ev
, torture
->lp_ctx
);
296 ctx
->cred
= cmdline_credentials
;
298 req
.in
.user_name
= TEST_USERNAME
;
299 req
.in
.domain_name
= lp_workgroup(torture
->lp_ctx
);
301 status
= torture_rpc_connection(torture
,
304 if (!NT_STATUS_IS_OK(status
)) {
309 domain_name
.string
= lp_workgroup(torture
->lp_ctx
);
310 if (!test_opendomain(p
, prep_mem_ctx
, &h
, &domain_name
)) {
315 if (!test_createuser(p
, prep_mem_ctx
, &h
, name
)) {
320 mem_ctx
= talloc_init("test_deleteuser");
322 status
= libnet_DeleteUser(ctx
, mem_ctx
, &req
);
323 if (!NT_STATUS_IS_OK(status
)) {
324 printf("libnet_DeleteUser call failed: %s\n", nt_errstr(status
));
328 talloc_free(mem_ctx
);
332 talloc_free(prep_mem_ctx
);
338 Generate testing set of random changes
341 static void set_test_changes(TALLOC_CTX
*mem_ctx
, struct libnet_ModifyUser
*r
,
342 int num_changes
, char **user_name
, enum test_fields req_change
)
344 const char* logon_scripts
[] = { "start_login.cmd", "login.bat", "start.cmd" };
345 const char* home_dirs
[] = { "\\\\srv\\home", "\\\\homesrv\\home\\user", "\\\\pdcsrv\\domain" };
346 const char* home_drives
[] = { "H:", "z:", "I:", "J:", "n:" };
347 const uint32_t flags
[] = { (ACB_DISABLED
| ACB_NORMAL
| ACB_PW_EXPIRED
),
348 (ACB_NORMAL
| ACB_PWNOEXP
),
349 (ACB_NORMAL
| ACB_PW_EXPIRED
) };
350 const char *homedir
, *homedrive
, *logonscript
;
354 printf("Fields to change: [");
356 for (i
= 0; i
< num_changes
&& i
< FIELDS_NUM
; i
++) {
359 testfld
= (req_change
== none
) ? (random() % FIELDS_NUM
) : req_change
;
361 /* get one in case we hit time field this time */
362 gettimeofday(&now
, NULL
);
366 continue_if_field_set(r
->in
.account_name
);
367 r
->in
.account_name
= talloc_asprintf(mem_ctx
, TEST_CHG_ACCOUNTNAME
,
368 (int)(random() % 100));
369 fldname
= "account_name";
371 /* update the test's user name in case it's about to change */
372 *user_name
= talloc_strdup(mem_ctx
, r
->in
.account_name
);
376 continue_if_field_set(r
->in
.full_name
);
377 r
->in
.full_name
= talloc_asprintf(mem_ctx
, TEST_CHG_FULLNAME
,
378 (unsigned int)random(), (unsigned int)random());
379 fldname
= "full_name";
383 continue_if_field_set(r
->in
.description
);
384 r
->in
.description
= talloc_asprintf(mem_ctx
, TEST_CHG_DESCRIPTION
,
386 fldname
= "description";
390 continue_if_field_set(r
->in
.home_directory
);
391 homedir
= home_dirs
[random() % ARRAY_SIZE(home_dirs
)];
392 r
->in
.home_directory
= talloc_strdup(mem_ctx
, homedir
);
393 fldname
= "home_dir";
397 continue_if_field_set(r
->in
.home_drive
);
398 homedrive
= home_drives
[random() % ARRAY_SIZE(home_drives
)];
399 r
->in
.home_drive
= talloc_strdup(mem_ctx
, homedrive
);
400 fldname
= "home_drive";
404 continue_if_field_set(r
->in
.comment
);
405 r
->in
.comment
= talloc_asprintf(mem_ctx
, TEST_CHG_COMMENT
,
406 (unsigned long)random(), (unsigned long)random());
411 continue_if_field_set(r
->in
.logon_script
);
412 logonscript
= logon_scripts
[random() % ARRAY_SIZE(logon_scripts
)];
413 r
->in
.logon_script
= talloc_strdup(mem_ctx
, logonscript
);
414 fldname
= "logon_script";
418 continue_if_field_set(r
->in
.profile_path
);
419 r
->in
.profile_path
= talloc_asprintf(mem_ctx
, TEST_CHG_PROFILEPATH
,
420 (unsigned long)random(), (unsigned int)random());
421 fldname
= "profile_path";
425 continue_if_field_set(r
->in
.acct_expiry
);
426 now
= timeval_add(&now
, (random() % (31*24*60*60)), 0);
427 r
->in
.acct_expiry
= (struct timeval
*)talloc_memdup(mem_ctx
, &now
, sizeof(now
));
428 fldname
= "acct_expiry";
432 continue_if_field_set(r
->in
.acct_flags
);
433 r
->in
.acct_flags
= flags
[random() % ARRAY_SIZE(flags
)];
434 fldname
= "acct_flags";
438 fldname
= "unknown_field";
441 printf(((i
< num_changes
- 1) ? "%s," : "%s"), fldname
);
443 /* disable requested field (it's supposed to be the only one used) */
444 if (req_change
!= none
) req_change
= none
;
451 #define TEST_STR_FLD(fld) \
452 if (!strequal(req.in.fld, user_req.out.fld)) { \
453 printf("failed to change '%s'\n", #fld); \
458 #define TEST_TIME_FLD(fld) \
459 if (timeval_compare(req.in.fld, user_req.out.fld)) { \
460 printf("failed to change '%s'\n", #fld); \
465 #define TEST_NUM_FLD(fld) \
466 if (req.in.fld != user_req.out.fld) { \
467 printf("failed to change '%s'\n", #fld); \
473 bool torture_modifyuser(struct torture_context
*torture
)
476 struct dcerpc_binding
*binding
;
477 struct dcerpc_pipe
*p
;
478 TALLOC_CTX
*prep_mem_ctx
;
479 struct policy_handle h
;
480 struct lsa_String domain_name
;
482 struct libnet_context
*ctx
;
483 struct libnet_ModifyUser req
;
484 struct libnet_UserInfo user_req
;
488 prep_mem_ctx
= talloc_init("prepare test_deleteuser");
490 ctx
= libnet_context_init(torture
->ev
, torture
->lp_ctx
);
491 ctx
->cred
= cmdline_credentials
;
493 status
= torture_rpc_connection(torture
,
496 if (!NT_STATUS_IS_OK(status
)) {
501 name
= talloc_strdup(prep_mem_ctx
, TEST_USERNAME
);
503 domain_name
.string
= lp_workgroup(torture
->lp_ctx
);
504 if (!test_opendomain(p
, prep_mem_ctx
, &h
, &domain_name
)) {
509 if (!test_createuser(p
, prep_mem_ctx
, &h
, name
)) {
514 status
= torture_rpc_binding(torture
, &binding
);
515 if (!NT_STATUS_IS_OK(status
)) {
520 printf("Testing change of all fields - each single one in turn\n");
522 for (fld
= 1; fld
< FIELDS_NUM
- 1; fld
++) {
524 req
.in
.domain_name
= lp_workgroup(torture
->lp_ctx
);
525 req
.in
.user_name
= name
;
527 set_test_changes(torture
, &req
, 1, &name
, fld
);
529 status
= libnet_ModifyUser(ctx
, torture
, &req
);
530 if (!NT_STATUS_IS_OK(status
)) {
531 printf("libnet_ModifyUser call failed: %s\n", nt_errstr(status
));
536 ZERO_STRUCT(user_req
);
537 user_req
.in
.domain_name
= lp_workgroup(torture
->lp_ctx
);
538 user_req
.in
.data
.user_name
= name
;
539 user_req
.in
.level
= USER_INFO_BY_NAME
;
541 status
= libnet_UserInfo(ctx
, torture
, &user_req
);
542 if (!NT_STATUS_IS_OK(status
)) {
543 printf("libnet_UserInfo call failed: %s\n", nt_errstr(status
));
549 case account_name
: TEST_STR_FLD(account_name
);
551 case full_name
: TEST_STR_FLD(full_name
);
553 case comment
: TEST_STR_FLD(comment
);
555 case description
: TEST_STR_FLD(description
);
557 case home_directory
: TEST_STR_FLD(home_directory
);
559 case home_drive
: TEST_STR_FLD(home_drive
);
561 case logon_script
: TEST_STR_FLD(logon_script
);
563 case profile_path
: TEST_STR_FLD(profile_path
);
565 case acct_expiry
: TEST_TIME_FLD(acct_expiry
);
567 case acct_flags
: TEST_NUM_FLD(acct_flags
);
573 if (fld
== account_name
) {
574 /* restore original testing username - it's useful when test fails
575 because it prevents from problems with recreating account */
577 req
.in
.domain_name
= lp_workgroup(torture
->lp_ctx
);
578 req
.in
.user_name
= name
;
579 req
.in
.account_name
= TEST_USERNAME
;
581 status
= libnet_ModifyUser(ctx
, torture
, &req
);
582 if (!NT_STATUS_IS_OK(status
)) {
583 printf("libnet_ModifyUser call failed: %s\n", nt_errstr(status
));
588 name
= talloc_strdup(torture
, TEST_USERNAME
);
593 if (!test_cleanup(ctx
->samr
.pipe
, torture
, &ctx
->samr
.handle
, name
)) {
594 printf("cleanup failed\n");
599 if (!test_samr_close(ctx
->samr
.pipe
, torture
, &ctx
->samr
.handle
)) {
600 printf("domain close failed\n");
606 talloc_free(prep_mem_ctx
);
611 bool torture_userinfo_api(struct torture_context
*torture
)
613 const char *name
= TEST_USERNAME
;
616 TALLOC_CTX
*mem_ctx
= NULL
, *prep_mem_ctx
;
617 struct libnet_context
*ctx
;
618 struct dcerpc_pipe
*p
;
619 struct policy_handle h
;
620 struct lsa_String domain_name
;
621 struct libnet_UserInfo req
;
623 prep_mem_ctx
= talloc_init("prepare torture user info");
625 ctx
= libnet_context_init(torture
->ev
, torture
->lp_ctx
);
626 ctx
->cred
= cmdline_credentials
;
628 status
= torture_rpc_connection(torture
,
631 if (!NT_STATUS_IS_OK(status
)) {
635 domain_name
.string
= lp_workgroup(torture
->lp_ctx
);
636 if (!test_opendomain(p
, prep_mem_ctx
, &h
, &domain_name
)) {
641 if (!test_createuser(p
, prep_mem_ctx
, &h
, name
)) {
646 mem_ctx
= talloc_init("torture user info");
650 req
.in
.domain_name
= domain_name
.string
;
651 req
.in
.data
.user_name
= name
;
652 req
.in
.level
= USER_INFO_BY_NAME
;
654 status
= libnet_UserInfo(ctx
, mem_ctx
, &req
);
655 if (!NT_STATUS_IS_OK(status
)) {
656 printf("libnet_UserInfo call failed: %s\n", nt_errstr(status
));
658 talloc_free(mem_ctx
);
662 if (!test_cleanup(ctx
->samr
.pipe
, mem_ctx
, &ctx
->samr
.handle
, TEST_USERNAME
)) {
663 printf("cleanup failed\n");
668 if (!test_samr_close(ctx
->samr
.pipe
, mem_ctx
, &ctx
->samr
.handle
)) {
669 printf("domain close failed\n");
676 talloc_free(mem_ctx
);
681 bool torture_userlist(struct torture_context
*torture
)
685 TALLOC_CTX
*mem_ctx
= NULL
;
686 struct libnet_context
*ctx
;
687 struct lsa_String domain_name
;
688 struct libnet_UserList req
;
691 ctx
= libnet_context_init(torture
->ev
, torture
->lp_ctx
);
692 ctx
->cred
= cmdline_credentials
;
694 domain_name
.string
= lp_workgroup(torture
->lp_ctx
);
695 mem_ctx
= talloc_init("torture user list");
699 printf("listing user accounts:\n");
703 req
.in
.domain_name
= domain_name
.string
;
704 req
.in
.page_size
= 128;
705 req
.in
.resume_index
= req
.out
.resume_index
;
707 status
= libnet_UserList(ctx
, mem_ctx
, &req
);
708 if (!NT_STATUS_IS_OK(status
) &&
709 !NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) break;
711 for (i
= 0; i
< req
.out
.count
; i
++) {
712 printf("\tuser: %s, sid=%s\n",
713 req
.out
.users
[i
].username
, req
.out
.users
[i
].sid
);
716 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
718 if (!(NT_STATUS_IS_OK(status
) ||
719 NT_STATUS_EQUAL(status
, NT_STATUS_NO_MORE_ENTRIES
))) {
720 printf("libnet_UserList call failed: %s\n", nt_errstr(status
));
725 if (!test_samr_close(ctx
->samr
.pipe
, mem_ctx
, &ctx
->samr
.handle
)) {
726 printf("samr domain close failed\n");
731 if (!test_lsa_close(ctx
->lsa
.pipe
, mem_ctx
, &ctx
->lsa
.handle
)) {
732 printf("lsa domain close failed\n");
739 talloc_free(mem_ctx
);