2 Unix SMB/CIFS implementation.
3 SMB torture tester utility functions
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libcli/raw/libcliraw.h"
23 #include "system/shmem.h"
24 #include "system/time.h"
25 #include "librpc/gen_ndr/ndr_security.h"
29 setup a directory ready for a test
31 BOOL torture_setup_dir(struct smbcli_state *cli, const char *dname)
33 smb_raw_exit(cli->session);
34 if (smbcli_deltree(cli->tree, dname) == -1 ||
35 NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
36 printf("Unable to setup %s - %s\n", dname, smbcli_errstr(cli->tree));
43 create a directory, returning a handle to it
45 int create_directory_handle(struct smbcli_tree *tree, const char *dname)
51 mem_ctx = talloc_init("create_directory_handle");
53 io.generic.level = RAW_OPEN_NTCREATEX;
54 io.ntcreatex.in.root_fid = 0;
55 io.ntcreatex.in.flags = 0;
56 io.ntcreatex.in.access_mask = SEC_FILE_ALL;
57 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
58 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
59 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
60 io.ntcreatex.in.alloc_size = 0;
61 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
62 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
63 io.ntcreatex.in.security_flags = 0;
64 io.ntcreatex.in.fname = dname;
66 status = smb_raw_open(tree, mem_ctx, &io);
67 if (!NT_STATUS_IS_OK(status)) {
68 talloc_destroy(mem_ctx);
72 talloc_destroy(mem_ctx);
73 return io.ntcreatex.out.fnum;
77 sometimes we need a fairly complex file to work with, so we can test
78 all possible attributes.
80 int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char *fname)
84 union smb_setfileinfo setfile;
85 union smb_fileinfo fileinfo;
86 time_t t = (time(NULL) & ~1);
89 smbcli_unlink(cli->tree, fname);
90 fnum = smbcli_nt_create_full(cli->tree, fname, 0,
92 FILE_ATTRIBUTE_NORMAL,
93 NTCREATEX_SHARE_ACCESS_DELETE|
94 NTCREATEX_SHARE_ACCESS_READ|
95 NTCREATEX_SHARE_ACCESS_WRITE,
96 NTCREATEX_DISP_OVERWRITE_IF,
98 if (fnum == -1) return -1;
100 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
103 setfile.generic.level = RAW_SFILEINFO_EA_SET;
104 setfile.generic.file.fnum = fnum;
105 setfile.ea_set.in.num_eas = 2;
106 setfile.ea_set.in.eas = talloc_array_p(mem_ctx, struct ea_struct, 2);
107 setfile.ea_set.in.eas[0].flags = 0;
108 setfile.ea_set.in.eas[0].name.s = "EAONE";
109 setfile.ea_set.in.eas[0].value = data_blob_talloc(mem_ctx, "VALUE1", 6);
110 setfile.ea_set.in.eas[1].flags = 0;
111 setfile.ea_set.in.eas[1].name.s = "SECONDEA";
112 setfile.ea_set.in.eas[1].value = data_blob_talloc(mem_ctx, "ValueTwo", 8);
113 status = smb_raw_setfileinfo(cli->tree, &setfile);
114 if (!NT_STATUS_IS_OK(status)) {
115 printf("Failed to setup EAs\n");
118 /* make sure all the timestamps aren't the same, and are also
119 in different DST zones*/
120 setfile.generic.level = RAW_SFILEINFO_SETATTRE;
121 setfile.generic.file.fnum = fnum;
123 setfile.setattre.in.create_time = t + 9*30*24*60*60;
124 setfile.setattre.in.access_time = t + 6*30*24*60*60;
125 setfile.setattre.in.write_time = t + 3*30*24*60*60;
127 status = smb_raw_setfileinfo(cli->tree, &setfile);
128 if (!NT_STATUS_IS_OK(status)) {
129 printf("Failed to setup file times - %s\n", nt_errstr(status));
132 /* make sure all the timestamps aren't the same */
133 fileinfo.generic.level = RAW_FILEINFO_GETATTRE;
134 fileinfo.generic.in.fnum = fnum;
136 status = smb_raw_fileinfo(cli->tree, mem_ctx, &fileinfo);
137 if (!NT_STATUS_IS_OK(status)) {
138 printf("Failed to query file times - %s\n", nt_errstr(status));
141 if (setfile.setattre.in.create_time != fileinfo.getattre.out.create_time) {
142 printf("create_time not setup correctly\n");
144 if (setfile.setattre.in.access_time != fileinfo.getattre.out.access_time) {
145 printf("access_time not setup correctly\n");
147 if (setfile.setattre.in.write_time != fileinfo.getattre.out.write_time) {
148 printf("write_time not setup correctly\n");
156 /* return a pointer to a anonymous shared memory segment of size "size"
157 which will persist across fork() but will disappear when all processes
160 The memory is not zeroed
162 This function uses system5 shared memory. It takes advantage of a property
163 that the memory is not destroyed if it is attached when the id is removed
165 void *shm_setup(int size)
170 shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
172 printf("can't get shared memory\n");
175 ret = (void *)shmat(shmid, 0, 0);
176 if (!ret || ret == (void *)-1) {
177 printf("can't attach to shared memory\n");
180 /* the following releases the ipc, but note that this process
181 and all its children will still have access to the memory, its
182 just that the shmid is no longer valid for other shm calls. This
183 means we don't leave behind lots of shm segments after we exit
185 See Stevens "advanced programming in unix env" for details
187 shmctl(shmid, IPC_RMID, 0);
194 check that a wire string matches the flags specified
195 not 100% accurate, but close enough for testing
197 BOOL wire_bad_flags(WIRE_STRING *str, int flags, struct smbcli_state *cli)
201 if (!str || !str->s) return True;
202 len = strlen(str->s);
203 if (flags & STR_TERMINATE) len++;
205 server_unicode = (cli->transport->negotiate.capabilities&CAP_UNICODE)?True:False;
206 if (getenv("CLI_FORCE_ASCII") || !lp_unicode()) {
207 server_unicode = False;
210 if ((flags & STR_UNICODE) || server_unicode) {
212 } else if (flags & STR_TERMINATE_ASCII) {
215 if (str->private_length != len) {
216 printf("Expected wire_length %d but got %d for '%s'\n",
217 len, str->private_length, str->s);
224 check if 2 NTTIMEs are equal
226 BOOL nt_time_equal(NTTIME *t1, NTTIME *t2)
232 dump a all_info QFILEINFO structure
234 void dump_all_info(TALLOC_CTX *mem_ctx, union smb_fileinfo *finfo)
236 d_printf("\tcreate_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.create_time));
237 d_printf("\taccess_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.access_time));
238 d_printf("\twrite_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.write_time));
239 d_printf("\tchange_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.change_time));
240 d_printf("\tattrib: 0x%x\n", finfo->all_info.out.attrib);
241 d_printf("\talloc_size: %llu\n", (uint64_t)finfo->all_info.out.alloc_size);
242 d_printf("\tsize: %llu\n", (uint64_t)finfo->all_info.out.size);
243 d_printf("\tnlink: %u\n", finfo->all_info.out.nlink);
244 d_printf("\tdelete_pending: %u\n", finfo->all_info.out.delete_pending);
245 d_printf("\tdirectory: %u\n", finfo->all_info.out.directory);
246 d_printf("\tea_size: %u\n", finfo->all_info.out.ea_size);
247 d_printf("\tfname: '%s'\n", finfo->all_info.out.fname.s);
251 dump file infor by name
253 void torture_all_info(struct smbcli_tree *tree, const char *fname)
255 TALLOC_CTX *mem_ctx = talloc_init("%s", fname);
256 union smb_fileinfo finfo;
259 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
260 finfo.generic.in.fname = fname;
261 status = smb_raw_pathinfo(tree, mem_ctx, &finfo);
262 if (!NT_STATUS_IS_OK(status)) {
263 d_printf("%s - %s\n", fname, nt_errstr(status));
267 d_printf("%s:\n", fname);
268 dump_all_info(mem_ctx, &finfo);
269 talloc_destroy(mem_ctx);
274 split a UNC name into server and share names
276 BOOL split_unc_name(const char *unc, char **server, char **share)
278 char *p = strdup(unc);
279 if (!p) return False;
280 all_string_sub(p, "\\", "/", 0);
281 if (strncmp(p, "//", 2) != 0) return False;
284 p = strchr(*server, '/');
285 if (!p) return False;
294 split a USER%PASS pair into username and password
296 BOOL split_username(const char *pair, char **user, char **pass)
298 char *p = strdup(pair);
299 if (!p) return False;
303 p = strchr(*user, '%');
304 if (!p) return False;
313 set a attribute on a file
315 BOOL torture_set_file_attribute(struct smbcli_tree *tree, const char *fname, uint16_t attrib)
317 union smb_setfileinfo sfinfo;
320 sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
321 sfinfo.generic.file.fname = fname;
323 ZERO_STRUCT(sfinfo.basic_info.in);
324 sfinfo.basic_info.in.attrib = attrib;
325 status = smb_raw_setpathinfo(tree, &sfinfo);
326 return NT_STATUS_IS_OK(status);
331 set a file descriptor as sparse
333 NTSTATUS torture_set_sparse(struct smbcli_tree *tree, int fnum)
339 mem_ctx = talloc_init("torture_set_sparse");
341 return NT_STATUS_NO_MEMORY;
344 nt.ntioctl.level = RAW_IOCTL_NTIOCTL;
345 nt.ntioctl.in.function = 0x900c4;
346 nt.ntioctl.in.fnum = fnum;
347 nt.ntioctl.in.fsctl = True;
348 nt.ntioctl.in.filter = 0;
350 status = smb_raw_ioctl(tree, mem_ctx, &nt);
352 talloc_destroy(mem_ctx);
358 check that an EA has the right value
360 NTSTATUS torture_check_ea(struct smbcli_state *cli,
361 const char *fname, const char *eaname, const char *value)
363 union smb_fileinfo info;
366 TALLOC_CTX *mem_ctx = talloc(cli, 0);
368 info.ea_list.level = RAW_FILEINFO_EA_LIST;
369 info.ea_list.file.fname = fname;
370 info.ea_list.in.num_names = 1;
371 info.ea_list.in.ea_names = &ea;
375 status = smb_raw_pathinfo(cli->tree, mem_ctx, &info);
376 if (!NT_STATUS_IS_OK(status)) {
377 talloc_free(mem_ctx);
381 if (info.ea_list.out.num_eas != 1) {
382 printf("Expected 1 ea in ea_list\n");
383 talloc_free(mem_ctx);
384 return NT_STATUS_EA_CORRUPT_ERROR;
387 if (StrCaseCmp(eaname, info.ea_list.out.eas[0].name.s) != 0) {
388 printf("Expected ea '%s' not '%s' in ea_list\n",
389 eaname, info.ea_list.out.eas[0].name.s);
390 talloc_free(mem_ctx);
391 return NT_STATUS_EA_CORRUPT_ERROR;
395 if (info.ea_list.out.eas[0].value.length != 0) {
396 printf("Expected zero length ea for %s\n", eaname);
397 talloc_free(mem_ctx);
398 return NT_STATUS_EA_CORRUPT_ERROR;
400 talloc_free(mem_ctx);
404 if (strlen(value) == info.ea_list.out.eas[0].value.length &&
405 memcmp(value, info.ea_list.out.eas[0].value.data,
406 info.ea_list.out.eas[0].value.length) == 0) {
407 talloc_free(mem_ctx);
411 printf("Expected value '%s' not '%*.*s' for ea %s\n",
413 info.ea_list.out.eas[0].value.length,
414 info.ea_list.out.eas[0].value.length,
415 info.ea_list.out.eas[0].value.data,
418 talloc_free(mem_ctx);
420 return NT_STATUS_EA_CORRUPT_ERROR;