LCOV - code coverage report
Current view: top level - source4/torture/libnet - libnet_user.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 226 315 71.7 %
Date: 2024-04-21 15:09:00 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Test suite for libnet calls.
       4             : 
       5             :    Copyright (C) Rafal Szczesniak 2005
       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 "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"
      31             : 
      32             : 
      33             : 
      34           1 : bool torture_createuser(struct torture_context *torture)
      35             : {
      36           0 :         NTSTATUS status;
      37           0 :         TALLOC_CTX *mem_ctx;
      38           1 :         struct libnet_context *ctx = NULL;
      39           0 :         struct libnet_CreateUser req;
      40           1 :         bool ret = true;
      41             : 
      42           1 :         mem_ctx = talloc_init("test_createuser");
      43             : 
      44           1 :         if (!test_libnet_context_init(torture, true, &ctx)) {
      45           0 :                 return false;
      46             :         }
      47             : 
      48           1 :         req.in.user_name = TEST_USERNAME;
      49           1 :         req.in.domain_name = lpcfg_workgroup(torture->lp_ctx);
      50           1 :         req.out.error_string = NULL;
      51             : 
      52           1 :         status = libnet_CreateUser(ctx, mem_ctx, &req);
      53           1 :         if (!NT_STATUS_IS_OK(status)) {
      54           0 :                 torture_comment(torture, "libnet_CreateUser call failed: %s\n", nt_errstr(status));
      55           0 :                 ret = false;
      56           0 :                 goto done;
      57             :         }
      58             : 
      59           1 :         if (!test_user_cleanup(torture, ctx->samr.pipe->binding_handle,
      60           1 :                                mem_ctx, &ctx->samr.handle, TEST_USERNAME)) {
      61           0 :                 torture_comment(torture, "cleanup failed\n");
      62           0 :                 ret = false;
      63           0 :                 goto done;
      64             :         }
      65             : 
      66           1 :         if (!test_samr_close_handle(torture,
      67           1 :                                     ctx->samr.pipe->binding_handle, mem_ctx, &ctx->samr.handle)) {
      68           0 :                 torture_comment(torture, "domain close failed\n");
      69           0 :                 ret = false;
      70             :         }
      71             : 
      72           1 : done:
      73           1 :         talloc_free(ctx);
      74           1 :         talloc_free(mem_ctx);
      75           1 :         return ret;
      76             : }
      77             : 
      78             : 
      79           1 : bool torture_deleteuser(struct torture_context *torture)
      80             : {
      81           0 :         NTSTATUS status;
      82           0 :         struct dcerpc_pipe *p;
      83           0 :         TALLOC_CTX *mem_ctx;
      84           0 :         struct policy_handle h;
      85           0 :         struct lsa_String domain_name;
      86           1 :         const char *name = TEST_USERNAME;
      87           1 :         struct libnet_context *ctx = NULL;
      88           0 :         struct libnet_DeleteUser req;
      89           1 :         bool ret = false;
      90             : 
      91           1 :         status = torture_rpc_connection(torture,
      92             :                                         &p,
      93             :                                         &ndr_table_samr);
      94           1 :         torture_assert_ntstatus_ok(torture, status, "torture_rpc_connection() failed");
      95             : 
      96           1 :         mem_ctx = talloc_init("torture_deleteuser");
      97             : 
      98             :         /*
      99             :          * Pre-create a user to be deleted later
     100             :          */
     101           1 :         domain_name.string = lpcfg_workgroup(torture->lp_ctx);
     102           1 :         ret = test_domain_open(torture, p->binding_handle, &domain_name, mem_ctx, &h, NULL);
     103           1 :         torture_assert_goto(torture, ret, ret, done, "test_domain_open() failed");
     104             : 
     105           1 :         ret = test_user_create(torture, p->binding_handle, mem_ctx, &h, name, NULL);
     106           1 :         torture_assert_goto(torture, ret, ret, done, "test_user_create() failed");
     107             : 
     108             :         /*
     109             :          * Delete the user using libnet layer
     110             :          */
     111           1 :         ret = test_libnet_context_init(torture, true, &ctx);
     112           1 :         torture_assert_goto(torture, ret, ret, done, "test_libnet_context_init() failed");
     113             : 
     114           1 :         req.in.user_name = TEST_USERNAME;
     115           1 :         req.in.domain_name = lpcfg_workgroup(torture->lp_ctx);
     116             : 
     117           1 :         status = libnet_DeleteUser(ctx, mem_ctx, &req);
     118           1 :         torture_assert_ntstatus_ok_goto(torture, status, ret, done, "libnet_DeleteUser() failed");
     119             : 
     120             :         /* mark test as successful */
     121           1 :         ret = true;
     122             : 
     123           1 : done:
     124           1 :         talloc_free(ctx);
     125           1 :         talloc_free(mem_ctx);
     126           1 :         return ret;
     127             : }
     128             : 
     129             : 
     130             : /*
     131             :   Generate testing set of random changes
     132             : */
     133             : 
     134          10 : 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)
     137             : {
     138          10 :         const char* logon_scripts[] = { "start_login.cmd", "login.bat", "start.cmd" };
     139          10 :         const char* home_dirs[] = { "\\\\srv\\home", "\\\\homesrv\\home\\user", "\\\\pdcsrv\\domain" };
     140          10 :         const char* home_drives[] = { "H:", "z:", "I:", "J:", "n:" };
     141          10 :         const uint32_t flags[] = { (ACB_DISABLED | ACB_NORMAL | ACB_PW_EXPIRED),
     142             :                                    (ACB_NORMAL | ACB_PWNOEXP),
     143             :                                    (ACB_NORMAL | ACB_PW_EXPIRED) };
     144           0 :         const char *homedir, *homedrive, *logonscript;
     145           0 :         struct timeval now;
     146           0 :         int i, testfld;
     147             : 
     148          10 :         torture_comment(tctx, "Fields to change: [");
     149             : 
     150          20 :         for (i = 0; i < num_changes && i <= USER_FIELD_LAST; i++) {
     151           0 :                 const char *fldname;
     152             : 
     153          10 :                 testfld = (req_change == none) ? (random() % USER_FIELD_LAST) + 1 : req_change;
     154             : 
     155             :                 /* get one in case we hit time field this time */
     156          10 :                 gettimeofday(&now, NULL);
     157             : 
     158          10 :                 switch (testfld) {
     159           1 :                 case acct_name:
     160           1 :                         continue_if_field_set(r->in.account_name);
     161           2 :                         r->in.account_name = talloc_asprintf(mem_ctx, TEST_CHG_ACCOUNTNAME,
     162           1 :                                                              (int)(random() % 100));
     163           1 :                         fldname = "account_name";
     164             : 
     165             :                         /* update the test's user name in case it's about to change */
     166           1 :                         *user_name = talloc_strdup(mem_ctx, r->in.account_name);
     167           1 :                         break;
     168             : 
     169           1 :                 case acct_full_name:
     170           1 :                         continue_if_field_set(r->in.full_name);
     171           1 :                         r->in.full_name = talloc_asprintf(mem_ctx, TEST_CHG_FULLNAME,
     172           1 :                                                           (unsigned int)random(), (unsigned int)random());
     173           1 :                         fldname = "full_name";
     174           1 :                         break;
     175             : 
     176           1 :                 case acct_description:
     177           1 :                         continue_if_field_set(r->in.description);
     178           1 :                         r->in.description = talloc_asprintf(mem_ctx, TEST_CHG_DESCRIPTION,
     179             :                                                             (long)random());
     180           1 :                         fldname = "description";
     181           1 :                         break;
     182             : 
     183           1 :                 case acct_home_directory:
     184           1 :                         continue_if_field_set(r->in.home_directory);
     185           1 :                         homedir = home_dirs[random() % ARRAY_SIZE(home_dirs)];
     186           1 :                         r->in.home_directory = talloc_strdup(mem_ctx, homedir);
     187           1 :                         fldname = "home_dir";
     188           1 :                         break;
     189             : 
     190           1 :                 case acct_home_drive:
     191           1 :                         continue_if_field_set(r->in.home_drive);
     192           1 :                         homedrive = home_drives[random() % ARRAY_SIZE(home_drives)];
     193           1 :                         r->in.home_drive = talloc_strdup(mem_ctx, homedrive);
     194           1 :                         fldname = "home_drive";
     195           1 :                         break;
     196             : 
     197           1 :                 case acct_comment:
     198           1 :                         continue_if_field_set(r->in.comment);
     199           1 :                         r->in.comment = talloc_asprintf(mem_ctx, TEST_CHG_COMMENT,
     200           1 :                                                         (unsigned long)random(), (unsigned long)random());
     201           1 :                         fldname = "comment";
     202           1 :                         break;
     203             : 
     204           1 :                 case acct_logon_script:
     205           1 :                         continue_if_field_set(r->in.logon_script);
     206           1 :                         logonscript = logon_scripts[random() % ARRAY_SIZE(logon_scripts)];
     207           1 :                         r->in.logon_script = talloc_strdup(mem_ctx, logonscript);
     208           1 :                         fldname = "logon_script";
     209           1 :                         break;
     210             : 
     211           1 :                 case acct_profile_path:
     212           1 :                         continue_if_field_set(r->in.profile_path);
     213           1 :                         r->in.profile_path = talloc_asprintf(mem_ctx, TEST_CHG_PROFILEPATH,
     214           1 :                                                              (unsigned long)random(), (unsigned int)random());
     215           1 :                         fldname = "profile_path";
     216           1 :                         break;
     217             : 
     218           1 :                 case acct_expiry:
     219           1 :                         continue_if_field_set(r->in.acct_expiry);
     220           1 :                         now = timeval_add(&now, (random() % (31*24*60*60)), 0);
     221           1 :                         r->in.acct_expiry = (struct timeval *)talloc_memdup(mem_ctx, &now, sizeof(now));
     222           1 :                         fldname = "acct_expiry";
     223           1 :                         break;
     224             : 
     225           1 :                 case acct_flags:
     226           1 :                         continue_if_field_set(r->in.acct_flags);
     227           1 :                         r->in.acct_flags = flags[random() % ARRAY_SIZE(flags)];
     228           1 :                         fldname = "acct_flags";
     229           1 :                         break;
     230             : 
     231           0 :                 default:
     232           0 :                         fldname = "unknown_field";
     233             :                 }
     234             : 
     235          10 :                 torture_comment(tctx, ((i < num_changes - 1) ? "%s," : "%s"), fldname);
     236             : 
     237             :                 /* disable requested field (it's supposed to be the only one used) */
     238          10 :                 if (req_change != none) req_change = none;
     239             :         }
     240             : 
     241          10 :         torture_comment(tctx, "]\n");
     242          10 : }
     243             : 
     244             : 
     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); \
     248             :                 ret = false; \
     249             :                 goto cleanup; \
     250             :         }
     251             : 
     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); \
     255             :                 ret = false; \
     256             :                 goto cleanup; \
     257             :         }
     258             : 
     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); \
     262             :                 ret = false; \
     263             :                 goto cleanup; \
     264             :         }
     265             : 
     266             : 
     267           1 : bool torture_modifyuser(struct torture_context *torture)
     268             : {
     269           0 :         NTSTATUS status;
     270           0 :         struct dcerpc_pipe *p;
     271           0 :         TALLOC_CTX *prep_mem_ctx;
     272           0 :         struct policy_handle h;
     273           0 :         struct lsa_String domain_name;
     274           0 :         char *name;
     275           1 :         struct libnet_context *ctx = NULL;
     276           0 :         struct libnet_ModifyUser req;
     277           0 :         struct libnet_UserInfo user_req;
     278           0 :         int fld;
     279           1 :         bool ret = true;
     280           0 :         struct dcerpc_binding_handle *b;
     281             : 
     282           1 :         prep_mem_ctx = talloc_init("prepare test_deleteuser");
     283             : 
     284           1 :         status = torture_rpc_connection(torture,
     285             :                                         &p,
     286             :                                         &ndr_table_samr);
     287           1 :         if (!NT_STATUS_IS_OK(status)) {
     288           0 :                 ret = false;
     289           0 :                 goto done;
     290             :         }
     291           1 :         b = p->binding_handle;
     292             : 
     293           1 :         name = talloc_strdup(prep_mem_ctx, TEST_USERNAME);
     294             : 
     295           1 :         domain_name.string = lpcfg_workgroup(torture->lp_ctx);
     296           1 :         if (!test_domain_open(torture, b, &domain_name, prep_mem_ctx, &h, NULL)) {
     297           0 :                 ret = false;
     298           0 :                 goto done;
     299             :         }
     300             : 
     301           1 :         if (!test_user_create(torture, b, prep_mem_ctx, &h, name, NULL)) {
     302           0 :                 ret = false;
     303           0 :                 goto done;
     304             :         }
     305             : 
     306           1 :         torture_comment(torture, "Testing change of all fields - each single one in turn\n");
     307             : 
     308           1 :         if (!test_libnet_context_init(torture, true, &ctx)) {
     309           0 :                 return false;
     310             :         }
     311             : 
     312          11 :         for (fld = USER_FIELD_FIRST; fld <= USER_FIELD_LAST; fld++) {
     313          10 :                 ZERO_STRUCT(req);
     314          10 :                 req.in.domain_name = lpcfg_workgroup(torture->lp_ctx);
     315          10 :                 req.in.user_name = name;
     316             : 
     317          10 :                 set_test_changes(torture, torture, &req, 1, &name, fld);
     318             : 
     319          10 :                 status = libnet_ModifyUser(ctx, torture, &req);
     320          10 :                 if (!NT_STATUS_IS_OK(status)) {
     321           0 :                         torture_comment(torture, "libnet_ModifyUser call failed: %s\n", nt_errstr(status));
     322           0 :                         ret = false;
     323           0 :                         continue;
     324             :                 }
     325             : 
     326          10 :                 ZERO_STRUCT(user_req);
     327          10 :                 user_req.in.domain_name = lpcfg_workgroup(torture->lp_ctx);
     328          10 :                 user_req.in.data.user_name = name;
     329          10 :                 user_req.in.level = USER_INFO_BY_NAME;
     330             : 
     331          10 :                 status = libnet_UserInfo(ctx, torture, &user_req);
     332          10 :                 if (!NT_STATUS_IS_OK(status)) {
     333           0 :                         torture_comment(torture, "libnet_UserInfo call failed: %s\n", nt_errstr(status));
     334           0 :                         ret = false;
     335           0 :                         continue;
     336             :                 }
     337             : 
     338          10 :                 switch (fld) {
     339           1 :                 case acct_name: TEST_STR_FLD(account_name);
     340           1 :                         break;
     341           1 :                 case acct_full_name: TEST_STR_FLD(full_name);
     342           1 :                         break;
     343           1 :                 case acct_comment: TEST_STR_FLD(comment);
     344           1 :                         break;
     345           1 :                 case acct_description: TEST_STR_FLD(description);
     346           1 :                         break;
     347           1 :                 case acct_home_directory: TEST_STR_FLD(home_directory);
     348           1 :                         break;
     349           1 :                 case acct_home_drive: TEST_STR_FLD(home_drive);
     350           1 :                         break;
     351           1 :                 case acct_logon_script: TEST_STR_FLD(logon_script);
     352           1 :                         break;
     353           1 :                 case acct_profile_path: TEST_STR_FLD(profile_path);
     354           1 :                         break;
     355           1 :                 case acct_expiry: TEST_TIME_FLD(acct_expiry);
     356           1 :                         break;
     357           1 :                 case acct_flags: TEST_NUM_FLD(acct_flags);
     358           1 :                         break;
     359           0 :                 default:
     360           0 :                         break;
     361             :                 }
     362             :         }
     363             : 
     364           1 : cleanup:
     365           1 :         if (!test_user_cleanup(torture, ctx->samr.pipe->binding_handle,
     366           1 :                                torture, &ctx->samr.handle, TEST_USERNAME)) {
     367           0 :                 torture_comment(torture, "cleanup failed\n");
     368           0 :                 ret = false;
     369           0 :                 goto done;
     370             :         }
     371             : 
     372           1 :         if (!test_samr_close_handle(torture,
     373           1 :                                     ctx->samr.pipe->binding_handle, torture, &ctx->samr.handle)) {
     374           0 :                 torture_comment(torture, "domain close failed\n");
     375           0 :                 ret = false;
     376             :         }
     377             : 
     378           1 : done:
     379           1 :         talloc_free(ctx);
     380           1 :         talloc_free(prep_mem_ctx);
     381           1 :         return ret;
     382             : }
     383             : 
     384             : 
     385           1 : bool torture_userinfo_api(struct torture_context *torture)
     386             : {
     387           1 :         const char *name = TEST_USERNAME;
     388           1 :         bool ret = true;
     389           0 :         NTSTATUS status;
     390           1 :         TALLOC_CTX *mem_ctx = NULL, *prep_mem_ctx;
     391           1 :         struct libnet_context *ctx = NULL;
     392           0 :         struct dcerpc_pipe *p;
     393           0 :         struct policy_handle h;
     394           0 :         struct lsa_String domain_name;
     395           0 :         struct libnet_UserInfo req;
     396           0 :         struct dcerpc_binding_handle *b;
     397             : 
     398           1 :         prep_mem_ctx = talloc_init("prepare torture user info");
     399             : 
     400           1 :         status = torture_rpc_connection(torture,
     401             :                                         &p,
     402             :                                         &ndr_table_samr);
     403           1 :         if (!NT_STATUS_IS_OK(status)) {
     404           0 :                 return false;
     405             :         }
     406           1 :         b = p->binding_handle;
     407             : 
     408           1 :         domain_name.string = lpcfg_workgroup(torture->lp_ctx);
     409           1 :         if (!test_domain_open(torture, b, &domain_name, prep_mem_ctx, &h, NULL)) {
     410           0 :                 ret = false;
     411           0 :                 goto done;
     412             :         }
     413             : 
     414           1 :         if (!test_user_create(torture, b, prep_mem_ctx, &h, name, NULL)) {
     415           0 :                 ret = false;
     416           0 :                 goto done;
     417             :         }
     418             : 
     419           1 :         mem_ctx = talloc_init("torture user info");
     420             : 
     421           1 :         if (!test_libnet_context_init(torture, true, &ctx)) {
     422           0 :                 return false;
     423             :         }
     424             : 
     425           1 :         ZERO_STRUCT(req);
     426             : 
     427           1 :         req.in.domain_name = domain_name.string;
     428           1 :         req.in.data.user_name   = name;
     429           1 :         req.in.level = USER_INFO_BY_NAME;
     430             : 
     431           1 :         status = libnet_UserInfo(ctx, mem_ctx, &req);
     432           1 :         if (!NT_STATUS_IS_OK(status)) {
     433           0 :                 torture_comment(torture, "libnet_UserInfo call failed: %s\n", nt_errstr(status));
     434           0 :                 ret = false;
     435           0 :                 goto done;
     436             :         }
     437             : 
     438           1 :         if (!test_user_cleanup(torture, ctx->samr.pipe->binding_handle,
     439           1 :                                mem_ctx, &ctx->samr.handle, TEST_USERNAME)) {
     440           0 :                 torture_comment(torture, "cleanup failed\n");
     441           0 :                 ret = false;
     442           0 :                 goto done;
     443             :         }
     444             : 
     445           1 :         if (!test_samr_close_handle(torture,
     446           1 :                                     ctx->samr.pipe->binding_handle, mem_ctx, &ctx->samr.handle)) {
     447           0 :                 torture_comment(torture, "domain close failed\n");
     448           0 :                 ret = false;
     449             :         }
     450             : 
     451           1 : done:
     452           1 :         talloc_free(ctx);
     453           1 :         talloc_free(mem_ctx);
     454           1 :         return ret;
     455             : }
     456             : 
     457             : 
     458           1 : bool torture_userlist(struct torture_context *torture)
     459             : {
     460           1 :         bool ret = true;
     461           0 :         NTSTATUS status;
     462           1 :         TALLOC_CTX *mem_ctx = NULL;
     463           0 :         struct libnet_context *ctx;
     464           0 :         struct lsa_String domain_name;
     465           0 :         struct libnet_UserList req;
     466           0 :         int i;
     467             : 
     468           1 :         ctx = libnet_context_init(torture->ev, torture->lp_ctx);
     469           1 :         ctx->cred = samba_cmdline_get_creds();
     470             : 
     471           1 :         domain_name.string = lpcfg_workgroup(torture->lp_ctx);
     472           1 :         mem_ctx = talloc_init("torture user list");
     473             : 
     474           1 :         ZERO_STRUCT(req);
     475             : 
     476           1 :         torture_comment(torture, "listing user accounts:\n");
     477             : 
     478           0 :         do {
     479             : 
     480           4 :                 req.in.domain_name = domain_name.string;
     481           4 :                 req.in.page_size   = 128;
     482           4 :                 req.in.resume_index = req.out.resume_index;
     483             : 
     484           4 :                 status = libnet_UserList(ctx, mem_ctx, &req);
     485           4 :                 if (!NT_STATUS_IS_OK(status) &&
     486           3 :                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) break;
     487             : 
     488          16 :                 for (i = 0; i < req.out.count; i++) {
     489          12 :                         torture_comment(torture, "\tuser: %s, sid=%s\n",
     490          12 :                                         req.out.users[i].username, req.out.users[i].sid);
     491             :                 }
     492             : 
     493           4 :         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
     494             : 
     495           1 :         if (!(NT_STATUS_IS_OK(status) ||
     496           0 :               NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES))) {
     497           0 :                 torture_comment(torture, "libnet_UserList call failed: %s\n", nt_errstr(status));
     498           0 :                 ret = false;
     499           0 :                 goto done;
     500             :         }
     501             : 
     502           1 :         if (!test_samr_close_handle(torture,
     503           1 :                                     ctx->samr.pipe->binding_handle, mem_ctx, &ctx->samr.handle)) {
     504           0 :                 torture_comment(torture, "samr domain close failed\n");
     505           0 :                 ret = false;
     506           0 :                 goto done;
     507             :         }
     508             : 
     509           1 :         if (!test_lsa_close_handle(torture,
     510           1 :                                    ctx->lsa.pipe->binding_handle, mem_ctx, &ctx->lsa.handle)) {
     511           0 :                 torture_comment(torture, "lsa domain close failed\n");
     512           0 :                 ret = false;
     513             :         }
     514             : 
     515           1 :         talloc_free(ctx);
     516             : 
     517           1 : done:
     518           1 :         talloc_free(mem_ctx);
     519           1 :         return ret;
     520             : }

Generated by: LCOV version 1.14