s3/docs: Remove reference to nonexistent file.
[Samba/gbeck.git] / source4 / torture / smb2 / setinfo.c
blob7a912b4989a27275908886c2df78eee5c09a4220
1 /*
2 Unix SMB/CIFS implementation.
4 SMB2 setinfo individual test suite
6 Copyright (C) Andrew Tridgell 2005
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.
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.
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/>.
22 #include "includes.h"
23 #include "system/time.h"
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
27 #include "torture/torture.h"
28 #include "torture/smb2/proto.h"
30 #include "libcli/security/security.h"
31 #include "librpc/gen_ndr/ndr_security.h"
33 #define BASEDIR ""
35 /* basic testing of all SMB2 setinfo calls
36 for each call we test that it succeeds, and where possible test
37 for consistency between the calls.
39 bool torture_smb2_setinfo(struct torture_context *torture)
41 struct smb2_tree *tree;
42 bool ret = true;
43 struct smb2_handle handle;
44 char *fname;
45 char *fname_new;
46 union smb_fileinfo finfo2;
47 union smb_setfileinfo sfinfo;
48 struct security_ace ace;
49 struct security_descriptor *sd;
50 struct dom_sid *test_sid;
51 NTSTATUS status, status2=NT_STATUS_OK;
52 const char *call_name;
53 time_t basetime = (time(NULL) - 86400) & ~1;
54 int n = time(NULL) % 100;
56 ZERO_STRUCT(handle);
58 fname = talloc_asprintf(torture, BASEDIR "fnum_test_%d.txt", n);
59 fname_new = talloc_asprintf(torture, BASEDIR "fnum_test_new_%d.txt", n);
61 if (!torture_smb2_connection(torture, &tree)) {
62 return false;
65 #define RECREATE_FILE(fname) do { \
66 smb2_util_close(tree, handle); \
67 status = smb2_create_complex_file(tree, fname, &handle); \
68 if (!NT_STATUS_IS_OK(status)) { \
69 printf("(%s) ERROR: open of %s failed (%s)\n", \
70 __location__, fname, nt_errstr(status)); \
71 ret = false; \
72 goto done; \
73 }} while (0)
75 #define RECREATE_BOTH do { \
76 RECREATE_FILE(fname); \
77 } while (0)
79 RECREATE_BOTH;
81 #define CHECK_CALL(call, rightstatus) do { \
82 call_name = #call; \
83 sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
84 sfinfo.generic.in.file.handle = handle; \
85 status = smb2_setinfo_file(tree, &sfinfo); \
86 if (!NT_STATUS_EQUAL(status, rightstatus)) { \
87 printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
88 nt_errstr(status), nt_errstr(rightstatus)); \
89 ret = false; \
90 goto done; \
91 } \
92 } while (0)
94 #define CHECK1(call) \
95 do { if (NT_STATUS_IS_OK(status)) { \
96 finfo2.generic.level = RAW_FILEINFO_ ## call; \
97 finfo2.generic.in.file.handle = handle; \
98 status2 = smb2_getinfo_file(tree, torture, &finfo2); \
99 if (!NT_STATUS_IS_OK(status2)) { \
100 printf("(%s) %s - %s\n", __location__, #call, nt_errstr(status2)); \
101 ret = false; \
102 goto done; \
104 }} while (0)
106 #define CHECK_VALUE(call, stype, field, value) do { \
107 CHECK1(call); \
108 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \
109 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
110 call_name, #stype, #field, \
111 (uint_t)value, (uint_t)finfo2.stype.out.field); \
112 torture_smb2_all_info(tree, handle); \
113 ret = false; \
114 goto done; \
115 }} while (0)
117 #define CHECK_TIME(call, stype, field, value) do { \
118 CHECK1(call); \
119 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \
120 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
121 call_name, #stype, #field, \
122 (uint_t)value, \
123 (uint_t)nt_time_to_unix(finfo2.stype.out.field)); \
124 printf("\t%s", timestring(torture, value)); \
125 printf("\t%s\n", nt_time_string(torture, finfo2.stype.out.field)); \
126 torture_smb2_all_info(tree, handle); \
127 ret = false; \
128 goto done; \
129 }} while (0)
131 #define CHECK_STATUS(status, correct) do { \
132 if (!NT_STATUS_EQUAL(status, correct)) { \
133 printf("(%s) Incorrect status %s - should be %s\n", \
134 __location__, nt_errstr(status), nt_errstr(correct)); \
135 ret = false; \
136 goto done; \
137 }} while (0)
139 torture_smb2_all_info(tree, handle);
141 printf("test basic_information level\n");
142 basetime += 86400;
143 unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100);
144 unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200);
145 unix_to_nt_time(&sfinfo.basic_info.in.write_time, basetime + 300);
146 unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400);
147 sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_READONLY;
148 CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
149 CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, create_time, basetime + 100);
150 CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, access_time, basetime + 200);
151 CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, write_time, basetime + 300);
152 CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, change_time, basetime + 400);
153 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_READONLY);
155 printf("a zero time means don't change\n");
156 unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0);
157 unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0);
158 unix_to_nt_time(&sfinfo.basic_info.in.write_time, 0);
159 unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0);
160 sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
161 CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
162 CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, create_time, basetime + 100);
163 CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, access_time, basetime + 200);
164 CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, write_time, basetime + 300);
165 CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, change_time, basetime + 400);
166 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_NORMAL);
168 printf("change the attribute\n");
169 sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_HIDDEN;
170 CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
171 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN);
173 printf("zero attrib means don't change\n");
174 sfinfo.basic_info.in.attrib = 0;
175 CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
176 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN);
178 printf("can't change a file to a directory\n");
179 sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
180 CHECK_CALL(BASIC_INFORMATION, NT_STATUS_INVALID_PARAMETER);
182 printf("restore attribute\n");
183 sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
184 CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
185 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_NORMAL);
187 printf("test disposition_information level\n");
188 sfinfo.disposition_info.in.delete_on_close = 1;
189 CHECK_CALL(DISPOSITION_INFORMATION, NT_STATUS_OK);
190 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, delete_pending, 1);
191 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, nlink, 0);
193 sfinfo.disposition_info.in.delete_on_close = 0;
194 CHECK_CALL(DISPOSITION_INFORMATION, NT_STATUS_OK);
195 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, delete_pending, 0);
196 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, nlink, 1);
198 printf("test allocation_information level\n");
199 sfinfo.allocation_info.in.alloc_size = 0;
200 CHECK_CALL(ALLOCATION_INFORMATION, NT_STATUS_OK);
201 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 0);
202 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, alloc_size, 0);
204 sfinfo.allocation_info.in.alloc_size = 4096;
205 CHECK_CALL(ALLOCATION_INFORMATION, NT_STATUS_OK);
206 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, alloc_size, 4096);
207 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 0);
209 printf("test end_of_file_info level\n");
210 sfinfo.end_of_file_info.in.size = 37;
211 CHECK_CALL(END_OF_FILE_INFORMATION, NT_STATUS_OK);
212 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 37);
214 sfinfo.end_of_file_info.in.size = 7;
215 CHECK_CALL(END_OF_FILE_INFORMATION, NT_STATUS_OK);
216 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 7);
218 printf("test position_information level\n");
219 sfinfo.position_information.in.position = 123456;
220 CHECK_CALL(POSITION_INFORMATION, NT_STATUS_OK);
221 CHECK_VALUE(POSITION_INFORMATION, position_information, position, 123456);
222 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, position, 123456);
224 printf("test mode_information level\n");
225 sfinfo.mode_information.in.mode = 2;
226 CHECK_CALL(MODE_INFORMATION, NT_STATUS_OK);
227 CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 2);
228 CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, mode, 2);
230 sfinfo.mode_information.in.mode = 1;
231 CHECK_CALL(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER);
233 sfinfo.mode_information.in.mode = 0;
234 CHECK_CALL(MODE_INFORMATION, NT_STATUS_OK);
235 CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);
237 printf("test sec_desc level\n");
238 ZERO_STRUCT(finfo2);
239 finfo2.query_secdesc.in.secinfo_flags =
240 SECINFO_OWNER |
241 SECINFO_GROUP |
242 SECINFO_DACL;
243 CHECK1(SEC_DESC);
244 sd = finfo2.query_secdesc.out.sd;
246 test_sid = dom_sid_parse_talloc(torture, "S-1-5-32-1234-5432");
247 ZERO_STRUCT(ace);
248 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
249 ace.flags = 0;
250 ace.access_mask = SEC_STD_ALL;
251 ace.trustee = *test_sid;
252 status = security_descriptor_dacl_add(sd, &ace);
253 CHECK_STATUS(status, NT_STATUS_OK);
255 printf("add a new ACE to the DACL\n");
257 sfinfo.set_secdesc.in.secinfo_flags = finfo2.query_secdesc.in.secinfo_flags;
258 sfinfo.set_secdesc.in.sd = sd;
259 CHECK_CALL(SEC_DESC, NT_STATUS_OK);
260 CHECK1(SEC_DESC);
262 if (!security_acl_equal(finfo2.query_secdesc.out.sd->dacl, sd->dacl)) {
263 printf("%s: security descriptors don't match!\n", __location__);
264 printf("got:\n");
265 NDR_PRINT_DEBUG(security_descriptor, finfo2.query_secdesc.out.sd);
266 printf("expected:\n");
267 NDR_PRINT_DEBUG(security_descriptor, sd);
268 ret = false;
271 printf("remove it again\n");
273 status = security_descriptor_dacl_del(sd, test_sid);
274 CHECK_STATUS(status, NT_STATUS_OK);
276 sfinfo.set_secdesc.in.secinfo_flags = finfo2.query_secdesc.in.secinfo_flags;
277 sfinfo.set_secdesc.in.sd = sd;
278 CHECK_CALL(SEC_DESC, NT_STATUS_OK);
279 CHECK1(SEC_DESC);
281 if (!security_acl_equal(finfo2.query_secdesc.out.sd->dacl, sd->dacl)) {
282 printf("%s: security descriptors don't match!\n", __location__);
283 printf("got:\n");
284 NDR_PRINT_DEBUG(security_descriptor, finfo2.query_secdesc.out.sd);
285 printf("expected:\n");
286 NDR_PRINT_DEBUG(security_descriptor, sd);
287 ret = false;
290 done:
291 status = smb2_util_close(tree, handle);
292 if (NT_STATUS_IS_ERR(status)) {
293 printf("Failed to delete %s - %s\n", fname, nt_errstr(status));
295 smb2_util_unlink(tree, fname);
297 return ret;