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"
28 create a directory, returning a handle to it
30 int create_directory_handle(struct smbcli_tree *tree, const char *dname)
36 mem_ctx = talloc_init("create_directory_handle");
38 io.generic.level = RAW_OPEN_NTCREATEX;
39 io.ntcreatex.in.root_fid = 0;
40 io.ntcreatex.in.flags = 0;
41 io.ntcreatex.in.access_mask = SA_RIGHT_FILE_ALL_ACCESS;
42 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
43 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
44 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
45 io.ntcreatex.in.alloc_size = 0;
46 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
47 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
48 io.ntcreatex.in.security_flags = 0;
49 io.ntcreatex.in.fname = dname;
51 status = smb_raw_open(tree, mem_ctx, &io);
52 if (!NT_STATUS_IS_OK(status)) {
53 talloc_destroy(mem_ctx);
57 talloc_destroy(mem_ctx);
58 return io.ntcreatex.out.fnum;
62 sometimes we need a fairly complex file to work with, so we can test
63 all possible attributes.
65 int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char *fname)
69 union smb_setfileinfo setfile;
70 union smb_fileinfo fileinfo;
71 time_t t = (time(NULL) & ~1);
74 smbcli_unlink(cli->tree, fname);
75 fnum = smbcli_nt_create_full(cli->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
76 FILE_ATTRIBUTE_NORMAL,
77 NTCREATEX_SHARE_ACCESS_DELETE|
78 NTCREATEX_SHARE_ACCESS_READ|
79 NTCREATEX_SHARE_ACCESS_WRITE,
80 NTCREATEX_DISP_OVERWRITE_IF,
82 if (fnum == -1) return -1;
84 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
87 setfile.generic.level = RAW_SFILEINFO_EA_SET;
88 setfile.generic.file.fnum = fnum;
89 setfile.ea_set.in.ea.flags = 0;
90 setfile.ea_set.in.ea.name.s = "EAONE";
91 setfile.ea_set.in.ea.value = data_blob_talloc(mem_ctx, "VALUE1", 6);
93 status = smb_raw_setfileinfo(cli->tree, &setfile);
94 if (!NT_STATUS_IS_OK(status)) {
95 printf("Failed to setup EAs\n");
98 setfile.ea_set.in.ea.name.s = "SECONDEA";
99 setfile.ea_set.in.ea.value = data_blob_talloc(mem_ctx, "ValueTwo", 8);
100 status = smb_raw_setfileinfo(cli->tree, &setfile);
101 if (!NT_STATUS_IS_OK(status)) {
102 printf("Failed to setup EAs\n");
105 /* make sure all the timestamps aren't the same, and are also
106 in different DST zones*/
107 setfile.generic.level = RAW_SFILEINFO_SETATTRE;
108 setfile.generic.file.fnum = fnum;
110 setfile.setattre.in.create_time = t + 9*30*24*60*60;
111 setfile.setattre.in.access_time = t + 6*30*24*60*60;
112 setfile.setattre.in.write_time = t + 3*30*24*60*60;
114 status = smb_raw_setfileinfo(cli->tree, &setfile);
115 if (!NT_STATUS_IS_OK(status)) {
116 printf("Failed to setup file times - %s\n", nt_errstr(status));
119 /* make sure all the timestamps aren't the same */
120 fileinfo.generic.level = RAW_FILEINFO_GETATTRE;
121 fileinfo.generic.in.fnum = fnum;
123 status = smb_raw_fileinfo(cli->tree, mem_ctx, &fileinfo);
124 if (!NT_STATUS_IS_OK(status)) {
125 printf("Failed to query file times - %s\n", nt_errstr(status));
128 if (setfile.setattre.in.create_time != fileinfo.getattre.out.create_time) {
129 printf("create_time not setup correctly\n");
131 if (setfile.setattre.in.access_time != fileinfo.getattre.out.access_time) {
132 printf("access_time not setup correctly\n");
134 if (setfile.setattre.in.write_time != fileinfo.getattre.out.write_time) {
135 printf("write_time not setup correctly\n");
143 /* return a pointer to a anonymous shared memory segment of size "size"
144 which will persist across fork() but will disappear when all processes
147 The memory is not zeroed
149 This function uses system5 shared memory. It takes advantage of a property
150 that the memory is not destroyed if it is attached when the id is removed
152 void *shm_setup(int size)
157 shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
159 printf("can't get shared memory\n");
162 ret = (void *)shmat(shmid, 0, 0);
163 if (!ret || ret == (void *)-1) {
164 printf("can't attach to shared memory\n");
167 /* the following releases the ipc, but note that this process
168 and all its children will still have access to the memory, its
169 just that the shmid is no longer valid for other shm calls. This
170 means we don't leave behind lots of shm segments after we exit
172 See Stevens "advanced programming in unix env" for details
174 shmctl(shmid, IPC_RMID, 0);
181 check that a wire string matches the flags specified
182 not 100% accurate, but close enough for testing
184 BOOL wire_bad_flags(WIRE_STRING *str, int flags, struct smbcli_state *cli)
188 if (!str || !str->s) return True;
189 len = strlen(str->s);
190 if (flags & STR_TERMINATE) len++;
192 server_unicode = (cli->transport->negotiate.capabilities&CAP_UNICODE)?True:False;
193 if (getenv("CLI_FORCE_ASCII") || !lp_unicode()) {
194 server_unicode = False;
197 if ((flags & STR_UNICODE) || server_unicode) {
199 } else if (flags & STR_TERMINATE_ASCII) {
202 if (str->private_length != len) {
203 printf("Expected wire_length %d but got %d for '%s'\n",
204 len, str->private_length, str->s);
211 check if 2 NTTIMEs are equal
213 BOOL nt_time_equal(NTTIME *t1, NTTIME *t2)
219 dump a all_info QFILEINFO structure
221 void dump_all_info(TALLOC_CTX *mem_ctx, union smb_fileinfo *finfo)
223 d_printf("\tcreate_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.create_time));
224 d_printf("\taccess_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.access_time));
225 d_printf("\twrite_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.write_time));
226 d_printf("\tchange_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.change_time));
227 d_printf("\tattrib: 0x%x\n", finfo->all_info.out.attrib);
228 d_printf("\talloc_size: %llu\n", (uint64_t)finfo->all_info.out.alloc_size);
229 d_printf("\tsize: %llu\n", (uint64_t)finfo->all_info.out.size);
230 d_printf("\tnlink: %u\n", finfo->all_info.out.nlink);
231 d_printf("\tdelete_pending: %u\n", finfo->all_info.out.delete_pending);
232 d_printf("\tdirectory: %u\n", finfo->all_info.out.directory);
233 d_printf("\tea_size: %u\n", finfo->all_info.out.ea_size);
234 d_printf("\tfname: '%s'\n", finfo->all_info.out.fname.s);
238 dump file infor by name
240 void torture_all_info(struct smbcli_tree *tree, const char *fname)
242 TALLOC_CTX *mem_ctx = talloc_init("%s", fname);
243 union smb_fileinfo finfo;
246 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
247 finfo.generic.in.fname = fname;
248 status = smb_raw_pathinfo(tree, mem_ctx, &finfo);
249 if (!NT_STATUS_IS_OK(status)) {
250 d_printf("%s - %s\n", fname, nt_errstr(status));
254 d_printf("%s:\n", fname);
255 dump_all_info(mem_ctx, &finfo);
256 talloc_destroy(mem_ctx);
261 split a UNC name into server and share names
263 BOOL split_unc_name(const char *unc, char **server, char **share)
265 char *p = strdup(unc);
266 if (!p) return False;
267 all_string_sub(p, "\\", "/", 0);
268 if (strncmp(p, "//", 2) != 0) return False;
271 p = strchr(*server, '/');
272 if (!p) return False;
281 split a USER%PASS pair into username and password
283 BOOL split_username(const char *pair, char **user, char **pass)
285 char *p = strdup(pair);
286 if (!p) return False;
290 p = strchr(*user, '%');
291 if (!p) return False;
300 set a attribute on a file
302 BOOL torture_set_file_attribute(struct smbcli_tree *tree, const char *fname, uint16_t attrib)
304 union smb_setfileinfo sfinfo;
307 sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
308 sfinfo.generic.file.fname = fname;
310 ZERO_STRUCT(sfinfo.basic_info.in);
311 sfinfo.basic_info.in.attrib = attrib;
312 status = smb_raw_setpathinfo(tree, &sfinfo);
313 return NT_STATUS_IS_OK(status);
318 set a file descriptor as sparse
320 NTSTATUS torture_set_sparse(struct smbcli_tree *tree, int fnum)
326 mem_ctx = talloc_init("torture_set_sparse");
328 return NT_STATUS_NO_MEMORY;
331 nt.ntioctl.level = RAW_IOCTL_NTIOCTL;
332 nt.ntioctl.in.function = 0x900c4;
333 nt.ntioctl.in.fnum = fnum;
334 nt.ntioctl.in.fsctl = True;
335 nt.ntioctl.in.filter = 0;
337 status = smb_raw_ioctl(tree, mem_ctx, &nt);
339 talloc_destroy(mem_ctx);