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