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);