LCOV - code coverage report
Current view: top level - source4/torture/libnet - userman.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 180 263 68.4 %
Date: 2024-04-21 15:09:00 Functions: 8 8 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 "torture/rpc/torture_rpc.h"
      23             : #include "torture/libnet/usertest.h"
      24             : #include "libnet/libnet.h"
      25             : #include "librpc/gen_ndr/ndr_samr_c.h"
      26             : #include "param/param.h"
      27             : 
      28             : #include "torture/libnet/proto.h"
      29             : 
      30             : 
      31           1 : static bool test_useradd(struct torture_context *tctx,
      32             :                          struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
      33             :                          struct policy_handle *domain_handle,
      34             :                          const char *name)
      35             : {
      36           0 :         NTSTATUS status;
      37           1 :         bool ret = true;
      38           0 :         struct libnet_rpc_useradd user;
      39             : 
      40           1 :         user.in.domain_handle = *domain_handle;
      41           1 :         user.in.username      = name;
      42             : 
      43           1 :         torture_comment(tctx, "Testing libnet_rpc_useradd\n");
      44             : 
      45           1 :         status = libnet_rpc_useradd(tctx->ev, p->binding_handle, mem_ctx, &user);
      46           1 :         if (!NT_STATUS_IS_OK(status)) {
      47           0 :                 torture_comment(tctx, "Failed to call libnet_rpc_useradd - %s\n", nt_errstr(status));
      48           0 :                 return false;
      49             :         }
      50             : 
      51           1 :         return ret;
      52             : }
      53             : 
      54             : 
      55           1 : static bool test_useradd_async(struct torture_context *tctx,
      56             :                                struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
      57             :                                struct policy_handle *handle, const char* username)
      58             : {
      59           0 :         NTSTATUS status;
      60           0 :         struct composite_context *c;
      61           0 :         struct libnet_rpc_useradd user;
      62             : 
      63           1 :         user.in.domain_handle = *handle;
      64           1 :         user.in.username      = username;
      65             : 
      66           1 :         torture_comment(tctx, "Testing async libnet_rpc_useradd\n");
      67             : 
      68           1 :         c = libnet_rpc_useradd_send(mem_ctx, tctx->ev, p->binding_handle,
      69             :                                     &user, msg_handler);
      70           1 :         if (!c) {
      71           0 :                 torture_comment(tctx, "Failed to call async libnet_rpc_useradd\n");
      72           0 :                 return false;
      73             :         }
      74             : 
      75           1 :         status = libnet_rpc_useradd_recv(c, mem_ctx, &user);
      76           1 :         if (!NT_STATUS_IS_OK(status)) {
      77           0 :                 torture_comment(tctx, "Calling async libnet_rpc_useradd failed - %s\n", nt_errstr(status));
      78           0 :                 return false;
      79             :         }
      80             : 
      81           1 :         return true;
      82             : 
      83             : }
      84             : 
      85          10 : static bool test_usermod(struct torture_context *tctx, struct dcerpc_pipe *p,
      86             :                          TALLOC_CTX *mem_ctx,
      87             :                          struct policy_handle *handle, int num_changes,
      88             :                          struct libnet_rpc_usermod *mod, char **username)
      89             : {
      90          10 :         const char* logon_scripts[] = { "start_login.cmd", "login.bat", "start.cmd" };
      91          10 :         const char* home_dirs[] = { "\\\\srv\\home", "\\\\homesrv\\home\\user", "\\\\pdcsrv\\domain" };
      92          10 :         const char* home_drives[] = { "H:", "z:", "I:", "J:", "n:" };
      93           0 :         const char *homedir, *homedrive, *logonscript;
      94          10 :         const uint32_t flags[] = { (ACB_DISABLED | ACB_NORMAL | ACB_PW_EXPIRED),
      95             :                                    (ACB_NORMAL | ACB_PWNOEXP),
      96             :                                    (ACB_NORMAL | ACB_PW_EXPIRED) };
      97             : 
      98           0 :         NTSTATUS status;
      99           0 :         struct timeval now;
     100           0 :         enum test_fields testfld;
     101           0 :         int i;
     102             : 
     103          10 :         ZERO_STRUCT(*mod);
     104          10 :         srandom((unsigned)time(NULL));
     105             : 
     106          10 :         mod->in.username = talloc_strdup(mem_ctx, *username);
     107          10 :         mod->in.domain_handle = *handle;
     108             : 
     109          10 :         torture_comment(tctx, "modifying user (%d simultaneous change(s))\n",
     110             :                         num_changes);
     111             : 
     112          10 :         torture_comment(tctx, "fields to change: [");
     113             : 
     114         154 :         for (i = 0; i < num_changes && i <= USER_FIELD_LAST; i++) {
     115           0 :                 const char *fldname;
     116             : 
     117         144 :                 testfld = (random() % USER_FIELD_LAST) + 1;
     118             : 
     119         144 :                 GetTimeOfDay(&now);
     120             : 
     121         144 :                 switch (testfld) {
     122           1 :                 case acct_name:
     123           1 :                         continue_if_field_set(mod->in.change.account_name);
     124           2 :                         mod->in.change.account_name = talloc_asprintf(mem_ctx, TEST_CHG_ACCOUNTNAME,
     125           1 :                                                                       (int)(random() % 100));
     126           1 :                         mod->in.change.fields |= USERMOD_FIELD_ACCOUNT_NAME;
     127           1 :                         fldname = "account_name";
     128           1 :                         *username = talloc_strdup(mem_ctx, mod->in.change.account_name);
     129           1 :                         break;
     130             : 
     131          28 :                 case acct_full_name:
     132          28 :                         continue_if_field_set(mod->in.change.full_name);
     133          10 :                         mod->in.change.full_name = talloc_asprintf(mem_ctx, TEST_CHG_FULLNAME,
     134          10 :                                                                   (int)random(), (int)random());
     135          10 :                         mod->in.change.fields |= USERMOD_FIELD_FULL_NAME;
     136          10 :                         fldname = "full_name";
     137          10 :                         break;
     138             : 
     139          26 :                 case acct_description:
     140          26 :                         continue_if_field_set(mod->in.change.description);
     141           7 :                         mod->in.change.description = talloc_asprintf(mem_ctx, TEST_CHG_DESCRIPTION,
     142             :                                                                     random());
     143           7 :                         mod->in.change.fields |= USERMOD_FIELD_DESCRIPTION;
     144           7 :                         fldname = "description";
     145           7 :                         break;
     146             : 
     147          17 :                 case acct_home_directory:
     148          17 :                         continue_if_field_set(mod->in.change.home_directory);
     149           6 :                         homedir = home_dirs[random() % (sizeof(home_dirs)/sizeof(char*))];
     150           6 :                         mod->in.change.home_directory = talloc_strdup(mem_ctx, homedir);
     151           6 :                         mod->in.change.fields |= USERMOD_FIELD_HOME_DIRECTORY;
     152           6 :                         fldname = "home_directory";
     153           6 :                         break;
     154             : 
     155          21 :                 case acct_home_drive:
     156          21 :                         continue_if_field_set(mod->in.change.home_drive);
     157           9 :                         homedrive = home_drives[random() % (sizeof(home_drives)/sizeof(char*))];
     158           9 :                         mod->in.change.home_drive = talloc_strdup(mem_ctx, homedrive);
     159           9 :                         mod->in.change.fields |= USERMOD_FIELD_HOME_DRIVE;
     160           9 :                         fldname = "home_drive";
     161           9 :                         break;
     162             : 
     163           9 :                 case acct_comment:
     164           9 :                         continue_if_field_set(mod->in.change.comment);
     165           8 :                         mod->in.change.comment = talloc_asprintf(mem_ctx, TEST_CHG_COMMENT,
     166             :                                                                 random(), random());
     167           8 :                         mod->in.change.fields |= USERMOD_FIELD_COMMENT;
     168           8 :                         fldname = "comment";
     169           8 :                         break;
     170             : 
     171           6 :                 case acct_logon_script:
     172           6 :                         continue_if_field_set(mod->in.change.logon_script);
     173           2 :                         logonscript = logon_scripts[random() % (sizeof(logon_scripts)/sizeof(char*))];
     174           2 :                         mod->in.change.logon_script = talloc_strdup(mem_ctx, logonscript);
     175           2 :                         mod->in.change.fields |= USERMOD_FIELD_LOGON_SCRIPT;
     176           2 :                         fldname = "logon_script";
     177           2 :                         break;
     178             : 
     179           8 :                 case acct_profile_path:
     180           8 :                         continue_if_field_set(mod->in.change.profile_path);
     181           3 :                         mod->in.change.profile_path = talloc_asprintf(mem_ctx, TEST_CHG_PROFILEPATH,
     182           3 :                                                                      (long int)random(), (unsigned int)random());
     183           3 :                         mod->in.change.fields |= USERMOD_FIELD_PROFILE_PATH;
     184           3 :                         fldname = "profile_path";
     185           3 :                         break;
     186             : 
     187          21 :                 case acct_expiry:
     188          21 :                         continue_if_field_set(mod->in.change.acct_expiry);
     189           5 :                         now = timeval_add(&now, (random() % (31*24*60*60)), 0);
     190           5 :                         mod->in.change.acct_expiry = (struct timeval *)talloc_memdup(mem_ctx, &now, sizeof(now));
     191           5 :                         mod->in.change.fields |= USERMOD_FIELD_ACCT_EXPIRY;
     192           5 :                         fldname = "acct_expiry";
     193           5 :                         break;
     194             : 
     195           7 :                 case acct_flags:
     196           7 :                         continue_if_field_set(mod->in.change.acct_flags);
     197           4 :                         mod->in.change.acct_flags = flags[random() % ARRAY_SIZE(flags)];
     198           4 :                         mod->in.change.fields |= USERMOD_FIELD_ACCT_FLAGS;
     199           4 :                         fldname = "acct_flags";
     200           4 :                         break;
     201             : 
     202           0 :                 default:
     203           0 :                         fldname = talloc_asprintf(mem_ctx, "unknown_field (%d)", testfld);
     204           0 :                         break;
     205             :                 }
     206             : 
     207          55 :                 torture_comment(tctx, ((i < num_changes - 1) ? "%s," : "%s"), fldname);
     208             :         }
     209          10 :         torture_comment(tctx, "]\n");
     210             : 
     211          10 :         status = libnet_rpc_usermod(tctx->ev, p->binding_handle, mem_ctx, mod);
     212          10 :         torture_assert_ntstatus_ok(tctx, status, "Failed to call sync libnet_rpc_usermod");
     213             : 
     214          10 :         return true;
     215             : }
     216             : 
     217             : 
     218           1 : static bool test_userdel(struct torture_context *tctx,
     219             :                          struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
     220             :                          struct policy_handle *handle, const char *username)
     221             : {
     222           0 :         NTSTATUS status;
     223           0 :         struct libnet_rpc_userdel user;
     224             : 
     225           1 :         ZERO_STRUCT(user);
     226             : 
     227           1 :         user.in.domain_handle = *handle;
     228           1 :         user.in.username = username;
     229             : 
     230           1 :         status = libnet_rpc_userdel(tctx->ev, p->binding_handle, mem_ctx, &user);
     231           1 :         if (!NT_STATUS_IS_OK(status)) {
     232           0 :                 torture_comment(tctx, "Failed to call sync libnet_rpc_userdel - %s\n", nt_errstr(status));
     233           0 :                 return false;
     234             :         }
     235             : 
     236           1 :         return true;
     237             : }
     238             : 
     239             : 
     240             : #define CMP_LSA_STRING_FLD(fld, flags) \
     241             :         if ((mod->in.change.fields & flags) && \
     242             :             !strequal(i->fld.string, mod->in.change.fld)) { \
     243             :                 torture_comment(tctx, "'%s' field does not match\n", #fld); \
     244             :                 torture_comment(tctx, "received: '%s'\n", i->fld.string); \
     245             :                 torture_comment(tctx, "expected: '%s'\n", mod->in.change.fld); \
     246             :                 return false; \
     247             :         }
     248             : 
     249             : 
     250             : #define CMP_TIME_FLD(fld, flags) \
     251             :         if (mod->in.change.fields & flags) { \
     252             :                 nttime_to_timeval(&t, i->fld); \
     253             :                 if (timeval_compare(&t, mod->in.change.fld)) { \
     254             :                         torture_comment(tctx, "'%s' field does not match\n", #fld); \
     255             :                         torture_comment(tctx, "received: '%s (+%ld us)'\n", \
     256             :                                timestring(mem_ctx, t.tv_sec), (long)t.tv_usec); \
     257             :                         torture_comment(tctx, "expected: '%s (+%ld us)'\n", \
     258             :                                timestring(mem_ctx, mod->in.change.fld->tv_sec), \
     259             :                                (long)mod->in.change.fld->tv_usec); \
     260             :                         return false; \
     261             :                 } \
     262             :         }
     263             : 
     264             : #define CMP_NUM_FLD(fld, flags) \
     265             :         if ((mod->in.change.fields & flags) && \
     266             :             (i->fld != mod->in.change.fld)) { \
     267             :                 torture_comment(tctx, "'%s' field does not match\n", #fld); \
     268             :                 torture_comment(tctx, "received: '%04x'\n", i->fld); \
     269             :                 torture_comment(tctx, "expected: '%04x'\n", mod->in.change.fld); \
     270             :                 return false; \
     271             :         }
     272             : 
     273             : 
     274          10 : static bool test_compare(struct torture_context *tctx,
     275             :                          struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
     276             :                          struct policy_handle *handle, struct libnet_rpc_usermod *mod,
     277             :                          const char *username)
     278             : {
     279           0 :         NTSTATUS status;
     280           0 :         struct libnet_rpc_userinfo info;
     281           0 :         struct samr_UserInfo21 *i;
     282           0 :         struct timeval t;
     283             : 
     284          10 :         ZERO_STRUCT(info);
     285             : 
     286          10 :         info.in.username = username;
     287          10 :         info.in.domain_handle = *handle;
     288          10 :         info.in.level = 21;             /* the most rich infolevel available */
     289             : 
     290          10 :         status = libnet_rpc_userinfo(tctx->ev, p->binding_handle, mem_ctx, &info);
     291          10 :         torture_assert_ntstatus_ok(tctx, status, "Failed to call sync libnet_rpc_userinfo");
     292             : 
     293          10 :         i = &info.out.info.info21;
     294             : 
     295          10 :         CMP_LSA_STRING_FLD(account_name, USERMOD_FIELD_ACCOUNT_NAME);
     296          10 :         CMP_LSA_STRING_FLD(full_name, USERMOD_FIELD_FULL_NAME);
     297          10 :         CMP_LSA_STRING_FLD(description, USERMOD_FIELD_DESCRIPTION);
     298          10 :         CMP_LSA_STRING_FLD(comment, USERMOD_FIELD_COMMENT);
     299          10 :         CMP_LSA_STRING_FLD(logon_script, USERMOD_FIELD_LOGON_SCRIPT);
     300          10 :         CMP_LSA_STRING_FLD(profile_path, USERMOD_FIELD_PROFILE_PATH);
     301          10 :         CMP_LSA_STRING_FLD(home_directory, USERMOD_FIELD_HOME_DIRECTORY);
     302          10 :         CMP_LSA_STRING_FLD(home_drive, USERMOD_FIELD_HOME_DRIVE);
     303          10 :         CMP_TIME_FLD(acct_expiry, USERMOD_FIELD_ACCT_EXPIRY);
     304          10 :         CMP_NUM_FLD(acct_flags, USERMOD_FIELD_ACCT_FLAGS)
     305             : 
     306          10 :         return true;
     307             : }
     308             : 
     309             : 
     310           1 : bool torture_useradd(struct torture_context *torture)
     311             : {
     312           0 :         NTSTATUS status;
     313           0 :         struct dcerpc_pipe *p;
     314           0 :         struct policy_handle h;
     315           0 :         struct lsa_String domain_name;
     316           0 :         struct dom_sid2 sid;
     317           1 :         const char *name = TEST_USERNAME;
     318           0 :         TALLOC_CTX *mem_ctx;
     319           1 :         bool ret = true;
     320           0 :         struct dcerpc_binding_handle *b;
     321             : 
     322           1 :         mem_ctx = talloc_init("test_useradd");
     323             : 
     324           1 :         status = torture_rpc_connection(torture,
     325             :                                         &p,
     326             :                                         &ndr_table_samr);
     327             : 
     328           1 :         torture_assert_ntstatus_ok(torture, status, "RPC connect failed");
     329           1 :         b = p->binding_handle;
     330             : 
     331           1 :         domain_name.string = lpcfg_workgroup(torture->lp_ctx);
     332           1 :         if (!test_domain_open(torture, b, &domain_name, mem_ctx, &h, &sid)) {
     333           0 :                 ret = false;
     334           0 :                 goto done;
     335             :         }
     336             : 
     337           1 :         if (!test_useradd(torture, p, mem_ctx, &h, name)) {
     338           0 :                 ret = false;
     339           0 :                 goto done;
     340             :         }
     341             : 
     342           1 :         if (!test_user_cleanup(torture, b, mem_ctx, &h, name)) {
     343           0 :                 ret = false;
     344           0 :                 goto done;
     345             :         }
     346             : 
     347           1 :         if (!test_domain_open(torture, b, &domain_name, mem_ctx, &h, &sid)) {
     348           0 :                 ret = false;
     349           0 :                 goto done;
     350             :         }
     351             : 
     352           1 :         if (!test_useradd_async(torture, p, mem_ctx, &h, name)) {
     353           0 :                 ret = false;
     354           0 :                 goto done;
     355             :         }
     356             : 
     357           1 :         if (!test_user_cleanup(torture, b, mem_ctx, &h, name)) {
     358           0 :                 ret = false;
     359           0 :                 goto done;
     360             :         }
     361             : 
     362           1 : done:
     363           1 :         talloc_free(mem_ctx);
     364           1 :         return ret;
     365             : }
     366             : 
     367             : 
     368           1 : bool torture_userdel(struct torture_context *torture)
     369             : {
     370           0 :         NTSTATUS status;
     371           0 :         struct dcerpc_pipe *p;
     372           0 :         struct policy_handle h;
     373           0 :         struct lsa_String domain_name;
     374           0 :         struct dom_sid2 sid;
     375           0 :         uint32_t rid;
     376           1 :         const char *name = TEST_USERNAME;
     377           0 :         TALLOC_CTX *mem_ctx;
     378           1 :         bool ret = true;
     379           0 :         struct dcerpc_binding_handle *b;
     380             : 
     381           1 :         mem_ctx = talloc_init("test_userdel");
     382             : 
     383           1 :         status = torture_rpc_connection(torture,
     384             :                                         &p,
     385             :                                         &ndr_table_samr);
     386             : 
     387           1 :         if (!NT_STATUS_IS_OK(status)) {
     388           0 :                 return false;
     389             :         }
     390           1 :         b = p->binding_handle;
     391             : 
     392           1 :         domain_name.string = lpcfg_workgroup(torture->lp_ctx);
     393           1 :         if (!test_domain_open(torture, b, &domain_name, mem_ctx, &h, &sid)) {
     394           0 :                 ret = false;
     395           0 :                 goto done;
     396             :         }
     397             : 
     398           1 :         if (!test_user_create(torture, b, mem_ctx, &h, name, &rid)) {
     399           0 :                 ret = false;
     400           0 :                 goto done;
     401             :         }
     402             : 
     403           1 :         if (!test_userdel(torture, p, mem_ctx, &h, name)) {
     404           0 :                 ret = false;
     405           0 :                 goto done;
     406             :         }
     407             : 
     408           1 : done:
     409           1 :         talloc_free(mem_ctx);
     410           1 :         return ret;
     411             : }
     412             : 
     413             : 
     414           1 : bool torture_usermod(struct torture_context *torture)
     415             : {
     416           0 :         NTSTATUS status;
     417           0 :         struct dcerpc_pipe *p;
     418           0 :         struct policy_handle h;
     419           0 :         struct lsa_String domain_name;
     420           0 :         struct dom_sid2 sid;
     421           0 :         uint32_t rid;
     422           0 :         int i;
     423           0 :         char *name;
     424           0 :         TALLOC_CTX *mem_ctx;
     425           1 :         bool ret = true;
     426           0 :         struct dcerpc_binding_handle *b;
     427             : 
     428           1 :         mem_ctx = talloc_init("test_userdel");
     429             : 
     430           1 :         status = torture_rpc_connection(torture,
     431             :                                         &p,
     432             :                                         &ndr_table_samr);
     433             : 
     434           1 :         torture_assert_ntstatus_ok(torture, status, "RPC connect");
     435           1 :         b = p->binding_handle;
     436             : 
     437           1 :         domain_name.string = lpcfg_workgroup(torture->lp_ctx);
     438           1 :         name = talloc_strdup(mem_ctx, TEST_USERNAME);
     439             : 
     440           1 :         if (!test_domain_open(torture, b, &domain_name, mem_ctx, &h, &sid)) {
     441           0 :                 ret = false;
     442           0 :                 goto done;
     443             :         }
     444             : 
     445           1 :         if (!test_user_create(torture, b, mem_ctx, &h, name, &rid)) {
     446           0 :                 ret = false;
     447           0 :                 goto done;
     448             :         }
     449             : 
     450          11 :         for (i = USER_FIELD_FIRST; i <= USER_FIELD_LAST; i++) {
     451           0 :                 struct libnet_rpc_usermod m;
     452             : 
     453          10 :                 if (!test_usermod(torture, p, mem_ctx, &h, i, &m, &name)) {
     454           0 :                         ret = false;
     455           0 :                         goto cleanup;
     456             :                 }
     457             : 
     458          10 :                 if (!test_compare(torture, p, mem_ctx, &h, &m, name)) {
     459           0 :                         ret = false;
     460           0 :                         goto cleanup;
     461             :                 }
     462             :         }
     463             : 
     464           1 : cleanup:
     465           1 :         if (!test_user_cleanup(torture, b, mem_ctx, &h, TEST_USERNAME)) {
     466           0 :                 ret = false;
     467           0 :                 goto done;
     468             :         }
     469             : 
     470           1 : done:
     471           1 :         talloc_free(mem_ctx);
     472           1 :         return ret;
     473             : }

Generated by: LCOV version 1.14