root/source4/torture/smb2/create.c

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

DEFINITIONS

This source file includes following definitions.
  1. test_create_gentest
  2. test_create_blob
  3. test_create_acl
  4. torture_smb2_create_init

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    SMB2 create test suite
   5 
   6    Copyright (C) Andrew Tridgell 2008
   7    
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 3 of the License, or
  11    (at your option) any later version.
  12    
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17    
  18    You should have received a copy of the GNU General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 #include "includes.h"
  23 #include "libcli/smb2/smb2.h"
  24 #include "libcli/smb2/smb2_calls.h"
  25 #include "torture/torture.h"
  26 #include "torture/smb2/proto.h"
  27 #include "librpc/gen_ndr/ndr_security.h"
  28 #include "libcli/security/security.h"
  29 
  30 #define FNAME "test_create.dat"
  31 
  32 #define CHECK_STATUS(status, correct) do { \
  33         if (!NT_STATUS_EQUAL(status, correct)) { \
  34                 printf("(%s) Incorrect status %s - should be %s\n", \
  35                        __location__, nt_errstr(status), nt_errstr(correct)); \
  36                 return false; \
  37         }} while (0)
  38 
  39 #define CHECK_EQUAL(v, correct) do { \
  40         if (v != correct) { \
  41                 printf("(%s) Incorrect value for %s 0x%08llx - should be 0x%08llx\n", \
  42                        __location__, #v, (unsigned long long)v, (unsigned long long)correct); \
  43                 return false;                                   \
  44         }} while (0)
  45 
  46 /*
  47   test some interesting combinations found by gentest
  48  */
  49 static bool test_create_gentest(struct torture_context *torture, struct smb2_tree *tree)
     /* [<][>][^][v][top][bottom][index][help] */
  50 {
  51         struct smb2_create io;
  52         NTSTATUS status;
  53         TALLOC_CTX *tmp_ctx = talloc_new(tree);
  54         uint32_t access_mask, file_attributes_set;
  55         uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
  56         uint32_t not_a_directory_mask, unexpected_mask;
  57         union smb_fileinfo q;
  58 
  59         ZERO_STRUCT(io);
  60         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
  61         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
  62         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
  63         io.in.share_access = 
  64                 NTCREATEX_SHARE_ACCESS_DELETE|
  65                 NTCREATEX_SHARE_ACCESS_READ|
  66                 NTCREATEX_SHARE_ACCESS_WRITE;
  67         io.in.create_options = 0;
  68         io.in.fname = FNAME;
  69 
  70         status = smb2_create(tree, tmp_ctx, &io);
  71         CHECK_STATUS(status, NT_STATUS_OK);
  72 
  73         status = smb2_util_close(tree, io.out.file.handle);
  74         CHECK_STATUS(status, NT_STATUS_OK);
  75 
  76         io.in.create_options = 0xF0000000;
  77         status = smb2_create(tree, tmp_ctx, &io);
  78         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
  79 
  80         io.in.create_options = 0;
  81 
  82         io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
  83         status = smb2_create(tree, tmp_ctx, &io);
  84         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
  85 
  86         io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
  87         status = smb2_create(tree, tmp_ctx, &io);
  88         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
  89 
  90         io.in.create_disposition = NTCREATEX_DISP_OPEN;
  91         io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
  92         status = smb2_create(tree, tmp_ctx, &io);
  93         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
  94         
  95         io.in.create_disposition = NTCREATEX_DISP_CREATE;
  96         io.in.desired_access = 0x08000000;
  97         status = smb2_create(tree, tmp_ctx, &io);
  98         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
  99 
 100         io.in.desired_access = 0x04000000;
 101         status = smb2_create(tree, tmp_ctx, &io);
 102         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
 103 
 104         io.in.file_attributes = 0;
 105         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
 106         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
 107         ok_mask = 0;
 108         not_supported_mask = 0;
 109         invalid_parameter_mask = 0;
 110         not_a_directory_mask = 0;
 111         unexpected_mask = 0;
 112         {
 113                 int i;
 114                 for (i=0;i<32;i++) {
 115                         io.in.create_options = 1<<i;
 116                         if (io.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
 117                                 continue;
 118                         }
 119                         status = smb2_create(tree, tmp_ctx, &io);
 120                         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
 121                                 not_supported_mask |= 1<<i;
 122                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
 123                                 invalid_parameter_mask |= 1<<i;
 124                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
 125                                 not_a_directory_mask |= 1<<i;
 126                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
 127                                 ok_mask |= 1<<i;
 128                                 status = smb2_util_close(tree, io.out.file.handle);
 129                                 CHECK_STATUS(status, NT_STATUS_OK);
 130                         } else {
 131                                 unexpected_mask |= 1<<i;
 132                                 printf("create option 0x%08x returned %s\n", 1<<i, nt_errstr(status));
 133                         }
 134                 }
 135         }
 136         io.in.create_options = 0;
 137 
 138         CHECK_EQUAL(ok_mask,                0x00efcf7e);
 139         CHECK_EQUAL(not_a_directory_mask,   0x00000001);
 140         CHECK_EQUAL(not_supported_mask,     0x00102080);
 141         CHECK_EQUAL(invalid_parameter_mask, 0xff000000);
 142         CHECK_EQUAL(unexpected_mask,        0x00000000);
 143 
 144         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
 145         io.in.file_attributes = 0;
 146         access_mask = 0;
 147         {
 148                 int i;
 149                 for (i=0;i<32;i++) {
 150                         io.in.desired_access = 1<<i;
 151                         status = smb2_create(tree, tmp_ctx, &io);
 152                         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
 153                             NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
 154                                 access_mask |= io.in.desired_access;
 155                         } else {
 156                                 CHECK_STATUS(status, NT_STATUS_OK);
 157                                 status = smb2_util_close(tree, io.out.file.handle);
 158                                 CHECK_STATUS(status, NT_STATUS_OK);
 159                         }
 160                 }
 161         }
 162 
 163         CHECK_EQUAL(access_mask, 0x0df0fe00);
 164 
 165         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
 166         io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
 167         io.in.file_attributes = 0;
 168         ok_mask = 0;
 169         invalid_parameter_mask = 0;
 170         unexpected_mask = 0;
 171         file_attributes_set = 0;
 172         {
 173                 int i;
 174                 for (i=0;i<32;i++) {
 175                         io.in.file_attributes = 1<<i;
 176                         if (io.in.file_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
 177                                 continue;
 178                         }
 179                         smb2_deltree(tree, FNAME);
 180                         status = smb2_create(tree, tmp_ctx, &io);
 181                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
 182                                 invalid_parameter_mask |= 1<<i;
 183                         } else if (NT_STATUS_IS_OK(status)) {
 184                                 uint32_t expected;
 185                                 ok_mask |= 1<<i;
 186 
 187                                 expected = (io.in.file_attributes | FILE_ATTRIBUTE_ARCHIVE) & 0x00005127;
 188                                 CHECK_EQUAL(io.out.file_attr, expected);
 189                                 file_attributes_set |= io.out.file_attr;
 190 
 191                                 status = smb2_util_close(tree, io.out.file.handle);
 192                                 CHECK_STATUS(status, NT_STATUS_OK);
 193                         } else {
 194                                 unexpected_mask |= 1<<i;
 195                                 printf("file attribute 0x%08x returned %s\n", 1<<i, nt_errstr(status));
 196                         }
 197                 }
 198         }
 199 
 200         CHECK_EQUAL(ok_mask,                0x00003fb7);
 201         CHECK_EQUAL(invalid_parameter_mask, 0xffff8048);
 202         CHECK_EQUAL(unexpected_mask,        0x00000000);
 203         CHECK_EQUAL(file_attributes_set,    0x00001127);
 204 
 205         smb2_deltree(tree, FNAME);
 206 
 207         /*
 208          * Standalone servers doesn't support encryption
 209          */
 210         io.in.file_attributes = FILE_ATTRIBUTE_ENCRYPTED;
 211         status = smb2_create(tree, tmp_ctx, &io);
 212         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
 213                 printf("FILE_ATTRIBUTE_ENCRYPTED returned %s\n", nt_errstr(status));
 214         } else {
 215                 CHECK_STATUS(status, NT_STATUS_OK);
 216                 CHECK_EQUAL(io.out.file_attr, (FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_ARCHIVE));
 217                 status = smb2_util_close(tree, io.out.file.handle);
 218                 CHECK_STATUS(status, NT_STATUS_OK);
 219         }
 220 
 221         smb2_deltree(tree, FNAME);
 222 
 223         ZERO_STRUCT(io);
 224         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
 225         io.in.file_attributes    = 0;
 226         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
 227         io.in.share_access = 
 228                 NTCREATEX_SHARE_ACCESS_READ|
 229                 NTCREATEX_SHARE_ACCESS_WRITE;
 230         io.in.create_options = 0;
 231         io.in.fname = FNAME ":stream1";
 232         status = smb2_create(tree, tmp_ctx, &io);
 233         CHECK_STATUS(status, NT_STATUS_OK);
 234 
 235         status = smb2_util_close(tree, io.out.file.handle);
 236         CHECK_STATUS(status, NT_STATUS_OK);
 237 
 238         io.in.fname = FNAME;
 239         io.in.file_attributes = 0x8040;
 240         io.in.share_access = 
 241                 NTCREATEX_SHARE_ACCESS_READ;
 242         status = smb2_create(tree, tmp_ctx, &io);
 243         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
 244 
 245         io.in.fname = FNAME;
 246         io.in.file_attributes = 0;
 247         io.in.desired_access  = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
 248         io.in.query_maximal_access = true;
 249         status = smb2_create(tree, tmp_ctx, &io);
 250         CHECK_STATUS(status, NT_STATUS_OK);
 251         CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
 252 
 253         q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
 254         q.access_information.in.file.handle = io.out.file.handle;
 255         status = smb2_getinfo_file(tree, tmp_ctx, &q);
 256         CHECK_STATUS(status, NT_STATUS_OK);
 257         CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
 258 
 259         io.in.file_attributes = 0;
 260         io.in.desired_access  = 0;
 261         io.in.query_maximal_access = false;
 262         io.in.share_access = 0;
 263         status = smb2_create(tree, tmp_ctx, &io);
 264         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
 265         
 266         talloc_free(tmp_ctx);
 267 
 268         smb2_deltree(tree, FNAME);
 269         
 270         return true;
 271 }
 272 
 273 
 274 /*
 275   try the various request blobs
 276  */
 277 static bool test_create_blob(struct torture_context *torture, struct smb2_tree *tree)
     /* [<][>][^][v][top][bottom][index][help] */
 278 {
 279         struct smb2_create io;
 280         NTSTATUS status;
 281         TALLOC_CTX *tmp_ctx = talloc_new(tree);
 282 
 283         smb2_deltree(tree, FNAME);
 284 
 285         ZERO_STRUCT(io);
 286         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
 287         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
 288         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
 289         io.in.share_access = 
 290                 NTCREATEX_SHARE_ACCESS_DELETE|
 291                 NTCREATEX_SHARE_ACCESS_READ|
 292                 NTCREATEX_SHARE_ACCESS_WRITE;
 293         io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
 294                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
 295                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
 296                                           0x00200000;
 297         io.in.fname = FNAME;
 298 
 299         status = smb2_create(tree, tmp_ctx, &io);
 300         CHECK_STATUS(status, NT_STATUS_OK);
 301 
 302         status = smb2_util_close(tree, io.out.file.handle);
 303         CHECK_STATUS(status, NT_STATUS_OK);
 304 
 305         printf("testing alloc size\n");
 306         io.in.alloc_size = 4096;
 307         status = smb2_create(tree, tmp_ctx, &io);
 308         CHECK_STATUS(status, NT_STATUS_OK);
 309         CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);
 310 
 311         status = smb2_util_close(tree, io.out.file.handle);
 312         CHECK_STATUS(status, NT_STATUS_OK);
 313 
 314         printf("testing durable open\n");
 315         io.in.durable_open = true;
 316         status = smb2_create(tree, tmp_ctx, &io);
 317         CHECK_STATUS(status, NT_STATUS_OK);
 318 
 319         status = smb2_util_close(tree, io.out.file.handle);
 320         CHECK_STATUS(status, NT_STATUS_OK);
 321 
 322         printf("testing query maximal access\n");
 323         io.in.query_maximal_access = true;
 324         status = smb2_create(tree, tmp_ctx, &io);
 325         CHECK_STATUS(status, NT_STATUS_OK);
 326         CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
 327 
 328         status = smb2_util_close(tree, io.out.file.handle);
 329         CHECK_STATUS(status, NT_STATUS_OK);
 330 
 331         printf("testing timewarp\n");
 332         io.in.timewarp = 10000;
 333         status = smb2_create(tree, tmp_ctx, &io);
 334         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 335         io.in.timewarp = 0;
 336 
 337         printf("testing query_on_disk\n");
 338         io.in.query_on_disk_id = true;
 339         status = smb2_create(tree, tmp_ctx, &io);
 340         CHECK_STATUS(status, NT_STATUS_OK);
 341 
 342         status = smb2_util_close(tree, io.out.file.handle);
 343         CHECK_STATUS(status, NT_STATUS_OK);
 344 
 345         printf("testing unknown tag\n");
 346         status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
 347                                       "FooO", data_blob(NULL, 0));
 348         CHECK_STATUS(status, NT_STATUS_OK);
 349 
 350         status = smb2_create(tree, tmp_ctx, &io);
 351         CHECK_STATUS(status, NT_STATUS_OK);
 352 
 353         status = smb2_util_close(tree, io.out.file.handle);
 354         CHECK_STATUS(status, NT_STATUS_OK);
 355 
 356         printf("testing bad tag length\n");
 357         status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
 358                                       "xxx", data_blob(NULL, 0));
 359         CHECK_STATUS(status, NT_STATUS_OK);
 360 
 361         status = smb2_create(tree, tmp_ctx, &io);
 362         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
 363 
 364         talloc_free(tmp_ctx);
 365 
 366         smb2_deltree(tree, FNAME);
 367         
 368         return true;
 369 }
 370 
 371 /*
 372   try creating with acls
 373  */
 374 static bool test_create_acl(struct torture_context *torture, struct smb2_tree *tree)
     /* [<][>][^][v][top][bottom][index][help] */
 375 {
 376         struct smb2_create io;
 377         NTSTATUS status;
 378         TALLOC_CTX *tmp_ctx = talloc_new(tree);
 379         struct security_ace ace;
 380         struct security_descriptor *sd, *sd2;
 381         struct dom_sid *test_sid;
 382         union smb_fileinfo q;
 383 
 384         smb2_deltree(tree, FNAME);
 385 
 386         ZERO_STRUCT(io);
 387         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
 388         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
 389         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
 390         io.in.share_access = 
 391                 NTCREATEX_SHARE_ACCESS_DELETE|
 392                 NTCREATEX_SHARE_ACCESS_READ|
 393                 NTCREATEX_SHARE_ACCESS_WRITE;
 394         io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
 395                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
 396                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
 397                                           0x00200000;
 398         io.in.fname = FNAME;
 399 
 400         status = smb2_create(tree, tmp_ctx, &io);
 401         CHECK_STATUS(status, NT_STATUS_OK);
 402 
 403         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
 404         q.query_secdesc.in.file.handle = io.out.file.handle;
 405         q.query_secdesc.in.secinfo_flags = 
 406                 SECINFO_OWNER |
 407                 SECINFO_GROUP |
 408                 SECINFO_DACL;
 409         status = smb2_getinfo_file(tree, tmp_ctx, &q);
 410         CHECK_STATUS(status, NT_STATUS_OK);
 411         sd = q.query_secdesc.out.sd;
 412 
 413         status = smb2_util_close(tree, io.out.file.handle);
 414         CHECK_STATUS(status, NT_STATUS_OK);
 415 
 416         smb2_util_unlink(tree, FNAME);
 417 
 418         printf("adding a new ACE\n");
 419         test_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-5-32-1234-54321");
 420 
 421         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
 422         ace.flags = 0;
 423         ace.access_mask = SEC_STD_ALL;
 424         ace.trustee = *test_sid;
 425 
 426         status = security_descriptor_dacl_add(sd, &ace);
 427         CHECK_STATUS(status, NT_STATUS_OK);
 428         
 429         printf("creating a file with an initial ACL\n");
 430 
 431         io.in.sec_desc = sd;
 432         status = smb2_create(tree, tmp_ctx, &io);
 433         CHECK_STATUS(status, NT_STATUS_OK);
 434 
 435         q.query_secdesc.in.file.handle = io.out.file.handle;
 436         status = smb2_getinfo_file(tree, tmp_ctx, &q);
 437         CHECK_STATUS(status, NT_STATUS_OK);
 438         sd2 = q.query_secdesc.out.sd;
 439 
 440         if (!security_acl_equal(sd->dacl, sd2->dacl)) {
 441                 printf("%s: security descriptors don't match!\n", __location__);
 442                 printf("got:\n");
 443                 NDR_PRINT_DEBUG(security_descriptor, sd2);
 444                 printf("expected:\n");
 445                 NDR_PRINT_DEBUG(security_descriptor, sd);
 446                 return false;
 447         }
 448 
 449         talloc_free(tmp_ctx);
 450         
 451         return true;
 452 }
 453 
 454 /* 
 455    basic testing of SMB2 read
 456 */
 457 struct torture_suite *torture_smb2_create_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 458 {
 459         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "CREATE");
 460 
 461         torture_suite_add_1smb2_test(suite, "GENTEST", test_create_gentest);
 462         torture_suite_add_1smb2_test(suite, "BLOB", test_create_blob);
 463         torture_suite_add_1smb2_test(suite, "ACL", test_create_acl);
 464 
 465         suite->description = talloc_strdup(suite, "SMB2-CREATE tests");
 466 
 467         return suite;
 468 }

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