root/source4/torture/smb2/util.c

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

DEFINITIONS

This source file includes following definitions.
  1. smb2_util_write
  2. smb2_create_complex
  3. smb2_create_complex_file
  4. smb2_create_complex_dir
  5. torture_smb2_all_info
  6. torture_smb2_connection
  7. torture_smb2_testfile
  8. torture_smb2_testdir
  9. torture_setup_complex_file
  10. torture_setup_complex_dir
  11. smb2_util_roothandle

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    helper functions for SMB2 test suite
   5 
   6    Copyright (C) Andrew Tridgell 2005
   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 "libcli/smb_composite/smb_composite.h"
  26 #include "lib/cmdline/popt_common.h"
  27 #include "lib/events/events.h"
  28 #include "system/time.h"
  29 #include "librpc/gen_ndr/ndr_security.h"
  30 #include "param/param.h"
  31 #include "libcli/resolve/resolve.h"
  32 
  33 #include "torture/torture.h"
  34 #include "torture/smb2/proto.h"
  35 
  36 
  37 /*
  38   write to a file on SMB2
  39 */
  40 NTSTATUS smb2_util_write(struct smb2_tree *tree,
     /* [<][>][^][v][top][bottom][index][help] */
  41                          struct smb2_handle handle, 
  42                          const void *buf, off_t offset, size_t size)
  43 {
  44         struct smb2_write w;
  45 
  46         ZERO_STRUCT(w);
  47         w.in.file.handle = handle;
  48         w.in.offset      = offset;
  49         w.in.data        = data_blob_const(buf, size);
  50 
  51         return smb2_write(tree, &w);
  52 }
  53 
  54 /*
  55   create a complex file/dir using the SMB2 protocol
  56 */
  57 static NTSTATUS smb2_create_complex(struct smb2_tree *tree, const char *fname, 
     /* [<][>][^][v][top][bottom][index][help] */
  58                                          struct smb2_handle *handle, bool dir)
  59 {
  60         TALLOC_CTX *tmp_ctx = talloc_new(tree);
  61         char buf[7] = "abc";
  62         struct smb2_create io;
  63         union smb_setfileinfo setfile;
  64         union smb_fileinfo fileinfo;
  65         time_t t = (time(NULL) & ~1);
  66         NTSTATUS status;
  67 
  68         smb2_util_unlink(tree, fname);
  69         ZERO_STRUCT(io);
  70         io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
  71         io.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
  72         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
  73         io.in.share_access = 
  74                 NTCREATEX_SHARE_ACCESS_DELETE|
  75                 NTCREATEX_SHARE_ACCESS_READ|
  76                 NTCREATEX_SHARE_ACCESS_WRITE;
  77         io.in.create_options = 0;
  78         io.in.fname = fname;
  79         if (dir) {
  80                 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
  81                 io.in.share_access &= ~NTCREATEX_SHARE_ACCESS_DELETE;
  82                 io.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
  83                 io.in.create_disposition = NTCREATEX_DISP_CREATE;
  84         }
  85 
  86         /* it seems vista is now fussier about alignment? */
  87         if (strchr(fname, ':') == NULL) {
  88                 /* setup some EAs */
  89                 io.in.eas.num_eas = 2;
  90                 io.in.eas.eas = talloc_array(tmp_ctx, struct ea_struct, 2);
  91                 io.in.eas.eas[0].flags = 0;
  92                 io.in.eas.eas[0].name.s = "EAONE";
  93                 io.in.eas.eas[0].value = data_blob_talloc(tmp_ctx, "VALUE1", 6);
  94                 io.in.eas.eas[1].flags = 0;
  95                 io.in.eas.eas[1].name.s = "SECONDEA";
  96                 io.in.eas.eas[1].value = data_blob_talloc(tmp_ctx, "ValueTwo", 8);
  97         }
  98 
  99         status = smb2_create(tree, tmp_ctx, &io);
 100         talloc_free(tmp_ctx);
 101         NT_STATUS_NOT_OK_RETURN(status);
 102 
 103         *handle = io.out.file.handle;
 104 
 105         if (!dir) {
 106                 status = smb2_util_write(tree, *handle, buf, 0, sizeof(buf));
 107                 NT_STATUS_NOT_OK_RETURN(status);
 108         }
 109 
 110         /* make sure all the timestamps aren't the same, and are also 
 111            in different DST zones*/
 112         setfile.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
 113         setfile.generic.in.file.handle = *handle;
 114 
 115         unix_to_nt_time(&setfile.basic_info.in.create_time, t + 9*30*24*60*60);
 116         unix_to_nt_time(&setfile.basic_info.in.access_time, t + 6*30*24*60*60);
 117         unix_to_nt_time(&setfile.basic_info.in.write_time,  t + 3*30*24*60*60);
 118         unix_to_nt_time(&setfile.basic_info.in.change_time, t + 1*30*24*60*60);
 119         setfile.basic_info.in.attrib      = FILE_ATTRIBUTE_NORMAL;
 120 
 121         status = smb2_setinfo_file(tree, &setfile);
 122         if (!NT_STATUS_IS_OK(status)) {
 123                 printf("Failed to setup file times - %s\n", nt_errstr(status));
 124                 return status;
 125         }
 126 
 127         /* make sure all the timestamps aren't the same */
 128         fileinfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
 129         fileinfo.generic.in.file.handle = *handle;
 130 
 131         status = smb2_getinfo_file(tree, tree, &fileinfo);
 132         if (!NT_STATUS_IS_OK(status)) {
 133                 printf("Failed to query file times - %s\n", nt_errstr(status));
 134                 return status;
 135                 
 136         }
 137 
 138 #define CHECK_TIME(field) do {\
 139         if (setfile.basic_info.in.field != fileinfo.all_info2.out.field) { \
 140                 printf("(%s) " #field " not setup correctly: %s(%llu) => %s(%llu)\n", \
 141                         __location__, \
 142                         nt_time_string(tree, setfile.basic_info.in.field), \
 143                         (unsigned long long)setfile.basic_info.in.field, \
 144                         nt_time_string(tree, fileinfo.basic_info.out.field), \
 145                         (unsigned long long)fileinfo.basic_info.out.field); \
 146                 status = NT_STATUS_INVALID_PARAMETER; \
 147         } \
 148 } while (0)
 149 
 150         CHECK_TIME(create_time);
 151         CHECK_TIME(access_time);
 152         CHECK_TIME(write_time);
 153         CHECK_TIME(change_time);
 154 
 155         return status;
 156 }
 157 
 158 /*
 159   create a complex file using the SMB2 protocol
 160 */
 161 NTSTATUS smb2_create_complex_file(struct smb2_tree *tree, const char *fname, 
     /* [<][>][^][v][top][bottom][index][help] */
 162                                          struct smb2_handle *handle)
 163 {
 164         return smb2_create_complex(tree, fname, handle, false);
 165 }
 166 
 167 /*
 168   create a complex dir using the SMB2 protocol
 169 */
 170 NTSTATUS smb2_create_complex_dir(struct smb2_tree *tree, const char *fname, 
     /* [<][>][^][v][top][bottom][index][help] */
 171                                  struct smb2_handle *handle)
 172 {
 173         return smb2_create_complex(tree, fname, handle, true);
 174 }
 175 
 176 /*
 177   show lots of information about a file
 178 */
 179 void torture_smb2_all_info(struct smb2_tree *tree, struct smb2_handle handle)
     /* [<][>][^][v][top][bottom][index][help] */
 180 {
 181         NTSTATUS status;
 182         TALLOC_CTX *tmp_ctx = talloc_new(tree);
 183         union smb_fileinfo io;
 184 
 185         io.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
 186         io.generic.in.file.handle = handle;
 187 
 188         status = smb2_getinfo_file(tree, tmp_ctx, &io);
 189         if (!NT_STATUS_IS_OK(status)) {
 190                 DEBUG(0,("getinfo failed - %s\n", nt_errstr(status)));
 191                 talloc_free(tmp_ctx);
 192                 return;
 193         }
 194 
 195         d_printf("all_info for '%s'\n", io.all_info2.out.fname.s);
 196         d_printf("\tcreate_time:    %s\n", nt_time_string(tmp_ctx, io.all_info2.out.create_time));
 197         d_printf("\taccess_time:    %s\n", nt_time_string(tmp_ctx, io.all_info2.out.access_time));
 198         d_printf("\twrite_time:     %s\n", nt_time_string(tmp_ctx, io.all_info2.out.write_time));
 199         d_printf("\tchange_time:    %s\n", nt_time_string(tmp_ctx, io.all_info2.out.change_time));
 200         d_printf("\tattrib:         0x%x\n", io.all_info2.out.attrib);
 201         d_printf("\tunknown1:       0x%x\n", io.all_info2.out.unknown1);
 202         d_printf("\talloc_size:     %llu\n", (long long)io.all_info2.out.alloc_size);
 203         d_printf("\tsize:           %llu\n", (long long)io.all_info2.out.size);
 204         d_printf("\tnlink:          %u\n", io.all_info2.out.nlink);
 205         d_printf("\tdelete_pending: %u\n", io.all_info2.out.delete_pending);
 206         d_printf("\tdirectory:      %u\n", io.all_info2.out.directory);
 207         d_printf("\tfile_id:        %llu\n", (long long)io.all_info2.out.file_id);
 208         d_printf("\tea_size:        %u\n", io.all_info2.out.ea_size);
 209         d_printf("\taccess_mask:    0x%08x\n", io.all_info2.out.access_mask);
 210         d_printf("\tposition:       0x%llx\n", (long long)io.all_info2.out.position);
 211         d_printf("\tmode:           0x%llx\n", (long long)io.all_info2.out.mode);
 212 
 213         /* short name, if any */
 214         io.generic.level = RAW_FILEINFO_ALT_NAME_INFORMATION;
 215         status = smb2_getinfo_file(tree, tmp_ctx, &io);
 216         if (NT_STATUS_IS_OK(status)) {
 217                 d_printf("\tshort name:     '%s'\n", io.alt_name_info.out.fname.s);
 218         }
 219 
 220         /* the EAs, if any */
 221         io.generic.level = RAW_FILEINFO_SMB2_ALL_EAS;
 222         status = smb2_getinfo_file(tree, tmp_ctx, &io);
 223         if (NT_STATUS_IS_OK(status)) {
 224                 int i;
 225                 for (i=0;i<io.all_eas.out.num_eas;i++) {
 226                         d_printf("\tEA[%d] flags=%d len=%d '%s'\n", i,
 227                                  io.all_eas.out.eas[i].flags,
 228                                  (int)io.all_eas.out.eas[i].value.length,
 229                                  io.all_eas.out.eas[i].name.s);
 230                 }
 231         }
 232 
 233         /* streams, if available */
 234         io.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
 235         status = smb2_getinfo_file(tree, tmp_ctx, &io);
 236         if (NT_STATUS_IS_OK(status)) {
 237                 int i;
 238                 for (i=0;i<io.stream_info.out.num_streams;i++) {
 239                         d_printf("\tstream %d:\n", i);
 240                         d_printf("\t\tsize       %ld\n", 
 241                                  (long)io.stream_info.out.streams[i].size);
 242                         d_printf("\t\talloc size %ld\n", 
 243                                  (long)io.stream_info.out.streams[i].alloc_size);
 244                         d_printf("\t\tname       %s\n", io.stream_info.out.streams[i].stream_name.s);
 245                 }
 246         }       
 247 
 248         if (DEBUGLVL(1)) {
 249                 /* the security descriptor */
 250                 io.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
 251                 io.query_secdesc.in.secinfo_flags = 
 252                         SECINFO_OWNER|SECINFO_GROUP|
 253                         SECINFO_DACL;
 254                 status = smb2_getinfo_file(tree, tmp_ctx, &io);
 255                 if (NT_STATUS_IS_OK(status)) {
 256                         NDR_PRINT_DEBUG(security_descriptor, io.query_secdesc.out.sd);
 257                 }
 258         }
 259 
 260         talloc_free(tmp_ctx);   
 261 }
 262 
 263 
 264 /*
 265   open a smb2 connection
 266 */
 267 bool torture_smb2_connection(struct torture_context *tctx, struct smb2_tree **tree)
     /* [<][>][^][v][top][bottom][index][help] */
 268 {
 269         NTSTATUS status;
 270         const char *host = torture_setting_string(tctx, "host", NULL);
 271         const char *share = torture_setting_string(tctx, "share", NULL);
 272         struct cli_credentials *credentials = cmdline_credentials;
 273         struct smbcli_options options;
 274 
 275         lp_smbcli_options(tctx->lp_ctx, &options);
 276 
 277         status = smb2_connect(tctx, host, 
 278                                                   lp_smb_ports(tctx->lp_ctx),
 279                                                   share, 
 280                               lp_resolve_context(tctx->lp_ctx),
 281                               credentials, tree, 
 282                               tctx->ev, &options,
 283                                   lp_socket_options(tctx->lp_ctx),
 284                                   lp_gensec_settings(tctx, tctx->lp_ctx)
 285                                   );
 286         if (!NT_STATUS_IS_OK(status)) {
 287                 printf("Failed to connect to SMB2 share \\\\%s\\%s - %s\n",
 288                        host, share, nt_errstr(status));
 289                 return false;
 290         }
 291         return true;
 292 }
 293 
 294 
 295 /*
 296   create and return a handle to a test file
 297 */
 298 NTSTATUS torture_smb2_testfile(struct smb2_tree *tree, const char *fname, 
     /* [<][>][^][v][top][bottom][index][help] */
 299                                struct smb2_handle *handle)
 300 {
 301         struct smb2_create io;
 302         struct smb2_read r;
 303         NTSTATUS status;
 304 
 305         ZERO_STRUCT(io);
 306         io.in.oplock_level = 0;
 307         io.in.desired_access = SEC_RIGHTS_FILE_ALL;
 308         io.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
 309         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
 310         io.in.share_access = 
 311                 NTCREATEX_SHARE_ACCESS_DELETE|
 312                 NTCREATEX_SHARE_ACCESS_READ|
 313                 NTCREATEX_SHARE_ACCESS_WRITE;
 314         io.in.create_options = 0;
 315         io.in.fname = fname;
 316 
 317         status = smb2_create(tree, tree, &io);
 318         NT_STATUS_NOT_OK_RETURN(status);
 319 
 320         *handle = io.out.file.handle;
 321 
 322         ZERO_STRUCT(r);
 323         r.in.file.handle = *handle;
 324         r.in.length      = 5;
 325         r.in.offset      = 0;
 326 
 327         smb2_read(tree, tree, &r);
 328 
 329         return NT_STATUS_OK;
 330 }
 331 
 332 /*
 333   create and return a handle to a test directory
 334 */
 335 NTSTATUS torture_smb2_testdir(struct smb2_tree *tree, const char *fname, 
     /* [<][>][^][v][top][bottom][index][help] */
 336                               struct smb2_handle *handle)
 337 {
 338         struct smb2_create io;
 339         NTSTATUS status;
 340 
 341         ZERO_STRUCT(io);
 342         io.in.oplock_level = 0;
 343         io.in.desired_access = SEC_RIGHTS_DIR_ALL;
 344         io.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
 345         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
 346         io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE;
 347         io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
 348         io.in.fname = fname;
 349 
 350         status = smb2_create(tree, tree, &io);
 351         NT_STATUS_NOT_OK_RETURN(status);
 352 
 353         *handle = io.out.file.handle;
 354 
 355         return NT_STATUS_OK;
 356 }
 357 
 358 
 359 /*
 360   create a complex file using the old SMB protocol, to make it easier to 
 361   find fields in SMB2 getinfo levels
 362 */
 363 NTSTATUS torture_setup_complex_file(struct smb2_tree *tree, const char *fname)
     /* [<][>][^][v][top][bottom][index][help] */
 364 {
 365         struct smb2_handle handle;
 366         NTSTATUS status = smb2_create_complex_file(tree, fname, &handle);
 367         NT_STATUS_NOT_OK_RETURN(status);
 368         return smb2_util_close(tree, handle);
 369 }
 370 
 371 
 372 /*
 373   create a complex dir using the old SMB protocol, to make it easier to 
 374   find fields in SMB2 getinfo levels
 375 */
 376 NTSTATUS torture_setup_complex_dir(struct smb2_tree *tree, const char *fname)
     /* [<][>][^][v][top][bottom][index][help] */
 377 {
 378         struct smb2_handle handle;
 379         NTSTATUS status = smb2_create_complex_dir(tree, fname, &handle);
 380         NT_STATUS_NOT_OK_RETURN(status);
 381         return smb2_util_close(tree, handle);
 382 }
 383 
 384 
 385 /*
 386   return a handle to the root of the share
 387 */
 388 NTSTATUS smb2_util_roothandle(struct smb2_tree *tree, struct smb2_handle *handle)
     /* [<][>][^][v][top][bottom][index][help] */
 389 {
 390         struct smb2_create io;
 391         NTSTATUS status;
 392 
 393         ZERO_STRUCT(io);
 394         io.in.oplock_level = 0;
 395         io.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_DIR_READ_ATTRIBUTE | SEC_DIR_LIST;
 396         io.in.file_attributes   = 0;
 397         io.in.create_disposition = NTCREATEX_DISP_OPEN;
 398         io.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE;
 399         io.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT;
 400         io.in.fname = NULL;
 401 
 402         status = smb2_create(tree, tree, &io);
 403         NT_STATUS_NOT_OK_RETURN(status);
 404 
 405         *handle = io.out.file.handle;
 406 
 407         return NT_STATUS_OK;
 408 }

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