Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : openattr tester
5 :
6 : Copyright (C) Andrew Tridgell 2003
7 : Copyright (C) David Mulder 2019
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "libcli/smb2/smb2.h"
25 : #include "libcli/smb2/smb2_calls.h"
26 : #include "torture/torture.h"
27 : #include "libcli/security/security_descriptor.h"
28 : #include "torture/smb2/proto.h"
29 :
30 : static const uint32_t open_attrs_table[] = {
31 : FILE_ATTRIBUTE_NORMAL,
32 : FILE_ATTRIBUTE_ARCHIVE,
33 : FILE_ATTRIBUTE_READONLY,
34 : FILE_ATTRIBUTE_HIDDEN,
35 : FILE_ATTRIBUTE_SYSTEM,
36 :
37 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
38 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
39 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
40 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
41 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
42 : FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
43 :
44 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
45 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
46 : FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
47 : FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
48 : };
49 :
50 : struct trunc_open_results {
51 : unsigned int num;
52 : uint32_t init_attr;
53 : uint32_t trunc_attr;
54 : uint32_t result_attr;
55 : };
56 :
57 : static const struct trunc_open_results attr_results[] = {
58 : { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
59 : { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
60 : { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
61 : { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
62 : { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
63 : { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
64 : { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
65 : { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
66 : { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
67 : { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
68 : { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
69 : { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
70 : { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
71 : { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
72 : { 104, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
73 : { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
74 : { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
75 : { 121, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
76 : { 170, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN },
77 : { 173, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM },
78 : { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
79 : { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
80 : { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
81 : { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
82 : { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
83 : { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
84 : };
85 :
86 49 : static NTSTATUS smb2_setatr(struct smb2_tree *tree, const char *name,
87 : uint32_t attrib)
88 : {
89 : NTSTATUS status;
90 49 : struct smb2_create create_io = {0};
91 : union smb_setfileinfo io;
92 :
93 49 : create_io.in.desired_access = SEC_FILE_READ_DATA |
94 : SEC_FILE_WRITE_ATTRIBUTE;
95 49 : create_io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
96 49 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
97 49 : create_io.in.create_disposition = NTCREATEX_DISP_OPEN;
98 49 : create_io.in.fname = name;
99 49 : status = smb2_create(tree, tree, &create_io);
100 49 : if (!NT_STATUS_IS_OK(status)) {
101 1 : return status;
102 : }
103 :
104 48 : ZERO_STRUCT(io);
105 48 : io.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION;
106 48 : io.basic_info.in.file.handle = create_io.out.file.handle;
107 48 : io.basic_info.in.attrib = attrib;
108 48 : status = smb2_setinfo_file(tree, &io);
109 48 : if (!NT_STATUS_IS_OK(status)) {
110 0 : return status;
111 : }
112 :
113 48 : status = smb2_util_close(tree, create_io.out.file.handle);
114 48 : if (!NT_STATUS_IS_OK(status)) {
115 0 : return status;
116 : }
117 :
118 48 : return status;
119 : }
120 :
121 1 : bool torture_smb2_openattrtest(struct torture_context *tctx,
122 : struct smb2_tree *tree)
123 : {
124 : NTSTATUS status;
125 1 : const char *fname = "openattr.file";
126 : uint16_t attr;
127 : unsigned int i, j, k, l;
128 1 : int ret = true;
129 :
130 17 : for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
131 16 : struct smb2_create create_io = {0};
132 16 : smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
133 16 : smb2_util_unlink(tree, fname);
134 16 : create_io.in.create_flags = 0;
135 16 : create_io.in.desired_access = SEC_FILE_WRITE_DATA;
136 16 : create_io.in.file_attributes = open_attrs_table[i];
137 16 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
138 16 : create_io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
139 16 : create_io.in.create_options = 0;
140 16 : create_io.in.security_flags = 0;
141 16 : create_io.in.fname = fname;
142 16 : status = smb2_create(tree, tctx, &create_io);
143 16 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
144 : talloc_asprintf(tctx, "open %d (1) of %s failed (%s)",
145 : i, fname, nt_errstr(status)));
146 :
147 16 : status = smb2_util_close(tree, create_io.out.file.handle);
148 16 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
149 : talloc_asprintf(tctx, "close %d (1) of %s failed (%s)",
150 : i, fname, nt_errstr(status)));
151 :
152 272 : for (j = 0; j < ARRAY_SIZE(open_attrs_table); j++) {
153 256 : create_io = (struct smb2_create){0};
154 256 : create_io.in.create_flags = 0;
155 256 : create_io.in.desired_access = SEC_FILE_READ_DATA|
156 : SEC_FILE_WRITE_DATA;
157 256 : create_io.in.file_attributes = open_attrs_table[j];
158 256 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
159 256 : create_io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
160 256 : create_io.in.create_options = 0;
161 256 : create_io.in.security_flags = 0;
162 256 : create_io.in.fname = fname;
163 256 : status = smb2_create(tree, tctx, &create_io);
164 :
165 256 : if (!NT_STATUS_IS_OK(status)) {
166 0 : for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
167 0 : torture_assert_goto(tctx,
168 : attr_results[l].num != k,
169 : ret, error_exit,
170 : talloc_asprintf(tctx,
171 : "[%d] trunc open 0x%x "
172 : "-> 0x%x of %s failed "
173 : "- should have "
174 : "succeeded !(%s)",
175 : k, open_attrs_table[i],
176 : open_attrs_table[j],
177 : fname,
178 : nt_errstr(status)));
179 : }
180 0 : torture_assert_ntstatus_equal_goto(tctx,
181 : status, NT_STATUS_ACCESS_DENIED,
182 : ret, error_exit,
183 : talloc_asprintf(tctx,
184 : "[%d] trunc open 0x%x "
185 : "-> 0x%x failed with "
186 : "wrong error code %s",
187 : k, open_attrs_table[i],
188 : open_attrs_table[j],
189 : nt_errstr(status)));
190 0 : k++;
191 0 : continue;
192 : }
193 :
194 256 : status = smb2_util_close(tree, create_io.out.file.handle);
195 256 : torture_assert_ntstatus_ok_goto(tctx, status, ret,
196 : error_exit, talloc_asprintf(tctx,
197 : "close %d (2) of %s failed (%s)", j,
198 : fname, nt_errstr(status)));
199 :
200 256 : status = smb2_util_getatr(tree, fname, &attr, NULL, NULL);
201 256 : torture_assert_ntstatus_ok_goto(tctx, status, ret,
202 : error_exit, talloc_asprintf(tctx,
203 : "getatr(2) failed (%s)",
204 : nt_errstr(status)));
205 :
206 6561 : for (l = 0; l < ARRAY_SIZE(attr_results); l++) {
207 6331 : if (attr_results[l].num == k) {
208 52 : if (attr != attr_results[l].result_attr ||
209 52 : open_attrs_table[i] != attr_results[l].init_attr ||
210 26 : open_attrs_table[j] != attr_results[l].trunc_attr) {
211 0 : ret = false;
212 0 : torture_fail_goto(tctx, error_exit,
213 : talloc_asprintf(tctx,
214 : "[%d] getatr check "
215 : "failed. [0x%x] trunc "
216 : "[0x%x] got attr 0x%x,"
217 : " should be 0x%x",
218 : k, open_attrs_table[i],
219 : open_attrs_table[j],
220 : (unsigned int)attr,
221 : attr_results[l].result_attr));
222 : }
223 26 : break;
224 : }
225 : }
226 256 : k++;
227 : }
228 : }
229 1 : error_exit:
230 1 : smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
231 1 : smb2_util_unlink(tree, fname);
232 :
233 :
234 1 : return ret;
235 : }
236 :
237 1 : bool torture_smb2_winattrtest(struct torture_context *tctx,
238 : struct smb2_tree *tree)
239 : {
240 1 : const char *fname = "winattr1.file";
241 1 : const char *dname = "winattr1.dir";
242 : uint16_t attr;
243 : uint16_t j;
244 : uint32_t aceno;
245 1 : bool ret = true;
246 : union smb_fileinfo query, query_org;
247 : NTSTATUS status;
248 1 : struct security_descriptor *sd1 = NULL, *sd2 = NULL;
249 1 : struct smb2_create create_io = {0};
250 1 : ZERO_STRUCT(query);
251 1 : ZERO_STRUCT(query_org);
252 :
253 : /* Test winattrs for file */
254 1 : smb2_util_unlink(tree, fname);
255 :
256 : /* Open a file*/
257 1 : create_io.in.create_flags = 0;
258 1 : create_io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA |
259 : SEC_STD_READ_CONTROL;
260 1 : create_io.in.file_attributes = 0;
261 1 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
262 1 : create_io.in.create_disposition = FILE_SUPERSEDE;
263 1 : create_io.in.create_options = 0;
264 1 : create_io.in.security_flags = 0;
265 1 : create_io.in.fname = fname;
266 1 : status = smb2_create(tree, tctx, &create_io);
267 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
268 : talloc_asprintf(tctx, "open(1) of %s failed (%s)\n",
269 : fname, nt_errstr(status)));
270 :
271 : /* Get security descriptor and store it*/
272 1 : query_org.generic.level = RAW_FILEINFO_SEC_DESC;
273 1 : query_org.generic.in.file.handle = create_io.out.file.handle;
274 1 : query_org.query_secdesc.in.secinfo_flags = SECINFO_OWNER|
275 : SECINFO_GROUP|
276 : SECINFO_DACL;
277 1 : status = smb2_getinfo_file(tree, tctx, &query_org);
278 1 : if(!NT_STATUS_IS_OK(status)){
279 0 : NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
280 0 : torture_assert_ntstatus_ok_goto(tctx, s, ret, error_exit,
281 : talloc_asprintf(tctx,
282 : "close(1) of %s failed (%s)\n",
283 : fname, nt_errstr(s)));
284 0 : ret = false;
285 0 : torture_fail_goto(tctx, error_exit, talloc_asprintf(tctx,
286 : "smb2_getinfo_file(1) of %s failed (%s)\n",
287 : fname, nt_errstr(status)));
288 : }
289 1 : sd1 = query_org.query_secdesc.out.sd;
290 :
291 1 : status = smb2_util_close(tree, create_io.out.file.handle);
292 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
293 : talloc_asprintf(tctx, "close(1) of %s failed (%s)\n",
294 : fname, nt_errstr(status)));
295 :
296 : /*Set and get attributes*/
297 17 : for (j = 0; j < ARRAY_SIZE(open_attrs_table); j++) {
298 16 : status = smb2_setatr(tree, fname, open_attrs_table[j]);
299 16 : torture_assert_ntstatus_ok_goto(tctx, status, ret,
300 : error_exit,
301 : talloc_asprintf(tctx, "setatr(2) failed (%s)",
302 : nt_errstr(status)));
303 :
304 16 : status = smb2_util_getatr(tree, fname, &attr, NULL, NULL);
305 16 : torture_assert_ntstatus_ok_goto(tctx, status, ret,
306 : error_exit,
307 : talloc_asprintf(tctx, "getatr(2) failed (%s)",
308 : nt_errstr(status)));
309 :
310 : /* Check the result */
311 16 : torture_assert_goto(tctx, attr == open_attrs_table[j], ret,
312 : error_exit, talloc_asprintf(tctx,
313 : "getatr check failed. \
314 : Attr applied [0x%x],got attr 0x%x, \
315 : should be 0x%x ", open_attrs_table[j],
316 : (uint16_t)attr, open_attrs_table[j]));
317 :
318 16 : create_io = (struct smb2_create){0};
319 16 : create_io.in.create_flags = 0;
320 16 : create_io.in.desired_access = SEC_FILE_READ_ATTRIBUTE|
321 : SEC_STD_READ_CONTROL;
322 16 : create_io.in.file_attributes = 0;
323 16 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
324 16 : create_io.in.create_disposition = FILE_OPEN_IF;
325 16 : create_io.in.create_options = 0;
326 16 : create_io.in.security_flags = 0;
327 16 : create_io.in.fname = fname;
328 16 : status = smb2_create(tree, tctx, &create_io);
329 16 : torture_assert_ntstatus_ok_goto(tctx, status, ret,
330 : error_exit,
331 : talloc_asprintf(tctx, "open(2) of %s failed (%s)\n",
332 : fname, nt_errstr(status)));
333 : /*Get security descriptor */
334 16 : query.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
335 16 : query.query_secdesc.in.file.handle = create_io.out.file.handle;
336 16 : query.query_secdesc.in.secinfo_flags = SECINFO_OWNER|
337 : SECINFO_GROUP|
338 : SECINFO_DACL;
339 16 : status = smb2_getinfo_file(tree, tctx, &query);
340 16 : if(!NT_STATUS_IS_OK(status)){
341 0 : NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
342 0 : torture_assert_ntstatus_ok_goto(tctx, s, ret,
343 : error_exit,
344 : talloc_asprintf(tctx,
345 : "close(2) of %s failed (%s)\n",
346 : fname, nt_errstr(s)));
347 0 : ret = false;
348 0 : torture_fail_goto(tctx, error_exit,
349 : talloc_asprintf(tctx,
350 : "smb2_getinfo_file(2) of %s failed (%s)\n",
351 : fname, nt_errstr(status)));
352 : }
353 16 : sd2 = query.query_secdesc.out.sd;
354 :
355 16 : status = smb2_util_close(tree, create_io.out.file.handle);
356 16 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
357 : talloc_asprintf(tctx, "close(2) of %s failed (%s)\n",
358 : fname, nt_errstr(status)));
359 :
360 : /*Compare security descriptors -- Must be same*/
361 80 : for (aceno=0;(sd1->dacl&&aceno < sd1->dacl->num_aces);aceno++){
362 64 : struct security_ace *ace1 = &sd1->dacl->aces[aceno];
363 64 : struct security_ace *ace2 = &sd2->dacl->aces[aceno];
364 :
365 64 : torture_assert_goto(tctx, security_ace_equal(ace1, ace2),
366 : ret, error_exit,
367 : "ACLs changed! Not expected!\n");
368 : }
369 :
370 16 : torture_comment(tctx, "[%d] setattr = [0x%x] got attr 0x%x\n",
371 0 : j, open_attrs_table[j], attr );
372 :
373 : }
374 :
375 :
376 : /* Check for Directory. */
377 :
378 1 : smb2_deltree(tree, dname);
379 1 : smb2_util_rmdir(tree, dname);
380 :
381 : /* Open a directory */
382 1 : create_io = (struct smb2_create){0};
383 1 : create_io.in.create_flags = 0;
384 1 : create_io.in.desired_access = SEC_RIGHTS_DIR_ALL;
385 1 : create_io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
386 1 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
387 1 : create_io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
388 1 : create_io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
389 1 : create_io.in.security_flags = 0;
390 1 : create_io.in.fname = dname;
391 1 : status = smb2_create(tree, tctx, &create_io);
392 :
393 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
394 : talloc_asprintf(tctx,
395 : "open (1) of %s failed (%s)",
396 : dname, nt_errstr(status)));
397 :
398 :
399 : /* Get Security Descriptor */
400 1 : query_org.generic.level = RAW_FILEINFO_SEC_DESC;
401 1 : query_org.generic.in.file.handle = create_io.out.file.handle;
402 1 : status = smb2_getinfo_file(tree, tctx, &query_org);
403 1 : if(!NT_STATUS_IS_OK(status)){
404 0 : NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
405 0 : torture_assert_ntstatus_ok_goto(tctx, s, ret, error_exit,
406 : talloc_asprintf(tctx,
407 : "close(1) of %s failed (%s)\n",
408 : dname, nt_errstr(s)));
409 0 : ret = false;
410 0 : torture_fail_goto(tctx, error_exit, talloc_asprintf(tctx,
411 : "smb2_getinfo_file(1) of %s failed (%s)\n", dname,
412 : nt_errstr(status)));
413 : }
414 1 : sd1 = query_org.query_secdesc.out.sd;
415 :
416 1 : status = smb2_util_close(tree, create_io.out.file.handle);
417 1 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
418 : talloc_asprintf(tctx,
419 : "close (1) of %s failed (%s)", dname,
420 : nt_errstr(status)));
421 :
422 : /* Set and get win attributes*/
423 16 : for (j = 1; j < ARRAY_SIZE(open_attrs_table); j++) {
424 :
425 15 : status = smb2_setatr(tree, dname, open_attrs_table[j]);
426 15 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
427 : talloc_asprintf(tctx, "setatr(2) failed (%s)",
428 : nt_errstr(status)));
429 :
430 15 : status = smb2_util_getatr(tree, dname, &attr, NULL, NULL);
431 15 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
432 : talloc_asprintf(tctx, "getatr(2) failed (%s)",
433 : nt_errstr(status)));
434 :
435 15 : torture_comment(tctx, "[%d] setatt = [0x%x] got attr 0x%x\n",
436 0 : j, open_attrs_table[j], attr );
437 :
438 : /* Check the result */
439 15 : torture_assert_goto(tctx,
440 : attr == (open_attrs_table[j]|FILE_ATTRIBUTE_DIRECTORY),
441 : ret, error_exit, talloc_asprintf(tctx,
442 : "getatr check failed. set attr "
443 : "[0x%x], got attr 0x%x, should be 0x%x\n",
444 : open_attrs_table[j], (uint16_t)attr,
445 : (unsigned int)(open_attrs_table[j]|FILE_ATTRIBUTE_DIRECTORY)));
446 :
447 15 : create_io = (struct smb2_create){0};
448 15 : create_io.in.create_flags = 0;
449 15 : create_io.in.desired_access = SEC_RIGHTS_DIR_READ;
450 15 : create_io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
451 15 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
452 15 : create_io.in.create_disposition = NTCREATEX_DISP_OPEN;
453 15 : create_io.in.create_options = 0;
454 15 : create_io.in.security_flags = 0;
455 15 : create_io.in.fname = dname;
456 15 : status = smb2_create(tree, tctx, &create_io);
457 :
458 15 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
459 : talloc_asprintf(tctx,
460 : "open (2) of %s failed (%s)",
461 : dname, nt_errstr(status)));
462 : /* Get security descriptor */
463 15 : query.generic.level = RAW_FILEINFO_SEC_DESC;
464 15 : query.generic.in.file.handle = create_io.out.file.handle;
465 15 : status = smb2_getinfo_file(tree, tctx, &query);
466 15 : if(!NT_STATUS_IS_OK(status)){
467 0 : NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
468 0 : torture_assert_ntstatus_ok_goto(tctx, s, ret, error_exit,
469 : talloc_asprintf(tctx,
470 : "close (2) of %s failed (%s)", dname,
471 : nt_errstr(s)));
472 0 : ret = false;
473 0 : torture_fail_goto(tctx, error_exit,
474 : talloc_asprintf(tctx,
475 : "smb2_getinfo_file(2) of %s failed(%s)\n",
476 : dname, nt_errstr(status)));
477 : }
478 15 : sd2 = query.query_secdesc.out.sd;
479 15 : status = smb2_util_close(tree, create_io.out.file.handle);
480 15 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
481 : talloc_asprintf(tctx,
482 : "close (2) of %s failed (%s)", dname,
483 : nt_errstr(status)));
484 :
485 : /* Security descriptor must be same*/
486 75 : for (aceno=0;(sd1->dacl&&aceno < sd1->dacl->num_aces);aceno++){
487 60 : struct security_ace *ace1 = &sd1->dacl->aces[aceno];
488 60 : struct security_ace *ace2 = &sd2->dacl->aces[aceno];
489 :
490 60 : torture_assert_goto(tctx, security_ace_equal(ace1, ace2),
491 : ret, error_exit,
492 : "ACLs changed! Not expected!\n");
493 : }
494 :
495 : }
496 :
497 1 : error_exit:
498 1 : smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
499 1 : smb2_util_unlink(tree, fname);
500 1 : smb2_deltree(tree, dname);
501 1 : smb2_util_rmdir(tree, dname);
502 :
503 1 : return ret;
504 : }
505 :
506 0 : bool torture_smb2_sdreadtest(struct torture_context *tctx,
507 : struct smb2_tree *tree)
508 : {
509 0 : const char *fname = "sdread.file";
510 0 : bool ret = true;
511 : union smb_fileinfo query;
512 : NTSTATUS status;
513 0 : struct security_descriptor *sd = NULL;
514 0 : struct smb2_create create_io = {0};
515 0 : uint32_t sd_bits[] = { SECINFO_OWNER,
516 : SECINFO_GROUP,
517 : SECINFO_DACL };
518 : size_t i;
519 :
520 0 : ZERO_STRUCT(query);
521 :
522 0 : smb2_util_unlink(tree, fname);
523 :
524 : /* Create then close a file*/
525 0 : create_io.in.create_flags = 0;
526 0 : create_io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
527 0 : create_io.in.file_attributes = 0;
528 0 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
529 0 : create_io.in.create_disposition = FILE_SUPERSEDE;
530 0 : create_io.in.create_options = 0;
531 0 : create_io.in.security_flags = 0;
532 0 : create_io.in.fname = fname;
533 0 : status = smb2_create(tree, tctx, &create_io);
534 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
535 : talloc_asprintf(tctx, "open(1) of %s failed (%s)\n",
536 : fname, nt_errstr(status)));
537 0 : status = smb2_util_close(tree, create_io.out.file.handle);
538 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret, error_exit,
539 : talloc_asprintf(tctx, "close(1) of %s failed (%s)\n",
540 : fname, nt_errstr(status)));
541 :
542 : /*
543 : * Open the file with READ_ATTRIBUTES *only*,
544 : * no READ_CONTROL.
545 : *
546 : * This should deny access for any attempt to
547 : * get a security descriptor if we ask for
548 : * any of OWNER|GROUP|DACL, but if
549 : * we ask for *NO* info but still ask for
550 : * the security descriptor, then Windows
551 : * returns an ACL but with zero entries
552 : * for OWNER|GROUP|DACL.
553 : */
554 :
555 0 : create_io = (struct smb2_create){0};
556 0 : create_io.in.create_flags = 0;
557 0 : create_io.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
558 0 : create_io.in.file_attributes = 0;
559 0 : create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
560 0 : create_io.in.create_disposition = FILE_OPEN;
561 0 : create_io.in.create_options = 0;
562 0 : create_io.in.security_flags = 0;
563 0 : create_io.in.fname = fname;
564 0 : status = smb2_create(tree, tctx, &create_io);
565 0 : torture_assert_ntstatus_ok_goto(tctx, status, ret,
566 : error_exit,
567 : talloc_asprintf(tctx, "open(2) of %s failed (%s)\n",
568 : fname, nt_errstr(status)));
569 :
570 : /* Check asking for SD fails ACCESS_DENIED with actual bits set. */
571 0 : for (i = 0; i < ARRAY_SIZE(sd_bits); i++) {
572 0 : query.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
573 0 : query.query_secdesc.in.file.handle = create_io.out.file.handle;
574 0 : query.query_secdesc.in.secinfo_flags = sd_bits[i];
575 :
576 0 : status = smb2_getinfo_file(tree, tctx, &query);
577 :
578 : /* Must return ACESS_DENIED. */
579 0 : if(!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)){
580 0 : NTSTATUS s = smb2_util_close(tree,
581 : create_io.out.file.handle);
582 0 : torture_assert_ntstatus_ok_goto(tctx, s, ret,
583 : error_exit,
584 : talloc_asprintf(tctx,
585 : "close(2) of %s failed (%s)\n",
586 : fname, nt_errstr(s)));
587 0 : ret = false;
588 0 : torture_fail_goto(tctx, error_exit,
589 : talloc_asprintf(tctx,
590 : "smb2_getinfo_file(2) of %s failed (%s)\n",
591 : fname, nt_errstr(status)));
592 : }
593 : }
594 :
595 : /*
596 : * Get security descriptor whilst asking for *NO* bits.
597 : * This succeeds even though we don't have READ_CONTROL
598 : * access but returns an SD with zero data.
599 : */
600 0 : query.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
601 0 : query.query_secdesc.in.file.handle = create_io.out.file.handle;
602 0 : query.query_secdesc.in.secinfo_flags = 0;
603 :
604 0 : status = smb2_getinfo_file(tree, tctx, &query);
605 0 : if(!NT_STATUS_IS_OK(status)){
606 0 : NTSTATUS s = smb2_util_close(tree, create_io.out.file.handle);
607 0 : torture_assert_ntstatus_ok_goto(tctx, s, ret, error_exit,
608 : talloc_asprintf(tctx,
609 : "close(3) of %s failed (%s)\n",
610 : fname, nt_errstr(s)));
611 0 : ret = false;
612 0 : torture_fail_goto(tctx, error_exit, talloc_asprintf(tctx,
613 : "smb2_getinfo_file(3) of %s failed (%s)\n",
614 : fname, nt_errstr(status)));
615 : }
616 :
617 0 : sd = query.query_secdesc.out.sd;
618 :
619 : /* Check it's empty. */
620 0 : torture_assert_goto(tctx,
621 : (sd->owner_sid == NULL),
622 : ret,
623 : error_exit,
624 : "sd->owner_sid != NULL\n");
625 :
626 0 : torture_assert_goto(tctx,
627 : (sd->group_sid == NULL),
628 : ret,
629 : error_exit,
630 : "sd->group_sid != NULL\n");
631 :
632 0 : torture_assert_goto(tctx,
633 : (sd->dacl == NULL),
634 : ret,
635 : error_exit,
636 : "sd->dacl != NULL\n");
637 :
638 0 : status = smb2_util_close(tree, create_io.out.file.handle);
639 0 : torture_assert_ntstatus_ok_goto(tctx,
640 : status,
641 : ret,
642 : error_exit,
643 : talloc_asprintf(tctx, "close(4) of %s failed (%s)\n",
644 : fname,
645 : nt_errstr(status)));
646 :
647 0 : error_exit:
648 :
649 0 : smb2_setatr(tree, fname, FILE_ATTRIBUTE_NORMAL);
650 0 : smb2_util_unlink(tree, fname);
651 :
652 0 : return ret;
653 : }
|