• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source4/torture/smb2/
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*/
40NTSTATUS smb2_util_write(struct smb2_tree *tree,
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*/
57static NTSTATUS smb2_create_complex(struct smb2_tree *tree, const char *fname,
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*/
161NTSTATUS smb2_create_complex_file(struct smb2_tree *tree, const char *fname,
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*/
170NTSTATUS smb2_create_complex_dir(struct smb2_tree *tree, const char *fname,
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*/
179void torture_smb2_all_info(struct smb2_tree *tree, struct smb2_handle handle)
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*/
267bool torture_smb2_connection(struct torture_context *tctx, struct smb2_tree **tree)
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*/
298NTSTATUS torture_smb2_testfile(struct smb2_tree *tree, const char *fname,
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*/
335NTSTATUS torture_smb2_testdir(struct smb2_tree *tree, const char *fname,
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*/
363NTSTATUS torture_setup_complex_file(struct smb2_tree *tree, const char *fname)
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*/
376NTSTATUS torture_setup_complex_dir(struct smb2_tree *tree, const char *fname)
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*/
388NTSTATUS smb2_util_roothandle(struct smb2_tree *tree, struct smb2_handle *handle)
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}
409