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/cmdline.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/torture_rpc.h"
28 #include "torture/libnet/usertest.h"
29 #include "torture/libnet/proto.h"
30 #include "param/param.h"
34 bool torture_createuser(struct torture_context
*torture
)
38 struct libnet_context
*ctx
= NULL
;
39 struct libnet_CreateUser req
;
42 mem_ctx
= talloc_init("test_createuser");
44 if (!test_libnet_context_init(torture
, true, &ctx
)) {
48 req
.in
.user_name
= TEST_USERNAME
;
49 req
.in
.domain_name
= lpcfg_workgroup(torture
->lp_ctx
);
50 req
.out
.error_string
= NULL
;
52 status
= libnet_CreateUser(ctx
, mem_ctx
, &req
);
53 if (!NT_STATUS_IS_OK(status
)) {
54 torture_comment(torture
, "libnet_CreateUser call failed: %s\n", nt_errstr(status
));
59 if (!test_user_cleanup(torture
, ctx
->samr
.pipe
->binding_handle
,
60 mem_ctx
, &ctx
->samr
.handle
, TEST_USERNAME
)) {
61 torture_comment(torture
, "cleanup failed\n");
66 if (!test_samr_close_handle(torture
,
67 ctx
->samr
.pipe
->binding_handle
, mem_ctx
, &ctx
->samr
.handle
)) {
68 torture_comment(torture
, "domain close failed\n");
79 bool torture_deleteuser(struct torture_context
*torture
)
82 struct dcerpc_pipe
*p
;
84 struct policy_handle h
;
85 struct lsa_String domain_name
;
86 const char *name
= TEST_USERNAME
;
87 struct libnet_context
*ctx
= NULL
;
88 struct libnet_DeleteUser req
;
91 status
= torture_rpc_connection(torture
,
94 torture_assert_ntstatus_ok(torture
, status
, "torture_rpc_connection() failed");
96 mem_ctx
= talloc_init("torture_deleteuser");
99 * Pre-create a user to be deleted later
101 domain_name
.string
= lpcfg_workgroup(torture
->lp_ctx
);
102 ret
= test_domain_open(torture
, p
->binding_handle
, &domain_name
, mem_ctx
, &h
, NULL
);
103 torture_assert_goto(torture
, ret
, ret
, done
, "test_domain_open() failed");
105 ret
= test_user_create(torture
, p
->binding_handle
, mem_ctx
, &h
, name
, NULL
);
106 torture_assert_goto(torture
, ret
, ret
, done
, "test_user_create() failed");
109 * Delete the user using libnet layer
111 ret
= test_libnet_context_init(torture
, true, &ctx
);
112 torture_assert_goto(torture
, ret
, ret
, done
, "test_libnet_context_init() failed");
114 req
.in
.user_name
= TEST_USERNAME
;
115 req
.in
.domain_name
= lpcfg_workgroup(torture
->lp_ctx
);
117 status
= libnet_DeleteUser(ctx
, mem_ctx
, &req
);
118 torture_assert_ntstatus_ok_goto(torture
, status
, ret
, done
, "libnet_DeleteUser() failed");
120 /* mark test as successful */
125 talloc_free(mem_ctx
);
131 Generate testing set of random changes
134 static void set_test_changes(struct torture_context
*tctx
,
135 TALLOC_CTX
*mem_ctx
, struct libnet_ModifyUser
*r
,
136 int num_changes
, char **user_name
, enum test_fields req_change
)
138 const char* logon_scripts
[] = { "start_login.cmd", "login.bat", "start.cmd" };
139 const char* home_dirs
[] = { "\\\\srv\\home", "\\\\homesrv\\home\\user", "\\\\pdcsrv\\domain" };
140 const char* home_drives
[] = { "H:", "z:", "I:", "J:", "n:" };
141 const uint32_t flags
[] = { (ACB_DISABLED
| ACB_NORMAL
| ACB_PW_EXPIRED
),
142 (ACB_NORMAL
| ACB_PWNOEXP
),
143 (ACB_NORMAL
| ACB_PW_EXPIRED
) };
144 const char *homedir
, *homedrive
, *logonscript
;
148 torture_comment(tctx
, "Fields to change: [");
150 for (i
= 0; i
< num_changes
&& i
<= USER_FIELD_LAST
; i
++) {
153 testfld
= (req_change
== none
) ? (random() % USER_FIELD_LAST
) + 1 : req_change
;
155 /* get one in case we hit time field this time */
156 gettimeofday(&now
, NULL
);
160 continue_if_field_set(r
->in
.account_name
);
161 r
->in
.account_name
= talloc_asprintf(mem_ctx
, TEST_CHG_ACCOUNTNAME
,
162 (int)(random() % 100));
163 fldname
= "account_name";
165 /* update the test's user name in case it's about to change */
166 *user_name
= talloc_strdup(mem_ctx
, r
->in
.account_name
);
170 continue_if_field_set(r
->in
.full_name
);
171 r
->in
.full_name
= talloc_asprintf(mem_ctx
, TEST_CHG_FULLNAME
,
172 (unsigned int)random(), (unsigned int)random());
173 fldname
= "full_name";
176 case acct_description
:
177 continue_if_field_set(r
->in
.description
);
178 r
->in
.description
= talloc_asprintf(mem_ctx
, TEST_CHG_DESCRIPTION
,
180 fldname
= "description";
183 case acct_home_directory
:
184 continue_if_field_set(r
->in
.home_directory
);
185 homedir
= home_dirs
[random() % ARRAY_SIZE(home_dirs
)];
186 r
->in
.home_directory
= talloc_strdup(mem_ctx
, homedir
);
187 fldname
= "home_dir";
190 case acct_home_drive
:
191 continue_if_field_set(r
->in
.home_drive
);
192 homedrive
= home_drives
[random() % ARRAY_SIZE(home_drives
)];
193 r
->in
.home_drive
= talloc_strdup(mem_ctx
, homedrive
);
194 fldname
= "home_drive";
198 continue_if_field_set(r
->in
.comment
);
199 r
->in
.comment
= talloc_asprintf(mem_ctx
, TEST_CHG_COMMENT
,
200 (unsigned long)random(), (unsigned long)random());
204 case acct_logon_script
:
205 continue_if_field_set(r
->in
.logon_script
);
206 logonscript
= logon_scripts
[random() % ARRAY_SIZE(logon_scripts
)];
207 r
->in
.logon_script
= talloc_strdup(mem_ctx
, logonscript
);
208 fldname
= "logon_script";
211 case acct_profile_path
:
212 continue_if_field_set(r
->in
.profile_path
);
213 r
->in
.profile_path
= talloc_asprintf(mem_ctx
, TEST_CHG_PROFILEPATH
,
214 (unsigned long)random(), (unsigned int)random());
215 fldname
= "profile_path";
219 continue_if_field_set(r
->in
.acct_expiry
);
220 now
= timeval_add(&now
, (random() % (31*24*60*60)), 0);
221 r
->in
.acct_expiry
= (struct timeval
*)talloc_memdup(mem_ctx
, &now
, sizeof(now
));
222 fldname
= "acct_expiry";
226 continue_if_field_set(r
->in
.acct_flags
);
227 r
->in
.acct_flags
= flags
[random() % ARRAY_SIZE(flags
)];
228 fldname
= "acct_flags";
232 fldname
= "unknown_field";
235 torture_comment(tctx
, ((i
< num_changes
- 1) ? "%s," : "%s"), fldname
);
237 /* disable requested field (it's supposed to be the only one used) */
238 if (req_change
!= none
) req_change
= none
;
241 torture_comment(tctx
, "]\n");
245 #define TEST_STR_FLD(fld) \
246 if (!strequal(req.in.fld, user_req.out.fld)) { \
247 torture_comment(torture, "failed to change '%s'\n", #fld); \
252 #define TEST_TIME_FLD(fld) \
253 if (timeval_compare(req.in.fld, user_req.out.fld)) { \
254 torture_comment(torture, "failed to change '%s'\n", #fld); \
259 #define TEST_NUM_FLD(fld) \
260 if (req.in.fld != user_req.out.fld) { \
261 torture_comment(torture, "failed to change '%s'\n", #fld); \
267 bool torture_modifyuser(struct torture_context
*torture
)
270 struct dcerpc_pipe
*p
;
271 TALLOC_CTX
*prep_mem_ctx
;
272 struct policy_handle h
;
273 struct lsa_String domain_name
;
275 struct libnet_context
*ctx
= NULL
;
276 struct libnet_ModifyUser req
;
277 struct libnet_UserInfo user_req
;
280 struct dcerpc_binding_handle
*b
;
282 prep_mem_ctx
= talloc_init("prepare test_deleteuser");
284 status
= torture_rpc_connection(torture
,
287 if (!NT_STATUS_IS_OK(status
)) {
291 b
= p
->binding_handle
;
293 name
= talloc_strdup(prep_mem_ctx
, TEST_USERNAME
);
295 domain_name
.string
= lpcfg_workgroup(torture
->lp_ctx
);
296 if (!test_domain_open(torture
, b
, &domain_name
, prep_mem_ctx
, &h
, NULL
)) {
301 if (!test_user_create(torture
, b
, prep_mem_ctx
, &h
, name
, NULL
)) {
306 torture_comment(torture
, "Testing change of all fields - each single one in turn\n");
308 if (!test_libnet_context_init(torture
, true, &ctx
)) {
312 for (fld
= USER_FIELD_FIRST
; fld
<= USER_FIELD_LAST
; fld
++) {
314 req
.in
.domain_name
= lpcfg_workgroup(torture
->lp_ctx
);
315 req
.in
.user_name
= name
;
317 set_test_changes(torture
, torture
, &req
, 1, &name
, fld
);
319 status
= libnet_ModifyUser(ctx
, torture
, &req
);
320 if (!NT_STATUS_IS_OK(status
)) {
321 torture_comment(torture
, "libnet_ModifyUser call failed: %s\n", nt_errstr(status
));
326 ZERO_STRUCT(user_req
);
327 user_req
.in
.domain_name
= lpcfg_workgroup(torture
->lp_ctx
);
328 user_req
.in
.data
.user_name
= name
;
329 user_req
.in
.level
= USER_INFO_BY_NAME
;
331 status
= libnet_UserInfo(ctx
, torture
, &user_req
);
332 if (!NT_STATUS_IS_OK(status
)) {
333 torture_comment(torture
, "libnet_UserInfo call failed: %s\n", nt_errstr(status
));
339 case acct_name
: TEST_STR_FLD(account_name
);
341 case acct_full_name
: TEST_STR_FLD(full_name
);
343 case acct_comment
: TEST_STR_FLD(comment
);
345 case acct_description
: TEST_STR_FLD(description
);
347 case acct_home_directory
: TEST_STR_FLD(home_directory
);
349 case acct_home_drive
: TEST_STR_FLD(home_drive
);
351 case acct_logon_script
: TEST_STR_FLD(logon_script
);
353 case acct_profile_path
: TEST_STR_FLD(profile_path
);
355 case acct_expiry
: TEST_TIME_FLD(acct_expiry
);
357 case acct_flags
: TEST_NUM_FLD(acct_flags
);
365 if (!test_user_cleanup(torture
, ctx
->samr
.pipe
->binding_handle
,
366 torture
, &ctx
->samr
.handle
, TEST_USERNAME
)) {
367 torture_comment(torture
, "cleanup failed\n");
372 if (!test_samr_close_handle(torture
,
373 ctx
->samr
.pipe
->binding_handle
, torture
, &ctx
->samr
.handle
)) {
374 torture_comment(torture
, "domain close failed\n");
380 talloc_free(prep_mem_ctx
);
385 bool torture_userinfo_api(struct torture_context
*torture
)
387 const char *name
= TEST_USERNAME
;
390 TALLOC_CTX
*mem_ctx
= NULL
, *prep_mem_ctx
;
391 struct libnet_context
*ctx
= NULL
;
392 struct dcerpc_pipe
*p
;
393 struct policy_handle h
;
394 struct lsa_String domain_name
;
395 struct libnet_UserInfo req
;
396 struct dcerpc_binding_handle
*b
;
398 prep_mem_ctx
= talloc_init("prepare torture user info");
400 status
= torture_rpc_connection(torture
,
403 if (!NT_STATUS_IS_OK(status
)) {
406 b
= p
->binding_handle
;
408 domain_name
.string
= lpcfg_workgroup(torture
->lp_ctx
);
409 if (!test_domain_open(torture
, b
, &domain_name
, prep_mem_ctx
, &h
, NULL
)) {
414 if (!test_user_create(torture
, b
, prep_mem_ctx
, &h
, name
, NULL
)) {
419 mem_ctx
= talloc_init("torture user info");
421 if (!test_libnet_context_init(torture
, true, &ctx
)) {
427 req
.in
.domain_name
= domain_name
.string
;
428 req
.in
.data
.user_name
= name
;
429 req
.in
.level
= USER_INFO_BY_NAME
;
431 status
= libnet_UserInfo(ctx
, mem_ctx
, &req
);
432 if (!NT_STATUS_IS_OK(status
)) {
433 torture_comment(torture
, "libnet_UserInfo call failed: %s\n", nt_errstr(status
));
438 if (!test_user_cleanup(torture
, ctx
->samr
.pipe
->binding_handle
,
439 mem_ctx
, &ctx
->samr
.handle
, TEST_USERNAME
)) {
440 torture_comment(torture
, "cleanup failed\n");
445 if (!test_samr_close_handle(torture
,
446 ctx
->samr
.pipe
->binding_handle
, mem_ctx
, &ctx
->samr
.handle
)) {
447 torture_comment(torture
, "domain close failed\n");
453 talloc_free(mem_ctx
);
458 bool torture_userlist(struct torture_context
*torture
)
462 TALLOC_CTX
*mem_ctx
= NULL
;
463 struct libnet_context
*ctx
;
464 struct lsa_String domain_name
;
465 struct libnet_UserList req
;
468 ctx
= libnet_context_init(torture
->ev
, torture
->lp_ctx
);
469 ctx
->cred
= samba_cmdline_get_creds();
471 domain_name
.string
= lpcfg_workgroup(torture
->lp_ctx
);
472 mem_ctx
= talloc_init("torture user list");
476 torture_comment(torture
, "listing user accounts:\n");
480 req
.in
.domain_name
= domain_name
.string
;
481 req
.in
.page_size
= 128;
482 req
.in
.resume_index
= req
.out
.resume_index
;
484 status
= libnet_UserList(ctx
, mem_ctx
, &req
);
485 if (!NT_STATUS_IS_OK(status
) &&
486 !NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) break;
488 for (i
= 0; i
< req
.out
.count
; i
++) {
489 torture_comment(torture
, "\tuser: %s, sid=%s\n",
490 req
.out
.users
[i
].username
, req
.out
.users
[i
].sid
);
493 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
495 if (!(NT_STATUS_IS_OK(status
) ||
496 NT_STATUS_EQUAL(status
, NT_STATUS_NO_MORE_ENTRIES
))) {
497 torture_comment(torture
, "libnet_UserList call failed: %s\n", nt_errstr(status
));
502 if (!test_samr_close_handle(torture
,
503 ctx
->samr
.pipe
->binding_handle
, mem_ctx
, &ctx
->samr
.handle
)) {
504 torture_comment(torture
, "samr domain close failed\n");
509 if (!test_lsa_close_handle(torture
,
510 ctx
->lsa
.pipe
->binding_handle
, mem_ctx
, &ctx
->lsa
.handle
)) {
511 torture_comment(torture
, "lsa domain close failed\n");
518 talloc_free(mem_ctx
);