s4:torture: Do not free full_name before we printed it
[Samba.git] / source4 / torture / vfs / fruit.c
blob45c7aaac7a352760d169a94362cdec7e23edba88
1 /*
2 Unix SMB/CIFS implementation.
4 vfs_fruit tests
6 Copyright (C) Ralph Boehme 2014
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/filesys.h"
24 #include "libcli/libcli.h"
25 #include "libcli/smb2/smb2.h"
26 #include "libcli/smb2/smb2_calls.h"
27 #include "libcli/smb/smb2_create_ctx.h"
28 #include "lib/cmdline/popt_common.h"
29 #include "param/param.h"
30 #include "libcli/resolve/resolve.h"
31 #include "MacExtensions.h"
32 #include "lib/util/tsort.h"
34 #include "torture/torture.h"
35 #include "torture/util.h"
36 #include "torture/smb2/proto.h"
37 #include "torture/vfs/proto.h"
38 #include "librpc/gen_ndr/ndr_ioctl.h"
39 #include "libcli/security/dom_sid.h"
40 #include "../librpc/gen_ndr/ndr_security.h"
41 #include "libcli/security/secace.h"
42 #include "libcli/security/security_descriptor.h"
44 #define BASEDIR "vfs_fruit_dir"
45 #define FNAME_CC_SRC "testfsctl.dat"
46 #define FNAME_CC_DST "testfsctl2.dat"
48 #define CHECK_STATUS(status, correct) do { \
49 if (!NT_STATUS_EQUAL(status, correct)) { \
50 torture_result(tctx, TORTURE_FAIL, \
51 "(%s) Incorrect status %s - should be %s\n", \
52 __location__, nt_errstr(status), nt_errstr(correct)); \
53 ret = false; \
54 goto done; \
55 }} while (0)
57 #define CHECK_VALUE(v, correct) do { \
58 if ((v) != (correct)) { \
59 torture_result(tctx, TORTURE_FAIL, \
60 "(%s) Incorrect value %s=%u - should be %u\n", \
61 __location__, #v, (unsigned)v, (unsigned)correct); \
62 ret = false; \
63 goto done; \
64 }} while (0)
66 static bool check_stream_list(struct smb2_tree *tree,
67 struct torture_context *tctx,
68 const char *fname,
69 int num_exp,
70 const char **exp,
71 bool is_dir);
73 static int qsort_string(char * const *s1, char * const *s2)
75 return strcmp(*s1, *s2);
78 static int qsort_stream(const struct stream_struct * s1, const struct stream_struct *s2)
80 return strcmp(s1->stream_name.s, s2->stream_name.s);
84 * REVIEW:
85 * This is hokey, but what else can we do?
87 #if defined(HAVE_ATTROPEN) || defined(FREEBSD)
88 #define AFPINFO_EA_NETATALK "org.netatalk.Metadata"
89 #define AFPRESOURCE_EA_NETATALK "org.netatalk.ResourceFork"
90 #else
91 #define AFPINFO_EA_NETATALK "user.org.netatalk.Metadata"
92 #define AFPRESOURCE_EA_NETATALK "user.org.netatalk.ResourceFork"
93 #endif
96 The metadata xattr char buf below contains the following attributes:
98 -------------------------------------------------------------------------------
99 Entry ID : 00000008 : File Dates Info
100 Offset : 00000162 : 354
101 Length : 00000010 : 16
103 -DATE------: : (GMT) : (Local)
104 create : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
105 modify : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
106 backup : 80000000 : Unknown or Initial
107 access : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
109 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
110 00000000 : 1B 44 21 69 1B 44 21 69 80 00 00 00 1B 44 21 69 : .D!i.D!i.....D!i
112 -------------------------------------------------------------------------------
113 Entry ID : 00000009 : Finder Info
114 Offset : 0000007A : 122
115 Length : 00000020 : 32
117 -FInfo-----:
118 Type : 42415252 : BARR
119 Creator : 464F4F4F : FOOO
120 isAlias : 0
121 Invisible : 1
122 hasBundle : 0
123 nameLocked : 0
124 Stationery : 0
125 CustomIcon : 0
126 Reserved : 0
127 Inited : 0
128 NoINITS : 0
129 Shared : 0
130 SwitchLaunc: 0
131 Hidden Ext : 0
132 color : 000 : none
133 isOnDesk : 0
134 Location v : 0000 : 0
135 Location h : 0000 : 0
136 Fldr : 0000 : ..
138 -FXInfo----:
139 Rsvd|IconID: 0000 : 0
140 Rsvd : 0000 : ..
141 Rsvd : 0000 : ..
142 Rsvd : 0000 : ..
143 AreInvalid : 0
144 unknown bit: 0
145 unknown bit: 0
146 unknown bit: 0
147 unknown bit: 0
148 unknown bit: 0
149 unknown bit: 0
150 CustomBadge: 0
151 ObjctIsBusy: 0
152 unknown bit: 0
153 unknown bit: 0
154 unknown bit: 0
155 unknown bit: 0
156 RoutingInfo: 0
157 unknown bit: 0
158 unknown bit: 0
159 Rsvd|commnt: 0000 : 0
160 PutAway : 00000000 : 0
162 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
163 00000000 : 42 41 52 52 46 4F 4F 4F 40 00 00 00 00 00 00 00 : BARRFOOO@.......
164 00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
166 -------------------------------------------------------------------------------
167 Entry ID : 0000000E : AFP File Info
168 Offset : 00000172 : 370
169 Length : 00000004 : 4
171 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
172 00000000 : 00 00 01 A1 : ....
175 char metadata_xattr[] = {
176 0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
180 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 0x00, 0x08, 0x00, 0x00, 0x01, 0x62, 0x00, 0x00,
182 0x00, 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
183 0x00, 0x7a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
184 0x00, 0x0e, 0x00, 0x00, 0x01, 0x72, 0x00, 0x00,
185 0x00, 0x04, 0x80, 0x44, 0x45, 0x56, 0x00, 0x00,
186 0x01, 0x76, 0x00, 0x00, 0x00, 0x08, 0x80, 0x49,
187 0x4e, 0x4f, 0x00, 0x00, 0x01, 0x7e, 0x00, 0x00,
188 0x00, 0x08, 0x80, 0x53, 0x59, 0x4e, 0x00, 0x00,
189 0x01, 0x86, 0x00, 0x00, 0x00, 0x08, 0x80, 0x53,
190 0x56, 0x7e, 0x00, 0x00, 0x01, 0x8e, 0x00, 0x00,
191 0x00, 0x04, 0x42, 0x41, 0x52, 0x52, 0x46, 0x4f,
192 0x4f, 0x4f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x1b, 0x44, 0x21, 0x69, 0x1b, 0x44,
221 0x21, 0x69, 0x80, 0x00, 0x00, 0x00, 0x1b, 0x44,
222 0x21, 0x69, 0x00, 0x00, 0x01, 0xa1, 0x00, 0xfd,
223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x20,
224 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xe3,
225 0x86, 0x53, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x01,
226 0x00, 0x00
230 The buf below contains the following AppleDouble encoded data:
232 -------------------------------------------------------------------------------
233 MagicNumber: 00051607 : AppleDouble
234 Version : 00020000 : Version 2
235 Filler : 4D 61 63 20 4F 53 20 58 20 20 20 20 20 20 20 20 : Mac OS X
236 Num. of ent: 0002 : 2
238 -------------------------------------------------------------------------------
239 Entry ID : 00000009 : Finder Info
240 Offset : 00000032 : 50
241 Length : 00000EB0 : 3760
243 -FInfo-----:
244 Type : 54455354 : TEST
245 Creator : 534C4F57 : SLOW
246 isAlias : 0
247 Invisible : 0
248 hasBundle : 0
249 nameLocked : 0
250 Stationery : 0
251 CustomIcon : 0
252 Reserved : 0
253 Inited : 0
254 NoINITS : 0
255 Shared : 0
256 SwitchLaunc: 0
257 Hidden Ext : 0
258 color : 100 : blue
259 isOnDesk : 0
260 Location v : 0000 : 0
261 Location h : 0000 : 0
262 Fldr : 0000 : ..
264 -FXInfo----:
265 Rsvd|IconID: 0000 : 0
266 Rsvd : 0000 : ..
267 Rsvd : 0000 : ..
268 Rsvd : 0000 : ..
269 AreInvalid : 0
270 unknown bit: 0
271 unknown bit: 0
272 unknown bit: 0
273 unknown bit: 0
274 unknown bit: 0
275 unknown bit: 0
276 CustomBadge: 0
277 ObjctIsBusy: 0
278 unknown bit: 0
279 unknown bit: 0
280 unknown bit: 0
281 unknown bit: 0
282 RoutingInfo: 0
283 unknown bit: 0
284 unknown bit: 0
285 Rsvd|commnt: 0000 : 0
286 PutAway : 00000000 : 0
288 -EA--------:
289 pad : 0000 : ..
290 magic : 41545452 : ATTR
291 debug_tag : 53D4580C : 1406425100
292 total_size : 00000EE2 : 3810
293 data_start : 000000BC : 188
294 data_length: 0000005E : 94
295 reserved[0]: 00000000 : ....
296 reserved[1]: 00000000 : ....
297 reserved[2]: 00000000 : ....
298 flags : 0000 : ..
299 num_attrs : 0002 : 2
300 -EA ENTRY--:
301 offset : 000000BC : 188
302 length : 0000005B : 91
303 flags : 0000 : ..
304 namelen : 24 : 36
305 -EA NAME---: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
306 00000000 : 63 6F 6D 2E 61 70 70 6C 65 2E 6D 65 74 61 64 61 : com.apple.metada
307 00000010 : 74 61 3A 5F 6B 4D 44 49 74 65 6D 55 73 65 72 54 : ta:_kMDItemUserT
308 00000020 : 61 67 73 00 : ags.
309 -EA VALUE--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
310 00000000 : 62 70 6C 69 73 74 30 30 A5 01 02 03 04 05 54 74 : bplist00......Tt
311 00000010 : 65 73 74 66 00 47 00 72 00 FC 00 6E 00 0A 00 32 : estf.G.r...n...2
312 00000020 : 56 4C 69 6C 61 0A 33 56 47 65 6C 62 0A 35 56 42 : VLila.3VGelb.5VB
313 00000030 : 6C 61 75 0A 34 08 0E 13 20 27 2E 00 00 00 00 00 : lau.4... '......
314 00000040 : 00 01 01 00 00 00 00 00 00 00 06 00 00 00 00 00 : ................
315 00000050 : 00 00 00 00 00 00 00 00 00 00 35 : ..........5
316 -EA ENTRY--:
317 offset : 00000117 : 279
318 length : 00000003 : 3
319 flags : 0000 : ..
320 namelen : 08 : 8
321 -EA NAME---: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
322 00000000 : 66 6F 6F 3A 62 61 72 00 : foo:bar.
323 -EA VALUE--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
324 00000000 : 62 61 7A : baz
326 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
327 00000000 : 54 45 53 54 53 4C 4F 57 00 08 00 00 00 00 00 00 : TESTSLOW........
328 00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
329 00000020 : 00 00 41 54 54 52 53 D4 58 0C 00 00 0E E2 00 00 : ..ATTRS.X.......
330 00000030 : 00 BC 00 00 00 5E 00 00 00 00 00 00 00 00 00 00 : .....^..........
331 00000040 : 00 00 00 00 00 02 00 00 00 BC 00 00 00 5B 00 00 : .............[..
332 00000050 : 24 63 6F 6D 2E 61 70 70 6C 65 2E 6D 65 74 61 64 : $com.apple.metad
333 00000060 : 61 74 61 3A 5F 6B 4D 44 49 74 65 6D 55 73 65 72 : ata:_kMDItemUser
334 00000070 : 54 61 67 73 00 00 00 00 01 17 00 00 00 03 00 00 : Tags............
335 00000080 : 08 66 6F 6F 3A 62 61 72 00 66 62 70 6C 69 73 74 : .foo:bar.fbplist
336 00000090 : 30 30 A5 01 02 03 04 05 54 74 65 73 74 66 00 47 : 00......Ttestf.G
337 000000A0 : 00 72 00 FC 00 6E 00 0A 00 32 56 4C 69 6C 61 0A : .r...n...2VLila.
338 000000B0 : 33 56 47 65 6C 62 0A 35 56 42 6C 61 75 0A 34 08 : 3VGelb.5VBlau.4.
339 000000C0 : 0E 13 20 27 2E 00 00 00 00 00 00 01 01 00 00 00 : .. '............
340 000000D0 : 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 : ................
341 000000E0 : 00 00 00 00 35 62 61 7A 00 00 00 00 00 00 00 00 : ....5baz........
342 000000F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
343 ... all zeroes ...
344 00000EA0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
346 -------------------------------------------------------------------------------
347 Entry ID : 00000002 : Resource Fork
348 Offset : 00000EE2 : 3810
349 Length : 0000011E : 286
351 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
352 00000000 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
353 00000010 : 54 68 69 73 20 72 65 73 6F 75 72 63 65 20 66 6F : This resource fo
354 00000020 : 72 6B 20 69 6E 74 65 6E 74 69 6F 6E 61 6C 6C 79 : rk intentionally
355 00000030 : 20 6C 65 66 74 20 62 6C 61 6E 6B 20 20 20 00 00 : left blank ..
356 00000040 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
357 00000050 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
358 00000060 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
359 00000070 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
360 00000080 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
361 00000090 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
362 000000A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
363 000000B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
364 000000C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
365 000000D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
366 000000E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
367 000000F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
368 00000100 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
369 00000110 : 00 00 00 00 00 00 00 00 00 1C 00 1E FF FF : ..............
371 It was created with:
372 $ hexdump -ve '"\t" 7/1 "0x%02x, " 1/1 " 0x%02x," "\n"'
374 static char osx_adouble_w_xattr[] = {
375 0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
376 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58,
377 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
378 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
379 0x00, 0x32, 0x00, 0x00, 0x0e, 0xb0, 0x00, 0x00,
380 0x00, 0x02, 0x00, 0x00, 0x0e, 0xe2, 0x00, 0x00,
381 0x01, 0x1e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x4c,
382 0x4f, 0x57, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x41, 0x54, 0x54, 0x52,
386 0x53, 0xd4, 0x58, 0x0c, 0x00, 0x00, 0x0e, 0xe2,
387 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x5e,
388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
390 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x5b,
391 0x00, 0x00, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x61,
392 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x6d, 0x65, 0x74,
393 0x61, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x5f, 0x6b,
394 0x4d, 0x44, 0x49, 0x74, 0x65, 0x6d, 0x55, 0x73,
395 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x00, 0x00,
396 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x00, 0x03,
397 0x00, 0x00, 0x08, 0x66, 0x6f, 0x6f, 0x3a, 0x62,
398 0x61, 0x72, 0x00, 0x66, 0x62, 0x70, 0x6c, 0x69,
399 0x73, 0x74, 0x30, 0x30, 0xa5, 0x01, 0x02, 0x03,
400 0x04, 0x05, 0x54, 0x74, 0x65, 0x73, 0x74, 0x66,
401 0x00, 0x47, 0x00, 0x72, 0x00, 0xfc, 0x00, 0x6e,
402 0x00, 0x0a, 0x00, 0x32, 0x56, 0x4c, 0x69, 0x6c,
403 0x61, 0x0a, 0x33, 0x56, 0x47, 0x65, 0x6c, 0x62,
404 0x0a, 0x35, 0x56, 0x42, 0x6c, 0x61, 0x75, 0x0a,
405 0x34, 0x08, 0x0e, 0x13, 0x20, 0x27, 0x2e, 0x00,
406 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
407 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x62,
410 0x61, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
418 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
500 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
501 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
695 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
708 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
709 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
713 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
721 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
723 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
733 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
734 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
736 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
737 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
738 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
739 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
746 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
747 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
749 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
750 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
752 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
754 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
755 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
757 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
758 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
759 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
760 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
761 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
762 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
764 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
765 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
772 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
778 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
779 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
780 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
781 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
782 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
783 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
784 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
785 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
786 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
787 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
788 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
789 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
790 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
791 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
792 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
793 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
794 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
795 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
796 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
797 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
798 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
799 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
800 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
801 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
802 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
803 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
804 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
805 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
806 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
808 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
809 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
810 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
811 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
812 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
813 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
814 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
815 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
817 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
818 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
819 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
820 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
821 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
822 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
823 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
824 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
825 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
826 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
827 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
828 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
834 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
835 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
836 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
837 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
838 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
839 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
840 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
841 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
842 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
843 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
844 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
845 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
846 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
847 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
848 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
849 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
850 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
851 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
852 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
853 0x00, 0x1e, 0x54, 0x68, 0x69, 0x73, 0x20, 0x72,
854 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20,
855 0x66, 0x6f, 0x72, 0x6b, 0x20, 0x69, 0x6e, 0x74,
856 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
857 0x6c, 0x79, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20,
858 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x20, 0x20, 0x20,
859 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
860 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
861 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
862 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
863 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
864 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
865 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
866 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
867 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
868 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
869 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
870 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
871 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
872 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
873 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
874 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
875 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
876 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
878 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
883 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
884 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
885 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
886 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1e, 0xff, 0xff
890 * The buf below contains the following AppleDouble encoded data:
892 * -------------------------------------------------------------------------------
893 * MagicNumber: 00051607 : AppleDouble
894 * Version : 00020000 : Version 2
895 * Filler : 4D 61 63 20 4F 53 20 58 20 20 20 20 20 20 20 20 : Mac OS X
896 * Num. of ent: 0002 : 2
898 * -------------------------------------------------------------------------------
899 * Entry ID : 00000002 : Resource Fork
900 * Offset : 00000052 : 82
901 * Length : 0000011E : 286
903 * -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
904 * 00000000 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
905 * 00000010 : 54 68 69 73 20 72 65 73 6F 75 72 63 65 20 66 6F : This resource fo
906 * 00000020 : 72 6B 20 69 6E 74 65 6E 74 69 6F 6E 61 6C 6C 79 : rk intentionally
907 * 00000030 : 20 6C 65 66 74 20 62 6C 61 6E 6B 20 20 20 00 00 : left blank ..
908 * 00000040 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
909 * 00000050 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
910 * 00000060 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
911 * 00000070 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
912 * 00000080 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
913 * 00000090 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
914 * 000000A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
915 * 000000B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
916 * 000000C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
917 * 000000D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
918 * 000000E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
919 * 000000F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
920 * 00000100 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
921 * 00000110 : 00 00 00 00 00 00 00 00 00 1C 00 1E FF FF : ..............
923 * Entry ID : 00000009 : Finder Info
924 * Offset : 00000032 : 50
925 * Length : 00000020 : 32
927 * -NOTE------: cannot detect whether FInfo or DInfo. assume FInfo.
929 * -FInfo-----:
930 * Type : 57415645 : WAVE
931 * Creator : 5054756C : PTul
932 * isAlias : 0
933 * Invisible : 0
934 * hasBundle : 0
935 * nameLocked : 0
936 * Stationery : 0
937 * CustomIcon : 0
938 * Reserved : 0
939 * Inited : 0
940 * NoINITS : 0
941 * Shared : 0
942 * SwitchLaunc: 0
943 * Hidden Ext : 0
944 * color : 000 : none
945 * isOnDesk : 0
946 * Location v : 0000 : 0
947 * Location h : 0000 : 0
948 * Fldr : 0000 : ..
950 * -FXInfo----:
951 * Rsvd|IconID: 0000 : 0
952 * Rsvd : 0000 : ..
953 * Rsvd : 0000 : ..
954 * Rsvd : 0000 : ..
955 * AreInvalid : 0
956 * unknown bit: 0
957 * unknown bit: 0
958 * unknown bit: 0
959 * unknown bit: 0
960 * unknown bit: 0
961 * unknown bit: 0
962 * CustomBadge: 0
963 * ObjctIsBusy: 0
964 * unknown bit: 0
965 * unknown bit: 0
966 * unknown bit: 0
967 * unknown bit: 0
968 * RoutingInfo: 0
969 * unknown bit: 0
970 * unknown bit: 0
971 * Rsvd|commnt: 0000 : 0
972 * PutAway : 00000000 : 0
974 * -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
975 * 00000000 : 57 41 56 45 50 54 75 6C 00 00 00 00 00 00 00 00 : WAVEPTul........
976 * 00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
978 * It was created with:
979 * $ hexdump -ve '"\t" 7/1 "0x%02x, " 1/1 " 0x%02x," "\n"'
981 static char osx_adouble_without_xattr[] = {
982 0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
983 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58,
984 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
985 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
986 0x00, 0x52, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00,
987 0x00, 0x09, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00,
988 0x00, 0x20, 0x57, 0x41, 0x56, 0x45, 0x50, 0x54,
989 0x75, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
990 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
991 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
992 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
993 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
994 0x00, 0x1e, 0x54, 0x68, 0x69, 0x73, 0x20, 0x72,
995 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20,
996 0x66, 0x6f, 0x72, 0x6b, 0x20, 0x69, 0x6e, 0x74,
997 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
998 0x6c, 0x79, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20,
999 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x20, 0x20, 0x20,
1000 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1001 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1002 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1003 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1004 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1005 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1006 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1007 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1008 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1009 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1011 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1012 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1013 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1014 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1015 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1016 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1017 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1018 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1019 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1020 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1021 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1022 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1023 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1024 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1025 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1026 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1027 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1e, 0xff, 0xff
1031 * talloc and intialize an AfpInfo
1033 static AfpInfo *torture_afpinfo_new(TALLOC_CTX *mem_ctx)
1035 AfpInfo *info;
1037 info = talloc_zero(mem_ctx, AfpInfo);
1038 if (info == NULL) {
1039 return NULL;
1042 info->afpi_Signature = AFP_Signature;
1043 info->afpi_Version = AFP_Version;
1044 info->afpi_BackupTime = AFP_BackupTime;
1046 return info;
1050 * Pack AfpInfo into a talloced buffer
1052 static char *torture_afpinfo_pack(TALLOC_CTX *mem_ctx,
1053 AfpInfo *info)
1055 char *buf;
1057 buf = talloc_zero_array(mem_ctx, char, AFP_INFO_SIZE);
1058 if (buf == NULL) {
1059 return NULL;
1062 RSIVAL(buf, 0, info->afpi_Signature);
1063 RSIVAL(buf, 4, info->afpi_Version);
1064 RSIVAL(buf, 12, info->afpi_BackupTime);
1065 memcpy(buf + 16, info->afpi_FinderInfo, sizeof(info->afpi_FinderInfo));
1067 return buf;
1071 * Unpack AfpInfo
1073 #if 0
1074 static void torture_afpinfo_unpack(AfpInfo *info, char *data)
1076 info->afpi_Signature = RIVAL(data, 0);
1077 info->afpi_Version = RIVAL(data, 4);
1078 info->afpi_BackupTime = RIVAL(data, 12);
1079 memcpy(info->afpi_FinderInfo, (const char *)data + 16,
1080 sizeof(info->afpi_FinderInfo));
1082 #endif
1084 static bool torture_write_afpinfo(struct smb2_tree *tree,
1085 struct torture_context *tctx,
1086 TALLOC_CTX *mem_ctx,
1087 const char *fname,
1088 AfpInfo *info)
1090 struct smb2_handle handle;
1091 struct smb2_create io;
1092 NTSTATUS status;
1093 const char *full_name;
1094 char *infobuf;
1095 bool ret = true;
1097 full_name = talloc_asprintf(mem_ctx, "%s%s", fname, AFPINFO_STREAM_NAME);
1098 if (full_name == NULL) {
1099 torture_comment(tctx, "talloc_asprintf error\n");
1100 return false;
1102 ZERO_STRUCT(io);
1103 io.in.desired_access = SEC_FILE_WRITE_DATA;
1104 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1105 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1106 io.in.create_options = 0;
1107 io.in.fname = full_name;
1109 status = smb2_create(tree, mem_ctx, &io);
1110 CHECK_STATUS(status, NT_STATUS_OK);
1112 handle = io.out.file.handle;
1114 infobuf = torture_afpinfo_pack(mem_ctx, info);
1115 if (infobuf == NULL) {
1116 return false;
1119 status = smb2_util_write(tree, handle, infobuf, 0, AFP_INFO_SIZE);
1120 CHECK_STATUS(status, NT_STATUS_OK);
1122 smb2_util_close(tree, handle);
1124 done:
1125 return ret;
1129 * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1130 * compare against buffer 'value'
1132 static bool check_stream(struct smb2_tree *tree,
1133 const char *location,
1134 struct torture_context *tctx,
1135 TALLOC_CTX *mem_ctx,
1136 const char *fname,
1137 const char *sname,
1138 off_t read_offset,
1139 size_t read_count,
1140 off_t comp_offset,
1141 size_t comp_count,
1142 const char *value)
1144 struct smb2_handle handle;
1145 struct smb2_create create;
1146 struct smb2_read r;
1147 NTSTATUS status;
1148 char *full_name;
1149 bool ret = true;
1151 full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
1152 if (full_name == NULL) {
1153 torture_comment(tctx, "talloc_asprintf error\n");
1154 return false;
1156 ZERO_STRUCT(create);
1157 create.in.desired_access = SEC_FILE_READ_DATA;
1158 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1159 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1160 create.in.fname = full_name;
1162 torture_comment(tctx, "Open stream %s\n", full_name);
1164 status = smb2_create(tree, mem_ctx, &create);
1165 if (!NT_STATUS_IS_OK(status)) {
1166 if (value == NULL) {
1167 return true;
1169 torture_comment(tctx, "Unable to open stream %s\n", full_name);
1170 TALLOC_FREE(full_name);
1171 return false;
1174 handle = create.out.file.handle;
1175 if (value == NULL) {
1176 TALLOC_FREE(full_name);
1177 smb2_util_close(tree, handle);
1178 return true;
1181 ZERO_STRUCT(r);
1182 r.in.file.handle = handle;
1183 r.in.length = read_count;
1184 r.in.offset = read_offset;
1186 status = smb2_read(tree, tree, &r);
1188 torture_assert_ntstatus_ok_goto(
1189 tctx, status, ret, done,
1190 talloc_asprintf(tctx, "(%s) Failed to read %lu bytes from stream '%s'\n",
1191 location, (long)strlen(value), full_name));
1193 torture_assert_goto(tctx, r.out.data.length == read_count, ret, done,
1194 talloc_asprintf(tctx, "smb2_read returned %jd bytes, expected %jd\n",
1195 (intmax_t)r.out.data.length, (intmax_t)read_count));
1197 torture_assert_goto(
1198 tctx, memcmp(r.out.data.data + comp_offset, value, comp_count) == 0,
1199 ret, done,
1200 talloc_asprintf(tctx, "(%s) Bad data in stream\n", location));
1202 done:
1203 TALLOC_FREE(full_name);
1204 smb2_util_close(tree, handle);
1205 return ret;
1209 * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1210 * compare against buffer 'value'
1212 static ssize_t read_stream(struct smb2_tree *tree,
1213 const char *location,
1214 struct torture_context *tctx,
1215 TALLOC_CTX *mem_ctx,
1216 const char *fname,
1217 const char *sname,
1218 off_t read_offset,
1219 size_t read_count)
1221 struct smb2_handle handle;
1222 struct smb2_create create;
1223 struct smb2_read r;
1224 NTSTATUS status;
1225 const char *full_name;
1226 bool ret = true;
1228 full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
1229 if (full_name == NULL) {
1230 torture_comment(tctx, "talloc_asprintf error\n");
1231 return -1;
1233 ZERO_STRUCT(create);
1234 create.in.desired_access = SEC_FILE_READ_DATA;
1235 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1236 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1237 create.in.fname = full_name;
1239 torture_comment(tctx, "Open stream %s\n", full_name);
1241 status = smb2_create(tree, mem_ctx, &create);
1242 if (!NT_STATUS_IS_OK(status)) {
1243 torture_comment(tctx, "Unable to open stream %s\n",
1244 full_name);
1245 return -1;
1248 handle = create.out.file.handle;
1250 ZERO_STRUCT(r);
1251 r.in.file.handle = handle;
1252 r.in.length = read_count;
1253 r.in.offset = read_offset;
1255 status = smb2_read(tree, tree, &r);
1256 if (!NT_STATUS_IS_OK(status)) {
1257 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
1260 smb2_util_close(tree, handle);
1262 done:
1263 if (ret == false) {
1264 return -1;
1266 return r.out.data.length;
1270 * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1271 * compare against buffer 'value'
1273 static bool write_stream(struct smb2_tree *tree,
1274 const char *location,
1275 struct torture_context *tctx,
1276 TALLOC_CTX *mem_ctx,
1277 const char *fname,
1278 const char *sname,
1279 off_t offset,
1280 size_t size,
1281 const char *value)
1283 struct smb2_handle handle;
1284 struct smb2_create create;
1285 NTSTATUS status;
1286 const char *full_name;
1288 full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname ? sname : "");
1289 if (full_name == NULL) {
1290 torture_comment(tctx, "talloc_asprintf error\n");
1291 return false;
1293 ZERO_STRUCT(create);
1294 create.in.desired_access = SEC_FILE_WRITE_DATA;
1295 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1296 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1297 create.in.fname = full_name;
1299 status = smb2_create(tree, mem_ctx, &create);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 if (value == NULL) {
1302 return true;
1303 } else {
1304 torture_comment(tctx, "Unable to open stream %s\n",
1305 full_name);
1306 sleep(10000000);
1307 return false;
1311 handle = create.out.file.handle;
1312 if (value == NULL) {
1313 return true;
1316 status = smb2_util_write(tree, handle, value, offset, size);
1318 if (!NT_STATUS_IS_OK(status)) {
1319 torture_comment(tctx, "(%s) Failed to write %lu bytes to "
1320 "stream '%s'\n", location, (long)size, full_name);
1321 return false;
1324 smb2_util_close(tree, handle);
1325 return true;
1328 static bool torture_setup_local_xattr(struct torture_context *tctx,
1329 const char *path_option,
1330 const char *name,
1331 const char *xattr,
1332 const char *metadata,
1333 size_t size)
1335 int ret = true;
1336 int result;
1337 const char *spath;
1338 char *path;
1340 spath = torture_setting_string(tctx, path_option, NULL);
1341 if (spath == NULL) {
1342 printf("No sharepath for option %s\n", path_option);
1343 return false;
1346 path = talloc_asprintf(tctx, "%s/%s", spath, name);
1348 result = setxattr(path, xattr, metadata, size, 0);
1349 if (result != 0) {
1350 ret = false;
1353 TALLOC_FREE(path);
1355 return ret;
1359 * Create a file or directory
1361 static bool torture_setup_file(TALLOC_CTX *mem_ctx, struct smb2_tree *tree,
1362 const char *name, bool dir)
1364 struct smb2_create io;
1365 NTSTATUS status;
1367 smb2_util_unlink(tree, name);
1368 ZERO_STRUCT(io);
1369 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1370 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1371 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1372 io.in.share_access =
1373 NTCREATEX_SHARE_ACCESS_DELETE|
1374 NTCREATEX_SHARE_ACCESS_READ|
1375 NTCREATEX_SHARE_ACCESS_WRITE;
1376 io.in.create_options = 0;
1377 io.in.fname = name;
1378 if (dir) {
1379 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1380 io.in.share_access &= ~NTCREATEX_SHARE_ACCESS_DELETE;
1381 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1382 io.in.create_disposition = NTCREATEX_DISP_CREATE;
1385 status = smb2_create(tree, mem_ctx, &io);
1386 if (!NT_STATUS_IS_OK(status)) {
1387 return false;
1390 status = smb2_util_close(tree, io.out.file.handle);
1391 if (!NT_STATUS_IS_OK(status)) {
1392 return false;
1395 return true;
1398 static bool enable_aapl(struct torture_context *tctx,
1399 struct smb2_tree *tree)
1401 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1402 NTSTATUS status;
1403 bool ret = true;
1404 struct smb2_create io;
1405 DATA_BLOB data;
1406 struct smb2_create_blob *aapl = NULL;
1407 uint32_t aapl_server_caps;
1408 uint32_t expected_scaps = (SMB2_CRTCTX_AAPL_UNIX_BASED |
1409 SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
1410 SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
1411 SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
1412 bool is_osx_server = torture_setting_bool(tctx, "osx", false);
1414 ZERO_STRUCT(io);
1415 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1416 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1417 io.in.create_disposition = NTCREATEX_DISP_OPEN;
1418 io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
1419 NTCREATEX_SHARE_ACCESS_READ |
1420 NTCREATEX_SHARE_ACCESS_WRITE);
1421 io.in.fname = "";
1424 * Issuing an SMB2/CREATE with a suitably formed AAPL context,
1425 * controls behaviour of Apple's SMB2 extensions for the whole
1426 * session!
1429 data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
1430 SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
1431 SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
1432 SMB2_CRTCTX_AAPL_VOLUME_CAPS |
1433 SMB2_CRTCTX_AAPL_MODEL_INFO));
1434 SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
1435 SMB2_CRTCTX_AAPL_UNIX_BASED |
1436 SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
1438 status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
1439 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_blob_add");
1441 status = smb2_create(tree, tctx, &io);
1442 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1444 status = smb2_util_close(tree, io.out.file.handle);
1445 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close");
1448 * Now check returned AAPL context
1450 torture_comment(tctx, "Comparing returned AAPL capabilities\n");
1452 aapl = smb2_create_blob_find(&io.out.blobs,
1453 SMB2_CREATE_TAG_AAPL);
1454 torture_assert_goto(tctx, aapl != NULL, ret, done, "missing AAPL context");
1456 if (!is_osx_server) {
1457 size_t expected_aapl_ctx_size;
1459 expected_aapl_ctx_size = strlen("MacSamba") * 2 + 40;
1461 torture_assert_goto(
1462 tctx, aapl->data.length == expected_aapl_ctx_size,
1463 ret, done, "bad AAPL size");
1466 aapl_server_caps = BVAL(aapl->data.data, 16);
1467 torture_assert_goto(tctx, aapl_server_caps == expected_scaps,
1468 ret, done, "bad AAPL caps");
1470 done:
1471 talloc_free(mem_ctx);
1472 return ret;
1475 static bool test_read_netatalk_metadata(struct torture_context *tctx,
1476 struct smb2_tree *tree)
1478 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1479 const char *fname = BASEDIR "\\torture_read_metadata";
1480 NTSTATUS status;
1481 struct smb2_handle testdirh;
1482 bool ret = true;
1483 ssize_t len;
1484 const char *localdir = NULL;
1486 torture_comment(tctx, "Checking metadata access\n");
1488 localdir = torture_setting_string(tctx, "localdir", NULL);
1489 if (localdir == NULL) {
1490 torture_skip(tctx, "Need localdir for test");
1493 smb2_util_unlink(tree, fname);
1495 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1496 CHECK_STATUS(status, NT_STATUS_OK);
1497 smb2_util_close(tree, testdirh);
1499 ret = torture_setup_file(mem_ctx, tree, fname, false);
1500 if (ret == false) {
1501 goto done;
1504 ret = torture_setup_local_xattr(tctx, "localdir",
1505 BASEDIR "/torture_read_metadata",
1506 AFPINFO_EA_NETATALK,
1507 metadata_xattr, sizeof(metadata_xattr));
1508 if (ret == false) {
1509 goto done;
1512 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1513 0, 60, 0, 4, "AFP");
1514 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1516 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1517 0, 60, 16, 8, "BARRFOOO");
1518 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1520 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1521 16, 8, 0, 3, "AFP");
1522 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1524 /* Check reading offset and read size > sizeof(AFPINFO_STREAM) */
1526 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1527 AFPINFO_STREAM, 0, 61);
1528 CHECK_VALUE(len, 60);
1530 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1531 AFPINFO_STREAM, 59, 2);
1532 CHECK_VALUE(len, 2);
1534 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1535 AFPINFO_STREAM, 60, 1);
1536 CHECK_VALUE(len, 1);
1538 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1539 AFPINFO_STREAM, 61, 1);
1540 CHECK_VALUE(len, 0);
1542 done:
1543 smb2_deltree(tree, BASEDIR);
1544 talloc_free(mem_ctx);
1545 return ret;
1548 static bool test_read_afpinfo(struct torture_context *tctx,
1549 struct smb2_tree *tree)
1551 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1552 const char *fname = BASEDIR "\\torture_read_metadata";
1553 NTSTATUS status;
1554 struct smb2_handle testdirh;
1555 bool ret = true;
1556 ssize_t len;
1557 AfpInfo *info;
1558 const char *type_creator = "SMB,OLE!";
1560 torture_comment(tctx, "Checking metadata access\n");
1562 smb2_util_unlink(tree, fname);
1564 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1565 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
1566 smb2_util_close(tree, testdirh);
1568 ret = torture_setup_file(mem_ctx, tree, fname, false);
1569 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
1571 info = torture_afpinfo_new(mem_ctx);
1572 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
1574 memcpy(info->afpi_FinderInfo, type_creator, 8);
1575 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
1576 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
1578 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1579 0, 60, 0, 4, "AFP");
1580 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1582 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1583 0, 60, 16, 8, type_creator);
1584 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1587 * OS X ignores offset <= 60 and treats the as
1588 * offset=0. Reading from offsets > 60 returns EOF=0.
1591 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1592 16, 8, 0, 8, "AFP\0\0\0\001\0");
1593 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1595 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1596 AFPINFO_STREAM, 0, 61);
1597 torture_assert_goto(tctx, len == 60, ret, done, "read_stream failed");
1599 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1600 AFPINFO_STREAM, 59, 2);
1601 torture_assert_goto(tctx, len == 2, ret, done, "read_stream failed");
1603 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1604 59, 2, 0, 2, "AF");
1605 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1607 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1608 AFPINFO_STREAM, 60, 1);
1609 torture_assert_goto(tctx, len == 1, ret, done, "read_stream failed");
1611 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1612 60, 1, 0, 1, "A");
1613 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1615 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1616 AFPINFO_STREAM, 61, 1);
1617 torture_assert_goto(tctx, len == 0, ret, done, "read_stream failed");
1619 done:
1620 smb2_util_unlink(tree, fname);
1621 smb2_deltree(tree, BASEDIR);
1622 talloc_free(mem_ctx);
1623 return ret;
1626 static bool test_write_atalk_metadata(struct torture_context *tctx,
1627 struct smb2_tree *tree)
1629 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1630 const char *fname = BASEDIR "\\torture_write_metadata";
1631 const char *type_creator = "SMB,OLE!";
1632 NTSTATUS status;
1633 struct smb2_handle testdirh;
1634 bool ret = true;
1635 AfpInfo *info;
1637 smb2_deltree(tree, BASEDIR);
1638 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1639 CHECK_STATUS(status, NT_STATUS_OK);
1640 smb2_util_close(tree, testdirh);
1642 ret = torture_setup_file(mem_ctx, tree, fname, false);
1643 if (ret == false) {
1644 goto done;
1647 info = torture_afpinfo_new(mem_ctx);
1648 if (info == NULL) {
1649 goto done;
1652 memcpy(info->afpi_FinderInfo, type_creator, 8);
1653 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
1654 ret &= check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1655 0, 60, 16, 8, type_creator);
1657 done:
1658 smb2_util_unlink(tree, fname);
1659 smb2_deltree(tree, BASEDIR);
1660 talloc_free(mem_ctx);
1661 return ret;
1664 static bool test_write_atalk_rfork_io(struct torture_context *tctx,
1665 struct smb2_tree *tree)
1667 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1668 const char *fname = BASEDIR "\\torture_write_rfork_io";
1669 const char *rfork = BASEDIR "\\torture_write_rfork_io" AFPRESOURCE_STREAM_NAME;
1670 const char *rfork_content = "1234567890";
1671 NTSTATUS status;
1672 struct smb2_handle testdirh;
1673 bool ret = true;
1675 union smb_open io;
1676 struct smb2_handle filehandle;
1677 union smb_fileinfo finfo;
1678 union smb_setfileinfo sinfo;
1680 smb2_util_unlink(tree, fname);
1682 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1683 CHECK_STATUS(status, NT_STATUS_OK);
1684 smb2_util_close(tree, testdirh);
1686 ret = torture_setup_file(mem_ctx, tree, fname, false);
1687 if (ret == false) {
1688 goto done;
1691 torture_comment(tctx, "(%s) writing to resource fork\n",
1692 __location__);
1694 ret &= write_stream(tree, __location__, tctx, mem_ctx,
1695 fname, AFPRESOURCE_STREAM_NAME,
1696 10, 10, rfork_content);
1698 ret &= check_stream(tree, __location__, tctx, mem_ctx,
1699 fname, AFPRESOURCE_STREAM_NAME,
1700 0, 20, 10, 10, rfork_content);
1702 /* Check size after write */
1704 ZERO_STRUCT(io);
1705 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1706 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1707 SEC_FILE_WRITE_ATTRIBUTE;
1708 io.smb2.in.fname = rfork;
1709 status = smb2_create(tree, mem_ctx, &(io.smb2));
1710 CHECK_STATUS(status, NT_STATUS_OK);
1711 filehandle = io.smb2.out.file.handle;
1713 torture_comment(tctx, "(%s) check resource fork size after write\n",
1714 __location__);
1716 ZERO_STRUCT(finfo);
1717 finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1718 finfo.generic.in.file.handle = filehandle;
1719 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1720 CHECK_STATUS(status, NT_STATUS_OK);
1721 if (finfo.all_info.out.size != 20) {
1722 torture_result(tctx, TORTURE_FAIL,
1723 "(%s) Incorrect resource fork size\n",
1724 __location__);
1725 ret = false;
1726 smb2_util_close(tree, filehandle);
1727 goto done;
1729 smb2_util_close(tree, filehandle);
1731 /* Write at large offset */
1733 torture_comment(tctx, "(%s) writing to resource fork at large offset\n",
1734 __location__);
1736 ret &= write_stream(tree, __location__, tctx, mem_ctx,
1737 fname, AFPRESOURCE_STREAM_NAME,
1738 (off_t)64*1024*1024, 10, rfork_content);
1740 ret &= check_stream(tree, __location__, tctx, mem_ctx,
1741 fname, AFPRESOURCE_STREAM_NAME,
1742 (off_t)64*1024*1024, 10, 0, 10, rfork_content);
1744 /* Truncate back to size of 1 byte */
1746 torture_comment(tctx, "(%s) truncate resource fork and check size\n",
1747 __location__);
1749 ZERO_STRUCT(io);
1750 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1751 io.smb2.in.desired_access = SEC_FILE_ALL;
1752 io.smb2.in.fname = rfork;
1753 status = smb2_create(tree, mem_ctx, &(io.smb2));
1754 CHECK_STATUS(status, NT_STATUS_OK);
1755 filehandle = io.smb2.out.file.handle;
1757 ZERO_STRUCT(sinfo);
1758 sinfo.end_of_file_info.level =
1759 RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1760 sinfo.end_of_file_info.in.file.handle = filehandle;
1761 sinfo.end_of_file_info.in.size = 1;
1762 status = smb2_setinfo_file(tree, &sinfo);
1763 CHECK_STATUS(status, NT_STATUS_OK);
1765 smb2_util_close(tree, filehandle);
1767 /* Now check size */
1768 ZERO_STRUCT(io);
1769 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1770 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1771 SEC_FILE_WRITE_ATTRIBUTE;
1772 io.smb2.in.fname = rfork;
1773 status = smb2_create(tree, mem_ctx, &(io.smb2));
1774 CHECK_STATUS(status, NT_STATUS_OK);
1775 filehandle = io.smb2.out.file.handle;
1777 ZERO_STRUCT(finfo);
1778 finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1779 finfo.generic.in.file.handle = filehandle;
1780 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1781 CHECK_STATUS(status, NT_STATUS_OK);
1782 if (finfo.all_info.out.size != 1) {
1783 torture_result(tctx, TORTURE_FAIL,
1784 "(%s) Incorrect resource fork size\n",
1785 __location__);
1786 ret = false;
1787 smb2_util_close(tree, filehandle);
1788 goto done;
1790 smb2_util_close(tree, filehandle);
1792 done:
1793 smb2_util_unlink(tree, fname);
1794 smb2_deltree(tree, BASEDIR);
1795 talloc_free(mem_ctx);
1796 return ret;
1799 static bool test_rfork_truncate(struct torture_context *tctx,
1800 struct smb2_tree *tree)
1802 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1803 const char *fname = BASEDIR "\\torture_rfork_truncate";
1804 const char *rfork = BASEDIR "\\torture_rfork_truncate" AFPRESOURCE_STREAM;
1805 const char *rfork_content = "1234567890";
1806 NTSTATUS status;
1807 struct smb2_handle testdirh;
1808 bool ret = true;
1809 struct smb2_create create;
1810 struct smb2_handle fh1, fh2, fh3;
1811 union smb_setfileinfo sinfo;
1813 ret = enable_aapl(tctx, tree);
1814 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
1816 smb2_util_unlink(tree, fname);
1818 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1819 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1820 smb2_util_close(tree, testdirh);
1822 ret = torture_setup_file(mem_ctx, tree, fname, false);
1823 if (ret == false) {
1824 goto done;
1827 ret &= write_stream(tree, __location__, tctx, mem_ctx,
1828 fname, AFPRESOURCE_STREAM,
1829 10, 10, rfork_content);
1831 /* Truncate back to size 0, further access MUST return ENOENT */
1833 torture_comment(tctx, "(%s) truncate resource fork to size 0\n",
1834 __location__);
1836 ZERO_STRUCT(create);
1837 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1838 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1839 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1840 create.in.fname = fname;
1841 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1842 NTCREATEX_SHARE_ACCESS_READ |
1843 NTCREATEX_SHARE_ACCESS_WRITE;
1844 status = smb2_create(tree, mem_ctx, &create);
1845 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1846 fh1 = create.out.file.handle;
1848 ZERO_STRUCT(create);
1849 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1850 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1851 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1852 create.in.fname = rfork;
1853 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1854 NTCREATEX_SHARE_ACCESS_READ |
1855 NTCREATEX_SHARE_ACCESS_WRITE;
1856 status = smb2_create(tree, mem_ctx, &create);
1857 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1858 fh2 = create.out.file.handle;
1860 ZERO_STRUCT(sinfo);
1861 sinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1862 sinfo.end_of_file_info.in.file.handle = fh2;
1863 sinfo.end_of_file_info.in.size = 0;
1864 status = smb2_setinfo_file(tree, &sinfo);
1865 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file");
1868 * Now check size, we should get OBJECT_NAME_NOT_FOUND (!)
1870 ZERO_STRUCT(create);
1871 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1872 create.in.desired_access = SEC_FILE_ALL;
1873 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1874 create.in.fname = rfork;
1875 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1876 NTCREATEX_SHARE_ACCESS_READ |
1877 NTCREATEX_SHARE_ACCESS_WRITE;
1878 status = smb2_create(tree, mem_ctx, &create);
1879 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1882 * Do another open on the rfork and write to the new handle. A
1883 * naive server might unlink the AppleDouble resource fork
1884 * file when its truncated to 0 bytes above, so in case both
1885 * open handles share the same underlying fd, the unlink would
1886 * cause the below write to be lost.
1888 ZERO_STRUCT(create);
1889 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1890 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1891 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1892 create.in.fname = rfork;
1893 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1894 NTCREATEX_SHARE_ACCESS_READ |
1895 NTCREATEX_SHARE_ACCESS_WRITE;
1896 status = smb2_create(tree, mem_ctx, &create);
1897 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1898 fh3 = create.out.file.handle;
1900 status = smb2_util_write(tree, fh3, "foo", 0, 3);
1901 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write");
1903 smb2_util_close(tree, fh3);
1904 smb2_util_close(tree, fh2);
1905 smb2_util_close(tree, fh1);
1907 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM,
1908 0, 3, 0, 3, "foo");
1909 torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
1911 done:
1912 smb2_util_unlink(tree, fname);
1913 smb2_deltree(tree, BASEDIR);
1914 talloc_free(mem_ctx);
1915 return ret;
1918 static bool test_rfork_create(struct torture_context *tctx,
1919 struct smb2_tree *tree)
1921 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1922 const char *fname = BASEDIR "\\torture_rfork_create";
1923 const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
1924 NTSTATUS status;
1925 struct smb2_handle testdirh;
1926 bool ret = true;
1927 struct smb2_create create;
1928 struct smb2_handle fh1;
1929 const char *streams[] = {
1930 "::$DATA"
1932 union smb_fileinfo finfo;
1934 ret = enable_aapl(tctx, tree);
1935 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
1937 smb2_util_unlink(tree, fname);
1939 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1940 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1941 smb2_util_close(tree, testdirh);
1943 ret = torture_setup_file(mem_ctx, tree, fname, false);
1944 if (ret == false) {
1945 goto done;
1948 torture_comment(tctx, "(%s) open rfork, should return ENOENT\n",
1949 __location__);
1951 ZERO_STRUCT(create);
1952 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1953 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1954 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1955 create.in.fname = rfork;
1956 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1957 NTCREATEX_SHARE_ACCESS_READ |
1958 NTCREATEX_SHARE_ACCESS_WRITE;
1959 status = smb2_create(tree, mem_ctx, &create);
1960 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1962 torture_comment(tctx, "(%s) create resource fork\n", __location__);
1964 ZERO_STRUCT(create);
1965 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1966 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1967 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1968 create.in.fname = rfork;
1969 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1970 NTCREATEX_SHARE_ACCESS_READ |
1971 NTCREATEX_SHARE_ACCESS_WRITE;
1972 status = smb2_create(tree, mem_ctx, &create);
1973 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1974 fh1 = create.out.file.handle;
1976 torture_comment(tctx, "(%s) getinfo on create handle\n",
1977 __location__);
1979 ZERO_STRUCT(finfo);
1980 finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1981 finfo.generic.in.file.handle = fh1;
1982 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1983 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file");
1984 if (finfo.all_info.out.size != 0) {
1985 torture_result(tctx, TORTURE_FAIL,
1986 "(%s) Incorrect resource fork size\n",
1987 __location__);
1988 ret = false;
1989 smb2_util_close(tree, fh1);
1990 goto done;
1993 torture_comment(tctx, "(%s) open rfork, should still return ENOENT\n",
1994 __location__);
1996 ZERO_STRUCT(create);
1997 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1998 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1999 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2000 create.in.fname = rfork;
2001 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
2002 NTCREATEX_SHARE_ACCESS_READ |
2003 NTCREATEX_SHARE_ACCESS_WRITE;
2004 status = smb2_create(tree, mem_ctx, &create);
2005 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
2007 ret = check_stream_list(tree, tctx, fname, 1, streams, false);
2008 torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2010 torture_comment(tctx, "(%s) close empty created rfork, open should return ENOENT\n",
2011 __location__);
2013 ZERO_STRUCT(create);
2014 create.in.create_disposition = NTCREATEX_DISP_OPEN;
2015 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
2016 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2017 create.in.fname = rfork;
2018 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
2019 NTCREATEX_SHARE_ACCESS_READ |
2020 NTCREATEX_SHARE_ACCESS_WRITE;
2021 status = smb2_create(tree, mem_ctx, &create);
2022 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
2024 done:
2025 smb2_util_unlink(tree, fname);
2026 smb2_deltree(tree, BASEDIR);
2027 talloc_free(mem_ctx);
2028 return ret;
2031 static bool test_rfork_create_ro(struct torture_context *tctx,
2032 struct smb2_tree *tree)
2034 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2035 const char *fname = BASEDIR "\\torture_rfork_create";
2036 const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
2037 NTSTATUS status;
2038 struct smb2_handle testdirh;
2039 bool ret = true;
2040 struct smb2_create create;
2042 smb2_util_unlink(tree, fname);
2043 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2044 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2045 "torture_smb2_testdir\n");
2046 smb2_util_close(tree, testdirh);
2048 ret = torture_setup_file(mem_ctx, tree, fname, false);
2049 if (ret == false) {
2050 goto done;
2053 torture_comment(tctx, "(%s) Try opening read-only with "
2054 "open_if create disposition, should work\n",
2055 __location__);
2057 ZERO_STRUCT(create);
2058 create.in.fname = rfork;
2059 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2060 create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
2061 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2062 create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
2063 status = smb2_create(tree, mem_ctx, &(create));
2064 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2065 "smb2_create failed\n");
2067 smb2_util_close(tree, create.out.file.handle);
2069 done:
2070 smb2_util_unlink(tree, fname);
2071 smb2_deltree(tree, BASEDIR);
2072 talloc_free(mem_ctx);
2073 return ret;
2076 static bool test_adouble_conversion(struct torture_context *tctx,
2077 struct smb2_tree *tree)
2079 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2080 const char *fname = BASEDIR "\\test_adouble_conversion";
2081 const char *adname = BASEDIR "/._test_adouble_conversion";
2082 NTSTATUS status;
2083 struct smb2_handle testdirh;
2084 bool ret = true;
2085 const char *data = "This resource fork intentionally left blank";
2086 size_t datalen = strlen(data);
2087 const char *streams[] = {
2088 "::$DATA",
2089 AFPINFO_STREAM,
2090 AFPRESOURCE_STREAM,
2091 ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
2092 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2094 bool is_osx = torture_setting_bool(tctx, "osx", false);
2096 if (is_osx) {
2097 torture_skip(tctx, "Test only works with Samba\n");
2100 smb2_deltree(tree, BASEDIR);
2102 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2103 CHECK_STATUS(status, NT_STATUS_OK);
2104 smb2_util_close(tree, testdirh);
2106 ret = torture_setup_file(tctx, tree, fname, false);
2107 torture_assert_goto(tctx, ret == true, ret, done,
2108 "torture_setup_file failed\n");
2110 ret = torture_setup_file(tctx, tree, adname, false);
2111 torture_assert_goto(tctx, ret == true, ret, done,
2112 "torture_setup_file failed\n");
2114 ret = write_stream(tree, __location__, tctx, mem_ctx,
2115 adname, NULL,
2116 0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr);
2117 torture_assert_goto(tctx, ret == true, ret, done,
2118 "write_stream failed\n");
2120 torture_comment(tctx, "(%s) test OS X AppleDouble conversion\n",
2121 __location__);
2123 ret = check_stream(tree, __location__, tctx, mem_ctx,
2124 fname, AFPRESOURCE_STREAM,
2125 16, datalen, 0, datalen, data);
2126 torture_assert_goto(tctx, ret == true, ret, done,
2127 "check AFPRESOURCE_STREAM failed\n");
2129 ret = check_stream(tree, __location__, tctx, mem_ctx,
2130 fname, AFPINFO_STREAM,
2131 0, 60, 16, 8, "TESTSLOW");
2132 torture_assert_goto(tctx, ret == true, ret, done,
2133 "check AFPINFO_STREAM failed\n");
2135 ret = check_stream(tree, __location__, tctx, mem_ctx, fname,
2136 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2137 0, 3, 0, 3, "baz");
2138 torture_assert_goto(tctx, ret == true, ret, done,
2139 "check foo:bar stream failed\n");
2141 ret = check_stream_list(tree, tctx, fname, 5, streams, false);
2142 torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2144 done:
2145 smb2_deltree(tree, BASEDIR);
2146 talloc_free(mem_ctx);
2147 return ret;
2151 * Test conversion of AppleDouble file without embedded xattr data
2153 static bool test_adouble_conversion_wo_xattr(struct torture_context *tctx,
2154 struct smb2_tree *tree)
2156 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2157 const char *fname = BASEDIR "\\test_adouble_conversion";
2158 const char *adname = BASEDIR "/._test_adouble_conversion";
2159 NTSTATUS status;
2160 struct smb2_handle testdirh;
2161 bool ret = true;
2162 const char *streams[] = {
2163 "::$DATA",
2164 AFPINFO_STREAM,
2165 AFPRESOURCE_STREAM
2167 struct smb2_create create;
2168 struct smb2_find find;
2169 unsigned int count;
2170 union smb_search_data *d;
2171 const char *data = "This resource fork intentionally left blank";
2172 size_t datalen = strlen(data);
2173 bool is_osx = torture_setting_bool(tctx, "osx", false);
2175 if (is_osx) {
2176 torture_skip(tctx, "Test only works with Samba\n");
2179 smb2_deltree(tree, BASEDIR);
2181 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2182 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2183 "torture_smb2_testdir failed\n");
2184 smb2_util_close(tree, testdirh);
2186 ret = torture_setup_file(tctx, tree, fname, false);
2187 torture_assert_goto(tctx, ret == true, ret, done,
2188 "torture_setup_file failed\n");
2190 ret = torture_setup_file(tctx, tree, adname, false);
2191 torture_assert_goto(tctx, ret == true, ret, done,
2192 "torture_setup_file failed\n");
2194 ret = write_stream(tree, __location__, tctx, mem_ctx,
2195 adname, NULL, 0,
2196 sizeof(osx_adouble_without_xattr),
2197 osx_adouble_without_xattr);
2198 torture_assert_goto(tctx, ret == true, ret, done,
2199 "write_stream failed\n");
2201 ret = enable_aapl(tctx, tree);
2202 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
2205 * Issue a smb2_find(), this triggers the server-side conversion
2208 create = (struct smb2_create) {
2209 .in.desired_access = SEC_RIGHTS_DIR_READ,
2210 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
2211 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
2212 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
2213 .in.create_disposition = NTCREATEX_DISP_OPEN,
2214 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
2215 .in.fname = BASEDIR,
2218 status = smb2_create(tree, tctx, &create);
2219 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2220 "smb2_create failed\n");
2222 find = (struct smb2_find) {
2223 .in.file.handle = create.out.file.handle,
2224 .in.pattern = "*",
2225 .in.max_response_size = 0x1000,
2226 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
2229 status = smb2_find_level(tree, tree, &find, &count, &d);
2230 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2231 "smb2_find_level failed\n");
2233 status = smb2_util_close(tree, create.out.file.handle);
2234 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2235 "smb2_util_close failed");
2238 * Check number of streams
2241 ret = check_stream_list(tree, tctx, fname, 3, streams, false);
2242 torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2246 * Check Resourcefork data can be read.
2249 ret = check_stream(tree, __location__, tctx, mem_ctx,
2250 fname, AFPRESOURCE_STREAM,
2251 16, datalen, 0, datalen, data);
2252 torture_assert_goto(tctx, ret == true, ret, done,
2253 "check AFPRESOURCE_STREAM failed\n");
2256 * Check FinderInfo data has been migrated to stream.
2259 ret = check_stream(tree, __location__, tctx, mem_ctx,
2260 fname, AFPINFO_STREAM,
2261 0, 60, 16, 8, "WAVEPTul");
2262 torture_assert_goto(tctx, ret == true, ret, done,
2263 "check AFPINFO_STREAM failed\n");
2265 done:
2266 smb2_deltree(tree, BASEDIR);
2267 talloc_free(mem_ctx);
2268 return ret;
2271 static bool test_aapl(struct torture_context *tctx,
2272 struct smb2_tree *tree)
2274 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2275 const char *fname = BASEDIR "\\test_aapl";
2276 NTSTATUS status;
2277 struct smb2_handle testdirh;
2278 bool ret = true;
2279 struct smb2_create io;
2280 DATA_BLOB data;
2281 struct smb2_create_blob *aapl = NULL;
2282 AfpInfo *info;
2283 const char *type_creator = "SMB,OLE!";
2284 char type_creator_buf[9];
2285 uint32_t aapl_cmd;
2286 uint32_t aapl_reply_bitmap;
2287 uint32_t aapl_server_caps;
2288 uint32_t aapl_vol_caps;
2289 uint32_t expected_vol_caps = 0;
2290 char *model;
2291 struct smb2_find f;
2292 unsigned int count;
2293 union smb_search_data *d;
2294 uint64_t rfork_len;
2295 bool is_osx_server = torture_setting_bool(tctx, "osx", false);
2297 smb2_deltree(tree, BASEDIR);
2299 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2300 CHECK_STATUS(status, NT_STATUS_OK);
2301 smb2_util_close(tree, testdirh);
2303 ZERO_STRUCT(io);
2304 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
2305 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2306 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2307 io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2308 NTCREATEX_SHARE_ACCESS_READ |
2309 NTCREATEX_SHARE_ACCESS_WRITE);
2310 io.in.fname = fname;
2313 * Issuing an SMB2/CREATE with a suitably formed AAPL context,
2314 * controls behaviour of Apple's SMB2 extensions for the whole
2315 * session!
2318 data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2319 SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2320 SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2321 SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2322 SMB2_CRTCTX_AAPL_MODEL_INFO));
2323 SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2324 SMB2_CRTCTX_AAPL_UNIX_BASED |
2325 SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
2327 torture_comment(tctx, "Testing SMB2 create context AAPL\n");
2328 status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2329 CHECK_STATUS(status, NT_STATUS_OK);
2331 status = smb2_create(tree, tctx, &io);
2332 CHECK_STATUS(status, NT_STATUS_OK);
2333 status = smb2_util_close(tree, io.out.file.handle);
2334 CHECK_STATUS(status, NT_STATUS_OK);
2337 * Now check returned AAPL context
2339 torture_comment(tctx, "Comparing returned AAPL capabilities\n");
2341 aapl = smb2_create_blob_find(&io.out.blobs,
2342 SMB2_CREATE_TAG_AAPL);
2344 if (aapl == NULL) {
2345 torture_result(tctx, TORTURE_FAIL,
2346 "(%s) unexpectedly no AAPL capabilities were returned.",
2347 __location__);
2348 ret = false;
2349 goto done;
2352 if (!is_osx_server) {
2353 size_t expected_aapl_ctx_size;
2354 bool size_ok;
2357 * uint32_t CommandCode = kAAPL_SERVER_QUERY
2358 * uint32_t Reserved = 0;
2359 * uint64_t ReplyBitmap = kAAPL_SERVER_CAPS |
2360 * kAAPL_VOLUME_CAPS |
2361 * kAAPL_MODEL_INFO;
2362 * uint64_t ServerCaps = kAAPL_SUPPORTS_READDIR_ATTR |
2363 * kAAPL_SUPPORTS_OSX_COPYFILE;
2364 * uint64_t VolumeCaps = kAAPL_SUPPORT_RESOLVE_ID |
2365 * kAAPL_CASE_SENSITIVE;
2366 * uint32_t Pad2 = 0;
2367 * uint32_t ModelStringLen = 10;
2368 * ucs2_t ModelString[5] = "MacSamba";
2370 expected_aapl_ctx_size = strlen("MacSamba") * 2 + 40;
2372 size_ok = aapl->data.length == expected_aapl_ctx_size;
2373 torture_assert_goto(tctx, size_ok, ret, done, "bad AAPL size");
2376 aapl_cmd = IVAL(aapl->data.data, 0);
2377 if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2378 torture_result(tctx, TORTURE_FAIL,
2379 "(%s) unexpected cmd: %d",
2380 __location__, (int)aapl_cmd);
2381 ret = false;
2382 goto done;
2385 aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2386 if (aapl_reply_bitmap != (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2387 SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2388 SMB2_CRTCTX_AAPL_MODEL_INFO)) {
2389 torture_result(tctx, TORTURE_FAIL,
2390 "(%s) unexpected reply_bitmap: %d",
2391 __location__, (int)aapl_reply_bitmap);
2392 ret = false;
2393 goto done;
2396 aapl_server_caps = BVAL(aapl->data.data, 16);
2397 if (aapl_server_caps != (SMB2_CRTCTX_AAPL_UNIX_BASED |
2398 SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2399 SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
2400 SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE)) {
2401 torture_result(tctx, TORTURE_FAIL,
2402 "(%s) unexpected server_caps: %d",
2403 __location__, (int)aapl_server_caps);
2404 ret = false;
2405 goto done;
2408 if (is_osx_server) {
2409 expected_vol_caps = 5;
2411 aapl_vol_caps = BVAL(aapl->data.data, 24);
2412 if (aapl_vol_caps != expected_vol_caps) {
2413 /* this will fail on a case insensitive fs ... */
2414 torture_result(tctx, TORTURE_FAIL,
2415 "(%s) unexpected vol_caps: %d",
2416 __location__, (int)aapl_vol_caps);
2419 ret = convert_string_talloc(mem_ctx,
2420 CH_UTF16LE, CH_UNIX,
2421 aapl->data.data + 40, 10,
2422 &model, NULL);
2423 if (ret == false) {
2424 torture_result(tctx, TORTURE_FAIL,
2425 "(%s) convert_string_talloc() failed",
2426 __location__);
2427 goto done;
2429 torture_comment(tctx, "Got server model: \"%s\"\n", model);
2432 * Now that Requested AAPL extensions are enabled, setup some
2433 * Mac files with metadata and resource fork
2435 ret = torture_setup_file(mem_ctx, tree, fname, false);
2436 if (ret == false) {
2437 torture_result(tctx, TORTURE_FAIL,
2438 "(%s) torture_setup_file() failed",
2439 __location__);
2440 goto done;
2443 info = torture_afpinfo_new(mem_ctx);
2444 if (info == NULL) {
2445 torture_result(tctx, TORTURE_FAIL,
2446 "(%s) torture_afpinfo_new() failed",
2447 __location__);
2448 ret = false;
2449 goto done;
2452 memcpy(info->afpi_FinderInfo, type_creator, 8);
2453 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
2454 if (ret == false) {
2455 torture_result(tctx, TORTURE_FAIL,
2456 "(%s) torture_write_afpinfo() failed",
2457 __location__);
2458 goto done;
2461 ret = write_stream(tree, __location__, tctx, mem_ctx,
2462 fname, AFPRESOURCE_STREAM_NAME,
2463 0, 3, "foo");
2464 if (ret == false) {
2465 torture_result(tctx, TORTURE_FAIL,
2466 "(%s) write_stream() failed",
2467 __location__);
2468 goto done;
2472 * Ok, file is prepared, now call smb2/find
2475 ZERO_STRUCT(io);
2476 io.in.desired_access = SEC_RIGHTS_DIR_READ;
2477 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2478 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2479 io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
2480 NTCREATEX_SHARE_ACCESS_WRITE |
2481 NTCREATEX_SHARE_ACCESS_DELETE);
2482 io.in.create_disposition = NTCREATEX_DISP_OPEN;
2483 io.in.fname = BASEDIR;
2484 status = smb2_create(tree, tctx, &io);
2485 CHECK_STATUS(status, NT_STATUS_OK);
2487 ZERO_STRUCT(f);
2488 f.in.file.handle = io.out.file.handle;
2489 f.in.pattern = "test_aapl";
2490 f.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE;
2491 f.in.max_response_size = 0x1000;
2492 f.in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
2494 status = smb2_find_level(tree, tree, &f, &count, &d);
2495 CHECK_STATUS(status, NT_STATUS_OK);
2497 status = smb2_util_close(tree, io.out.file.handle);
2498 CHECK_STATUS(status, NT_STATUS_OK);
2500 if (strcmp(d[0].id_both_directory_info.name.s, "test_aapl") != 0) {
2501 torture_result(tctx, TORTURE_FAIL,
2502 "(%s) write_stream() failed",
2503 __location__);
2504 ret = false;
2505 goto done;
2508 if (d[0].id_both_directory_info.short_name.private_length != 24) {
2509 torture_result(tctx, TORTURE_FAIL,
2510 "(%s) bad short_name length %" PRIu32 ", expected 24",
2511 __location__, d[0].id_both_directory_info.short_name.private_length);
2512 ret = false;
2513 goto done;
2516 torture_comment(tctx, "short_name buffer:\n");
2517 dump_data(0, d[0].id_both_directory_info.short_name_buf, 24);
2520 * Extract data as specified by the AAPL extension:
2521 * - ea_size contains max_access
2522 * - short_name contains resource fork length + FinderInfo
2523 * - reserved2 contains the unix mode
2525 torture_comment(tctx, "mac_access: %" PRIx32 "\n",
2526 d[0].id_both_directory_info.ea_size);
2528 rfork_len = BVAL(d[0].id_both_directory_info.short_name_buf, 0);
2529 if (rfork_len != 3) {
2530 torture_result(tctx, TORTURE_FAIL,
2531 "(%s) expected resource fork length 3, got: %" PRIu64,
2532 __location__, rfork_len);
2533 ret = false;
2534 goto done;
2537 memcpy(type_creator_buf, d[0].id_both_directory_info.short_name_buf + 8, 8);
2538 type_creator_buf[8] = 0;
2539 if (strcmp(type_creator, type_creator_buf) != 0) {
2540 torture_result(tctx, TORTURE_FAIL,
2541 "(%s) expected type/creator \"%s\" , got: %s",
2542 __location__, type_creator, type_creator_buf);
2543 ret = false;
2544 goto done;
2547 done:
2548 smb2_util_unlink(tree, fname);
2549 smb2_deltree(tree, BASEDIR);
2550 talloc_free(mem_ctx);
2551 return ret;
2554 static uint64_t patt_hash(uint64_t off)
2556 return off;
2559 static bool write_pattern(struct torture_context *torture,
2560 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2561 struct smb2_handle h, uint64_t off, uint64_t len,
2562 uint64_t patt_off)
2564 NTSTATUS status;
2565 uint64_t i;
2566 uint8_t *buf;
2567 uint64_t io_sz = MIN(1024 * 64, len);
2569 if (len == 0) {
2570 return true;
2573 torture_assert(torture, (len % 8) == 0, "invalid write len");
2575 buf = talloc_zero_size(mem_ctx, io_sz);
2576 torture_assert(torture, (buf != NULL), "no memory for file data buf");
2578 while (len > 0) {
2579 for (i = 0; i <= io_sz - 8; i += 8) {
2580 SBVAL(buf, i, patt_hash(patt_off));
2581 patt_off += 8;
2584 status = smb2_util_write(tree, h,
2585 buf, off, io_sz);
2586 torture_assert_ntstatus_ok(torture, status, "file write");
2588 len -= io_sz;
2589 off += io_sz;
2592 talloc_free(buf);
2594 return true;
2597 static bool check_pattern(struct torture_context *torture,
2598 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2599 struct smb2_handle h, uint64_t off, uint64_t len,
2600 uint64_t patt_off)
2602 if (len == 0) {
2603 return true;
2606 torture_assert(torture, (len % 8) == 0, "invalid read len");
2608 while (len > 0) {
2609 uint64_t i;
2610 struct smb2_read r;
2611 NTSTATUS status;
2612 uint64_t io_sz = MIN(1024 * 64, len);
2614 ZERO_STRUCT(r);
2615 r.in.file.handle = h;
2616 r.in.length = io_sz;
2617 r.in.offset = off;
2618 status = smb2_read(tree, mem_ctx, &r);
2619 torture_assert_ntstatus_ok(torture, status, "read");
2621 torture_assert_u64_equal(torture, r.out.data.length, io_sz,
2622 "read data len mismatch");
2624 for (i = 0; i <= io_sz - 8; i += 8, patt_off += 8) {
2625 uint64_t data = BVAL(r.out.data.data, i);
2626 torture_assert_u64_equal(torture, data, patt_hash(patt_off),
2627 talloc_asprintf(torture, "read data "
2628 "pattern bad at %llu\n",
2629 (unsigned long long)off + i));
2631 talloc_free(r.out.data.data);
2632 len -= io_sz;
2633 off += io_sz;
2636 return true;
2639 static bool test_setup_open(struct torture_context *torture,
2640 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2641 const char *fname,
2642 struct smb2_handle *fh,
2643 uint32_t desired_access,
2644 uint32_t file_attributes)
2646 struct smb2_create io;
2647 NTSTATUS status;
2649 ZERO_STRUCT(io);
2650 io.in.desired_access = desired_access;
2651 io.in.file_attributes = file_attributes;
2652 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2653 io.in.share_access =
2654 NTCREATEX_SHARE_ACCESS_DELETE|
2655 NTCREATEX_SHARE_ACCESS_READ|
2656 NTCREATEX_SHARE_ACCESS_WRITE;
2657 if (file_attributes & FILE_ATTRIBUTE_DIRECTORY) {
2658 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2660 io.in.fname = fname;
2662 status = smb2_create(tree, mem_ctx, &io);
2663 torture_assert_ntstatus_ok(torture, status, "file create");
2665 *fh = io.out.file.handle;
2667 return true;
2670 static bool test_setup_create_fill(struct torture_context *torture,
2671 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2672 const char *fname,
2673 struct smb2_handle *fh,
2674 uint64_t size,
2675 uint32_t desired_access,
2676 uint32_t file_attributes)
2678 bool ok;
2680 ok = test_setup_open(torture, tree, mem_ctx,
2681 fname,
2683 desired_access,
2684 file_attributes);
2685 torture_assert(torture, ok, "file open");
2687 if (size > 0) {
2688 ok = write_pattern(torture, tree, mem_ctx, *fh, 0, size, 0);
2689 torture_assert(torture, ok, "write pattern");
2691 return true;
2694 static bool test_setup_copy_chunk(struct torture_context *torture,
2695 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2696 uint32_t nchunks,
2697 const char *src_name,
2698 struct smb2_handle *src_h,
2699 uint64_t src_size,
2700 uint32_t src_desired_access,
2701 const char *dst_name,
2702 struct smb2_handle *dest_h,
2703 uint64_t dest_size,
2704 uint32_t dest_desired_access,
2705 struct srv_copychunk_copy *cc_copy,
2706 union smb_ioctl *io)
2708 struct req_resume_key_rsp res_key;
2709 bool ok;
2710 NTSTATUS status;
2711 enum ndr_err_code ndr_ret;
2713 ok = test_setup_create_fill(torture, tree, mem_ctx, src_name,
2714 src_h, src_size, src_desired_access,
2715 FILE_ATTRIBUTE_NORMAL);
2716 torture_assert(torture, ok, "src file create fill");
2718 ok = test_setup_create_fill(torture, tree, mem_ctx, dst_name,
2719 dest_h, dest_size, dest_desired_access,
2720 FILE_ATTRIBUTE_NORMAL);
2721 torture_assert(torture, ok, "dest file create fill");
2723 ZERO_STRUCTPN(io);
2724 io->smb2.level = RAW_IOCTL_SMB2;
2725 io->smb2.in.file.handle = *src_h;
2726 io->smb2.in.function = FSCTL_SRV_REQUEST_RESUME_KEY;
2727 /* Allow for Key + ContextLength + Context */
2728 io->smb2.in.max_output_response = 32;
2729 io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2731 status = smb2_ioctl(tree, mem_ctx, &io->smb2);
2732 torture_assert_ntstatus_ok(torture, status,
2733 "FSCTL_SRV_REQUEST_RESUME_KEY");
2735 ndr_ret = ndr_pull_struct_blob(&io->smb2.out.out, mem_ctx, &res_key,
2736 (ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
2738 torture_assert_ndr_success(torture, ndr_ret,
2739 "ndr_pull_req_resume_key_rsp");
2741 ZERO_STRUCTPN(io);
2742 io->smb2.level = RAW_IOCTL_SMB2;
2743 io->smb2.in.file.handle = *dest_h;
2744 io->smb2.in.function = FSCTL_SRV_COPYCHUNK;
2745 io->smb2.in.max_output_response = sizeof(struct srv_copychunk_rsp);
2746 io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2748 ZERO_STRUCTPN(cc_copy);
2749 memcpy(cc_copy->source_key, res_key.resume_key, ARRAY_SIZE(cc_copy->source_key));
2750 cc_copy->chunk_count = nchunks;
2751 cc_copy->chunks = talloc_zero_array(mem_ctx, struct srv_copychunk, nchunks);
2752 torture_assert(torture, (cc_copy->chunks != NULL), "no memory for chunks");
2754 return true;
2758 static bool check_copy_chunk_rsp(struct torture_context *torture,
2759 struct srv_copychunk_rsp *cc_rsp,
2760 uint32_t ex_chunks_written,
2761 uint32_t ex_chunk_bytes_written,
2762 uint32_t ex_total_bytes_written)
2764 torture_assert_int_equal(torture, cc_rsp->chunks_written,
2765 ex_chunks_written, "num chunks");
2766 torture_assert_int_equal(torture, cc_rsp->chunk_bytes_written,
2767 ex_chunk_bytes_written, "chunk bytes written");
2768 torture_assert_int_equal(torture, cc_rsp->total_bytes_written,
2769 ex_total_bytes_written, "chunk total bytes");
2770 return true;
2773 static bool neg_aapl_copyfile(struct torture_context *tctx,
2774 struct smb2_tree *tree,
2775 uint64_t flags)
2777 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2778 const char *fname = "aapl";
2779 NTSTATUS status;
2780 struct smb2_create io;
2781 DATA_BLOB data;
2782 struct smb2_create_blob *aapl = NULL;
2783 uint32_t aapl_cmd;
2784 uint32_t aapl_reply_bitmap;
2785 uint32_t aapl_server_caps;
2786 bool ret = true;
2788 ZERO_STRUCT(io);
2789 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
2790 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2791 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2792 io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2793 NTCREATEX_SHARE_ACCESS_READ |
2794 NTCREATEX_SHARE_ACCESS_WRITE);
2795 io.in.fname = fname;
2797 data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2798 SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2799 SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS));
2800 SBVAL(data.data, 16, flags);
2802 status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2803 CHECK_STATUS(status, NT_STATUS_OK);
2805 status = smb2_create(tree, tctx, &io);
2806 CHECK_STATUS(status, NT_STATUS_OK);
2808 aapl = smb2_create_blob_find(&io.out.blobs,
2809 SMB2_CREATE_TAG_AAPL);
2810 if (aapl == NULL) {
2811 ret = false;
2812 goto done;
2815 if (aapl->data.length < 24) {
2816 ret = false;
2817 goto done;
2820 aapl_cmd = IVAL(aapl->data.data, 0);
2821 if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2822 torture_result(tctx, TORTURE_FAIL,
2823 "(%s) unexpected cmd: %d",
2824 __location__, (int)aapl_cmd);
2825 ret = false;
2826 goto done;
2829 aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2830 if (!(aapl_reply_bitmap & SMB2_CRTCTX_AAPL_SERVER_CAPS)) {
2831 torture_result(tctx, TORTURE_FAIL,
2832 "(%s) unexpected reply_bitmap: %d",
2833 __location__, (int)aapl_reply_bitmap);
2834 ret = false;
2835 goto done;
2838 aapl_server_caps = BVAL(aapl->data.data, 16);
2839 if (!(aapl_server_caps & flags)) {
2840 torture_result(tctx, TORTURE_FAIL,
2841 "(%s) unexpected server_caps: %d",
2842 __location__, (int)aapl_server_caps);
2843 ret = false;
2844 goto done;
2847 done:
2848 status = smb2_util_close(tree, io.out.file.handle);
2849 CHECK_STATUS(status, NT_STATUS_OK);
2851 smb2_util_unlink(tree, "aapl");
2852 talloc_free(mem_ctx);
2853 return ret;
2856 static bool test_copyfile(struct torture_context *torture,
2857 struct smb2_tree *tree)
2859 struct smb2_handle src_h;
2860 struct smb2_handle dest_h;
2861 NTSTATUS status;
2862 union smb_ioctl io;
2863 TALLOC_CTX *tmp_ctx = talloc_new(tree);
2864 struct srv_copychunk_copy cc_copy;
2865 struct srv_copychunk_rsp cc_rsp;
2866 enum ndr_err_code ndr_ret;
2867 bool ok;
2868 const char *sname = ":foo" "\xef\x80\xa2" "bar:$DATA";
2871 * First test a copy_chunk with a 0 chunk count without having
2872 * enabled this via AAPL. The request must not fail and the
2873 * copied length in the response must be 0. This is verified
2874 * against Windows 2008r2.
2877 ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2878 0, /* 0 chunks, copyfile semantics */
2879 FNAME_CC_SRC,
2880 &src_h, 4096, /* fill 4096 byte src file */
2881 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2882 FNAME_CC_DST,
2883 &dest_h, 0, /* 0 byte dest file */
2884 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2885 &cc_copy,
2886 &io);
2887 if (!ok) {
2888 torture_fail_goto(torture, done, "setup copy chunk error");
2891 ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2892 &cc_copy,
2893 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2894 torture_assert_ndr_success(torture, ndr_ret,
2895 "ndr_push_srv_copychunk_copy");
2897 status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2898 torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2900 ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2901 &cc_rsp,
2902 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2903 torture_assert_ndr_success(torture, ndr_ret,
2904 "ndr_pull_srv_copychunk_rsp");
2906 ok = check_copy_chunk_rsp(torture, &cc_rsp,
2907 0, /* chunks written */
2908 0, /* chunk bytes unsuccessfully written */
2909 0); /* total bytes written */
2910 if (!ok) {
2911 torture_fail_goto(torture, done, "bad copy chunk response data");
2915 * Now enable AAPL copyfile and test again, the file and the
2916 * stream must be copied by the server.
2918 ok = neg_aapl_copyfile(torture, tree,
2919 SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
2920 if (!ok) {
2921 torture_skip_goto(torture, done, "missing AAPL copyfile");
2922 goto done;
2925 smb2_util_close(tree, src_h);
2926 smb2_util_close(tree, dest_h);
2927 smb2_util_unlink(tree, FNAME_CC_SRC);
2928 smb2_util_unlink(tree, FNAME_CC_DST);
2930 ok = torture_setup_file(tmp_ctx, tree, FNAME_CC_SRC, false);
2931 if (!ok) {
2932 torture_fail(torture, "setup file error");
2934 ok = write_stream(tree, __location__, torture, tmp_ctx,
2935 FNAME_CC_SRC, AFPRESOURCE_STREAM,
2936 10, 10, "1234567890");
2937 if (!ok) {
2938 torture_fail(torture, "setup stream error");
2941 ok = write_stream(tree, __location__, torture, tmp_ctx,
2942 FNAME_CC_SRC, sname,
2943 10, 10, "abcdefghij");
2944 torture_assert_goto(torture, ok == true, ok, done, "write_stream failed\n");
2946 ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2947 0, /* 0 chunks, copyfile semantics */
2948 FNAME_CC_SRC,
2949 &src_h, 4096, /* fill 4096 byte src file */
2950 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2951 FNAME_CC_DST,
2952 &dest_h, 0, /* 0 byte dest file */
2953 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2954 &cc_copy,
2955 &io);
2956 if (!ok) {
2957 torture_fail_goto(torture, done, "setup copy chunk error");
2960 ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2961 &cc_copy,
2962 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2963 torture_assert_ndr_success(torture, ndr_ret,
2964 "ndr_push_srv_copychunk_copy");
2966 status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2967 torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2969 ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2970 &cc_rsp,
2971 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2972 torture_assert_ndr_success(torture, ndr_ret,
2973 "ndr_pull_srv_copychunk_rsp");
2975 ok = check_copy_chunk_rsp(torture, &cc_rsp,
2976 0, /* chunks written */
2977 0, /* chunk bytes unsuccessfully written */
2978 4096); /* total bytes written */
2979 if (!ok) {
2980 torture_fail_goto(torture, done, "bad copy chunk response data");
2983 ok = test_setup_open(torture, tree, tmp_ctx, FNAME_CC_DST, &dest_h,
2984 SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL);
2985 if (!ok) {
2986 torture_fail_goto(torture, done,"open failed");
2988 ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 4096, 0);
2989 if (!ok) {
2990 torture_fail_goto(torture, done, "inconsistent file data");
2993 ok = check_stream(tree, __location__, torture, tmp_ctx,
2994 FNAME_CC_DST, AFPRESOURCE_STREAM,
2995 0, 20, 10, 10, "1234567890");
2996 if (!ok) {
2997 torture_fail_goto(torture, done, "inconsistent stream data");
3000 ok = check_stream(tree, __location__, torture, tmp_ctx,
3001 FNAME_CC_DST, sname,
3002 0, 20, 10, 10, "abcdefghij");
3003 torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
3005 done:
3006 smb2_util_close(tree, src_h);
3007 smb2_util_close(tree, dest_h);
3008 smb2_util_unlink(tree, FNAME_CC_SRC);
3009 smb2_util_unlink(tree, FNAME_CC_DST);
3010 talloc_free(tmp_ctx);
3011 return true;
3014 static bool check_stream_list(struct smb2_tree *tree,
3015 struct torture_context *tctx,
3016 const char *fname,
3017 int num_exp,
3018 const char **exp,
3019 bool is_dir)
3021 bool ret = true;
3022 union smb_fileinfo finfo;
3023 NTSTATUS status;
3024 int i;
3025 TALLOC_CTX *tmp_ctx = talloc_new(tctx);
3026 char **exp_sort;
3027 struct stream_struct *stream_sort;
3028 struct smb2_create create;
3029 struct smb2_handle h;
3031 ZERO_STRUCT(h);
3032 torture_assert_goto(tctx, tmp_ctx != NULL, ret, done, "talloc_new failed");
3034 ZERO_STRUCT(create);
3035 create.in.fname = fname;
3036 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3037 create.in.desired_access = SEC_FILE_ALL;
3038 create.in.create_options = is_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
3039 create.in.file_attributes = is_dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
3040 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3041 status = smb2_create(tree, tmp_ctx, &create);
3042 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
3043 h = create.out.file.handle;
3045 finfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
3046 finfo.generic.in.file.handle = h;
3048 status = smb2_getinfo_file(tree, tctx, &finfo);
3049 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "get stream info");
3051 smb2_util_close(tree, h);
3053 torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams, num_exp,
3054 ret, done, "stream count");
3056 if (num_exp == 0) {
3057 TALLOC_FREE(tmp_ctx);
3058 goto done;
3061 exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
3062 torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
3064 TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
3066 stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
3067 finfo.stream_info.out.num_streams *
3068 sizeof(*stream_sort));
3069 torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
3071 TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
3073 for (i=0; i<num_exp; i++) {
3074 torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
3075 i, exp_sort[i], stream_sort[i].stream_name.s);
3076 torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s, exp_sort[i],
3077 ret, done, "stream name");
3080 done:
3081 TALLOC_FREE(tmp_ctx);
3082 return ret;
3085 static bool check_stream_list_handle(struct smb2_tree *tree,
3086 struct torture_context *tctx,
3087 struct smb2_handle h,
3088 int num_exp,
3089 const char **exp,
3090 bool is_dir)
3092 bool ret = true;
3093 union smb_fileinfo finfo;
3094 NTSTATUS status;
3095 int i;
3096 TALLOC_CTX *tmp_ctx = talloc_new(tctx);
3097 char **exp_sort;
3098 struct stream_struct *stream_sort;
3100 torture_assert_goto(tctx, tmp_ctx != NULL, ret, done,
3101 "talloc_new failed\n");
3103 finfo = (union smb_fileinfo) {
3104 .stream_info.level = RAW_FILEINFO_STREAM_INFORMATION,
3105 .stream_info.in.file.handle = h,
3108 status = smb2_getinfo_file(tree, tctx, &finfo);
3109 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3110 "get stream info\n");
3112 torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams,
3113 num_exp, ret, done, "stream count\n");
3115 if (num_exp == 0) {
3116 TALLOC_FREE(tmp_ctx);
3117 goto done;
3120 exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
3121 torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
3123 TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
3125 stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
3126 finfo.stream_info.out.num_streams *
3127 sizeof(*stream_sort));
3128 torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
3130 TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
3132 for (i=0; i<num_exp; i++) {
3133 torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
3134 i, exp_sort[i], stream_sort[i].stream_name.s);
3135 torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s,
3136 exp_sort[i], ret, done,
3137 "stream name\n");
3140 done:
3141 TALLOC_FREE(tmp_ctx);
3142 return ret;
3146 test stream names
3148 static bool test_stream_names(struct torture_context *tctx,
3149 struct smb2_tree *tree)
3151 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3152 NTSTATUS status;
3153 struct smb2_create create;
3154 struct smb2_handle h;
3155 const char *fname = BASEDIR "\\stream_names.txt";
3156 const char *sname1;
3157 bool ret;
3158 /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
3159 const char *streams[] = {
3160 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
3161 "::$DATA"
3164 sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
3166 /* clean slate ...*/
3167 smb2_util_unlink(tree, fname);
3168 smb2_deltree(tree, fname);
3169 smb2_deltree(tree, BASEDIR);
3171 status = torture_smb2_testdir(tree, BASEDIR, &h);
3172 CHECK_STATUS(status, NT_STATUS_OK);
3173 smb2_util_close(tree, h);
3175 ret = torture_setup_file(mem_ctx, tree, fname, false);
3176 torture_assert_goto(tctx, ret, ret, done, "torture_setup_file");
3178 torture_comment(tctx, "(%s) testing stream names\n", __location__);
3179 ZERO_STRUCT(create);
3180 create.in.desired_access = SEC_FILE_WRITE_DATA;
3181 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3182 create.in.share_access =
3183 NTCREATEX_SHARE_ACCESS_DELETE|
3184 NTCREATEX_SHARE_ACCESS_READ|
3185 NTCREATEX_SHARE_ACCESS_WRITE;
3186 create.in.create_disposition = NTCREATEX_DISP_CREATE;
3187 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3188 create.in.fname = sname1;
3190 status = smb2_create(tree, mem_ctx, &create);
3191 CHECK_STATUS(status, NT_STATUS_OK);
3193 status = smb2_util_write(tree, create.out.file.handle, "foo", 0, 3);
3194 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3195 "smb2_util_write failed\n");
3197 smb2_util_close(tree, create.out.file.handle);
3199 ret = check_stream_list(tree, tctx, fname, 2, streams, false);
3200 CHECK_VALUE(ret, true);
3202 done:
3203 status = smb2_util_unlink(tree, fname);
3204 smb2_deltree(tree, BASEDIR);
3205 talloc_free(mem_ctx);
3207 return ret;
3210 /* Renaming a directory with open file, should work for OS X AAPL clients */
3211 static bool test_rename_dir_openfile(struct torture_context *torture,
3212 struct smb2_tree *tree)
3214 bool ret = true;
3215 NTSTATUS status;
3216 union smb_open io;
3217 union smb_close cl;
3218 union smb_setfileinfo sinfo;
3219 struct smb2_handle d1, h1;
3220 const char *renamedir = BASEDIR "-new";
3221 bool server_is_osx = torture_setting_bool(torture, "osx", false);
3223 smb2_deltree(tree, BASEDIR);
3224 smb2_util_rmdir(tree, BASEDIR);
3225 smb2_deltree(tree, renamedir);
3227 ZERO_STRUCT(io.smb2);
3228 io.generic.level = RAW_OPEN_SMB2;
3229 io.smb2.in.create_flags = 0;
3230 io.smb2.in.desired_access = 0x0017019f;
3231 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
3232 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
3233 io.smb2.in.share_access = 0;
3234 io.smb2.in.alloc_size = 0;
3235 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
3236 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3237 io.smb2.in.security_flags = 0;
3238 io.smb2.in.fname = BASEDIR;
3240 status = smb2_create(tree, torture, &(io.smb2));
3241 torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
3242 d1 = io.smb2.out.file.handle;
3244 ZERO_STRUCT(io.smb2);
3245 io.generic.level = RAW_OPEN_SMB2;
3246 io.smb2.in.create_flags = 0;
3247 io.smb2.in.desired_access = 0x0017019f;
3248 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
3249 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3250 io.smb2.in.share_access = 0;
3251 io.smb2.in.alloc_size = 0;
3252 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
3253 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3254 io.smb2.in.security_flags = 0;
3255 io.smb2.in.fname = BASEDIR "\\file.txt";
3257 status = smb2_create(tree, torture, &(io.smb2));
3258 torture_assert_ntstatus_ok(torture, status, "smb2_create file");
3259 h1 = io.smb2.out.file.handle;
3261 if (!server_is_osx) {
3262 torture_comment(torture, "Renaming directory without AAPL, must fail\n");
3264 ZERO_STRUCT(sinfo);
3265 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
3266 sinfo.rename_information.in.file.handle = d1;
3267 sinfo.rename_information.in.overwrite = 0;
3268 sinfo.rename_information.in.root_fid = 0;
3269 sinfo.rename_information.in.new_name = renamedir;
3270 status = smb2_setinfo_file(tree, &sinfo);
3272 torture_assert_ntstatus_equal(torture, status,
3273 NT_STATUS_ACCESS_DENIED,
3274 "smb2_setinfo_file");
3277 status = smb2_util_close(tree, d1);
3278 torture_assert_ntstatus_ok(torture, status, "smb2_util_close\n");
3279 ZERO_STRUCT(d1);
3281 torture_comment(torture, "Enabling AAPL\n");
3283 ret = enable_aapl(torture, tree);
3284 torture_assert(torture, ret == true, "enable_aapl failed");
3286 torture_comment(torture, "Renaming directory with AAPL\n");
3288 ZERO_STRUCT(io.smb2);
3289 io.generic.level = RAW_OPEN_SMB2;
3290 io.smb2.in.desired_access = 0x0017019f;
3291 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
3292 io.smb2.in.share_access = 0;
3293 io.smb2.in.alloc_size = 0;
3294 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
3295 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3296 io.smb2.in.security_flags = 0;
3297 io.smb2.in.fname = BASEDIR;
3299 status = smb2_create(tree, torture, &(io.smb2));
3300 torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
3301 d1 = io.smb2.out.file.handle;
3303 ZERO_STRUCT(sinfo);
3304 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
3305 sinfo.rename_information.in.file.handle = d1;
3306 sinfo.rename_information.in.overwrite = 0;
3307 sinfo.rename_information.in.root_fid = 0;
3308 sinfo.rename_information.in.new_name = renamedir;
3310 status = smb2_setinfo_file(tree, &sinfo);
3311 torture_assert_ntstatus_ok(torture, status, "smb2_setinfo_file");
3313 ZERO_STRUCT(cl.smb2);
3314 cl.smb2.level = RAW_CLOSE_SMB2;
3315 cl.smb2.in.file.handle = d1;
3316 status = smb2_close(tree, &(cl.smb2));
3317 torture_assert_ntstatus_ok(torture, status, "smb2_close");
3318 ZERO_STRUCT(d1);
3320 cl.smb2.in.file.handle = h1;
3321 status = smb2_close(tree, &(cl.smb2));
3322 torture_assert_ntstatus_ok(torture, status, "smb2_close");
3323 ZERO_STRUCT(h1);
3325 torture_comment(torture, "Cleaning up\n");
3327 if (h1.data[0] || h1.data[1]) {
3328 ZERO_STRUCT(cl.smb2);
3329 cl.smb2.level = RAW_CLOSE_SMB2;
3330 cl.smb2.in.file.handle = h1;
3331 status = smb2_close(tree, &(cl.smb2));
3334 smb2_util_unlink(tree, BASEDIR "\\file.txt");
3335 smb2_util_unlink(tree, BASEDIR "-new\\file.txt");
3336 smb2_deltree(tree, renamedir);
3337 smb2_deltree(tree, BASEDIR);
3338 return ret;
3341 static bool test_afpinfo_enoent(struct torture_context *tctx,
3342 struct smb2_tree *tree)
3344 bool ret = true;
3345 NTSTATUS status;
3346 struct smb2_create create;
3347 struct smb2_handle h1;
3348 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3349 const char *fname = BASEDIR "\\file";
3350 const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3352 torture_comment(tctx, "Opening file without AFP_AfpInfo\n");
3354 smb2_deltree(tree, BASEDIR);
3355 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3356 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3357 smb2_util_close(tree, h1);
3358 ret = torture_setup_file(mem_ctx, tree, fname, false);
3359 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3361 torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3363 ZERO_STRUCT(create);
3364 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3365 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3366 create.in.fname = sname;
3368 status = smb2_create(tree, mem_ctx, &create);
3369 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3370 ret, done, "Got unexpected AFP_AfpInfo stream");
3372 done:
3373 smb2_util_unlink(tree, fname);
3374 smb2_util_rmdir(tree, BASEDIR);
3375 return ret;
3378 static bool test_create_delete_on_close(struct torture_context *tctx,
3379 struct smb2_tree *tree)
3381 bool ret = true;
3382 NTSTATUS status;
3383 struct smb2_create create;
3384 struct smb2_handle h1;
3385 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3386 const char *fname = BASEDIR "\\file";
3387 const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3388 const char *type_creator = "SMB,OLE!";
3389 AfpInfo *info = NULL;
3390 const char *streams_basic[] = {
3391 "::$DATA"
3393 const char *streams_afpinfo[] = {
3394 "::$DATA",
3395 AFPINFO_STREAM
3398 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3400 torture_comment(tctx, "Checking whether create with delete-on-close work with AFP_AfpInfo\n");
3402 smb2_deltree(tree, BASEDIR);
3403 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3404 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3405 smb2_util_close(tree, h1);
3406 ret = torture_setup_file(mem_ctx, tree, fname, false);
3407 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3409 torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3411 ZERO_STRUCT(create);
3412 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3413 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3414 create.in.fname = sname;
3416 status = smb2_create(tree, mem_ctx, &create);
3417 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3418 ret, done, "Got unexpected AFP_AfpInfo stream");
3420 ZERO_STRUCT(create);
3421 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3422 create.in.desired_access = SEC_FILE_ALL;
3423 create.in.fname = sname;
3425 status = smb2_create(tree, mem_ctx, &create);
3426 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3427 ret, done, "Got unexpected AFP_AfpInfo stream");
3429 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3430 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3432 torture_comment(tctx, "Deleting AFP_AfpInfo via create with delete-on-close\n");
3434 info = torture_afpinfo_new(mem_ctx);
3435 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3437 memcpy(info->afpi_FinderInfo, type_creator, 8);
3438 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3439 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3441 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3442 0, 60, 16, 8, type_creator);
3443 torture_assert_goto(tctx, ret == true, ret, done, "Bad type/creator in AFP_AfpInfo");
3445 ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3446 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3448 ZERO_STRUCT(create);
3449 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3450 create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3451 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3452 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3453 create.in.fname = sname;
3454 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3456 status = smb2_create(tree, mem_ctx, &create);
3457 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3459 h1 = create.out.file.handle;
3460 smb2_util_close(tree, h1);
3462 ZERO_STRUCT(create);
3463 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3464 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
3465 create.in.fname = sname;
3466 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3467 status = smb2_create(tree, mem_ctx, &create);
3468 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3469 ret, done, "Got unexpected AFP_AfpInfo stream");
3471 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3472 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3474 done:
3475 smb2_util_unlink(tree, fname);
3476 smb2_util_rmdir(tree, BASEDIR);
3477 return ret;
3480 static bool test_setinfo_delete_on_close(struct torture_context *tctx,
3481 struct smb2_tree *tree)
3483 bool ret = true;
3484 NTSTATUS status;
3485 struct smb2_create create;
3486 union smb_setfileinfo sfinfo;
3487 struct smb2_handle h1;
3488 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3489 const char *fname = BASEDIR "\\file";
3490 const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3491 const char *type_creator = "SMB,OLE!";
3492 AfpInfo *info = NULL;
3493 const char *streams[] = {
3494 AFPINFO_STREAM,
3495 "::$DATA"
3497 const char *streams_basic[] = {
3498 "::$DATA"
3501 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3503 torture_comment(tctx, "Deleting AFP_AfpInfo via setinfo with delete-on-close\n");
3505 smb2_deltree(tree, BASEDIR);
3506 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3507 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3508 smb2_util_close(tree, h1);
3509 ret = torture_setup_file(mem_ctx, tree, fname, false);
3510 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3512 info = torture_afpinfo_new(mem_ctx);
3513 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3514 memcpy(info->afpi_FinderInfo, type_creator, 8);
3515 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3516 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3518 ZERO_STRUCT(create);
3519 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3520 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3521 create.in.fname = sname;
3522 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3523 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3525 status = smb2_create(tree, mem_ctx, &create);
3526 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3528 h1 = create.out.file.handle;
3530 /* Delete stream via setinfo delete-on-close */
3531 ZERO_STRUCT(sfinfo);
3532 sfinfo.disposition_info.in.delete_on_close = 1;
3533 sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3534 sfinfo.generic.in.file.handle = h1;
3535 status = smb2_setinfo_file(tree, &sfinfo);
3536 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3538 ret = check_stream_list(tree, tctx, fname, 2, streams, false);
3539 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3541 ZERO_STRUCT(create);
3542 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3543 create.in.desired_access = SEC_FILE_ALL;
3544 create.in.fname = sname;
3545 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3546 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3547 status = smb2_create(tree, mem_ctx, &create);
3548 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_DELETE_PENDING,
3549 ret, done, "Got unexpected AFP_AfpInfo stream");
3551 smb2_util_close(tree, h1);
3553 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3554 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3556 ZERO_STRUCT(create);
3557 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3558 create.in.desired_access = SEC_FILE_ALL;
3559 create.in.fname = sname;
3560 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3561 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3562 status = smb2_create(tree, mem_ctx, &create);
3563 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3564 ret, done, "Got unexpected AFP_AfpInfo stream");
3566 done:
3567 smb2_util_unlink(tree, fname);
3568 smb2_util_rmdir(tree, BASEDIR);
3569 return ret;
3572 static bool test_setinfo_eof(struct torture_context *tctx,
3573 struct smb2_tree *tree)
3575 bool ret = true;
3576 NTSTATUS status;
3577 struct smb2_create create;
3578 union smb_setfileinfo sfinfo;
3579 struct smb2_handle h1;
3580 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3581 const char *fname = BASEDIR "\\file";
3582 const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3583 const char *type_creator = "SMB,OLE!";
3584 AfpInfo *info = NULL;
3585 const char *streams_afpinfo[] = {
3586 "::$DATA",
3587 AFPINFO_STREAM
3590 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3592 torture_comment(tctx, "Set AFP_AfpInfo EOF to 61, 1 and 0\n");
3594 smb2_deltree(tree, BASEDIR);
3595 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3596 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3597 smb2_util_close(tree, h1);
3598 ret = torture_setup_file(mem_ctx, tree, fname, false);
3599 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3601 info = torture_afpinfo_new(mem_ctx);
3602 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3603 memcpy(info->afpi_FinderInfo, type_creator, 8);
3604 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3605 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3607 ZERO_STRUCT(create);
3608 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3609 create.in.desired_access = SEC_FILE_ALL;
3610 create.in.fname = sname;
3611 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3612 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3614 status = smb2_create(tree, mem_ctx, &create);
3615 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3617 h1 = create.out.file.handle;
3619 torture_comment(tctx, "Set AFP_AfpInfo EOF to 61\n");
3621 /* Test setinfo end-of-file info */
3622 ZERO_STRUCT(sfinfo);
3623 sfinfo.generic.in.file.handle = h1;
3624 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3625 sfinfo.position_information.in.position = 61;
3626 status = smb2_setinfo_file(tree, &sfinfo);
3627 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ALLOTTED_SPACE_EXCEEDED,
3628 ret, done, "set eof 61 failed");
3630 torture_comment(tctx, "Set AFP_AfpInfo EOF to 1\n");
3632 /* Truncation returns success, but has no effect */
3633 ZERO_STRUCT(sfinfo);
3634 sfinfo.generic.in.file.handle = h1;
3635 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3636 sfinfo.position_information.in.position = 1;
3637 status = smb2_setinfo_file(tree, &sfinfo);
3638 torture_assert_ntstatus_ok_goto(tctx, status,
3639 ret, done, "set eof 1 failed");
3640 smb2_util_close(tree, h1);
3642 ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3643 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3645 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3646 0, 60, 16, 8, type_creator);
3647 torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3649 ZERO_STRUCT(create);
3650 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3651 create.in.desired_access = SEC_FILE_ALL;
3652 create.in.fname = sname;
3653 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3654 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3656 status = smb2_create(tree, mem_ctx, &create);
3657 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3659 h1 = create.out.file.handle;
3662 * Delete stream via setinfo end-of-file info to 0, should
3663 * return success but stream MUST NOT deleted
3665 ZERO_STRUCT(sfinfo);
3666 sfinfo.generic.in.file.handle = h1;
3667 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3668 sfinfo.position_information.in.position = 0;
3669 status = smb2_setinfo_file(tree, &sfinfo);
3670 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
3672 smb2_util_close(tree, h1);
3674 ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3675 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3677 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3678 0, 60, 16, 8, type_creator);
3679 torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3681 done:
3682 smb2_util_unlink(tree, fname);
3683 smb2_util_rmdir(tree, BASEDIR);
3684 return ret;
3687 static bool test_afpinfo_all0(struct torture_context *tctx,
3688 struct smb2_tree *tree)
3690 bool ret = true;
3691 NTSTATUS status;
3692 struct smb2_create create;
3693 struct smb2_handle h1 = {{0}};
3694 struct smb2_handle baseh = {{0}};
3695 union smb_setfileinfo setfinfo;
3696 union smb_fileinfo getfinfo;
3697 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3698 const char *fname = BASEDIR "\\file";
3699 const char *sname = BASEDIR "\\file" AFPINFO_STREAM;
3700 const char *type_creator = "SMB,OLE!";
3701 AfpInfo *info = NULL;
3702 char *infobuf = NULL;
3703 const char *streams_basic[] = {
3704 "::$DATA"
3706 const char *streams_afpinfo[] = {
3707 "::$DATA",
3708 AFPINFO_STREAM
3711 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3713 torture_comment(tctx, "Write all 0 to AFP_AfpInfo and see what happens\n");
3715 smb2_deltree(tree, BASEDIR);
3716 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3717 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3718 smb2_util_close(tree, h1);
3719 ret = torture_setup_file(mem_ctx, tree, fname, false);
3720 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3722 info = torture_afpinfo_new(mem_ctx);
3723 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3724 memcpy(info->afpi_FinderInfo, type_creator, 8);
3725 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3726 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3728 ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3729 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3731 /* Write all 0 to AFP_AfpInfo */
3732 memset(info->afpi_FinderInfo, 0, AFP_FinderSize);
3733 infobuf = torture_afpinfo_pack(mem_ctx, info);
3734 torture_assert_not_null_goto(tctx, infobuf, ret, done,
3735 "torture_afpinfo_pack failed\n");
3737 ZERO_STRUCT(create);
3738 create.in.desired_access = SEC_FILE_ALL;
3739 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3740 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3741 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3742 create.in.fname = fname;
3744 status = smb2_create(tree, mem_ctx, &create);
3745 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3746 "smb2_create failed\n");
3747 baseh = create.out.file.handle;
3749 ZERO_STRUCT(create);
3750 create.in.desired_access = SEC_FILE_ALL;
3751 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3752 create.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
3753 create.in.fname = sname;
3755 status = smb2_create(tree, mem_ctx, &create);
3756 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3757 "smb2_create failed\n");
3758 h1 = create.out.file.handle;
3760 status = smb2_util_write(tree, h1, infobuf, 0, AFP_INFO_SIZE);
3761 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3762 "smb2_util_write failed\n");
3765 * Get stream information on open handle, must return only default
3766 * stream, the AFP_AfpInfo stream must not be returned.
3769 ZERO_STRUCT(getfinfo);
3770 getfinfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
3771 getfinfo.generic.in.file.handle = baseh;
3773 status = smb2_getinfo_file(tree, tctx, &getfinfo);
3774 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3775 "get stream info\n");
3777 torture_assert_int_equal_goto(tctx, getfinfo.stream_info.out.num_streams,
3778 1, ret, done, "stream count");
3780 smb2_util_close(tree, baseh);
3781 ZERO_STRUCT(baseh);
3784 * Try to set some file-basic-info (time) on the stream. This catches
3785 * naive implementation mistakes that simply deleted the backing store
3786 * from the filesystem in the zero-out step.
3789 ZERO_STRUCT(setfinfo);
3790 unix_to_nt_time(&setfinfo.basic_info.in.write_time, time(NULL));
3791 setfinfo.basic_info.in.attrib = 0x20;
3792 setfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
3793 setfinfo.generic.in.file.handle = h1;
3795 status = smb2_setinfo_file(tree, &setfinfo);
3796 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3797 "smb2_getinfo_file failed\n");
3799 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3800 torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
3802 smb2_util_close(tree, h1);
3803 ZERO_STRUCT(h1);
3805 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3806 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3808 done:
3809 if (!smb2_util_handle_empty(h1)) {
3810 smb2_util_close(tree, h1);
3812 if (!smb2_util_handle_empty(baseh)) {
3813 smb2_util_close(tree, baseh);
3815 smb2_util_unlink(tree, fname);
3816 smb2_util_rmdir(tree, BASEDIR);
3817 return ret;
3820 static bool test_create_delete_on_close_resource(struct torture_context *tctx,
3821 struct smb2_tree *tree)
3823 bool ret = true;
3824 NTSTATUS status;
3825 struct smb2_create create;
3826 struct smb2_handle h1;
3827 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3828 const char *fname = BASEDIR "\\file";
3829 const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3830 const char *streams_basic[] = {
3831 "::$DATA"
3833 const char *streams_afpresource[] = {
3834 "::$DATA",
3835 AFPRESOURCE_STREAM
3838 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3840 torture_comment(tctx, "Checking whether create with delete-on-close is ignored for AFP_AfpResource\n");
3842 smb2_deltree(tree, BASEDIR);
3843 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3844 torture_assert_ntstatus_ok(tctx, status, "torture_smb2_testdir");
3845 smb2_util_close(tree, h1);
3846 ret = torture_setup_file(mem_ctx, tree, fname, false);
3847 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3849 torture_comment(tctx, "Opening not existing AFP_AfpResource\n");
3851 ZERO_STRUCT(create);
3852 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3853 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3854 create.in.fname = sname;
3856 status = smb2_create(tree, mem_ctx, &create);
3857 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3858 ret, done, "Got unexpected AFP_AfpResource stream");
3860 ZERO_STRUCT(create);
3861 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3862 create.in.desired_access = SEC_FILE_ALL;
3863 create.in.fname = sname;
3865 status = smb2_create(tree, mem_ctx, &create);
3866 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3867 ret, done, "Got unexpected AFP_AfpResource stream");
3869 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3870 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3872 torture_comment(tctx, "Trying to delete AFP_AfpResource via create with delete-on-close\n");
3874 ret = write_stream(tree, __location__, tctx, mem_ctx,
3875 fname, AFPRESOURCE_STREAM_NAME,
3876 0, 10, "1234567890");
3877 torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3879 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3880 0, 10, 0, 10, "1234567890");
3881 torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3883 ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3884 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3886 ZERO_STRUCT(create);
3887 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3888 create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3889 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3890 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3891 create.in.fname = sname;
3892 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3894 status = smb2_create(tree, mem_ctx, &create);
3895 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3897 h1 = create.out.file.handle;
3898 smb2_util_close(tree, h1);
3900 ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3901 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3903 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3904 0, 10, 0, 10, "1234567890");
3905 torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3907 done:
3908 smb2_util_unlink(tree, fname);
3909 smb2_util_rmdir(tree, BASEDIR);
3910 return ret;
3913 static bool test_setinfo_delete_on_close_resource(struct torture_context *tctx,
3914 struct smb2_tree *tree)
3916 bool ret = true;
3917 NTSTATUS status;
3918 struct smb2_create create;
3919 union smb_setfileinfo sfinfo;
3920 struct smb2_handle h1;
3921 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3922 const char *fname = BASEDIR "\\file";
3923 const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3924 const char *streams_afpresource[] = {
3925 "::$DATA",
3926 AFPRESOURCE_STREAM
3929 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3931 torture_comment(tctx, "Trying to delete AFP_AfpResource via setinfo with delete-on-close\n");
3933 smb2_deltree(tree, BASEDIR);
3934 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3935 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3936 smb2_util_close(tree, h1);
3937 ret = torture_setup_file(mem_ctx, tree, fname, false);
3938 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3940 ret = write_stream(tree, __location__, tctx, mem_ctx,
3941 fname, AFPRESOURCE_STREAM_NAME,
3942 10, 10, "1234567890");
3943 torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3945 ZERO_STRUCT(create);
3946 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3947 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3948 create.in.fname = sname;
3949 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3950 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3952 status = smb2_create(tree, mem_ctx, &create);
3953 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3955 h1 = create.out.file.handle;
3957 /* Try to delete stream via setinfo delete-on-close */
3958 ZERO_STRUCT(sfinfo);
3959 sfinfo.disposition_info.in.delete_on_close = 1;
3960 sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3961 sfinfo.generic.in.file.handle = h1;
3962 status = smb2_setinfo_file(tree, &sfinfo);
3963 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3965 smb2_util_close(tree, h1);
3967 ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3968 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3970 ZERO_STRUCT(create);
3971 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3972 create.in.desired_access = SEC_FILE_ALL;
3973 create.in.fname = sname;
3974 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3975 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3976 status = smb2_create(tree, mem_ctx, &create);
3977 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3978 "Got unexpected AFP_AfpResource stream");
3980 done:
3981 smb2_util_unlink(tree, fname);
3982 smb2_util_rmdir(tree, BASEDIR);
3983 return ret;
3986 static bool test_setinfo_eof_resource(struct torture_context *tctx,
3987 struct smb2_tree *tree)
3989 bool ret = true;
3990 NTSTATUS status;
3991 struct smb2_create create;
3992 union smb_setfileinfo sfinfo;
3993 union smb_fileinfo finfo;
3994 struct smb2_handle h1;
3995 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3996 const char *fname = BASEDIR "\\file";
3997 const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3998 const char *streams_basic[] = {
3999 "::$DATA"
4002 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
4004 ret = enable_aapl(tctx, tree);
4005 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
4007 torture_comment(tctx, "Set AFP_AfpResource EOF to 1 and 0\n");
4009 smb2_deltree(tree, BASEDIR);
4010 status = torture_smb2_testdir(tree, BASEDIR, &h1);
4011 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
4012 smb2_util_close(tree, h1);
4013 ret = torture_setup_file(mem_ctx, tree, fname, false);
4014 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4016 ret = write_stream(tree, __location__, tctx, mem_ctx,
4017 fname, AFPRESOURCE_STREAM_NAME,
4018 10, 10, "1234567890");
4019 torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
4021 ZERO_STRUCT(create);
4022 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4023 create.in.desired_access = SEC_FILE_ALL;
4024 create.in.fname = sname;
4025 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4026 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4028 status = smb2_create(tree, mem_ctx, &create);
4029 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4031 h1 = create.out.file.handle;
4033 torture_comment(tctx, "Set AFP_AfpResource EOF to 1\n");
4035 /* Test setinfo end-of-file info */
4036 ZERO_STRUCT(sfinfo);
4037 sfinfo.generic.in.file.handle = h1;
4038 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
4039 sfinfo.position_information.in.position = 1;
4040 status = smb2_setinfo_file(tree, &sfinfo);
4041 torture_assert_ntstatus_ok_goto(tctx, status,
4042 ret, done, "set eof 1 failed");
4044 smb2_util_close(tree, h1);
4046 /* Check size == 1 */
4047 ZERO_STRUCT(create);
4048 create.in.fname = sname;
4049 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4050 create.in.desired_access = SEC_FILE_ALL;
4051 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4052 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4053 status = smb2_create(tree, mem_ctx, &create);
4054 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4056 h1 = create.out.file.handle;
4058 ZERO_STRUCT(finfo);
4059 finfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
4060 finfo.generic.in.file.handle = h1;
4061 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
4062 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file failed");
4064 smb2_util_close(tree, h1);
4066 torture_assert_goto(tctx, finfo.all_info.out.size == 1, ret, done, "size != 1");
4068 ZERO_STRUCT(create);
4069 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4070 create.in.desired_access = SEC_FILE_ALL;
4071 create.in.fname = sname;
4072 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4073 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4075 status = smb2_create(tree, mem_ctx, &create);
4076 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4078 h1 = create.out.file.handle;
4081 * Delete stream via setinfo end-of-file info to 0, this
4082 * should delete the stream.
4084 ZERO_STRUCT(sfinfo);
4085 sfinfo.generic.in.file.handle = h1;
4086 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
4087 sfinfo.position_information.in.position = 0;
4088 status = smb2_setinfo_file(tree, &sfinfo);
4089 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
4091 smb2_util_close(tree, h1);
4093 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
4094 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4096 ZERO_STRUCT(create);
4097 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4098 create.in.desired_access = SEC_FILE_ALL;
4099 create.in.fname = sname;
4100 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4101 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4103 status = smb2_create(tree, mem_ctx, &create);
4104 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4105 ret, done, "smb2_create failed");
4107 done:
4108 smb2_util_unlink(tree, fname);
4109 smb2_util_rmdir(tree, BASEDIR);
4110 return ret;
4114 * This tests that right after creating the AFP_AfpInfo stream,
4115 * reading from the stream returns an empty, default metadata blob of
4116 * 60 bytes.
4118 * NOTE: against OS X SMB server this only works if the read request
4119 * is compounded with the create that created the stream, is fails
4120 * otherwise. We don't care...
4122 static bool test_null_afpinfo(struct torture_context *tctx,
4123 struct smb2_tree *tree)
4125 TALLOC_CTX *mem_ctx = talloc_new(tctx);
4126 const char *fname = "test_null_afpinfo";
4127 const char *sname = "test_null_afpinfo" AFPINFO_STREAM_NAME;
4128 NTSTATUS status;
4129 bool ret = true;
4130 struct smb2_request *req[3];
4131 struct smb2_handle handle;
4132 struct smb2_create create;
4133 struct smb2_read read;
4134 AfpInfo *afpinfo = NULL;
4135 char *afpinfo_buf = NULL;
4136 const char *type_creator = "SMB,OLE!";
4137 struct smb2_handle handle2;
4138 struct smb2_read r;
4140 torture_comment(tctx, "Checking create of AfpInfo stream\n");
4142 smb2_util_unlink(tree, fname);
4144 ret = torture_setup_file(mem_ctx, tree, fname, false);
4145 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
4147 ZERO_STRUCT(create);
4148 create.in.desired_access = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA;
4149 create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
4150 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4151 create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4152 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4153 create.in.fname = sname;
4155 smb2_transport_compound_start(tree->session->transport, 2);
4157 req[0] = smb2_create_send(tree, &create);
4159 handle.data[0] = UINT64_MAX;
4160 handle.data[1] = UINT64_MAX;
4162 smb2_transport_compound_set_related(tree->session->transport, true);
4164 ZERO_STRUCT(read);
4165 read.in.file.handle = handle;
4166 read.in.length = AFP_INFO_SIZE;
4167 req[1] = smb2_read_send(tree, &read);
4169 status = smb2_create_recv(req[0], tree, &create);
4170 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_recv failed");
4172 handle = create.out.file.handle;
4174 status = smb2_read_recv(req[1], tree, &read);
4175 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read_recv failed");
4177 status = torture_smb2_testfile_access(tree, sname, &handle2,
4178 SEC_FILE_READ_DATA);
4179 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4180 "torture_smb2_testfile failed\n");
4181 r = (struct smb2_read) {
4182 .in.file.handle = handle2,
4183 .in.length = AFP_INFO_SIZE,
4186 status = smb2_read(tree, tree, &r);
4187 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4188 "torture_smb2_testfile failed\n");
4189 smb2_util_close(tree, handle2);
4191 afpinfo = torture_afpinfo_new(mem_ctx);
4192 torture_assert_goto(tctx, afpinfo != NULL, ret, done, "torture_afpinfo_new failed");
4194 memcpy(afpinfo->afpi_FinderInfo, type_creator, 8);
4196 afpinfo_buf = torture_afpinfo_pack(tctx, afpinfo);
4197 torture_assert_goto(tctx, afpinfo_buf != NULL, ret, done, "torture_afpinfo_new failed");
4199 status = smb2_util_write(tree, handle, afpinfo_buf, 0, AFP_INFO_SIZE);
4200 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write failed");
4202 smb2_util_close(tree, handle);
4204 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
4205 0, 60, 16, 8, type_creator);
4206 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
4208 done:
4209 smb2_util_unlink(tree, fname);
4210 talloc_free(mem_ctx);
4211 return ret;
4214 static bool test_delete_file_with_rfork(struct torture_context *tctx,
4215 struct smb2_tree *tree)
4217 const char *fname = "torture_write_rfork_io";
4218 const char *rfork_content = "1234567890";
4219 NTSTATUS status;
4220 bool ret = true;
4222 smb2_util_unlink(tree, fname);
4224 torture_comment(tctx, "Test deleting file with resource fork\n");
4226 ret = torture_setup_file(tctx, tree, fname, false);
4227 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed\n");
4229 ret = write_stream(tree, __location__, tctx, tctx,
4230 fname, AFPRESOURCE_STREAM_NAME,
4231 10, 10, rfork_content);
4232 torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed\n");
4234 ret = check_stream(tree, __location__, tctx, tctx,
4235 fname, AFPRESOURCE_STREAM_NAME,
4236 0, 20, 10, 10, rfork_content);
4237 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed\n");
4239 status = smb2_util_unlink(tree, fname);
4240 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "check_stream failed\n");
4242 done:
4243 return ret;
4246 static bool test_rename_and_read_rsrc(struct torture_context *tctx,
4247 struct smb2_tree *tree)
4249 bool ret = true;
4250 NTSTATUS status;
4251 struct smb2_create create, create2;
4252 struct smb2_handle h1, h2;
4253 const char *fname = "test_rename_openfile";
4254 const char *sname = "test_rename_openfile" AFPRESOURCE_STREAM_NAME;
4255 const char *fname_renamed = "test_rename_openfile_renamed";
4256 const char *data = "1234567890";
4257 union smb_setfileinfo sinfo;
4258 bool server_is_macos = torture_setting_bool(tctx, "osx", false);
4259 NTSTATUS expected_status;
4261 ret = enable_aapl(tctx, tree);
4262 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
4264 torture_comment(tctx, "Create file with resource fork\n");
4266 ret = torture_setup_file(tctx, tree, fname, false);
4267 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4269 ret = write_stream(tree, __location__, tctx, tctx,
4270 fname, AFPRESOURCE_STREAM_NAME, 0, 10, data);
4271 torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4273 torture_comment(tctx, "Open resource fork\n");
4275 ZERO_STRUCT(create);
4276 create.in.desired_access = SEC_FILE_ALL;
4277 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4278 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4279 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4280 create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4281 create.in.fname = sname;
4283 status = smb2_create(tree, tctx, &create);
4284 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4286 h1 = create.out.file.handle;
4288 torture_comment(tctx, "Rename base file\n");
4290 ZERO_STRUCT(create2);
4291 create2.in.desired_access = SEC_FILE_ALL;
4292 create2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4293 create2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4294 create2.in.create_disposition = NTCREATEX_DISP_OPEN;
4295 create2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4296 create2.in.fname = fname;
4298 status = smb2_create(tree, tctx, &create2);
4299 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4301 h2 = create2.out.file.handle;
4303 ZERO_STRUCT(sinfo);
4304 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
4305 sinfo.rename_information.in.file.handle = h2;
4306 sinfo.rename_information.in.overwrite = 0;
4307 sinfo.rename_information.in.root_fid = 0;
4308 sinfo.rename_information.in.new_name = fname_renamed;
4310 if (server_is_macos) {
4311 expected_status = NT_STATUS_SHARING_VIOLATION;
4312 } else {
4313 expected_status = NT_STATUS_ACCESS_DENIED;
4316 status = smb2_setinfo_file(tree, &sinfo);
4317 torture_assert_ntstatus_equal_goto(
4318 tctx, status, expected_status, ret, done,
4319 "smb2_setinfo_file failed");
4321 smb2_util_close(tree, h2);
4323 status = smb2_util_write(tree, h1, "foo", 0, 3);
4324 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4325 "write failed\n");
4327 smb2_util_close(tree, h1);
4329 done:
4330 smb2_util_unlink(tree, fname);
4331 smb2_util_unlink(tree, fname_renamed);
4333 return ret;
4336 static bool test_readdir_attr_illegal_ntfs(struct torture_context *tctx,
4337 struct smb2_tree *tree)
4339 TALLOC_CTX *mem_ctx = talloc_new(tctx);
4340 const char *name = "test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
4341 const char *fname = BASEDIR "\\test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
4342 NTSTATUS status;
4343 struct smb2_handle testdirh;
4344 bool ret = true;
4345 struct smb2_create io;
4346 AfpInfo *info;
4347 const char *type_creator = "SMB,OLE!";
4348 struct smb2_find f;
4349 unsigned int count;
4350 union smb_search_data *d;
4351 uint64_t rfork_len;
4352 int i;
4354 smb2_deltree(tree, BASEDIR);
4356 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
4357 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
4358 smb2_util_close(tree, testdirh);
4360 torture_comment(tctx, "Enabling AAPL\n");
4362 ret = enable_aapl(tctx, tree);
4363 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
4366 * Now that Requested AAPL extensions are enabled, setup some
4367 * Mac files with metadata and resource fork
4370 torture_comment(tctx, "Preparing file\n");
4372 ret = torture_setup_file(mem_ctx, tree, fname, false);
4373 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
4375 info = torture_afpinfo_new(mem_ctx);
4376 torture_assert_not_null_goto(tctx, info, ret, done, "torture_afpinfo_new failed");
4378 memcpy(info->afpi_FinderInfo, type_creator, 8);
4379 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
4380 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
4382 ret = write_stream(tree, __location__, tctx, mem_ctx,
4383 fname, AFPRESOURCE_STREAM_NAME,
4384 0, 3, "foo");
4385 torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4388 * Ok, file is prepared, now call smb2/find
4391 torture_comment(tctx, "Issue find\n");
4393 ZERO_STRUCT(io);
4394 io.in.desired_access = SEC_RIGHTS_DIR_READ;
4395 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
4396 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
4397 io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
4398 NTCREATEX_SHARE_ACCESS_WRITE |
4399 NTCREATEX_SHARE_ACCESS_DELETE);
4400 io.in.create_disposition = NTCREATEX_DISP_OPEN;
4401 io.in.fname = BASEDIR;
4402 status = smb2_create(tree, tctx, &io);
4403 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4405 ZERO_STRUCT(f);
4406 f.in.file.handle = io.out.file.handle;
4407 f.in.pattern = "*";
4408 f.in.max_response_size = 0x1000;
4409 f.in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
4411 status = smb2_find_level(tree, tree, &f, &count, &d);
4412 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_level failed");
4414 status = smb2_util_close(tree, io.out.file.handle);
4415 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close failed");
4417 torture_comment(tctx, "Checking find response with enriched macOS metadata\n");
4419 for (i = 0; i < count; i++) {
4420 const char *found = d[i].id_both_directory_info.name.s;
4422 if (!strcmp(found, ".") || !strcmp(found, ".."))
4423 continue;
4424 if (strncmp(found, "._", 2) == 0) {
4425 continue;
4427 break;
4430 torture_assert_str_equal_goto(tctx,
4431 d[i].id_both_directory_info.name.s, name,
4432 ret, done, "bad name");
4434 rfork_len = BVAL(d[i].id_both_directory_info.short_name_buf, 0);
4435 torture_assert_int_equal_goto(tctx, rfork_len, 3, ret, done, "bad resource fork length");
4437 torture_assert_mem_equal_goto(tctx, type_creator,
4438 d[i].id_both_directory_info.short_name_buf + 8,
4439 8, ret, done, "Bad FinderInfo");
4440 done:
4441 smb2_util_unlink(tree, fname);
4442 smb2_deltree(tree, BASEDIR);
4443 talloc_free(mem_ctx);
4444 return ret;
4447 static bool test_invalid_afpinfo(struct torture_context *tctx,
4448 struct smb2_tree *tree1,
4449 struct smb2_tree *tree2)
4451 const char *fname = "filtest_invalid_afpinfo";
4452 const char *sname = "filtest_invalid_afpinfo" AFPINFO_STREAM_NAME;
4453 struct smb2_create create;
4454 const char *streams_basic[] = {
4455 "::$DATA"
4457 const char *streams_afpinfo[] = {
4458 "::$DATA",
4459 AFPINFO_STREAM
4461 NTSTATUS status;
4462 bool ret = true;
4464 if (tree2 == NULL) {
4465 torture_skip_goto(tctx, done, "need second share without fruit\n");
4468 torture_comment(tctx, "Testing invalid AFP_AfpInfo stream\n");
4470 ret = torture_setup_file(tctx, tree2, fname, false);
4471 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4473 ret = write_stream(tree2, __location__, tctx, tctx,
4474 fname, AFPINFO_STREAM_NAME,
4475 0, 3, "foo");
4476 torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4478 ret = check_stream_list(tree2, tctx, fname, 2, streams_afpinfo, false);
4479 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4481 torture_comment(tctx, "Listing streams, bad AFPINFO stream must not be present\n");
4483 ret = check_stream_list(tree1, tctx, fname, 1, streams_basic, false);
4484 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4486 torture_comment(tctx, "Try to open AFPINFO stream, must fail\n");
4488 ZERO_STRUCT(create);
4489 create.in.desired_access = SEC_FILE_ALL;
4490 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4491 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4492 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4493 create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4494 create.in.fname = sname;
4496 status = smb2_create(tree1, tctx, &create);
4497 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4498 ret, done, "Stream still around?");
4500 done:
4501 smb2_util_unlink(tree1, fname);
4502 return ret;
4505 static bool test_writing_afpinfo(struct torture_context *tctx,
4506 struct smb2_tree *tree)
4508 const char *fname = "filtest_invalid_afpinfo";
4509 const char *sname = "filtest_invalid_afpinfo" AFPINFO_STREAM;
4510 const char *streams_afpinfo[] = {
4511 "::$DATA",
4512 AFPINFO_STREAM
4514 bool ret = true;
4515 static AfpInfo *afpi = NULL;
4516 char *buf = NULL;
4517 char *afpi_buf = NULL;
4518 char *zero_buf = NULL;
4519 bool broken_osx = torture_setting_bool(tctx, "broken_osx_45759458", false);
4520 off_t min_offset_for_2streams = 16;
4521 int i;
4522 NTSTATUS status;
4523 struct test_sizes {
4524 off_t offset;
4525 size_t size;
4526 bool expected_result;
4527 } test_sizes[] = {
4528 { 0, 1, false},
4529 { 0, 2, false},
4530 { 0, 3, true},
4531 { 0, 4, true},
4532 { 0, 14, true},
4533 { 0, 15, true},
4534 { 0, 16, true},
4535 { 0, 24, true},
4536 { 0, 34, true},
4537 { 0, 44, true},
4538 { 0, 54, true},
4539 { 0, 55, true},
4540 { 0, 56, true},
4541 { 0, 57, true},
4542 { 0, 58, true},
4543 { 0, 59, true},
4544 { 0, 60, true},
4545 { 0, 61, true},
4546 { 0, 64, true},
4547 { 0, 1024, true},
4548 { 0, 10064, true},
4550 { 1, 1, false},
4551 { 1, 2, false},
4552 { 1, 3, false},
4553 { 1, 4, false},
4554 { 1, 14, false},
4555 { 1, 15, false},
4556 { 1, 16, false},
4557 { 1, 24, false},
4558 { 1, 34, false},
4559 { 1, 44, false},
4560 { 1, 54, false},
4561 { 1, 55, false},
4562 { 1, 56, false},
4563 { 1, 57, false},
4564 { 1, 58, false},
4565 { 1, 59, false},
4566 { 1, 60, true},
4567 { 1, 61, true},
4568 { 1, 1024, true},
4569 { 1, 10064, true},
4571 { 30, 1, false},
4572 { 30, 2, false},
4573 { 30, 3, false},
4574 { 30, 4, false},
4575 { 30, 14, false},
4576 { 30, 15, false},
4577 { 30, 16, false},
4578 { 30, 24, false},
4579 { 30, 34, false},
4580 { 30, 44, false},
4581 { 30, 54, false},
4582 { 30, 55, false},
4583 { 30, 56, false},
4584 { 30, 57, false},
4585 { 30, 58, false},
4586 { 30, 59, false},
4587 { 30, 60, true},
4588 { 30, 61, true},
4589 { 30, 1024, true},
4590 { 30, 10064, true},
4592 { 58, 1, false},
4593 { 58, 2, false},
4594 { 58, 3, false},
4595 { 58, 4, false},
4596 { 58, 14, false},
4597 { 58, 15, false},
4598 { 58, 16, false},
4599 { 58, 24, false},
4600 { 58, 34, false},
4601 { 58, 44, false},
4602 { 58, 54, false},
4603 { 58, 55, false},
4604 { 58, 56, false},
4605 { 58, 57, false},
4606 { 58, 58, false},
4607 { 58, 59, false},
4608 { 58, 60, true},
4609 { 58, 61, true},
4610 { 58, 1024, true},
4611 { 58, 10064, true},
4613 { 59, 1, false},
4614 { 59, 2, false},
4615 { 59, 3, false},
4616 { 59, 4, false},
4617 { 59, 14, false},
4618 { 59, 15, false},
4619 { 59, 16, false},
4620 { 59, 24, false},
4621 { 59, 34, false},
4622 { 59, 44, false},
4623 { 59, 54, false},
4624 { 59, 55, false},
4625 { 59, 56, false},
4626 { 59, 57, false},
4627 { 59, 58, false},
4628 { 59, 59, false},
4629 { 59, 60, true},
4630 { 59, 61, true},
4631 { 59, 1024, true},
4632 { 59, 10064, true},
4634 { 60, 1, false},
4635 { 60, 2, false},
4636 { 60, 3, false},
4637 { 60, 4, false},
4638 { 60, 14, false},
4639 { 60, 15, false},
4640 { 60, 16, false},
4641 { 60, 24, false},
4642 { 60, 34, false},
4643 { 60, 44, false},
4644 { 60, 54, false},
4645 { 60, 55, false},
4646 { 60, 56, false},
4647 { 60, 57, false},
4648 { 60, 58, false},
4649 { 60, 59, false},
4650 { 60, 60, true},
4651 { 60, 61, true},
4652 { 60, 1024, true},
4653 { 60, 10064, true},
4655 { 61, 1, false},
4656 { 61, 2, false},
4657 { 61, 3, false},
4658 { 61, 4, false},
4659 { 61, 14, false},
4660 { 61, 15, false},
4661 { 61, 16, false},
4662 { 61, 24, false},
4663 { 61, 34, false},
4664 { 61, 44, false},
4665 { 61, 54, false},
4666 { 61, 55, false},
4667 { 61, 56, false},
4668 { 61, 57, false},
4669 { 61, 58, false},
4670 { 61, 59, false},
4671 { 61, 60, true},
4672 { 61, 61, true},
4673 { 61, 1024, true},
4674 { 61, 10064, true},
4676 { 10000, 1, false},
4677 { 10000, 2, false},
4678 { 10000, 3, false},
4679 { 10000, 4, false},
4680 { 10000, 14, false},
4681 { 10000, 15, false},
4682 { 10000, 16, false},
4683 { 10000, 24, false},
4684 { 10000, 34, false},
4685 { 10000, 44, false},
4686 { 10000, 54, false},
4687 { 10000, 55, false},
4688 { 10000, 56, false},
4689 { 10000, 57, false},
4690 { 10000, 58, false},
4691 { 10000, 59, false},
4692 { 10000, 60, true},
4693 { 10000, 61, true},
4694 { 10000, 1024, true},
4695 { 10000, 10064, true},
4697 { -1, 0, false},
4700 afpi = torture_afpinfo_new(tctx);
4701 torture_assert_not_null_goto(tctx, afpi, ret, done,
4702 "torture_afpinfo_new failed\n");
4704 memcpy(afpi->afpi_FinderInfo, "FOO BAR ", 8);
4706 buf = torture_afpinfo_pack(afpi, afpi);
4707 torture_assert_not_null_goto(tctx, buf, ret, done,
4708 "torture_afpinfo_pack failed\n");
4710 afpi_buf = talloc_zero_array(tctx, char, 10064);
4711 torture_assert_not_null_goto(tctx, afpi_buf, ret, done,
4712 "talloc_zero_array failed\n");
4713 memcpy(afpi_buf, buf, 60);
4715 zero_buf = talloc_zero_array(tctx, char, 10064);
4716 torture_assert_not_null_goto(tctx, zero_buf, ret, done,
4717 "talloc_zero_array failed\n");
4719 ret = torture_setup_file(tctx, tree, fname, false);
4720 torture_assert_goto(tctx, ret == true, ret, done,
4721 "torture_setup_file\n");
4723 for (i = 0; test_sizes[i].offset != -1; i++) {
4724 struct smb2_handle h;
4725 struct smb2_create c;
4726 int expected_num_streams;
4727 size_t fi_check_size;
4729 torture_comment(tctx,
4730 "Test %d: offset=%jd size=%zu result=%s\n",
4732 (intmax_t)test_sizes[i].offset,
4733 test_sizes[i].size,
4734 test_sizes[i].expected_result ? "true":"false");
4737 c = (struct smb2_create) {
4738 .in.desired_access = SEC_FILE_WRITE_DATA,
4739 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
4740 .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
4741 .in.fname = sname,
4744 status = smb2_create(tree, tree, &c);
4745 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4746 "smb2_create\n");
4747 h = c.out.file.handle;
4749 status = smb2_util_write(tree,
4751 zero_buf,
4752 test_sizes[i].offset,
4753 test_sizes[i].size);
4754 torture_assert_ntstatus_equal_goto(
4755 tctx, status, NT_STATUS_INVALID_PARAMETER,
4756 ret, done, "smb2_util_write\n");
4758 status = smb2_util_write(tree,
4760 afpi_buf,
4761 test_sizes[i].offset,
4762 test_sizes[i].size);
4763 smb2_util_close(tree, h);
4764 if (test_sizes[i].expected_result == true) {
4765 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4766 "smb2_util_write\n");
4767 } else {
4768 torture_assert_ntstatus_equal_goto(
4769 tctx, status, NT_STATUS_INVALID_PARAMETER,
4770 ret, done, "smb2_util_write\n");
4773 if (broken_osx) {
4775 * Currently macOS has a bug (Radar #45759458) where it
4776 * writes more bytes then requested from uninitialized
4777 * memory to the filesystem. That means it will likely
4778 * write data to FinderInfo so the stream is not empty
4779 * and thus listed when the number of streams is
4780 * queried.
4782 min_offset_for_2streams = 2;
4785 if ((test_sizes[i].expected_result == true) &&
4786 (test_sizes[i].size > min_offset_for_2streams))
4788 expected_num_streams = 2;
4789 } else {
4790 expected_num_streams = 1;
4793 ret = check_stream_list(tree, tctx, fname,
4794 expected_num_streams,
4795 streams_afpinfo, false);
4796 torture_assert_goto(tctx, ret == true, ret, done,
4797 "Bad streams\n");
4799 if (test_sizes[i].expected_result == false) {
4800 continue;
4803 if (test_sizes[i].size <= 16) {
4805 * FinderInfo with the "FOO BAR " string we wrote above
4806 * would start at offset 16. Check whether this test
4807 * wrote 1 byte or more.
4809 goto next;
4812 fi_check_size = test_sizes[i].size - 16;
4813 fi_check_size = MIN(fi_check_size, 8);
4815 ret = check_stream(tree, __location__,
4816 tctx, tctx,
4817 fname, AFPINFO_STREAM,
4818 0, 60, 16, fi_check_size, "FOO BAR ");
4819 torture_assert_goto(tctx, ret == true, ret, done,
4820 "Bad streams\n");
4822 next:
4823 status = smb2_util_unlink(tree, sname);
4824 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4825 bool missing_ok;
4827 missing_ok = test_sizes[i].expected_result == false;
4828 missing_ok |= test_sizes[i].size <= 16;
4830 torture_assert_goto(tctx, missing_ok,
4831 ret, done, "smb2_util_unlink\n");
4835 done:
4836 smb2_util_unlink(tree, fname);
4837 return ret;
4840 static bool test_zero_file_id(struct torture_context *tctx,
4841 struct smb2_tree *tree)
4843 const char *fname = "filtest_file_id";
4844 struct smb2_create create = {0};
4845 NTSTATUS status;
4846 bool ret = true;
4847 uint8_t zero_file_id[8] = {0};
4849 torture_comment(tctx, "Testing zero file id\n");
4851 ret = torture_setup_file(tctx, tree, fname, false);
4852 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4854 ZERO_STRUCT(create);
4855 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4856 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4857 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4858 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4859 create.in.fname = fname;
4860 create.in.query_on_disk_id = true;
4862 status = smb2_create(tree, tctx, &create);
4863 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
4864 done,
4865 "test file could not be opened");
4866 torture_assert_mem_not_equal_goto(tctx, create.out.on_disk_id,
4867 zero_file_id, 8, ret, done,
4868 "unexpected zero file id");
4870 smb2_util_close(tree, create.out.file.handle);
4872 ret = enable_aapl(tctx, tree);
4873 torture_assert(tctx, ret == true, "enable_aapl failed");
4875 ZERO_STRUCT(create);
4876 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4877 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4878 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4879 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4880 create.in.fname = fname;
4881 create.in.query_on_disk_id = true;
4883 status = smb2_create(tree, tctx, &create);
4884 torture_assert_ntstatus_equal_goto(
4885 tctx, status, NT_STATUS_OK, ret, done,
4886 "test file could not be opened with AAPL");
4887 torture_assert_mem_equal_goto(tctx, create.out.on_disk_id, zero_file_id,
4888 8, ret, done, "non-zero file id");
4890 smb2_util_close(tree, create.out.file.handle);
4892 done:
4893 smb2_util_unlink(tree, fname);
4894 return ret;
4897 static bool copy_one_stream(struct torture_context *torture,
4898 struct smb2_tree *tree,
4899 TALLOC_CTX *tmp_ctx,
4900 const char *src_sname,
4901 const char *dst_sname)
4903 struct smb2_handle src_h = {{0}};
4904 struct smb2_handle dest_h = {{0}};
4905 NTSTATUS status;
4906 union smb_ioctl io;
4907 struct srv_copychunk_copy cc_copy;
4908 struct srv_copychunk_rsp cc_rsp;
4909 enum ndr_err_code ndr_ret;
4910 bool ok = false;
4912 ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4913 1, /* 1 chunk */
4914 src_sname,
4915 &src_h, 256, /* fill 256 byte src file */
4916 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4917 dst_sname,
4918 &dest_h, 0, /* 0 byte dest file */
4919 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4920 &cc_copy,
4921 &io);
4922 torture_assert_goto(torture, ok == true, ok, done,
4923 "setup copy chunk error\n");
4925 /* copy all src file data (via a single chunk desc) */
4926 cc_copy.chunks[0].source_off = 0;
4927 cc_copy.chunks[0].target_off = 0;
4928 cc_copy.chunks[0].length = 256;
4930 ndr_ret = ndr_push_struct_blob(
4931 &io.smb2.in.out, tmp_ctx, &cc_copy,
4932 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4934 torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4935 "ndr_push_srv_copychunk_copy\n");
4937 status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4938 torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4939 "FSCTL_SRV_COPYCHUNK\n");
4941 ndr_ret = ndr_pull_struct_blob(
4942 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4943 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4945 torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4946 "ndr_pull_srv_copychunk_rsp\n");
4948 ok = check_copy_chunk_rsp(torture, &cc_rsp,
4949 1, /* chunks written */
4950 0, /* chunk bytes unsuccessfully written */
4951 256); /* total bytes written */
4952 torture_assert_goto(torture, ok == true, ok, done,
4953 "bad copy chunk response data\n");
4955 ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 256, 0);
4956 if (!ok) {
4957 torture_fail(torture, "inconsistent file data\n");
4960 done:
4961 if (!smb2_util_handle_empty(src_h)) {
4962 smb2_util_close(tree, src_h);
4964 if (!smb2_util_handle_empty(dest_h)) {
4965 smb2_util_close(tree, dest_h);
4968 return ok;
4971 static bool copy_finderinfo_stream(struct torture_context *torture,
4972 struct smb2_tree *tree,
4973 TALLOC_CTX *tmp_ctx,
4974 const char *src_name,
4975 const char *dst_name)
4977 struct smb2_handle src_h = {{0}};
4978 struct smb2_handle dest_h = {{0}};
4979 NTSTATUS status;
4980 union smb_ioctl io;
4981 struct srv_copychunk_copy cc_copy;
4982 struct srv_copychunk_rsp cc_rsp;
4983 enum ndr_err_code ndr_ret;
4984 const char *type_creator = "SMB,OLE!";
4985 AfpInfo *info = NULL;
4986 const char *src_name_afpinfo = NULL;
4987 const char *dst_name_afpinfo = NULL;
4988 bool ok = false;
4990 src_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", src_name,
4991 AFPINFO_STREAM);
4992 torture_assert_not_null_goto(torture, src_name_afpinfo, ok, done,
4993 "talloc_asprintf failed\n");
4995 dst_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", dst_name,
4996 AFPINFO_STREAM);
4997 torture_assert_not_null_goto(torture, dst_name_afpinfo, ok, done,
4998 "talloc_asprintf failed\n");
5000 info = torture_afpinfo_new(tmp_ctx);
5001 torture_assert_not_null_goto(torture, info, ok, done,
5002 "torture_afpinfo_new failed\n");
5004 memcpy(info->afpi_FinderInfo, type_creator, 8);
5005 ok = torture_write_afpinfo(tree, torture, tmp_ctx, src_name, info);
5006 torture_assert_goto(torture, ok == true, ok, done,
5007 "torture_write_afpinfo failed\n");
5009 ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
5010 1, /* 1 chunk */
5011 src_name_afpinfo,
5012 &src_h, 0,
5013 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
5014 dst_name_afpinfo,
5015 &dest_h, 0,
5016 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
5017 &cc_copy,
5018 &io);
5019 torture_assert_goto(torture, ok == true, ok, done,
5020 "setup copy chunk error\n");
5022 /* copy all src file data (via a single chunk desc) */
5023 cc_copy.chunks[0].source_off = 0;
5024 cc_copy.chunks[0].target_off = 0;
5025 cc_copy.chunks[0].length = 60;
5027 ndr_ret = ndr_push_struct_blob(
5028 &io.smb2.in.out, tmp_ctx, &cc_copy,
5029 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
5031 torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
5032 "ndr_push_srv_copychunk_copy\n");
5034 status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
5035 torture_assert_ntstatus_ok_goto(torture, status, ok, done,
5036 "FSCTL_SRV_COPYCHUNK\n");
5038 ndr_ret = ndr_pull_struct_blob(
5039 &io.smb2.out.out, tmp_ctx, &cc_rsp,
5040 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
5042 torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
5043 "ndr_pull_srv_copychunk_rsp\n");
5045 smb2_util_close(tree, src_h);
5046 ZERO_STRUCT(src_h);
5047 smb2_util_close(tree, dest_h);
5048 ZERO_STRUCT(dest_h);
5050 ok = check_copy_chunk_rsp(torture, &cc_rsp,
5051 1, /* chunks written */
5052 0, /* chunk bytes unsuccessfully written */
5053 60); /* total bytes written */
5054 torture_assert_goto(torture, ok == true, ok, done,
5055 "bad copy chunk response data\n");
5057 ok = check_stream(tree, __location__, torture, tmp_ctx,
5058 dst_name, AFPINFO_STREAM,
5059 0, 60, 16, 8, type_creator);
5060 torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
5062 done:
5063 if (!smb2_util_handle_empty(src_h)) {
5064 smb2_util_close(tree, src_h);
5066 if (!smb2_util_handle_empty(dest_h)) {
5067 smb2_util_close(tree, dest_h);
5070 return ok;
5073 static bool test_copy_chunk_streams(struct torture_context *torture,
5074 struct smb2_tree *tree)
5076 const char *src_name = "src";
5077 const char *dst_name = "dst";
5078 struct names {
5079 const char *src_sname;
5080 const char *dst_sname;
5081 } names[] = {
5082 { "src:foo", "dst:foo" },
5083 { "src" AFPRESOURCE_STREAM, "dst" AFPRESOURCE_STREAM }
5085 int i;
5086 TALLOC_CTX *tmp_ctx = NULL;
5087 bool ok = false;
5089 tmp_ctx = talloc_new(tree);
5090 torture_assert_not_null_goto(torture, tmp_ctx, ok, done,
5091 "torture_setup_file\n");
5093 smb2_util_unlink(tree, src_name);
5094 smb2_util_unlink(tree, dst_name);
5096 ok = torture_setup_file(torture, tree, src_name, false);
5097 torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
5098 ok = torture_setup_file(torture, tree, dst_name, false);
5099 torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
5101 for (i = 0; i < ARRAY_SIZE(names); i++) {
5102 ok = copy_one_stream(torture, tree, tmp_ctx,
5103 names[i].src_sname,
5104 names[i].dst_sname);
5105 torture_assert_goto(torture, ok == true, ok, done,
5106 "copy_one_stream failed\n");
5109 ok = copy_finderinfo_stream(torture, tree, tmp_ctx,
5110 src_name, dst_name);
5111 torture_assert_goto(torture, ok == true, ok, done,
5112 "copy_finderinfo_stream failed\n");
5114 done:
5115 smb2_util_unlink(tree, src_name);
5116 smb2_util_unlink(tree, dst_name);
5117 talloc_free(tmp_ctx);
5118 return ok;
5122 * Ensure this security descriptor has exactly one mode, uid
5123 * and gid.
5126 static NTSTATUS check_nfs_sd(const struct security_descriptor *psd)
5128 uint32_t i;
5129 bool got_one_mode = false;
5130 bool got_one_uid = false;
5131 bool got_one_gid = false;
5133 if (psd->dacl == NULL) {
5134 return NT_STATUS_INVALID_SECURITY_DESCR;
5137 for (i = 0; i < psd->dacl->num_aces; i++) {
5138 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Mode,
5139 &psd->dacl->aces[i].trustee) == 0) {
5140 if (got_one_mode == true) {
5141 /* Can't have more than one. */
5142 return NT_STATUS_INVALID_SECURITY_DESCR;
5144 got_one_mode = true;
5147 for (i = 0; i < psd->dacl->num_aces; i++) {
5148 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Users,
5149 &psd->dacl->aces[i].trustee) == 0) {
5150 if (got_one_uid == true) {
5151 /* Can't have more than one. */
5152 return NT_STATUS_INVALID_SECURITY_DESCR;
5154 got_one_uid = true;
5157 for (i = 0; i < psd->dacl->num_aces; i++) {
5158 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Groups,
5159 &psd->dacl->aces[i].trustee) == 0) {
5160 if (got_one_gid == true) {
5161 /* Can't have more than one. */
5162 return NT_STATUS_INVALID_SECURITY_DESCR;
5164 got_one_gid = true;
5167 /* Must have at least one of each. */
5168 if (got_one_mode == false ||
5169 got_one_uid == false ||
5170 got_one_gid == false) {
5171 return NT_STATUS_INVALID_SECURITY_DESCR;
5173 return NT_STATUS_OK;
5176 static bool test_nfs_aces(struct torture_context *tctx,
5177 struct smb2_tree *tree)
5179 TALLOC_CTX *mem_ctx = talloc_new(tctx);
5180 struct security_ace ace;
5181 struct dom_sid sid;
5182 const char *fname = BASEDIR "\\nfs_aces.txt";
5183 struct smb2_handle h = {{0}};
5184 union smb_fileinfo finfo2;
5185 union smb_setfileinfo set;
5186 struct security_descriptor *psd = NULL;
5187 NTSTATUS status;
5188 bool ret = true;
5189 bool is_osx = torture_setting_bool(tctx, "osx", false);
5191 if (is_osx) {
5192 torture_skip(tctx, "Test only works with Samba\n");
5195 ret = enable_aapl(tctx, tree);
5196 torture_assert(tctx, ret == true, "enable_aapl failed");
5198 /* clean slate ...*/
5199 smb2_util_unlink(tree, fname);
5200 smb2_deltree(tree, fname);
5201 smb2_deltree(tree, BASEDIR);
5203 status = torture_smb2_testdir(tree, BASEDIR, &h);
5204 CHECK_STATUS(status, NT_STATUS_OK);
5205 smb2_util_close(tree, h);
5207 /* Create a test file. */
5208 status = torture_smb2_testfile_access(tree,
5209 fname,
5211 SEC_STD_READ_CONTROL |
5212 SEC_STD_WRITE_DAC |
5213 SEC_RIGHTS_FILE_ALL);
5214 CHECK_STATUS(status, NT_STATUS_OK);
5216 /* Get the ACL. */
5217 finfo2.query_secdesc.in.secinfo_flags =
5218 SECINFO_OWNER |
5219 SECINFO_GROUP |
5220 SECINFO_DACL;
5221 finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
5222 finfo2.generic.in.file.handle = h;
5223 status = smb2_getinfo_file(tree, tctx, &finfo2);
5224 CHECK_STATUS(status, NT_STATUS_OK);
5226 psd = finfo2.query_secdesc.out.sd;
5228 /* Ensure we have only single mode/uid/gid NFS entries. */
5229 status = check_nfs_sd(psd);
5230 if (!NT_STATUS_IS_OK(status)) {
5231 NDR_PRINT_DEBUG(
5232 security_descriptor,
5233 discard_const_p(struct security_descriptor, psd));
5235 CHECK_STATUS(status, NT_STATUS_OK);
5237 /* Add a couple of extra NFS uids and gids. */
5238 sid_compose(&sid, &global_sid_Unix_NFS_Users, 27);
5239 init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
5240 status = security_descriptor_dacl_add(psd, &ace);
5241 CHECK_STATUS(status, NT_STATUS_OK);
5242 status = security_descriptor_dacl_add(psd, &ace);
5243 CHECK_STATUS(status, NT_STATUS_OK);
5245 sid_compose(&sid, &global_sid_Unix_NFS_Groups, 300);
5246 init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
5247 status = security_descriptor_dacl_add(psd, &ace);
5248 CHECK_STATUS(status, NT_STATUS_OK);
5249 status = security_descriptor_dacl_add(psd, &ace);
5250 CHECK_STATUS(status, NT_STATUS_OK);
5252 /* Now set on the file handle. */
5253 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
5254 set.set_secdesc.in.file.handle = h;
5255 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
5256 set.set_secdesc.in.sd = psd;
5257 status = smb2_setinfo_file(tree, &set);
5258 CHECK_STATUS(status, NT_STATUS_OK);
5260 /* Get the ACL again. */
5261 finfo2.query_secdesc.in.secinfo_flags =
5262 SECINFO_OWNER |
5263 SECINFO_GROUP |
5264 SECINFO_DACL;
5265 finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
5266 finfo2.generic.in.file.handle = h;
5267 status = smb2_getinfo_file(tree, tctx, &finfo2);
5268 CHECK_STATUS(status, NT_STATUS_OK);
5270 psd = finfo2.query_secdesc.out.sd;
5272 /* Ensure we have only single mode/uid/gid NFS entries. */
5273 status = check_nfs_sd(psd);
5274 if (!NT_STATUS_IS_OK(status)) {
5275 NDR_PRINT_DEBUG(
5276 security_descriptor,
5277 discard_const_p(struct security_descriptor, psd));
5279 CHECK_STATUS(status, NT_STATUS_OK);
5281 done:
5282 if (!smb2_util_handle_empty(h)) {
5283 smb2_util_close(tree, h);
5285 smb2_util_unlink(tree, fname);
5286 smb2_deltree(tree, fname);
5287 smb2_deltree(tree, BASEDIR);
5288 talloc_free(mem_ctx);
5289 return ret;
5292 static bool test_setinfo_stream_eof(struct torture_context *tctx,
5293 struct smb2_tree *tree)
5295 bool ret = true;
5296 NTSTATUS status;
5297 struct smb2_create create;
5298 union smb_setfileinfo sfinfo;
5299 union smb_fileinfo finfo;
5300 struct smb2_handle h1;
5301 TALLOC_CTX *mem_ctx = talloc_new(tctx);
5302 const char *fname = BASEDIR "\\file";
5303 const char *sname = BASEDIR "\\file:foo";
5305 torture_assert_goto(tctx, mem_ctx != NULL, ret, done,
5306 "talloc_new failed\n");
5308 ret = enable_aapl(tctx, tree);
5309 torture_assert(tctx, ret == true, "enable_aapl failed");
5311 torture_comment(tctx, "Test setting EOF on a stream\n");
5313 smb2_deltree(tree, BASEDIR);
5314 status = torture_smb2_testdir(tree, BASEDIR, &h1);
5315 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5316 "torture_smb2_testdir\n");
5317 smb2_util_close(tree, h1);
5319 status = torture_smb2_testfile(tree, fname, &h1);
5320 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5321 "torture_smb2_testfile failed\n");
5322 smb2_util_close(tree, h1);
5324 status = torture_smb2_testfile_access(tree, sname, &h1,
5325 SEC_FILE_WRITE_DATA);
5326 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5327 "torture_smb2_testfile failed\n");
5329 status = smb2_util_write(tree, h1, "1234567890", 0, 10);
5330 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5331 "smb2_util_write failed\n");
5332 smb2_util_close(tree, h1);
5335 * Test setting EOF to 21
5338 torture_comment(tctx, "Setting stream EOF to 21\n");
5340 status = torture_smb2_testfile_access(tree, sname, &h1,
5341 SEC_FILE_WRITE_DATA);
5342 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5343 "torture_smb2_testfile failed\n");
5345 ZERO_STRUCT(sfinfo);
5346 sfinfo.generic.in.file.handle = h1;
5347 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5348 sfinfo.position_information.in.position = 21;
5349 status = smb2_setinfo_file(tree, &sfinfo);
5350 torture_assert_ntstatus_ok_goto(tctx, status,
5351 ret, done, "set EOF 21 failed\n");
5353 smb2_util_close(tree, h1);
5355 status = torture_smb2_testfile_access(tree, sname, &h1,
5356 SEC_FILE_WRITE_DATA);
5357 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5358 "torture_smb2_testfile failed\n");
5360 ZERO_STRUCT(finfo);
5361 finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5362 finfo.generic.in.file.handle = h1;
5363 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5364 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5365 "smb2_getinfo_file failed");
5367 smb2_util_close(tree, h1);
5369 torture_assert_goto(tctx, finfo.standard_info.out.size == 21,
5370 ret, done, "size != 21\n");
5373 * Test setting EOF to 0
5376 torture_comment(tctx, "Setting stream EOF to 0\n");
5378 status = torture_smb2_testfile_access(tree, sname, &h1,
5379 SEC_FILE_WRITE_DATA);
5380 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5381 "torture_smb2_testfile failed\n");
5383 ZERO_STRUCT(sfinfo);
5384 sfinfo.generic.in.file.handle = h1;
5385 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5386 sfinfo.position_information.in.position = 0;
5387 status = smb2_setinfo_file(tree, &sfinfo);
5388 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5389 "set eof 0 failed\n");
5391 ZERO_STRUCT(create);
5392 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5393 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5394 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5395 create.in.create_disposition = NTCREATEX_DISP_OPEN;
5396 create.in.fname = sname;
5398 status = smb2_create(tree, tctx, &create);
5399 torture_assert_ntstatus_equal_goto(
5400 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5401 "Unexpected status\n");
5403 smb2_util_close(tree, h1);
5405 ZERO_STRUCT(create);
5406 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5407 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5408 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5409 create.in.create_disposition = NTCREATEX_DISP_OPEN;
5410 create.in.fname = sname;
5412 status = smb2_create(tree, tctx, &create);
5413 torture_assert_ntstatus_equal_goto(
5414 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5415 "Unexpected status\n");
5417 status = torture_smb2_testfile_access(tree, sname, &h1,
5418 SEC_FILE_WRITE_DATA);
5419 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5420 "torture_smb2_testfile failed\n");
5422 ZERO_STRUCT(finfo);
5423 finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5424 finfo.generic.in.file.handle = h1;
5425 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5426 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5427 "smb2_getinfo_file failed\n");
5429 smb2_util_close(tree, h1);
5431 torture_assert_goto(tctx, finfo.standard_info.out.size == 0,
5432 ret, done, "size != 0\n");
5435 * Test setinfo end-of-file info to 1
5438 torture_comment(tctx, "Setting stream EOF to 1\n");
5440 status = torture_smb2_testfile_access(tree, sname, &h1,
5441 SEC_FILE_WRITE_DATA);
5442 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5443 "torture_smb2_testfile failed\n");
5445 ZERO_STRUCT(sfinfo);
5446 sfinfo.generic.in.file.handle = h1;
5447 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5448 sfinfo.position_information.in.position = 1;
5449 status = smb2_setinfo_file(tree, &sfinfo);
5450 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5451 "set EOF 1 failed\n");
5453 smb2_util_close(tree, h1);
5455 status = torture_smb2_testfile_access(tree, sname, &h1,
5456 SEC_FILE_WRITE_DATA);
5457 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5458 "torture_smb2_testfile failed\n");
5460 ZERO_STRUCT(finfo);
5461 finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5462 finfo.generic.in.file.handle = h1;
5463 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5464 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5465 "smb2_getinfo_file failed\n");
5467 smb2_util_close(tree, h1);
5469 torture_assert_goto(tctx, finfo.standard_info.out.size == 1,
5470 ret, done, "size != 1\n");
5473 * Test setting EOF to 0 with AAPL enabled, should delete stream
5476 torture_comment(tctx, "Enabling AAPL extensions\n");
5478 ret = enable_aapl(tctx, tree);
5479 torture_assert(tctx, ret == true, "enable_aapl failed\n");
5481 torture_comment(tctx, "Setting stream EOF to 0\n");
5482 status = torture_smb2_testfile_access(tree, sname, &h1,
5483 SEC_FILE_WRITE_DATA);
5484 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5485 "torture_smb2_testfile failed\n");
5487 ZERO_STRUCT(sfinfo);
5488 sfinfo.generic.in.file.handle = h1;
5489 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5490 sfinfo.position_information.in.position = 0;
5491 status = smb2_setinfo_file(tree, &sfinfo);
5492 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5493 "set eof 0 failed\n");
5495 ZERO_STRUCT(create);
5496 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5497 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5498 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5499 create.in.create_disposition = NTCREATEX_DISP_OPEN;
5500 create.in.fname = sname;
5502 status = smb2_create(tree, tctx, &create);
5503 torture_assert_ntstatus_equal_goto(
5504 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5505 "Unexpected status\n");
5507 smb2_util_close(tree, h1);
5509 ZERO_STRUCT(create);
5510 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5511 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5512 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5513 create.in.create_disposition = NTCREATEX_DISP_OPEN;
5514 create.in.fname = sname;
5516 status = smb2_create(tree, tctx, &create);
5517 torture_assert_ntstatus_equal_goto(
5518 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5519 "Unexpected status\n");
5521 torture_comment(
5522 tctx, "Setting main file EOF to 1 to force 0-truncate\n");
5524 status = torture_smb2_testfile_access(
5525 tree,
5526 fname,
5527 &h1,
5528 SEC_FILE_WRITE_DATA);
5529 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5530 "torture_smb2_testfile failed\n");
5532 ZERO_STRUCT(sfinfo);
5533 sfinfo.generic.in.file.handle = h1;
5534 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5535 sfinfo.position_information.in.position = 1;
5536 status = smb2_setinfo_file(tree, &sfinfo);
5537 torture_assert_ntstatus_ok_goto(
5538 tctx,
5539 status,
5540 ret,
5541 done,
5542 "set eof 1 failed\n");
5544 sfinfo.position_information.in.position = 0;
5545 status = smb2_setinfo_file(tree, &sfinfo);
5546 torture_assert_ntstatus_ok_goto(
5547 tctx,
5548 status,
5549 ret,
5550 done,
5551 "set eof 0 failed\n");
5553 smb2_util_close(tree, h1);
5555 ZERO_STRUCT(create);
5556 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5557 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5558 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5559 create.in.create_disposition = NTCREATEX_DISP_OPEN;
5560 create.in.fname = fname;
5562 status = smb2_create(tree, tctx, &create);
5563 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5564 "torture_smb2_testfile failed\n");
5565 smb2_util_close(tree, h1);
5567 torture_comment(tctx, "Writing to stream after setting EOF to 0\n");
5568 status = torture_smb2_testfile_access(tree, sname, &h1,
5569 SEC_FILE_WRITE_DATA);
5570 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5571 "torture_smb2_testfile failed\n");
5573 status = smb2_util_write(tree, h1, "1234567890", 0, 10);
5574 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5575 "smb2_util_write failed\n");
5577 ZERO_STRUCT(sfinfo);
5578 sfinfo.generic.in.file.handle = h1;
5579 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5580 sfinfo.position_information.in.position = 0;
5581 status = smb2_setinfo_file(tree, &sfinfo);
5582 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5583 "set eof 0 failed\n");
5585 status = smb2_util_write(tree, h1, "1234567890", 0, 10);
5586 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5587 "smb2_util_write failed\n");
5589 smb2_util_close(tree, h1);
5591 done:
5592 smb2_util_unlink(tree, fname);
5593 smb2_util_rmdir(tree, BASEDIR);
5594 return ret;
5597 #define MAX_STREAMS 16
5599 struct tcase {
5600 const char *name;
5601 uint32_t access;
5602 const char *write_data;
5603 size_t write_size;
5604 struct tcase_results {
5605 size_t size;
5606 NTSTATUS initial_status;
5607 NTSTATUS final_status;
5608 int num_streams_open_handle;
5609 const char *streams_open_handle[MAX_STREAMS];
5610 int num_streams_closed_handle;
5611 const char *streams_closed_handle[MAX_STREAMS];
5612 } create, write, overwrite, eof, doc;
5615 typedef enum {T_CREATE, T_WRITE, T_OVERWRITE, T_EOF, T_DOC} subtcase_t;
5617 static bool test_empty_stream_do_checks(
5618 struct torture_context *tctx,
5619 struct smb2_tree *tree,
5620 struct smb2_tree *tree2,
5621 struct tcase *tcase,
5622 TALLOC_CTX *mem_ctx,
5623 struct smb2_handle baseh,
5624 struct smb2_handle streamh,
5625 subtcase_t subcase)
5627 bool ret = false;
5628 NTSTATUS status;
5629 struct smb2_handle h1;
5630 union smb_fileinfo finfo;
5631 struct tcase_results *tcase_results = NULL;
5633 switch (subcase) {
5634 case T_CREATE:
5635 tcase_results = &tcase->create;
5636 break;
5637 case T_OVERWRITE:
5638 tcase_results = &tcase->overwrite;
5639 break;
5640 case T_WRITE:
5641 tcase_results = &tcase->write;
5642 break;
5643 case T_EOF:
5644 tcase_results = &tcase->eof;
5645 break;
5646 case T_DOC:
5647 tcase_results = &tcase->doc;
5648 break;
5651 finfo = (union smb_fileinfo) {
5652 .generic.level = RAW_FILEINFO_STANDARD_INFORMATION,
5653 .generic.in.file.handle = streamh,
5657 * Test: check size, same client
5660 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5661 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5662 "torture_smb2_testfile failed\n");
5664 torture_assert_int_equal_goto(tctx, finfo.standard_info.out.size,
5665 tcase_results->size,
5666 ret, done, "Wrong size\n");
5669 * Test: open, same client
5672 status = torture_smb2_open(tree, tcase->name,
5673 SEC_FILE_READ_ATTRIBUTE, &h1);
5674 torture_assert_ntstatus_equal_goto(tctx, status,
5675 tcase_results->initial_status,
5676 ret, done,
5677 "smb2_create failed\n");
5678 if (NT_STATUS_IS_OK(status)) {
5679 status = smb2_util_close(tree, h1);
5680 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5681 "smb2_util_close failed\n");
5685 * Test: check streams, same client
5688 ret = check_stream_list_handle(tree, tctx, baseh,
5689 tcase_results->num_streams_open_handle,
5690 tcase_results->streams_open_handle,
5691 false);
5692 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
5695 * Test: open, different client
5698 status = torture_smb2_open(tree2, tcase->name,
5699 SEC_FILE_READ_ATTRIBUTE, &h1);
5700 torture_assert_ntstatus_equal_goto(tctx, status,
5701 tcase_results->initial_status,
5702 ret, done,
5703 "smb2_create failed\n");
5704 if (NT_STATUS_IS_OK(status)) {
5705 finfo = (union smb_fileinfo) {
5706 .generic.level = RAW_FILEINFO_STANDARD_INFORMATION,
5707 .generic.in.file.handle = h1,
5711 * Test: check size, different client
5714 status = smb2_getinfo_file(tree2, mem_ctx, &finfo);
5715 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5716 "smb2_getinfo_file failed\n");
5718 torture_assert_int_equal_goto(tctx, finfo.standard_info.out.size,
5719 tcase_results->size,
5720 ret, done, "Wrong size\n");
5723 * Test: check streams, different client
5726 ret = check_stream_list(tree2, tctx, BASEDIR "\\file",
5727 tcase_results->num_streams_open_handle,
5728 tcase_results->streams_open_handle,
5729 false);
5730 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
5732 status = smb2_util_close(tree2, h1);
5733 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5734 "smb2_util_close failed\n");
5737 status = smb2_util_close(tree, streamh);
5738 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5739 "smb2_util_close failed\n");
5742 * Test: open after close, same client
5745 status = torture_smb2_open(tree, tcase->name,
5746 SEC_FILE_READ_DATA, &h1);
5747 torture_assert_ntstatus_equal_goto(tctx, status,
5748 tcase_results->final_status,
5749 ret, done,
5750 "smb2_create failed\n");
5751 if (NT_STATUS_IS_OK(status)) {
5752 status = smb2_util_close(tree, h1);
5753 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5754 "smb2_util_close failed\n");
5758 * Test: open after close, different client
5761 status = torture_smb2_open(tree2, tcase->name,
5762 SEC_FILE_READ_DATA, &h1);
5763 torture_assert_ntstatus_equal_goto(tctx, status,
5764 tcase_results->final_status,
5765 ret, done,
5766 "smb2_create failed\n");
5767 if (NT_STATUS_IS_OK(status)) {
5768 status = smb2_util_close(tree2, h1);
5769 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5770 "smb2_util_close failed\n");
5774 * Test: check streams after close, same client
5777 ret = check_stream_list_handle(tree, tctx, baseh,
5778 tcase_results->num_streams_closed_handle,
5779 tcase_results->streams_closed_handle,
5780 false);
5781 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
5783 ret = true;
5785 done:
5786 smb2_util_close(tree, streamh);
5787 smb2_util_close(tree, baseh);
5788 return ret;
5791 static bool test_empty_stream_do_one(
5792 struct torture_context *tctx,
5793 struct smb2_tree *tree,
5794 struct smb2_tree *tree2,
5795 struct tcase *tcase)
5797 bool ret = false;
5798 NTSTATUS status;
5799 struct smb2_handle baseh = {{0}};
5800 struct smb2_handle streamh;
5801 struct smb2_create create;
5802 union smb_setfileinfo sfinfo;
5803 TALLOC_CTX *mem_ctx = talloc_new(tctx);
5805 torture_comment(tctx, "Testing stream [%s]\n", tcase->name);
5807 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new\n");
5810 * Subtest: create
5812 torture_comment(tctx, "Subtest: T_CREATE\n");
5814 status = smb2_util_unlink(tree, BASEDIR "\\file");
5815 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5816 "smb2_util_unlink failed\n");
5818 status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5819 &baseh, SEC_FILE_ALL);
5820 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5821 "torture_smb2_testfile_access failed\n");
5823 status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5824 tcase->access);
5825 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5826 "torture_smb2_testfile_access failed\n");
5828 ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5829 mem_ctx, baseh, streamh, T_CREATE);
5830 torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5832 if (!(tcase->access & SEC_FILE_WRITE_DATA)) {
5834 * All subsequent tests require write access
5836 ret = true;
5837 goto done;
5841 * Subtest: create and write
5843 torture_comment(tctx, "Subtest: T_WRITE\n");
5845 status = smb2_util_unlink(tree, BASEDIR "\\file");
5846 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5847 "smb2_util_unlink failed\n");
5849 status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5850 &baseh, SEC_FILE_ALL);
5851 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5852 "torture_smb2_testfile_access failed\n");
5854 status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5855 tcase->access);
5856 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5857 "torture_smb2_testfile_access failed\n");
5859 status = smb2_util_write(tree, streamh, tcase->write_data, 0,
5860 tcase->write_size);
5861 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5862 "torture_smb2_open failed\n");
5864 ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5865 mem_ctx, baseh, streamh, T_WRITE);
5866 torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5869 * Subtest: overwrite
5871 torture_comment(tctx, "Subtest: T_OVERWRITE\n");
5873 status = smb2_util_unlink(tree, BASEDIR "\\file");
5874 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5875 "smb2_util_unlink failed\n");
5877 status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5878 &baseh, SEC_FILE_ALL);
5879 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5880 "torture_smb2_testfile_access failed\n");
5882 create = (struct smb2_create) {
5883 .in.desired_access = SEC_FILE_ALL,
5884 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
5885 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
5886 .in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF,
5887 .in.fname = tcase->name,
5890 status = smb2_create(tree, tctx, &create);
5891 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5892 "torture_smb2_testfile failed\n");
5893 streamh = create.out.file.handle;
5895 ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5896 mem_ctx, baseh, streamh, T_OVERWRITE);
5897 torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5900 * Subtest: setinfo EOF 0
5902 torture_comment(tctx, "Subtest: T_EOF\n");
5904 status = smb2_util_unlink(tree, BASEDIR "\\file");
5905 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5906 "smb2_util_unlink failed\n");
5908 status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5909 &baseh, SEC_FILE_ALL);
5910 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5911 "torture_smb2_testfile_access failed\n");
5913 status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5914 tcase->access);
5915 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5916 "torture_smb2_testfile_access failed\n");
5918 status = smb2_util_write(tree, streamh, tcase->write_data, 0,
5919 tcase->write_size);
5920 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5921 "torture_smb2_open failed\n");
5923 sfinfo = (union smb_setfileinfo) {
5924 .end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION,
5925 .end_of_file_info.in.file.handle = streamh,
5926 .end_of_file_info.in.size = 0,
5928 status = smb2_setinfo_file(tree, &sfinfo);
5929 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5930 "set eof 0 failed\n");
5932 ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5933 mem_ctx, baseh, streamh, T_EOF);
5934 torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5937 * Subtest: delete-on-close
5939 torture_comment(tctx, "Subtest: T_DOC\n");
5941 status = smb2_util_unlink(tree, BASEDIR "\\file");
5942 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5943 "smb2_util_unlink failed\n");
5945 status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5946 &baseh, SEC_FILE_ALL);
5947 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5948 "torture_smb2_testfile_access failed\n");
5950 status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5951 tcase->access);
5952 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5953 "torture_smb2_testfile_access failed\n");
5955 status = smb2_util_write(tree, streamh, tcase->write_data, 0,
5956 tcase->write_size);
5957 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5958 "torture_smb2_open failed\n");
5960 sfinfo = (union smb_setfileinfo) {
5961 .disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFORMATION,
5962 .disposition_info.in.file.handle = streamh,
5963 .disposition_info.in.delete_on_close = true,
5965 status = smb2_setinfo_file(tree, &sfinfo);
5966 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5967 "set eof 0 failed\n");
5969 ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5970 mem_ctx, baseh, streamh,
5971 T_DOC);
5972 torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5974 ret = true;
5976 done:
5977 smb2_util_close(tree, baseh);
5978 TALLOC_FREE(mem_ctx);
5979 return ret;
5982 static bool test_empty_stream(struct torture_context *tctx,
5983 struct smb2_tree *tree)
5985 struct smb2_tree *tree2 = NULL;
5986 struct tcase *tcase = NULL;
5987 const char *fname = BASEDIR "\\file";
5988 struct smb2_handle h1;
5989 bool ret = true;
5990 NTSTATUS status;
5991 AfpInfo ai = (AfpInfo) {
5992 .afpi_Signature = AFP_Signature,
5993 .afpi_Version = AFP_Version,
5994 .afpi_BackupTime = AFP_BackupTime,
5995 .afpi_FinderInfo = "FOO BAR ",
5997 char *ai_blob = torture_afpinfo_pack(tctx, &ai);
5998 struct tcase tcase_afpinfo_ro = (struct tcase) {
5999 .name = BASEDIR "\\file" AFPINFO_STREAM,
6000 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
6001 .create = {
6002 .size = 60,
6003 .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6004 .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6005 .num_streams_open_handle = 1,
6006 .num_streams_closed_handle = 1,
6007 .streams_open_handle = {"::$DATA"},
6008 .streams_closed_handle = {"::$DATA"},
6011 struct tcase tcase_afpinfo_rw = (struct tcase) {
6012 .name = BASEDIR "\\file" AFPINFO_STREAM,
6013 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
6014 .write_data = ai_blob,
6015 .write_size = AFP_INFO_SIZE,
6016 .create = {
6017 .size = 60,
6018 .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6019 .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6020 .num_streams_open_handle = 1,
6021 .num_streams_closed_handle = 1,
6022 .streams_open_handle = {"::$DATA"},
6023 .streams_closed_handle = {"::$DATA"},
6025 .write = {
6026 .size = 60,
6027 .initial_status = NT_STATUS_OK,
6028 .final_status = NT_STATUS_OK,
6029 .num_streams_open_handle = 2,
6030 .num_streams_closed_handle = 2,
6031 .streams_open_handle = {"::$DATA", AFPINFO_STREAM},
6032 .streams_closed_handle = {"::$DATA", AFPINFO_STREAM},
6034 .overwrite = {
6035 .size = 60,
6036 .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6037 .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6038 .num_streams_open_handle = 1,
6039 .num_streams_closed_handle = 1,
6040 .streams_open_handle = {"::$DATA"},
6041 .streams_closed_handle = {"::$DATA"},
6043 .eof = {
6044 .size = 60,
6045 .initial_status = NT_STATUS_OK,
6046 .final_status = NT_STATUS_OK,
6047 .num_streams_open_handle = 2,
6048 .num_streams_closed_handle = 2,
6049 .streams_open_handle = {"::$DATA", AFPINFO_STREAM},
6050 .streams_closed_handle = {"::$DATA", AFPINFO_STREAM},
6052 .doc = {
6053 .size = 60,
6054 .initial_status = NT_STATUS_DELETE_PENDING,
6055 .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6056 .num_streams_open_handle = 2,
6057 .num_streams_closed_handle = 1,
6058 .streams_open_handle = {"::$DATA", AFPINFO_STREAM},
6059 .streams_closed_handle = {"::$DATA"},
6063 struct tcase tcase_afpresource_ro = (struct tcase) {
6064 .name = BASEDIR "\\file" AFPRESOURCE_STREAM,
6065 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
6066 .create = {
6067 .size = 0,
6068 .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6069 .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6070 .num_streams_open_handle = 1,
6071 .num_streams_closed_handle = 1,
6072 .streams_open_handle = {"::$DATA"},
6073 .streams_closed_handle = {"::$DATA"},
6076 struct tcase tcase_afpresource_rw = (struct tcase) {
6077 .name = BASEDIR "\\file" AFPRESOURCE_STREAM,
6078 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
6079 .write_data = "foo",
6080 .write_size = 3,
6081 .create = {
6082 .size = 0,
6083 .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6084 .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6085 .num_streams_open_handle = 1,
6086 .num_streams_closed_handle = 1,
6087 .streams_open_handle = {"::$DATA"},
6088 .streams_closed_handle = {"::$DATA"},
6090 .write = {
6091 .size = 3,
6092 .initial_status = NT_STATUS_OK,
6093 .final_status = NT_STATUS_OK,
6094 .num_streams_open_handle = 2,
6095 .num_streams_closed_handle = 2,
6096 .streams_open_handle = {"::$DATA", AFPRESOURCE_STREAM},
6097 .streams_closed_handle = {"::$DATA", AFPRESOURCE_STREAM},
6099 .overwrite = {
6100 .size = 0,
6101 .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6102 .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6103 .num_streams_open_handle = 1,
6104 .num_streams_closed_handle = 1,
6105 .streams_open_handle = {"::$DATA"},
6106 .streams_closed_handle = {"::$DATA"},
6108 .eof = {
6109 .size = 0,
6110 .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6111 .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6112 .num_streams_open_handle = 1,
6113 .num_streams_closed_handle = 1,
6114 .streams_open_handle = {"::$DATA"},
6115 .streams_closed_handle = {"::$DATA"},
6117 .doc = {
6118 .size = 3,
6119 .initial_status = NT_STATUS_DELETE_PENDING,
6120 .final_status = NT_STATUS_OK,
6121 .num_streams_open_handle = 2,
6122 .num_streams_closed_handle = 2,
6123 .streams_open_handle = {"::$DATA", AFPRESOURCE_STREAM},
6124 .streams_closed_handle = {"::$DATA", AFPRESOURCE_STREAM},
6128 struct tcase tcase_foo_ro = (struct tcase) {
6129 .name = BASEDIR "\\file:foo",
6130 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
6131 .write_data = "foo",
6132 .write_size = 3,
6133 .create = {
6134 .size = 0,
6135 .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6136 .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6137 .num_streams_open_handle = 1,
6138 .num_streams_closed_handle = 1,
6139 .streams_open_handle = {"::$DATA"},
6140 .streams_closed_handle = {"::$DATA"},
6144 struct tcase tcase_foo_rw = (struct tcase) {
6145 .name = BASEDIR "\\file:foo",
6146 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
6147 .write_data = "foo",
6148 .write_size = 3,
6149 .create = {
6150 .size = 0,
6151 .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6152 .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6153 .num_streams_open_handle = 1,
6154 .num_streams_closed_handle = 1,
6155 .streams_open_handle = {"::$DATA"},
6156 .streams_closed_handle = {"::$DATA"},
6158 .write = {
6159 .size = 3,
6160 .initial_status = NT_STATUS_OK,
6161 .final_status = NT_STATUS_OK,
6162 .num_streams_open_handle = 2,
6163 .num_streams_closed_handle = 2,
6164 .streams_open_handle = {"::$DATA", ":foo:$DATA"},
6165 .streams_closed_handle = {"::$DATA", ":foo:$DATA"},
6167 .overwrite = {
6168 .size = 0,
6169 .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6170 .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6171 .num_streams_open_handle = 1,
6172 .num_streams_closed_handle = 1,
6173 .streams_open_handle = {"::$DATA"},
6174 .streams_closed_handle = {"::$DATA"},
6176 .eof = {
6177 .size = 0,
6178 .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6179 .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6180 .num_streams_open_handle = 1,
6181 .num_streams_closed_handle = 1,
6182 .streams_open_handle = {"::$DATA"},
6183 .streams_closed_handle = {"::$DATA"},
6185 .doc = {
6186 .size = 3,
6187 .initial_status = NT_STATUS_DELETE_PENDING,
6188 .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6189 .num_streams_open_handle = 2,
6190 .num_streams_closed_handle = 1,
6191 .streams_open_handle = {"::$DATA", ":foo:$DATA"},
6192 .streams_closed_handle = {"::$DATA"},
6196 struct tcase tcases[] = {
6197 tcase_afpinfo_ro,
6198 tcase_afpinfo_rw,
6199 tcase_afpresource_ro,
6200 tcase_afpresource_rw,
6201 tcase_foo_ro,
6202 tcase_foo_rw,
6203 {NULL}
6206 ret = torture_smb2_connection(tctx, &tree2);
6207 torture_assert_goto(tctx, ret == true, ret, done,
6208 "torture_smb2_connection failed\n");
6210 ret = enable_aapl(tctx, tree);
6211 torture_assert(tctx, ret == true, "enable_aapl failed\n");
6213 ret = enable_aapl(tctx, tree2);
6214 torture_assert(tctx, ret == true, "enable_aapl failed\n");
6216 smb2_deltree(tree, BASEDIR);
6218 status = torture_smb2_testdir(tree, BASEDIR, &h1);
6219 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6220 "torture_smb2_testdir\n");
6221 smb2_util_close(tree, h1);
6223 for (tcase = &tcases[0]; tcase->name != NULL; tcase++) {
6224 ret = torture_setup_file(tctx, tree, fname, false);
6225 torture_assert_goto(tctx, ret == true, ret, done,
6226 "torture_setup_file failed\n");
6228 ret = test_empty_stream_do_one(tctx, tree, tree2, tcase);
6229 torture_assert_goto(tctx, ret == true, ret, done,
6230 "subtest failed\n");
6232 status = smb2_util_unlink(tree, fname);
6233 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6234 "smb2_util_unlink failed\n");
6237 done:
6238 smb2_deltree(tree, BASEDIR);
6239 TALLOC_FREE(tree2);
6240 return ret;
6244 * Note: This test depends on "vfs objects = catia fruit streams_xattr". For
6245 * some tests torture must be run on the host it tests and takes an additional
6246 * argument with the local path to the share:
6247 * "--option=torture:localdir=<SHAREPATH>".
6249 * When running against an OS X SMB server add "--option=torture:osx=true"
6251 struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx)
6253 struct torture_suite *suite = torture_suite_create(
6254 ctx, "fruit");
6256 suite->description = talloc_strdup(suite, "vfs_fruit tests");
6258 torture_suite_add_1smb2_test(suite, "copyfile", test_copyfile);
6259 torture_suite_add_1smb2_test(suite, "read metadata", test_read_afpinfo);
6260 torture_suite_add_1smb2_test(suite, "write metadata", test_write_atalk_metadata);
6261 torture_suite_add_1smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io);
6262 torture_suite_add_1smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl);
6263 torture_suite_add_1smb2_test(suite, "stream names", test_stream_names);
6264 torture_suite_add_1smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate);
6265 torture_suite_add_1smb2_test(suite, "opening and creating resource fork", test_rfork_create);
6266 torture_suite_add_1smb2_test(suite, "rename_dir_openfile", test_rename_dir_openfile);
6267 torture_suite_add_1smb2_test(suite, "File without AFP_AfpInfo", test_afpinfo_enoent);
6268 torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpInfo", test_create_delete_on_close);
6269 torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpInfo", test_setinfo_delete_on_close);
6270 torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpInfo", test_setinfo_eof);
6271 torture_suite_add_1smb2_test(suite, "delete AFP_AfpInfo by writing all 0", test_afpinfo_all0);
6272 torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpResource", test_create_delete_on_close_resource);
6273 torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpResource", test_setinfo_delete_on_close_resource);
6274 torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpResource", test_setinfo_eof_resource);
6275 torture_suite_add_1smb2_test(suite, "setinfo eof stream", test_setinfo_stream_eof);
6276 torture_suite_add_1smb2_test(suite, "null afpinfo", test_null_afpinfo);
6277 torture_suite_add_1smb2_test(suite, "delete", test_delete_file_with_rfork);
6278 torture_suite_add_1smb2_test(suite, "read open rsrc after rename", test_rename_and_read_rsrc);
6279 torture_suite_add_1smb2_test(suite, "readdir_attr with names with illegal ntfs characters", test_readdir_attr_illegal_ntfs);
6280 torture_suite_add_2ns_smb2_test(suite, "invalid AFP_AfpInfo", test_invalid_afpinfo);
6281 torture_suite_add_1smb2_test(suite, "creating rsrc with read-only access", test_rfork_create_ro);
6282 torture_suite_add_1smb2_test(suite, "copy-chunk streams", test_copy_chunk_streams);
6283 torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
6284 torture_suite_add_1smb2_test(suite, "NFS ACE entries", test_nfs_aces);
6285 torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion without embedded xattr", test_adouble_conversion_wo_xattr);
6286 torture_suite_add_1smb2_test(suite, "empty_stream", test_empty_stream);
6287 torture_suite_add_1smb2_test(suite, "writing_afpinfo", test_writing_afpinfo);
6289 return suite;
6292 static bool test_stream_names_local(struct torture_context *tctx,
6293 struct smb2_tree *tree)
6295 TALLOC_CTX *mem_ctx = talloc_new(tctx);
6296 NTSTATUS status;
6297 struct smb2_create create;
6298 struct smb2_handle h;
6299 const char *fname = BASEDIR "\\stream_names.txt";
6300 const char *sname1;
6301 bool ret;
6302 /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
6303 const char *streams[] = {
6304 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
6305 ":bar" "\xef\x80\xa2" "baz:$DATA", /* "bar:baz:$DATA" */
6306 "::$DATA"
6308 const char *localdir = NULL;
6310 localdir = torture_setting_string(tctx, "localdir", NULL);
6311 if (localdir == NULL) {
6312 torture_skip(tctx, "Need localdir for test");
6315 sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
6317 /* clean slate ...*/
6318 smb2_util_unlink(tree, fname);
6319 smb2_deltree(tree, fname);
6320 smb2_deltree(tree, BASEDIR);
6322 status = torture_smb2_testdir(tree, BASEDIR, &h);
6323 CHECK_STATUS(status, NT_STATUS_OK);
6324 smb2_util_close(tree, h);
6326 torture_comment(tctx, "(%s) testing stream names\n", __location__);
6327 ZERO_STRUCT(create);
6328 create.in.desired_access = SEC_FILE_WRITE_DATA;
6329 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
6330 create.in.share_access =
6331 NTCREATEX_SHARE_ACCESS_DELETE|
6332 NTCREATEX_SHARE_ACCESS_READ|
6333 NTCREATEX_SHARE_ACCESS_WRITE;
6334 create.in.create_disposition = NTCREATEX_DISP_CREATE;
6335 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
6336 create.in.fname = sname1;
6338 status = smb2_create(tree, mem_ctx, &create);
6339 CHECK_STATUS(status, NT_STATUS_OK);
6341 status = smb2_util_write(tree, create.out.file.handle, "foo", 0, 3);
6342 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6343 "smb2_util_write failed\n");
6345 smb2_util_close(tree, create.out.file.handle);
6347 ret = torture_setup_local_xattr(tctx, "localdir", BASEDIR "/stream_names.txt",
6348 "user.DosStream.bar:baz:$DATA",
6349 "data", strlen("data"));
6350 CHECK_VALUE(ret, true);
6352 ret = check_stream_list(tree, tctx, fname, 3, streams, false);
6353 CHECK_VALUE(ret, true);
6355 done:
6356 status = smb2_util_unlink(tree, fname);
6357 smb2_deltree(tree, BASEDIR);
6358 talloc_free(mem_ctx);
6360 return ret;
6363 static bool test_fruit_locking_conflict(struct torture_context *tctx,
6364 struct smb2_tree *tree,
6365 struct smb2_tree *tree2)
6367 TALLOC_CTX *mem_ctx;
6368 struct smb2_create create;
6369 struct smb2_handle h;
6370 struct smb2_lock lck;
6371 struct smb2_lock_element el;
6372 const char *fname = BASEDIR "\\locking_conflict.txt";
6373 NTSTATUS status;
6374 bool ret = false;
6376 mem_ctx = talloc_new(tctx);
6377 torture_assert_not_null(tctx, mem_ctx, "talloc_new failed");
6379 /* clean slate ...*/
6380 smb2_util_unlink(tree, fname);
6381 smb2_deltree(tree, fname);
6382 smb2_deltree(tree, BASEDIR);
6384 status = torture_smb2_testdir(tree, BASEDIR, &h);
6385 CHECK_STATUS(status, NT_STATUS_OK);
6386 smb2_util_close(tree, h);
6388 create = (struct smb2_create) {
6389 .in.desired_access = SEC_RIGHTS_FILE_READ,
6390 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
6391 .in.share_access =
6392 NTCREATEX_SHARE_ACCESS_READ|
6393 NTCREATEX_SHARE_ACCESS_WRITE,
6394 .in.create_disposition = NTCREATEX_DISP_CREATE,
6395 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6396 .in.fname = fname,
6399 status = smb2_create(tree, mem_ctx, &create);
6400 CHECK_STATUS(status, NT_STATUS_OK);
6401 h = create.out.file.handle;
6403 /* Add AD_FILELOCK_RSRC_DENY_WR lock. */
6404 el = (struct smb2_lock_element) {
6405 .offset = 0xfffffffffffffffc,
6406 .length = 1,
6407 .flags = SMB2_LOCK_FLAG_EXCLUSIVE,
6409 lck = (struct smb2_lock) {
6410 .in.lock_count = 1,
6411 .in.file.handle = h,
6412 .in.locks = &el,
6416 * Lock up to and including:
6417 * AD_FILELOCK_OPEN_WR
6418 * AD_FILELOCK_OPEN_RD
6419 * This is designed to cause a NetAtalk
6420 * locking conflict on the next open,
6421 * even though the share modes are
6422 * compatible.
6424 status = smb2_lock(tree, &lck);
6425 CHECK_STATUS(status, NT_STATUS_OK);
6427 el = (struct smb2_lock_element) {
6428 .offset = 0,
6429 .length = 0x7ffffffffffffff7,
6430 .flags = SMB2_LOCK_FLAG_EXCLUSIVE,
6432 status = smb2_lock(tree, &lck);
6433 CHECK_STATUS(status, NT_STATUS_OK);
6435 create = (struct smb2_create) {
6436 .in.desired_access =
6437 SEC_RIGHTS_FILE_READ|SEC_RIGHTS_FILE_WRITE,
6438 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
6439 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6440 .in.create_disposition = NTCREATEX_DISP_OPEN,
6441 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6442 .in.fname = fname,
6446 * Open on the second tree - ensure we are
6447 * emulating trying to access with a NetATalk
6448 * process with an existing open/deny mode.
6450 status = smb2_create(tree2, mem_ctx, &create);
6451 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
6454 struct smb2_close cl = {
6455 .level = RAW_CLOSE_SMB2,
6456 .in.file.handle = h,
6458 smb2_close(tree, &cl);
6461 ret = true;
6462 done:
6463 return ret;
6466 struct torture_suite *torture_vfs_fruit_netatalk(TALLOC_CTX *ctx)
6468 struct torture_suite *suite = torture_suite_create(
6469 ctx, "fruit_netatalk");
6471 suite->description = talloc_strdup(suite, "vfs_fruit tests for Netatalk interop that require fruit:metadata=netatalk");
6473 torture_suite_add_1smb2_test(suite, "read netatalk metadata", test_read_netatalk_metadata);
6474 torture_suite_add_1smb2_test(suite, "stream names with locally created xattr", test_stream_names_local);
6475 torture_suite_add_2smb2_test(
6476 suite, "locking conflict", test_fruit_locking_conflict);
6478 return suite;
6481 struct torture_suite *torture_vfs_fruit_file_id(TALLOC_CTX *ctx)
6483 struct torture_suite *suite =
6484 torture_suite_create(ctx, "fruit_file_id");
6486 suite->description =
6487 talloc_strdup(suite, "vfs_fruit tests for on-disk file ID that "
6488 "require fruit:zero_file_id=yes");
6490 torture_suite_add_1smb2_test(suite, "zero file id if AAPL negotiated",
6491 test_zero_file_id);
6493 return suite;
6496 static bool test_timemachine_volsize(struct torture_context *tctx,
6497 struct smb2_tree *tree)
6499 TALLOC_CTX *mem_ctx = talloc_new(tctx);
6500 struct smb2_handle h = {{0}};
6501 union smb_fsinfo fsinfo;
6502 NTSTATUS status;
6503 bool ok = true;
6504 const char *info_plist =
6505 "<dict>\n"
6506 " <key>band-size</key>\n"
6507 " <integer>8192</integer>\n"
6508 "</dict>\n";
6510 smb2_deltree(tree, "test.sparsebundle");
6512 ok = enable_aapl(tctx, tree);
6513 torture_assert_goto(tctx, ok, ok, done, "enable_aapl failed");
6515 status = smb2_util_mkdir(tree, "test.sparsebundle");
6516 torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
6517 "smb2_util_mkdir\n");
6519 ok = write_stream(tree, __location__, tctx, mem_ctx,
6520 "test.sparsebundle/Info.plist", NULL,
6521 0, strlen(info_plist), info_plist);
6522 torture_assert_goto(tctx, ok, ok, done, "write_stream failed\n");
6524 status = smb2_util_mkdir(tree, "test.sparsebundle/bands");
6525 torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
6526 "smb2_util_mkdir\n");
6528 ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/1", false);
6529 torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
6531 ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/2", false);
6532 torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
6534 status = smb2_util_roothandle(tree, &h);
6535 torture_assert_ntstatus_ok(tctx, status, "Unable to create root handle");
6537 ZERO_STRUCT(fsinfo);
6538 fsinfo.generic.level = RAW_QFS_SIZE_INFORMATION;
6539 fsinfo.generic.handle = h;
6541 status = smb2_getinfo_fs(tree, tree, &fsinfo);
6542 torture_assert_ntstatus_ok(tctx, status, "smb2_getinfo_fs failed");
6544 torture_comment(tctx, "sectors_per_unit: %" PRIu32"\n"
6545 "bytes_per_sector: %" PRIu32"\n"
6546 "total_alloc_units: %" PRIu64"\n"
6547 "avail_alloc_units: %" PRIu64"\n",
6548 fsinfo.size_info.out.sectors_per_unit,
6549 fsinfo.size_info.out.bytes_per_sector,
6550 fsinfo.size_info.out.total_alloc_units,
6551 fsinfo.size_info.out.avail_alloc_units);
6554 * Let me explain the numbers:
6556 * - the share is set to "fruit:time machine max size = 32K"
6557 * - we've faked a bandsize of 8 K in the Info.plist file
6558 * - we've created two bands files
6559 * - one allocation unit is made of two sectors with 512 B each
6560 * => we've consumed 16 allocation units, there should be 16 free
6563 torture_assert_goto(tctx, fsinfo.size_info.out.sectors_per_unit == 2,
6564 ok, done, "Bad sectors_per_unit");
6566 torture_assert_goto(tctx, fsinfo.size_info.out.bytes_per_sector == 512,
6567 ok, done, "Bad bytes_per_sector");
6569 torture_assert_goto(tctx, fsinfo.size_info.out.total_alloc_units == 32,
6570 ok, done, "Bad total_alloc_units");
6572 torture_assert_goto(tctx, fsinfo.size_info.out.avail_alloc_units == 16,
6573 ok, done, "Bad avail_alloc_units");
6575 done:
6576 if (!smb2_util_handle_empty(h)) {
6577 smb2_util_close(tree, h);
6579 smb2_deltree(tree, "test.sparsebundle");
6580 talloc_free(mem_ctx);
6581 return ok;
6584 struct torture_suite *torture_vfs_fruit_timemachine(TALLOC_CTX *ctx)
6586 struct torture_suite *suite = torture_suite_create(
6587 ctx, "fruit_timemachine");
6589 suite->description = talloc_strdup(
6590 suite, "vfs_fruit tests for TimeMachine");
6592 torture_suite_add_1smb2_test(suite, "Timemachine-volsize",
6593 test_timemachine_volsize);
6595 return suite;
6598 static bool test_convert_xattr_and_empty_rfork_then_delete(
6599 struct torture_context *tctx,
6600 struct smb2_tree *tree1,
6601 struct smb2_tree *tree2)
6603 TALLOC_CTX *mem_ctx = talloc_new(tctx);
6604 const char *fname = BASEDIR "\\test_adouble_conversion";
6605 const char *adname = BASEDIR "/._test_adouble_conversion";
6606 const char *rfork = BASEDIR "\\test_adouble_conversion" AFPRESOURCE_STREAM_NAME;
6607 NTSTATUS status;
6608 struct smb2_handle testdirh;
6609 bool ret = true;
6610 const char *streams[] = {
6611 "::$DATA",
6612 AFPINFO_STREAM,
6613 ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
6614 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
6616 struct smb2_create create;
6617 struct smb2_find find;
6618 unsigned int count;
6619 union smb_search_data *d;
6620 bool delete_empty_adfiles;
6621 int expected_num_files;
6623 delete_empty_adfiles = torture_setting_bool(tctx,
6624 "delete_empty_adfiles",
6625 false);
6627 smb2_deltree(tree1, BASEDIR);
6629 status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
6630 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6631 "torture_smb2_testdir failed\n");
6632 smb2_util_close(tree1, testdirh);
6634 ret = torture_setup_file(tctx, tree1, fname, false);
6635 torture_assert_goto(tctx, ret == true, ret, done,
6636 "torture_setup_file failed\n");
6638 ret = torture_setup_file(tctx, tree1, adname, false);
6639 torture_assert_goto(tctx, ret == true, ret, done,
6640 "torture_setup_file failed\n");
6642 ret = write_stream(tree1, __location__, tctx, mem_ctx,
6643 adname, NULL,
6644 0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr);
6645 torture_assert_goto(tctx, ret == true, ret, done,
6646 "write_stream failed\n");
6648 ret = enable_aapl(tctx, tree2);
6649 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
6652 * Issue a smb2_find(), this triggers the server-side conversion
6655 create = (struct smb2_create) {
6656 .in.desired_access = SEC_RIGHTS_DIR_READ,
6657 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
6658 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
6659 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6660 .in.create_disposition = NTCREATEX_DISP_OPEN,
6661 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6662 .in.fname = BASEDIR,
6665 status = smb2_create(tree2, tctx, &create);
6666 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6667 "smb2_create failed\n");
6669 find = (struct smb2_find) {
6670 .in.file.handle = create.out.file.handle,
6671 .in.pattern = "*",
6672 .in.max_response_size = 0x1000,
6673 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
6676 status = smb2_find_level(tree2, tree2, &find, &count, &d);
6677 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6678 "smb2_find_level failed\n");
6680 status = smb2_util_close(tree2, create.out.file.handle);
6681 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6682 "smb2_util_close failed");
6685 * Check number of streams
6688 ret = check_stream_list(tree2, tctx, fname, 4, streams, false);
6689 torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
6692 * Check Resource Fork is gone
6695 create = (struct smb2_create) {
6696 .in.desired_access = SEC_RIGHTS_FILE_READ|SEC_RIGHTS_FILE_WRITE,
6697 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
6698 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6699 .in.create_disposition = NTCREATEX_DISP_OPEN,
6700 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6701 .in.fname = rfork,
6704 status = smb2_create(tree2, mem_ctx, &create);
6705 torture_assert_ntstatus_equal_goto(
6706 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
6707 ret, done, "Bad smb2_create return\n");
6710 * Check xattr data has been migrated from the AppleDouble file to
6711 * streams.
6714 ret = check_stream(tree2, __location__, tctx, mem_ctx,
6715 fname, AFPINFO_STREAM,
6716 0, 60, 16, 8, "TESTSLOW");
6717 torture_assert_goto(tctx, ret == true, ret, done,
6718 "check AFPINFO_STREAM failed\n");
6720 ret = check_stream(tree2, __location__, tctx, mem_ctx,
6721 fname, ":foo" "\xef\x80\xa2" "bar", /* foo:bar */
6722 0, 3, 0, 3, "baz");
6723 torture_assert_goto(tctx, ret == true, ret, done,
6724 "check foo stream failed\n");
6727 * Now check number of files. If delete_empty_adfiles is set, the
6728 * AppleDouble files should have been deleted.
6731 create = (struct smb2_create) {
6732 .in.desired_access = SEC_RIGHTS_DIR_READ,
6733 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
6734 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
6735 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6736 .in.create_disposition = NTCREATEX_DISP_OPEN,
6737 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6738 .in.fname = BASEDIR,
6741 status = smb2_create(tree2, tctx, &create);
6742 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6743 "smb2_create failed\n");
6745 find = (struct smb2_find) {
6746 .in.file.handle = create.out.file.handle,
6747 .in.pattern = "*",
6748 .in.max_response_size = 0x1000,
6749 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
6752 status = smb2_find_level(tree2, tree2, &find, &count, &d);
6753 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6754 "smb2_find_level failed\n");
6756 status = smb2_util_close(tree2, create.out.file.handle);
6757 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6758 "smb2_util_close failed");
6760 if (delete_empty_adfiles) {
6761 expected_num_files = 3;
6762 } else {
6763 expected_num_files = 4;
6765 torture_assert_int_equal_goto(tctx, count, expected_num_files, ret, done,
6766 "Wrong number of files\n");
6768 done:
6769 smb2_deltree(tree1, BASEDIR);
6770 talloc_free(mem_ctx);
6771 return ret;
6774 struct torture_suite *torture_vfs_fruit_conversion(TALLOC_CTX *ctx)
6776 struct torture_suite *suite = torture_suite_create(
6777 ctx, "fruit_conversion");
6779 suite->description = talloc_strdup(
6780 suite, "vfs_fruit conversion tests");
6782 torture_suite_add_2ns_smb2_test(
6783 suite, "convert_xattr_and_empty_rfork_then_delete",
6784 test_convert_xattr_and_empty_rfork_then_delete);
6786 return suite;