root/source4/torture/libnet/userman.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. test_useradd
  2. test_useradd_async
  3. test_usermod
  4. test_userdel
  5. test_compare
  6. torture_useradd
  7. torture_userdel
  8. torture_usermod

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

/* [<][>][^][v][top][bottom][index][help] */