s4:torture/vfs/fruit: expand existing vfs_test "null afpinfo"
[kai/samba-autobuild/.git] / source4 / torture / vfs / fruit.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    vfs_fruit tests
5
6    Copyright (C) Ralph Boehme 2014
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "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"
33
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"
43
44 #define BASEDIR "vfs_fruit_dir"
45 #define FNAME_CC_SRC "testfsctl.dat"
46 #define FNAME_CC_DST "testfsctl2.dat"
47
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)
56
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)
65
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);
72
73 static int qsort_string(char * const *s1, char * const *s2)
74 {
75         return strcmp(*s1, *s2);
76 }
77
78 static int qsort_stream(const struct stream_struct * s1, const struct stream_struct *s2)
79 {
80         return strcmp(s1->stream_name.s, s2->stream_name.s);
81 }
82
83 /*
84  * REVIEW:
85  * This is hokey, but what else can we do?
86  */
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
94
95 /*
96 The metadata xattr char buf below contains the following attributes:
97
98 -------------------------------------------------------------------------------
99 Entry ID   : 00000008 : File Dates Info
100 Offset     : 00000162 : 354
101 Length     : 00000010 : 16
102
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
108
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
111
112 -------------------------------------------------------------------------------
113 Entry ID   : 00000009 : Finder Info
114 Offset     : 0000007A : 122
115 Length     : 00000020 : 32
116
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     : ..
137
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
161
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 : ................
165
166 -------------------------------------------------------------------------------
167 Entry ID   : 0000000E : AFP File Info
168 Offset     : 00000172 : 370
169 Length     : 00000004 : 4
170
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                                     : ....
173  */
174
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
227 };
228
229 /*
230 The buf below contains the following AppleDouble encoded data:
231
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
237
238 -------------------------------------------------------------------------------
239 Entry ID   : 00000009 : Finder Info
240 Offset     : 00000032 : 50
241 Length     : 00000EB0 : 3760
242
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     : ..
263
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
287
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
325
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 : ................
345
346 -------------------------------------------------------------------------------
347 Entry ID   : 00000002 : Resource Fork
348 Offset     : 00000EE2 : 3810
349 Length     : 0000011E : 286
350
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       : ..............
370
371 It was created with:
372 $ hexdump -ve '"\t" 7/1 "0x%02x, " 1/1 " 0x%02x," "\n"'
373 */
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
887 };
888
889 /*
890  * The buf below contains the following AppleDouble encoded data:
891  *
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
897  *
898  * -------------------------------------------------------------------------------
899  * Entry ID   : 00000002 : Resource Fork
900  * Offset     : 00000052 : 82
901  * Length     : 0000011E : 286
902  *
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       : ..............
922  *
923  * Entry ID   : 00000009 : Finder Info
924  * Offset     : 00000032 : 50
925  * Length     : 00000020 : 32
926  *
927  * -NOTE------: cannot detect whether FInfo or DInfo. assume FInfo.
928  *
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     : ..
949  *
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
973  *
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 : ................
977  *  *
978  * It was created with:
979  * $ hexdump -ve '"\t" 7/1 "0x%02x, " 1/1 " 0x%02x," "\n"'
980  */
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
1028 };
1029
1030 /**
1031  * talloc and intialize an AfpInfo
1032  **/
1033 static AfpInfo *torture_afpinfo_new(TALLOC_CTX *mem_ctx)
1034 {
1035         AfpInfo *info;
1036
1037         info = talloc_zero(mem_ctx, AfpInfo);
1038         if (info == NULL) {
1039                 return NULL;
1040         }
1041
1042         info->afpi_Signature = AFP_Signature;
1043         info->afpi_Version = AFP_Version;
1044         info->afpi_BackupTime = AFP_BackupTime;
1045
1046         return info;
1047 }
1048
1049 /**
1050  * Pack AfpInfo into a talloced buffer
1051  **/
1052 static char *torture_afpinfo_pack(TALLOC_CTX *mem_ctx,
1053                                   AfpInfo *info)
1054 {
1055         char *buf;
1056
1057         buf = talloc_zero_array(mem_ctx, char, AFP_INFO_SIZE);
1058         if (buf == NULL) {
1059                 return NULL;
1060         }
1061
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));
1066
1067         return buf;
1068 }
1069
1070 /**
1071  * Unpack AfpInfo
1072  **/
1073 #if 0
1074 static void torture_afpinfo_unpack(AfpInfo *info, char *data)
1075 {
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));
1081 }
1082 #endif
1083
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)
1089 {
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;
1096
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;
1101         }
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;
1108
1109         status = smb2_create(tree, mem_ctx, &io);
1110         CHECK_STATUS(status, NT_STATUS_OK);
1111
1112         handle = io.out.file.handle;
1113
1114         infobuf = torture_afpinfo_pack(mem_ctx, info);
1115         if (infobuf == NULL) {
1116                 return false;
1117         }
1118
1119         status = smb2_util_write(tree, handle, infobuf, 0, AFP_INFO_SIZE);
1120         CHECK_STATUS(status, NT_STATUS_OK);
1121
1122         smb2_util_close(tree, handle);
1123
1124 done:
1125         return ret;
1126 }
1127
1128 /**
1129  * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1130  * compare against buffer 'value'
1131  **/
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)
1143 {
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;
1150
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;
1155         }
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;
1161
1162         torture_comment(tctx, "Open stream %s\n", full_name);
1163
1164         status = smb2_create(tree, mem_ctx, &create);
1165         if (!NT_STATUS_IS_OK(status)) {
1166                 TALLOC_FREE(full_name);
1167                 if (value == NULL) {
1168                         return true;
1169                 }
1170                 torture_comment(tctx, "Unable to open stream %s\n", full_name);
1171                 return false;
1172         }
1173
1174         handle = create.out.file.handle;
1175         if (value == NULL) {
1176                 TALLOC_FREE(full_name);
1177                 smb2_util_close(tree, handle);
1178                 return true;
1179         }
1180
1181         ZERO_STRUCT(r);
1182         r.in.file.handle = handle;
1183         r.in.length      = read_count;
1184         r.in.offset      = read_offset;
1185
1186         status = smb2_read(tree, tree, &r);
1187
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));
1192
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));
1196
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));
1201
1202 done:
1203         TALLOC_FREE(full_name);
1204         smb2_util_close(tree, handle);
1205         return ret;
1206 }
1207
1208 /**
1209  * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1210  * compare against buffer 'value'
1211  **/
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)
1220 {
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;
1227
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;
1232         }
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;
1238
1239         torture_comment(tctx, "Open stream %s\n", full_name);
1240
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;
1246         }
1247
1248         handle = create.out.file.handle;
1249
1250         ZERO_STRUCT(r);
1251         r.in.file.handle = handle;
1252         r.in.length      = read_count;
1253         r.in.offset      = read_offset;
1254
1255         status = smb2_read(tree, tree, &r);
1256         if (!NT_STATUS_IS_OK(status)) {
1257                 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
1258         }
1259
1260         smb2_util_close(tree, handle);
1261
1262 done:
1263         if (ret == false) {
1264                 return -1;
1265         }
1266         return r.out.data.length;
1267 }
1268
1269 /**
1270  * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1271  * compare against buffer 'value'
1272  **/
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)
1282 {
1283         struct smb2_handle handle;
1284         struct smb2_create create;
1285         NTSTATUS status;
1286         const char *full_name;
1287
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;
1292         }
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;
1298
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;
1308                 }
1309         }
1310
1311         handle = create.out.file.handle;
1312         if (value == NULL) {
1313                 return true;
1314         }
1315
1316         status = smb2_util_write(tree, handle, value, offset, size);
1317
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;
1322         }
1323
1324         smb2_util_close(tree, handle);
1325         return true;
1326 }
1327
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)
1334 {
1335         int ret = true;
1336         int result;
1337         const char *spath;
1338         char *path;
1339
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;
1344         }
1345
1346         path = talloc_asprintf(tctx, "%s/%s", spath, name);
1347
1348         result = setxattr(path, xattr, metadata, size, 0);
1349         if (result != 0) {
1350                 ret = false;
1351         }
1352
1353         TALLOC_FREE(path);
1354
1355         return ret;
1356 }
1357
1358 /**
1359  * Create a file or directory
1360  **/
1361 static bool torture_setup_file(TALLOC_CTX *mem_ctx, struct smb2_tree *tree,
1362                                const char *name, bool dir)
1363 {
1364         struct smb2_create io;
1365         NTSTATUS status;
1366
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;
1383         }
1384
1385         status = smb2_create(tree, mem_ctx, &io);
1386         if (!NT_STATUS_IS_OK(status)) {
1387                 return false;
1388         }
1389
1390         status = smb2_util_close(tree, io.out.file.handle);
1391         if (!NT_STATUS_IS_OK(status)) {
1392                 return false;
1393         }
1394
1395         return true;
1396 }
1397
1398 static bool enable_aapl(struct torture_context *tctx,
1399                         struct smb2_tree *tree)
1400 {
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);
1413
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 = "";
1422
1423         /*
1424          * Issuing an SMB2/CREATE with a suitably formed AAPL context,
1425          * controls behaviour of Apple's SMB2 extensions for the whole
1426          * session!
1427          */
1428
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));
1437
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");
1440
1441         status = smb2_create(tree, tctx, &io);
1442         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1443
1444         status = smb2_util_close(tree, io.out.file.handle);
1445         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close");
1446
1447         /*
1448          * Now check returned AAPL context
1449          */
1450         torture_comment(tctx, "Comparing returned AAPL capabilities\n");
1451
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");
1455
1456         if (!is_osx_server) {
1457                 size_t expected_aapl_ctx_size;
1458
1459                 expected_aapl_ctx_size = strlen("MacSamba") * 2 + 40;
1460
1461                 torture_assert_goto(
1462                         tctx, aapl->data.length == expected_aapl_ctx_size,
1463                         ret, done, "bad AAPL size");
1464         }
1465
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");
1469
1470 done:
1471         talloc_free(mem_ctx);
1472         return ret;
1473 }
1474
1475 static bool test_read_netatalk_metadata(struct torture_context *tctx,
1476                                         struct smb2_tree *tree)
1477 {
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;
1485
1486         torture_comment(tctx, "Checking metadata access\n");
1487
1488         localdir = torture_setting_string(tctx, "localdir", NULL);
1489         if (localdir == NULL) {
1490                 torture_skip(tctx, "Need localdir for test");
1491         }
1492
1493         smb2_util_unlink(tree, fname);
1494
1495         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1496         CHECK_STATUS(status, NT_STATUS_OK);
1497         smb2_util_close(tree, testdirh);
1498
1499         ret = torture_setup_file(mem_ctx, tree, fname, false);
1500         if (ret == false) {
1501                 goto done;
1502         }
1503
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;
1510         }
1511
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");
1515
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");
1519
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");
1523
1524         /* Check reading offset and read size > sizeof(AFPINFO_STREAM) */
1525
1526         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1527                           AFPINFO_STREAM, 0, 61);
1528         CHECK_VALUE(len, 60);
1529
1530         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1531                           AFPINFO_STREAM, 59, 2);
1532         CHECK_VALUE(len, 2);
1533
1534         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1535                           AFPINFO_STREAM, 60, 1);
1536         CHECK_VALUE(len, 1);
1537
1538         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1539                           AFPINFO_STREAM, 61, 1);
1540         CHECK_VALUE(len, 0);
1541
1542 done:
1543         smb2_deltree(tree, BASEDIR);
1544         talloc_free(mem_ctx);
1545         return ret;
1546 }
1547
1548 static bool test_read_afpinfo(struct torture_context *tctx,
1549                               struct smb2_tree *tree)
1550 {
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!";
1559
1560         torture_comment(tctx, "Checking metadata access\n");
1561
1562         smb2_util_unlink(tree, fname);
1563
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);
1567
1568         ret = torture_setup_file(mem_ctx, tree, fname, false);
1569         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
1570
1571         info = torture_afpinfo_new(mem_ctx);
1572         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
1573
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");
1577
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");
1581
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");
1585
1586         /*
1587          * OS X ignores offset <= 60 and treats the as
1588          * offset=0. Reading from offsets > 60 returns EOF=0.
1589          */
1590
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");
1594
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");
1598
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");
1602
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");
1606
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");
1610
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");
1614
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");
1618
1619 done:
1620         smb2_util_unlink(tree, fname);
1621         smb2_deltree(tree, BASEDIR);
1622         talloc_free(mem_ctx);
1623         return ret;
1624 }
1625
1626 static bool test_write_atalk_metadata(struct torture_context *tctx,
1627                                       struct smb2_tree *tree)
1628 {
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;
1636
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);
1641
1642         ret = torture_setup_file(mem_ctx, tree, fname, false);
1643         if (ret == false) {
1644                 goto done;
1645         }
1646
1647         info = torture_afpinfo_new(mem_ctx);
1648         if (info == NULL) {
1649                 goto done;
1650         }
1651
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);
1656
1657 done:
1658         smb2_util_unlink(tree, fname);
1659         smb2_deltree(tree, BASEDIR);
1660         talloc_free(mem_ctx);
1661         return ret;
1662 }
1663
1664 static bool test_write_atalk_rfork_io(struct torture_context *tctx,
1665                                       struct smb2_tree *tree)
1666 {
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;
1674
1675         union smb_open io;
1676         struct smb2_handle filehandle;
1677         union smb_fileinfo finfo;
1678         union smb_setfileinfo sinfo;
1679
1680         smb2_util_unlink(tree, fname);
1681
1682         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1683         CHECK_STATUS(status, NT_STATUS_OK);
1684         smb2_util_close(tree, testdirh);
1685
1686         ret = torture_setup_file(mem_ctx, tree, fname, false);
1687         if (ret == false) {
1688                 goto done;
1689         }
1690
1691         torture_comment(tctx, "(%s) writing to resource fork\n",
1692             __location__);
1693
1694         ret &= write_stream(tree, __location__, tctx, mem_ctx,
1695                             fname, AFPRESOURCE_STREAM_NAME,
1696                             10, 10, rfork_content);
1697
1698         ret &= check_stream(tree, __location__, tctx, mem_ctx,
1699                             fname, AFPRESOURCE_STREAM_NAME,
1700                             0, 20, 10, 10, rfork_content);
1701
1702         /* Check size after write */
1703
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;
1712
1713         torture_comment(tctx, "(%s) check resource fork size after write\n",
1714             __location__);
1715
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;
1728         }
1729         smb2_util_close(tree, filehandle);
1730
1731         /* Write at large offset */
1732
1733         torture_comment(tctx, "(%s) writing to resource fork at large offset\n",
1734                         __location__);
1735
1736         ret &= write_stream(tree, __location__, tctx, mem_ctx,
1737                             fname, AFPRESOURCE_STREAM_NAME,
1738                             (off_t)64*1024*1024, 10, rfork_content);
1739
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);
1743
1744         /* Truncate back to size of 1 byte */
1745
1746         torture_comment(tctx, "(%s) truncate resource fork and check size\n",
1747                         __location__);
1748
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;
1756
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);
1764
1765         smb2_util_close(tree, filehandle);
1766
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;
1776
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;
1789         }
1790         smb2_util_close(tree, filehandle);
1791
1792 done:
1793         smb2_util_unlink(tree, fname);
1794         smb2_deltree(tree, BASEDIR);
1795         talloc_free(mem_ctx);
1796         return ret;
1797 }
1798
1799 static bool test_rfork_truncate(struct torture_context *tctx,
1800                                 struct smb2_tree *tree)
1801 {
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;
1812
1813         smb2_util_unlink(tree, fname);
1814
1815         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1816         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1817         smb2_util_close(tree, testdirh);
1818
1819         ret = torture_setup_file(mem_ctx, tree, fname, false);
1820         if (ret == false) {
1821                 goto done;
1822         }
1823
1824         ret &= write_stream(tree, __location__, tctx, mem_ctx,
1825                             fname, AFPRESOURCE_STREAM,
1826                             10, 10, rfork_content);
1827
1828         /* Truncate back to size 0, further access MUST return ENOENT */
1829
1830         torture_comment(tctx, "(%s) truncate resource fork to size 0\n",
1831                         __location__);
1832
1833         ZERO_STRUCT(create);
1834         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1835         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1836         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1837         create.in.fname               = fname;
1838         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1839                 NTCREATEX_SHARE_ACCESS_READ |
1840                 NTCREATEX_SHARE_ACCESS_WRITE;
1841         status = smb2_create(tree, mem_ctx, &create);
1842         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1843         fh1 = create.out.file.handle;
1844
1845         ZERO_STRUCT(create);
1846         create.in.create_disposition  = NTCREATEX_DISP_OPEN_IF;
1847         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1848         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1849         create.in.fname               = rfork;
1850         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1851                 NTCREATEX_SHARE_ACCESS_READ |
1852                 NTCREATEX_SHARE_ACCESS_WRITE;
1853         status = smb2_create(tree, mem_ctx, &create);
1854         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1855         fh2 = create.out.file.handle;
1856
1857         ZERO_STRUCT(sinfo);
1858         sinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1859         sinfo.end_of_file_info.in.file.handle = fh2;
1860         sinfo.end_of_file_info.in.size = 0;
1861         status = smb2_setinfo_file(tree, &sinfo);
1862         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file");
1863
1864         /*
1865          * Now check size, we should get OBJECT_NAME_NOT_FOUND (!)
1866          */
1867         ZERO_STRUCT(create);
1868         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1869         create.in.desired_access      = SEC_FILE_ALL;
1870         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1871         create.in.fname               = rfork;
1872         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1873                 NTCREATEX_SHARE_ACCESS_READ |
1874                 NTCREATEX_SHARE_ACCESS_WRITE;
1875         status = smb2_create(tree, mem_ctx, &create);
1876         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1877
1878         /*
1879          * Do another open on the rfork and write to the new handle. A
1880          * naive server might unlink the AppleDouble resource fork
1881          * file when its truncated to 0 bytes above, so in case both
1882          * open handles share the same underlying fd, the unlink would
1883          * cause the below write to be lost.
1884          */
1885         ZERO_STRUCT(create);
1886         create.in.create_disposition  = NTCREATEX_DISP_OPEN_IF;
1887         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1888         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1889         create.in.fname               = rfork;
1890         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1891                 NTCREATEX_SHARE_ACCESS_READ |
1892                 NTCREATEX_SHARE_ACCESS_WRITE;
1893         status = smb2_create(tree, mem_ctx, &create);
1894         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1895         fh3 = create.out.file.handle;
1896
1897         status = smb2_util_write(tree, fh3, "foo", 0, 3);
1898         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write");
1899
1900         smb2_util_close(tree, fh3);
1901         smb2_util_close(tree, fh2);
1902         smb2_util_close(tree, fh1);
1903
1904         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM,
1905                            0, 3, 0, 3, "foo");
1906         torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
1907
1908 done:
1909         smb2_util_unlink(tree, fname);
1910         smb2_deltree(tree, BASEDIR);
1911         talloc_free(mem_ctx);
1912         return ret;
1913 }
1914
1915 static bool test_rfork_create(struct torture_context *tctx,
1916                               struct smb2_tree *tree)
1917 {
1918         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1919         const char *fname = BASEDIR "\\torture_rfork_create";
1920         const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
1921         NTSTATUS status;
1922         struct smb2_handle testdirh;
1923         bool ret = true;
1924         struct smb2_create create;
1925         struct smb2_handle fh1;
1926         const char *streams[] = {
1927                 "::$DATA"
1928         };
1929         union smb_fileinfo finfo;
1930
1931         smb2_util_unlink(tree, fname);
1932
1933         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1934         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1935         smb2_util_close(tree, testdirh);
1936
1937         ret = torture_setup_file(mem_ctx, tree, fname, false);
1938         if (ret == false) {
1939                 goto done;
1940         }
1941
1942         torture_comment(tctx, "(%s) open rfork, should return ENOENT\n",
1943                         __location__);
1944
1945         ZERO_STRUCT(create);
1946         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1947         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1948         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1949         create.in.fname               = rfork;
1950         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1951                 NTCREATEX_SHARE_ACCESS_READ |
1952                 NTCREATEX_SHARE_ACCESS_WRITE;
1953         status = smb2_create(tree, mem_ctx, &create);
1954         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1955
1956         torture_comment(tctx, "(%s) create resource fork\n", __location__);
1957
1958         ZERO_STRUCT(create);
1959         create.in.create_disposition  = NTCREATEX_DISP_OPEN_IF;
1960         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1961         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1962         create.in.fname               = rfork;
1963         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1964                 NTCREATEX_SHARE_ACCESS_READ |
1965                 NTCREATEX_SHARE_ACCESS_WRITE;
1966         status = smb2_create(tree, mem_ctx, &create);
1967         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1968         fh1 = create.out.file.handle;
1969
1970         torture_comment(tctx, "(%s) getinfo on create handle\n",
1971                         __location__);
1972
1973         ZERO_STRUCT(finfo);
1974         finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1975         finfo.generic.in.file.handle = fh1;
1976         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1977         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file");
1978         if (finfo.all_info.out.size != 0) {
1979                 torture_result(tctx, TORTURE_FAIL,
1980                                "(%s) Incorrect resource fork size\n",
1981                                __location__);
1982                 ret = false;
1983                 smb2_util_close(tree, fh1);
1984                 goto done;
1985         }
1986
1987         torture_comment(tctx, "(%s) open rfork, should still return ENOENT\n",
1988                         __location__);
1989
1990         ZERO_STRUCT(create);
1991         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1992         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1993         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1994         create.in.fname               = rfork;
1995         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1996                 NTCREATEX_SHARE_ACCESS_READ |
1997                 NTCREATEX_SHARE_ACCESS_WRITE;
1998         status = smb2_create(tree, mem_ctx, &create);
1999         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
2000
2001         ret = check_stream_list(tree, tctx, fname, 1, streams, false);
2002         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2003
2004         torture_comment(tctx, "(%s) close empty created rfork, open should return ENOENT\n",
2005                         __location__);
2006
2007         ZERO_STRUCT(create);
2008         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
2009         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
2010         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
2011         create.in.fname               = rfork;
2012         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
2013                 NTCREATEX_SHARE_ACCESS_READ |
2014                 NTCREATEX_SHARE_ACCESS_WRITE;
2015         status = smb2_create(tree, mem_ctx, &create);
2016         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
2017
2018 done:
2019         smb2_util_unlink(tree, fname);
2020         smb2_deltree(tree, BASEDIR);
2021         talloc_free(mem_ctx);
2022         return ret;
2023 }
2024
2025 static bool test_rfork_create_ro(struct torture_context *tctx,
2026                                  struct smb2_tree *tree)
2027 {
2028         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2029         const char *fname = BASEDIR "\\torture_rfork_create";
2030         const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
2031         NTSTATUS status;
2032         struct smb2_handle testdirh;
2033         bool ret = true;
2034         struct smb2_create create;
2035
2036         smb2_util_unlink(tree, fname);
2037         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2038         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2039                 "torture_smb2_testdir\n");
2040         smb2_util_close(tree, testdirh);
2041
2042         ret = torture_setup_file(mem_ctx, tree, fname, false);
2043         if (ret == false) {
2044                 goto done;
2045         }
2046
2047         torture_comment(tctx, "(%s) Try opening read-only with "
2048                         "open_if create disposition, should return ENOENT\n",
2049                         __location__);
2050
2051         ZERO_STRUCT(create);
2052         create.in.fname = rfork;
2053         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2054         create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
2055         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2056         create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
2057         status = smb2_create(tree, mem_ctx, &(create));
2058         torture_assert_ntstatus_equal_goto(tctx, status,
2059                                         NT_STATUS_OBJECT_NAME_NOT_FOUND,
2060                                         ret, done, "smb2_create failed\n");
2061
2062         torture_comment(tctx, "(%s) Now write something to the "
2063                         "rsrc stream, then the same open should succeed\n",
2064                         __location__);
2065
2066         ret = write_stream(tree, __location__, tctx, mem_ctx,
2067                            fname, AFPRESOURCE_STREAM_NAME,
2068                            0, 3, "foo");
2069         torture_assert_goto(tctx, ret == true, ret, done,
2070                         "write_stream failed\n");
2071
2072         ret = check_stream(tree, __location__, tctx, mem_ctx,
2073                            fname, AFPRESOURCE_STREAM,
2074                            0, 3, 0, 3, "foo");
2075         torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
2076
2077         ZERO_STRUCT(create);
2078         create.in.fname = rfork;
2079         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2080         create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
2081         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2082         create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
2083         status = smb2_create(tree, mem_ctx, &(create));
2084         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2085                 "smb2_create failed\n");
2086
2087         smb2_util_close(tree, create.out.file.handle);
2088
2089 done:
2090         smb2_util_unlink(tree, fname);
2091         smb2_deltree(tree, BASEDIR);
2092         talloc_free(mem_ctx);
2093         return ret;
2094 }
2095
2096 static bool test_adouble_conversion(struct torture_context *tctx,
2097                                     struct smb2_tree *tree)
2098 {
2099         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2100         const char *fname = BASEDIR "\\test_adouble_conversion";
2101         const char *adname = BASEDIR "/._test_adouble_conversion";
2102         NTSTATUS status;
2103         struct smb2_handle testdirh;
2104         bool ret = true;
2105         const char *data = "This resource fork intentionally left blank";
2106         size_t datalen = strlen(data);
2107         const char *streams[] = {
2108                 "::$DATA",
2109                 AFPINFO_STREAM,
2110                 AFPRESOURCE_STREAM,
2111                 ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
2112                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2113         };
2114         bool is_osx = torture_setting_bool(tctx, "osx", false);
2115
2116         if (is_osx) {
2117                 torture_skip(tctx, "Test only works with Samba\n");
2118         }
2119
2120         smb2_deltree(tree, BASEDIR);
2121
2122         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2123         CHECK_STATUS(status, NT_STATUS_OK);
2124         smb2_util_close(tree, testdirh);
2125
2126         ret = torture_setup_file(tctx, tree, fname, false);
2127         torture_assert_goto(tctx, ret == true, ret, done,
2128                             "torture_setup_file failed\n");
2129
2130         ret = torture_setup_file(tctx, tree, adname, false);
2131         torture_assert_goto(tctx, ret == true, ret, done,
2132                             "torture_setup_file failed\n");
2133
2134         ret = write_stream(tree, __location__, tctx, mem_ctx,
2135                            adname, NULL,
2136                            0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr);
2137         torture_assert_goto(tctx, ret == true, ret, done,
2138                             "write_stream failed\n");
2139
2140         torture_comment(tctx, "(%s) test OS X AppleDouble conversion\n",
2141             __location__);
2142
2143         ret = check_stream(tree, __location__, tctx, mem_ctx,
2144                            fname, AFPRESOURCE_STREAM,
2145                            16, datalen, 0, datalen, data);
2146         torture_assert_goto(tctx, ret == true, ret, done,
2147                             "check AFPRESOURCE_STREAM failed\n");
2148
2149         ret = check_stream(tree, __location__, tctx, mem_ctx,
2150                            fname, AFPINFO_STREAM,
2151                            0, 60, 16, 8, "TESTSLOW");
2152         torture_assert_goto(tctx, ret == true, ret, done,
2153                             "check AFPINFO_STREAM failed\n");
2154
2155         ret = check_stream(tree, __location__, tctx, mem_ctx, fname,
2156                            ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2157                            0, 3, 0, 3, "baz");
2158         torture_assert_goto(tctx, ret == true, ret, done,
2159                             "check foo:bar stream failed\n");
2160
2161         ret = check_stream_list(tree, tctx, fname, 5, streams, false);
2162         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2163
2164 done:
2165         smb2_deltree(tree, BASEDIR);
2166         talloc_free(mem_ctx);
2167         return ret;
2168 }
2169
2170 /*
2171  * Test conversion of AppleDouble file without embedded xattr data
2172  */
2173 static bool test_adouble_conversion_wo_xattr(struct torture_context *tctx,
2174                                              struct smb2_tree *tree)
2175 {
2176         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2177         const char *fname = BASEDIR "\\test_adouble_conversion";
2178         const char *adname = BASEDIR "/._test_adouble_conversion";
2179         NTSTATUS status;
2180         struct smb2_handle testdirh;
2181         bool ret = true;
2182         const char *streams[] = {
2183                 "::$DATA",
2184                 AFPINFO_STREAM,
2185                 AFPRESOURCE_STREAM
2186         };
2187         struct smb2_create create;
2188         struct smb2_find find;
2189         unsigned int count;
2190         union smb_search_data *d;
2191         const char *data = "This resource fork intentionally left blank";
2192         size_t datalen = strlen(data);
2193         bool is_osx = torture_setting_bool(tctx, "osx", false);
2194
2195         if (is_osx) {
2196                 torture_skip(tctx, "Test only works with Samba\n");
2197         }
2198
2199         smb2_deltree(tree, BASEDIR);
2200
2201         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2202         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2203                                         "torture_smb2_testdir failed\n");
2204         smb2_util_close(tree, testdirh);
2205
2206         ret = torture_setup_file(tctx, tree, fname, false);
2207         torture_assert_goto(tctx, ret == true, ret, done,
2208                             "torture_setup_file failed\n");
2209
2210         ret = torture_setup_file(tctx, tree, adname, false);
2211         torture_assert_goto(tctx, ret == true, ret, done,
2212                             "torture_setup_file failed\n");
2213
2214         ret = write_stream(tree, __location__, tctx, mem_ctx,
2215                            adname, NULL, 0,
2216                            sizeof(osx_adouble_without_xattr),
2217                            osx_adouble_without_xattr);
2218         torture_assert_goto(tctx, ret == true, ret, done,
2219                             "write_stream failed\n");
2220
2221         ret = enable_aapl(tctx, tree);
2222         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
2223
2224         /*
2225          * Issue a smb2_find(), this triggers the server-side conversion
2226          */
2227
2228         create = (struct smb2_create) {
2229                 .in.desired_access = SEC_RIGHTS_DIR_READ,
2230                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
2231                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
2232                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
2233                 .in.create_disposition = NTCREATEX_DISP_OPEN,
2234                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
2235                 .in.fname = BASEDIR,
2236         };
2237
2238         status = smb2_create(tree, tctx, &create);
2239         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2240                                         "smb2_create failed\n");
2241
2242         find = (struct smb2_find) {
2243                 .in.file.handle = create.out.file.handle,
2244                 .in.pattern = "*",
2245                 .in.max_response_size = 0x1000,
2246                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
2247         };
2248
2249         status = smb2_find_level(tree, tree, &find, &count, &d);
2250         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2251                                         "smb2_find_level failed\n");
2252
2253         status = smb2_util_close(tree, create.out.file.handle);
2254         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2255                                         "smb2_util_close failed");
2256
2257         /*
2258          * Check number of streams
2259          */
2260
2261         ret = check_stream_list(tree, tctx, fname, 3, streams, false);
2262         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2263
2264
2265         /*
2266          * Check Resourcefork data can be read.
2267          */
2268
2269         ret = check_stream(tree, __location__, tctx, mem_ctx,
2270                            fname, AFPRESOURCE_STREAM,
2271                            16, datalen, 0, datalen, data);
2272         torture_assert_goto(tctx, ret == true, ret, done,
2273                             "check AFPRESOURCE_STREAM failed\n");
2274
2275         /*
2276          * Check FinderInfo data has been migrated to stream.
2277          */
2278
2279         ret = check_stream(tree, __location__, tctx, mem_ctx,
2280                            fname, AFPINFO_STREAM,
2281                            0, 60, 16, 8, "WAVEPTul");
2282         torture_assert_goto(tctx, ret == true, ret, done,
2283                             "check AFPINFO_STREAM failed\n");
2284
2285 done:
2286         smb2_deltree(tree, BASEDIR);
2287         talloc_free(mem_ctx);
2288         return ret;
2289 }
2290
2291 static bool test_aapl(struct torture_context *tctx,
2292                       struct smb2_tree *tree)
2293 {
2294         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2295         const char *fname = BASEDIR "\\test_aapl";
2296         NTSTATUS status;
2297         struct smb2_handle testdirh;
2298         bool ret = true;
2299         struct smb2_create io;
2300         DATA_BLOB data;
2301         struct smb2_create_blob *aapl = NULL;
2302         AfpInfo *info;
2303         const char *type_creator = "SMB,OLE!";
2304         char type_creator_buf[9];
2305         uint32_t aapl_cmd;
2306         uint32_t aapl_reply_bitmap;
2307         uint32_t aapl_server_caps;
2308         uint32_t aapl_vol_caps;
2309         uint32_t expected_vol_caps = 0;
2310         char *model;
2311         struct smb2_find f;
2312         unsigned int count;
2313         union smb_search_data *d;
2314         uint64_t rfork_len;
2315         bool is_osx_server = torture_setting_bool(tctx, "osx", false);
2316
2317         smb2_deltree(tree, BASEDIR);
2318
2319         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2320         CHECK_STATUS(status, NT_STATUS_OK);
2321         smb2_util_close(tree, testdirh);
2322
2323         ZERO_STRUCT(io);
2324         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
2325         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
2326         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2327         io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2328                               NTCREATEX_SHARE_ACCESS_READ |
2329                               NTCREATEX_SHARE_ACCESS_WRITE);
2330         io.in.fname = fname;
2331
2332         /*
2333          * Issuing an SMB2/CREATE with a suitably formed AAPL context,
2334          * controls behaviour of Apple's SMB2 extensions for the whole
2335          * session!
2336          */
2337
2338         data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2339         SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2340         SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2341                              SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2342                              SMB2_CRTCTX_AAPL_MODEL_INFO));
2343         SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2344                               SMB2_CRTCTX_AAPL_UNIX_BASED |
2345                               SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
2346
2347         torture_comment(tctx, "Testing SMB2 create context AAPL\n");
2348         status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2349         CHECK_STATUS(status, NT_STATUS_OK);
2350
2351         status = smb2_create(tree, tctx, &io);
2352         CHECK_STATUS(status, NT_STATUS_OK);
2353         status = smb2_util_close(tree, io.out.file.handle);
2354         CHECK_STATUS(status, NT_STATUS_OK);
2355
2356         /*
2357          * Now check returned AAPL context
2358          */
2359         torture_comment(tctx, "Comparing returned AAPL capabilities\n");
2360
2361         aapl = smb2_create_blob_find(&io.out.blobs,
2362                                      SMB2_CREATE_TAG_AAPL);
2363
2364         if (aapl == NULL) {
2365                 torture_result(tctx, TORTURE_FAIL,
2366                                "(%s) unexpectedly no AAPL capabilities were returned.",
2367                                __location__);
2368                 ret = false;
2369                 goto done;
2370         }
2371
2372         if (!is_osx_server) {
2373                 size_t expected_aapl_ctx_size;
2374                 bool size_ok;
2375
2376                 /*
2377                  * uint32_t CommandCode = kAAPL_SERVER_QUERY
2378                  * uint32_t Reserved = 0;
2379                  * uint64_t ReplyBitmap = kAAPL_SERVER_CAPS |
2380                  *                        kAAPL_VOLUME_CAPS |
2381                  *                        kAAPL_MODEL_INFO;
2382                  * uint64_t ServerCaps = kAAPL_SUPPORTS_READDIR_ATTR |
2383                  *                       kAAPL_SUPPORTS_OSX_COPYFILE;
2384                  * uint64_t VolumeCaps = kAAPL_SUPPORT_RESOLVE_ID |
2385                  *                       kAAPL_CASE_SENSITIVE;
2386                  * uint32_t Pad2 = 0;
2387                  * uint32_t ModelStringLen = 10;
2388                  * ucs2_t ModelString[5] = "MacSamba";
2389                  */
2390                 expected_aapl_ctx_size = strlen("MacSamba") * 2 + 40;
2391
2392                 size_ok = aapl->data.length == expected_aapl_ctx_size;
2393                 torture_assert_goto(tctx, size_ok, ret, done, "bad AAPL size");
2394         }
2395
2396         aapl_cmd = IVAL(aapl->data.data, 0);
2397         if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2398                 torture_result(tctx, TORTURE_FAIL,
2399                                "(%s) unexpected cmd: %d",
2400                                __location__, (int)aapl_cmd);
2401                 ret = false;
2402                 goto done;
2403         }
2404
2405         aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2406         if (aapl_reply_bitmap != (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2407                                   SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2408                                   SMB2_CRTCTX_AAPL_MODEL_INFO)) {
2409                 torture_result(tctx, TORTURE_FAIL,
2410                                "(%s) unexpected reply_bitmap: %d",
2411                                __location__, (int)aapl_reply_bitmap);
2412                 ret = false;
2413                 goto done;
2414         }
2415
2416         aapl_server_caps = BVAL(aapl->data.data, 16);
2417         if (aapl_server_caps != (SMB2_CRTCTX_AAPL_UNIX_BASED |
2418                                  SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2419                                  SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
2420                                  SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE)) {
2421                 torture_result(tctx, TORTURE_FAIL,
2422                                "(%s) unexpected server_caps: %d",
2423                                __location__, (int)aapl_server_caps);
2424                 ret = false;
2425                 goto done;
2426         }
2427
2428         if (is_osx_server) {
2429                 expected_vol_caps = 5;
2430         }
2431         aapl_vol_caps = BVAL(aapl->data.data, 24);
2432         if (aapl_vol_caps != expected_vol_caps) {
2433                 /* this will fail on a case insensitive fs ... */
2434                 torture_result(tctx, TORTURE_FAIL,
2435                                 "(%s) unexpected vol_caps: %d",
2436                                 __location__, (int)aapl_vol_caps);
2437         }
2438
2439         ret = convert_string_talloc(mem_ctx,
2440                                     CH_UTF16LE, CH_UNIX,
2441                                     aapl->data.data + 40, 10,
2442                                     &model, NULL);
2443         if (ret == false) {
2444                 torture_result(tctx, TORTURE_FAIL,
2445                                "(%s) convert_string_talloc() failed",
2446                                __location__);
2447                 goto done;
2448         }
2449         torture_comment(tctx, "Got server model: \"%s\"\n", model);
2450
2451         /*
2452          * Now that Requested AAPL extensions are enabled, setup some
2453          * Mac files with metadata and resource fork
2454          */
2455         ret = torture_setup_file(mem_ctx, tree, fname, false);
2456         if (ret == false) {
2457                 torture_result(tctx, TORTURE_FAIL,
2458                                "(%s) torture_setup_file() failed",
2459                                __location__);
2460                 goto done;
2461         }
2462
2463         info = torture_afpinfo_new(mem_ctx);
2464         if (info == NULL) {
2465                 torture_result(tctx, TORTURE_FAIL,
2466                                "(%s) torture_afpinfo_new() failed",
2467                                __location__);
2468                 ret = false;
2469                 goto done;
2470         }
2471
2472         memcpy(info->afpi_FinderInfo, type_creator, 8);
2473         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
2474         if (ret == false) {
2475                 torture_result(tctx, TORTURE_FAIL,
2476                                "(%s) torture_write_afpinfo() failed",
2477                                __location__);
2478                 goto done;
2479         }
2480
2481         ret = write_stream(tree, __location__, tctx, mem_ctx,
2482                            fname, AFPRESOURCE_STREAM_NAME,
2483                            0, 3, "foo");
2484         if (ret == false) {
2485                 torture_result(tctx, TORTURE_FAIL,
2486                                "(%s) write_stream() failed",
2487                                __location__);
2488                 goto done;
2489         }
2490
2491         /*
2492          * Ok, file is prepared, now call smb2/find
2493          */
2494
2495         ZERO_STRUCT(io);
2496         io.in.desired_access = SEC_RIGHTS_DIR_READ;
2497         io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2498         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2499         io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
2500                               NTCREATEX_SHARE_ACCESS_WRITE |
2501                               NTCREATEX_SHARE_ACCESS_DELETE);
2502         io.in.create_disposition = NTCREATEX_DISP_OPEN;
2503         io.in.fname = BASEDIR;
2504         status = smb2_create(tree, tctx, &io);
2505         CHECK_STATUS(status, NT_STATUS_OK);
2506
2507         ZERO_STRUCT(f);
2508         f.in.file.handle        = io.out.file.handle;
2509         f.in.pattern            = "test_aapl";
2510         f.in.continue_flags     = SMB2_CONTINUE_FLAG_SINGLE;
2511         f.in.max_response_size  = 0x1000;
2512         f.in.level              = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
2513
2514         status = smb2_find_level(tree, tree, &f, &count, &d);
2515         CHECK_STATUS(status, NT_STATUS_OK);
2516
2517         status = smb2_util_close(tree, io.out.file.handle);
2518         CHECK_STATUS(status, NT_STATUS_OK);
2519
2520         if (strcmp(d[0].id_both_directory_info.name.s, "test_aapl") != 0) {
2521                 torture_result(tctx, TORTURE_FAIL,
2522                                "(%s) write_stream() failed",
2523                                __location__);
2524                 ret = false;
2525                 goto done;
2526         }
2527
2528         if (d[0].id_both_directory_info.short_name.private_length != 24) {
2529                 torture_result(tctx, TORTURE_FAIL,
2530                                "(%s) bad short_name length %" PRIu32 ", expected 24",
2531                                __location__, d[0].id_both_directory_info.short_name.private_length);
2532                 ret = false;
2533                 goto done;
2534         }
2535
2536         torture_comment(tctx, "short_name buffer:\n");
2537         dump_data(0, d[0].id_both_directory_info.short_name_buf, 24);
2538
2539         /*
2540          * Extract data as specified by the AAPL extension:
2541          * - ea_size contains max_access
2542          * - short_name contains resource fork length + FinderInfo
2543          * - reserved2 contains the unix mode
2544          */
2545         torture_comment(tctx, "mac_access: %" PRIx32 "\n",
2546                         d[0].id_both_directory_info.ea_size);
2547
2548         rfork_len = BVAL(d[0].id_both_directory_info.short_name_buf, 0);
2549         if (rfork_len != 3) {
2550                 torture_result(tctx, TORTURE_FAIL,
2551                                "(%s) expected resource fork length 3, got: %" PRIu64,
2552                                __location__, rfork_len);
2553                 ret = false;
2554                 goto done;
2555         }
2556
2557         memcpy(type_creator_buf, d[0].id_both_directory_info.short_name_buf + 8, 8);
2558         type_creator_buf[8] = 0;
2559         if (strcmp(type_creator, type_creator_buf) != 0) {
2560                 torture_result(tctx, TORTURE_FAIL,
2561                                "(%s) expected type/creator \"%s\" , got: %s",
2562                                __location__, type_creator, type_creator_buf);
2563                 ret = false;
2564                 goto done;
2565         }
2566
2567 done:
2568         smb2_util_unlink(tree, fname);
2569         smb2_deltree(tree, BASEDIR);
2570         talloc_free(mem_ctx);
2571         return ret;
2572 }
2573
2574 static uint64_t patt_hash(uint64_t off)
2575 {
2576         return off;
2577 }
2578
2579 static bool write_pattern(struct torture_context *torture,
2580                           struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2581                           struct smb2_handle h, uint64_t off, uint64_t len,
2582                           uint64_t patt_off)
2583 {
2584         NTSTATUS status;
2585         uint64_t i;
2586         uint8_t *buf;
2587         uint64_t io_sz = MIN(1024 * 64, len);
2588
2589         if (len == 0) {
2590                 return true;
2591         }
2592
2593         torture_assert(torture, (len % 8) == 0, "invalid write len");
2594
2595         buf = talloc_zero_size(mem_ctx, io_sz);
2596         torture_assert(torture, (buf != NULL), "no memory for file data buf");
2597
2598         while (len > 0) {
2599                 for (i = 0; i <= io_sz - 8; i += 8) {
2600                         SBVAL(buf, i, patt_hash(patt_off));
2601                         patt_off += 8;
2602                 }
2603
2604                 status = smb2_util_write(tree, h,
2605                                          buf, off, io_sz);
2606                 torture_assert_ntstatus_ok(torture, status, "file write");
2607
2608                 len -= io_sz;
2609                 off += io_sz;
2610         }
2611
2612         talloc_free(buf);
2613
2614         return true;
2615 }
2616
2617 static bool check_pattern(struct torture_context *torture,
2618                           struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2619                           struct smb2_handle h, uint64_t off, uint64_t len,
2620                           uint64_t patt_off)
2621 {
2622         if (len == 0) {
2623                 return true;
2624         }
2625
2626         torture_assert(torture, (len % 8) == 0, "invalid read len");
2627
2628         while (len > 0) {
2629                 uint64_t i;
2630                 struct smb2_read r;
2631                 NTSTATUS status;
2632                 uint64_t io_sz = MIN(1024 * 64, len);
2633
2634                 ZERO_STRUCT(r);
2635                 r.in.file.handle = h;
2636                 r.in.length      = io_sz;
2637                 r.in.offset      = off;
2638                 status = smb2_read(tree, mem_ctx, &r);
2639                 torture_assert_ntstatus_ok(torture, status, "read");
2640
2641                 torture_assert_u64_equal(torture, r.out.data.length, io_sz,
2642                                          "read data len mismatch");
2643
2644                 for (i = 0; i <= io_sz - 8; i += 8, patt_off += 8) {
2645                         uint64_t data = BVAL(r.out.data.data, i);
2646                         torture_assert_u64_equal(torture, data, patt_hash(patt_off),
2647                                                  talloc_asprintf(torture, "read data "
2648                                                                  "pattern bad at %llu\n",
2649                                                                  (unsigned long long)off + i));
2650                 }
2651                 talloc_free(r.out.data.data);
2652                 len -= io_sz;
2653                 off += io_sz;
2654         }
2655
2656         return true;
2657 }
2658
2659 static bool test_setup_open(struct torture_context *torture,
2660                             struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2661                             const char *fname,
2662                             struct smb2_handle *fh,
2663                             uint32_t desired_access,
2664                             uint32_t file_attributes)
2665 {
2666         struct smb2_create io;
2667         NTSTATUS status;
2668
2669         ZERO_STRUCT(io);
2670         io.in.desired_access = desired_access;
2671         io.in.file_attributes = file_attributes;
2672         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2673         io.in.share_access =
2674                 NTCREATEX_SHARE_ACCESS_DELETE|
2675                 NTCREATEX_SHARE_ACCESS_READ|
2676                 NTCREATEX_SHARE_ACCESS_WRITE;
2677         if (file_attributes & FILE_ATTRIBUTE_DIRECTORY) {
2678                 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2679         }
2680         io.in.fname = fname;
2681
2682         status = smb2_create(tree, mem_ctx, &io);
2683         torture_assert_ntstatus_ok(torture, status, "file create");
2684
2685         *fh = io.out.file.handle;
2686
2687         return true;
2688 }
2689
2690 static bool test_setup_create_fill(struct torture_context *torture,
2691                                    struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2692                                    const char *fname,
2693                                    struct smb2_handle *fh,
2694                                    uint64_t size,
2695                                    uint32_t desired_access,
2696                                    uint32_t file_attributes)
2697 {
2698         bool ok;
2699
2700         ok = test_setup_open(torture, tree, mem_ctx,
2701                              fname,
2702                              fh,
2703                              desired_access,
2704                              file_attributes);
2705         torture_assert(torture, ok, "file open");
2706
2707         if (size > 0) {
2708                 ok = write_pattern(torture, tree, mem_ctx, *fh, 0, size, 0);
2709                 torture_assert(torture, ok, "write pattern");
2710         }
2711         return true;
2712 }
2713
2714 static bool test_setup_copy_chunk(struct torture_context *torture,
2715                                   struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2716                                   uint32_t nchunks,
2717                                   const char *src_name,
2718                                   struct smb2_handle *src_h,
2719                                   uint64_t src_size,
2720                                   uint32_t src_desired_access,
2721                                   const char *dst_name,
2722                                   struct smb2_handle *dest_h,
2723                                   uint64_t dest_size,
2724                                   uint32_t dest_desired_access,
2725                                   struct srv_copychunk_copy *cc_copy,
2726                                   union smb_ioctl *io)
2727 {
2728         struct req_resume_key_rsp res_key;
2729         bool ok;
2730         NTSTATUS status;
2731         enum ndr_err_code ndr_ret;
2732
2733         ok = test_setup_create_fill(torture, tree, mem_ctx, src_name,
2734                                     src_h, src_size, src_desired_access,
2735                                     FILE_ATTRIBUTE_NORMAL);
2736         torture_assert(torture, ok, "src file create fill");
2737
2738         ok = test_setup_create_fill(torture, tree, mem_ctx, dst_name,
2739                                     dest_h, dest_size, dest_desired_access,
2740                                     FILE_ATTRIBUTE_NORMAL);
2741         torture_assert(torture, ok, "dest file create fill");
2742
2743         ZERO_STRUCTPN(io);
2744         io->smb2.level = RAW_IOCTL_SMB2;
2745         io->smb2.in.file.handle = *src_h;
2746         io->smb2.in.function = FSCTL_SRV_REQUEST_RESUME_KEY;
2747         /* Allow for Key + ContextLength + Context */
2748         io->smb2.in.max_response_size = 32;
2749         io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2750
2751         status = smb2_ioctl(tree, mem_ctx, &io->smb2);
2752         torture_assert_ntstatus_ok(torture, status,
2753                                    "FSCTL_SRV_REQUEST_RESUME_KEY");
2754
2755         ndr_ret = ndr_pull_struct_blob(&io->smb2.out.out, mem_ctx, &res_key,
2756                         (ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
2757
2758         torture_assert_ndr_success(torture, ndr_ret,
2759                                    "ndr_pull_req_resume_key_rsp");
2760
2761         ZERO_STRUCTPN(io);
2762         io->smb2.level = RAW_IOCTL_SMB2;
2763         io->smb2.in.file.handle = *dest_h;
2764         io->smb2.in.function = FSCTL_SRV_COPYCHUNK;
2765         io->smb2.in.max_response_size = sizeof(struct srv_copychunk_rsp);
2766         io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2767
2768         ZERO_STRUCTPN(cc_copy);
2769         memcpy(cc_copy->source_key, res_key.resume_key, ARRAY_SIZE(cc_copy->source_key));
2770         cc_copy->chunk_count = nchunks;
2771         cc_copy->chunks = talloc_zero_array(mem_ctx, struct srv_copychunk, nchunks);
2772         torture_assert(torture, (cc_copy->chunks != NULL), "no memory for chunks");
2773
2774         return true;
2775 }
2776
2777
2778 static bool check_copy_chunk_rsp(struct torture_context *torture,
2779                                  struct srv_copychunk_rsp *cc_rsp,
2780                                  uint32_t ex_chunks_written,
2781                                  uint32_t ex_chunk_bytes_written,
2782                                  uint32_t ex_total_bytes_written)
2783 {
2784         torture_assert_int_equal(torture, cc_rsp->chunks_written,
2785                                  ex_chunks_written, "num chunks");
2786         torture_assert_int_equal(torture, cc_rsp->chunk_bytes_written,
2787                                  ex_chunk_bytes_written, "chunk bytes written");
2788         torture_assert_int_equal(torture, cc_rsp->total_bytes_written,
2789                                  ex_total_bytes_written, "chunk total bytes");
2790         return true;
2791 }
2792
2793 static bool neg_aapl_copyfile(struct torture_context *tctx,
2794                               struct smb2_tree *tree,
2795                               uint64_t flags)
2796 {
2797         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2798         const char *fname = "aapl";
2799         NTSTATUS status;
2800         struct smb2_create io;
2801         DATA_BLOB data;
2802         struct smb2_create_blob *aapl = NULL;
2803         uint32_t aapl_cmd;
2804         uint32_t aapl_reply_bitmap;
2805         uint32_t aapl_server_caps;
2806         bool ret = true;
2807
2808         ZERO_STRUCT(io);
2809         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
2810         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
2811         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2812         io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2813                               NTCREATEX_SHARE_ACCESS_READ |
2814                               NTCREATEX_SHARE_ACCESS_WRITE);
2815         io.in.fname = fname;
2816
2817         data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2818         SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2819         SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS));
2820         SBVAL(data.data, 16, flags);
2821
2822         status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2823         CHECK_STATUS(status, NT_STATUS_OK);
2824
2825         status = smb2_create(tree, tctx, &io);
2826         CHECK_STATUS(status, NT_STATUS_OK);
2827
2828         aapl = smb2_create_blob_find(&io.out.blobs,
2829                                      SMB2_CREATE_TAG_AAPL);
2830         if (aapl == NULL) {
2831                 ret = false;
2832                 goto done;
2833
2834         }
2835         if (aapl->data.length < 24) {
2836                 ret = false;
2837                 goto done;
2838         }
2839
2840         aapl_cmd = IVAL(aapl->data.data, 0);
2841         if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2842                 torture_result(tctx, TORTURE_FAIL,
2843                                "(%s) unexpected cmd: %d",
2844                                __location__, (int)aapl_cmd);
2845                 ret = false;
2846                 goto done;
2847         }
2848
2849         aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2850         if (!(aapl_reply_bitmap & SMB2_CRTCTX_AAPL_SERVER_CAPS)) {
2851                 torture_result(tctx, TORTURE_FAIL,
2852                                "(%s) unexpected reply_bitmap: %d",
2853                                __location__, (int)aapl_reply_bitmap);
2854                 ret = false;
2855                 goto done;
2856         }
2857
2858         aapl_server_caps = BVAL(aapl->data.data, 16);
2859         if (!(aapl_server_caps & flags)) {
2860                 torture_result(tctx, TORTURE_FAIL,
2861                                "(%s) unexpected server_caps: %d",
2862                                __location__, (int)aapl_server_caps);
2863                 ret = false;
2864                 goto done;
2865         }
2866
2867 done:
2868         status = smb2_util_close(tree, io.out.file.handle);
2869         CHECK_STATUS(status, NT_STATUS_OK);
2870
2871         smb2_util_unlink(tree, "aapl");
2872         talloc_free(mem_ctx);
2873         return ret;
2874 }
2875
2876 static bool test_copyfile(struct torture_context *torture,
2877                           struct smb2_tree *tree)
2878 {
2879         struct smb2_handle src_h;
2880         struct smb2_handle dest_h;
2881         NTSTATUS status;
2882         union smb_ioctl io;
2883         TALLOC_CTX *tmp_ctx = talloc_new(tree);
2884         struct srv_copychunk_copy cc_copy;
2885         struct srv_copychunk_rsp cc_rsp;
2886         enum ndr_err_code ndr_ret;
2887         bool ok;
2888         const char *sname = ":foo" "\xef\x80\xa2" "bar:$DATA";
2889
2890         /*
2891          * First test a copy_chunk with a 0 chunk count without having
2892          * enabled this via AAPL. The request must not fail and the
2893          * copied length in the response must be 0. This is verified
2894          * against Windows 2008r2.
2895          */
2896
2897         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2898                                    0, /* 0 chunks, copyfile semantics */
2899                                    FNAME_CC_SRC,
2900                                    &src_h, 4096, /* fill 4096 byte src file */
2901                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2902                                    FNAME_CC_DST,
2903                                    &dest_h, 0,  /* 0 byte dest file */
2904                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2905                                    &cc_copy,
2906                                    &io);
2907         if (!ok) {
2908                 torture_fail_goto(torture, done, "setup copy chunk error");
2909         }
2910
2911         ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2912                                        &cc_copy,
2913                         (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2914         torture_assert_ndr_success(torture, ndr_ret,
2915                                    "ndr_push_srv_copychunk_copy");
2916
2917         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2918         torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2919
2920         ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2921                                        &cc_rsp,
2922                         (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2923         torture_assert_ndr_success(torture, ndr_ret,
2924                                    "ndr_pull_srv_copychunk_rsp");
2925
2926         ok = check_copy_chunk_rsp(torture, &cc_rsp,
2927                                   0,    /* chunks written */
2928                                   0,    /* chunk bytes unsuccessfully written */
2929                                   0); /* total bytes written */
2930         if (!ok) {
2931                 torture_fail_goto(torture, done, "bad copy chunk response data");
2932         }
2933
2934         /*
2935          * Now enable AAPL copyfile and test again, the file and the
2936          * stream must be copied by the server.
2937          */
2938         ok = neg_aapl_copyfile(torture, tree,
2939                                SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
2940         if (!ok) {
2941                 torture_skip_goto(torture, done, "missing AAPL copyfile");
2942                 goto done;
2943         }
2944
2945         smb2_util_close(tree, src_h);
2946         smb2_util_close(tree, dest_h);
2947         smb2_util_unlink(tree, FNAME_CC_SRC);
2948         smb2_util_unlink(tree, FNAME_CC_DST);
2949
2950         ok = torture_setup_file(tmp_ctx, tree, FNAME_CC_SRC, false);
2951         if (!ok) {
2952                 torture_fail(torture, "setup file error");
2953         }
2954         ok = write_stream(tree, __location__, torture, tmp_ctx,
2955                             FNAME_CC_SRC, AFPRESOURCE_STREAM,
2956                             10, 10, "1234567890");
2957         if (!ok) {
2958                 torture_fail(torture, "setup stream error");
2959         }
2960
2961         ok = write_stream(tree, __location__, torture, tmp_ctx,
2962                             FNAME_CC_SRC, sname,
2963                             10, 10, "abcdefghij");
2964         torture_assert_goto(torture, ok == true, ok, done, "write_stream failed\n");
2965
2966         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2967                                    0, /* 0 chunks, copyfile semantics */
2968                                    FNAME_CC_SRC,
2969                                    &src_h, 4096, /* fill 4096 byte src file */
2970                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2971                                    FNAME_CC_DST,
2972                                    &dest_h, 0,  /* 0 byte dest file */
2973                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2974                                    &cc_copy,
2975                                    &io);
2976         if (!ok) {
2977                 torture_fail_goto(torture, done, "setup copy chunk error");
2978         }
2979
2980         ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2981                                        &cc_copy,
2982                         (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2983         torture_assert_ndr_success(torture, ndr_ret,
2984                                    "ndr_push_srv_copychunk_copy");
2985
2986         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2987         torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2988
2989         ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2990                                        &cc_rsp,
2991                         (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2992         torture_assert_ndr_success(torture, ndr_ret,
2993                                    "ndr_pull_srv_copychunk_rsp");
2994
2995         ok = check_copy_chunk_rsp(torture, &cc_rsp,
2996                                   0,    /* chunks written */
2997                                   0,    /* chunk bytes unsuccessfully written */
2998                                   4096); /* total bytes written */
2999         if (!ok) {
3000                 torture_fail_goto(torture, done, "bad copy chunk response data");
3001         }
3002
3003         ok = test_setup_open(torture, tree, tmp_ctx, FNAME_CC_DST, &dest_h,
3004                              SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL);
3005         if (!ok) {
3006                 torture_fail_goto(torture, done,"open failed");
3007         }
3008         ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 4096, 0);
3009         if (!ok) {
3010                 torture_fail_goto(torture, done, "inconsistent file data");
3011         }
3012
3013         ok = check_stream(tree, __location__, torture, tmp_ctx,
3014                             FNAME_CC_DST, AFPRESOURCE_STREAM,
3015                             0, 20, 10, 10, "1234567890");
3016         if (!ok) {
3017                 torture_fail_goto(torture, done, "inconsistent stream data");
3018         }
3019
3020         ok = check_stream(tree, __location__, torture, tmp_ctx,
3021                             FNAME_CC_DST, sname,
3022                             0, 20, 10, 10, "abcdefghij");
3023         torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
3024
3025 done:
3026         smb2_util_close(tree, src_h);
3027         smb2_util_close(tree, dest_h);
3028         smb2_util_unlink(tree, FNAME_CC_SRC);
3029         smb2_util_unlink(tree, FNAME_CC_DST);
3030         talloc_free(tmp_ctx);
3031         return true;
3032 }
3033
3034 static bool check_stream_list(struct smb2_tree *tree,
3035                               struct torture_context *tctx,
3036                               const char *fname,
3037                               int num_exp,
3038                               const char **exp,
3039                               bool is_dir)
3040 {
3041         bool ret = true;
3042         union smb_fileinfo finfo;
3043         NTSTATUS status;
3044         int i;
3045         TALLOC_CTX *tmp_ctx = talloc_new(tctx);
3046         char **exp_sort;
3047         struct stream_struct *stream_sort;
3048         struct smb2_create create;
3049         struct smb2_handle h;
3050
3051         ZERO_STRUCT(h);
3052         torture_assert_goto(tctx, tmp_ctx != NULL, ret, done, "talloc_new failed");
3053
3054         ZERO_STRUCT(create);
3055         create.in.fname = fname;
3056         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3057         create.in.desired_access = SEC_FILE_ALL;
3058         create.in.create_options = is_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
3059         create.in.file_attributes = is_dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
3060         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3061         status = smb2_create(tree, tmp_ctx, &create);
3062         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
3063         h = create.out.file.handle;
3064
3065         finfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
3066         finfo.generic.in.file.handle = h;
3067
3068         status = smb2_getinfo_file(tree, tctx, &finfo);
3069         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "get stream info");
3070
3071         smb2_util_close(tree, h);
3072
3073         torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams, num_exp,
3074                                       ret, done, "stream count");
3075
3076         if (num_exp == 0) {
3077                 TALLOC_FREE(tmp_ctx);
3078                 goto done;
3079         }
3080
3081         exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
3082         torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
3083
3084         TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
3085
3086         stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
3087                                     finfo.stream_info.out.num_streams *
3088                                     sizeof(*stream_sort));
3089         torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
3090
3091         TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
3092
3093         for (i=0; i<num_exp; i++) {
3094                 torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
3095                                 i, exp_sort[i], stream_sort[i].stream_name.s);
3096                 torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s, exp_sort[i],
3097                                               ret, done, "stream name");
3098         }
3099
3100 done:
3101         TALLOC_FREE(tmp_ctx);
3102         return ret;
3103 }
3104
3105 /*
3106   test stream names
3107 */
3108 static bool test_stream_names(struct torture_context *tctx,
3109                               struct smb2_tree *tree)
3110 {
3111         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3112         NTSTATUS status;
3113         struct smb2_create create;
3114         struct smb2_handle h;
3115         const char *fname = BASEDIR "\\stream_names.txt";
3116         const char *sname1;
3117         bool ret;
3118         /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
3119         const char *streams[] = {
3120                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
3121                 "::$DATA"
3122         };
3123
3124         sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
3125
3126         /* clean slate ...*/
3127         smb2_util_unlink(tree, fname);
3128         smb2_deltree(tree, fname);
3129         smb2_deltree(tree, BASEDIR);
3130
3131         status = torture_smb2_testdir(tree, BASEDIR, &h);
3132         CHECK_STATUS(status, NT_STATUS_OK);
3133         smb2_util_close(tree, h);
3134
3135         ret = torture_setup_file(mem_ctx, tree, fname, false);
3136         torture_assert_goto(tctx, ret, ret, done, "torture_setup_file");
3137
3138         torture_comment(tctx, "(%s) testing stream names\n", __location__);
3139         ZERO_STRUCT(create);
3140         create.in.desired_access = SEC_FILE_WRITE_DATA;
3141         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3142         create.in.share_access =
3143                 NTCREATEX_SHARE_ACCESS_DELETE|
3144                 NTCREATEX_SHARE_ACCESS_READ|
3145                 NTCREATEX_SHARE_ACCESS_WRITE;
3146         create.in.create_disposition = NTCREATEX_DISP_CREATE;
3147         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3148         create.in.fname = sname1;
3149
3150         status = smb2_create(tree, mem_ctx, &create);
3151         CHECK_STATUS(status, NT_STATUS_OK);
3152
3153         status = smb2_util_write(tree, create.out.file.handle, "foo", 0, 3);
3154         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3155                                         "smb2_util_write failed\n");
3156
3157         smb2_util_close(tree, create.out.file.handle);
3158
3159         ret = check_stream_list(tree, tctx, fname, 2, streams, false);
3160         CHECK_VALUE(ret, true);
3161
3162 done:
3163         status = smb2_util_unlink(tree, fname);
3164         smb2_deltree(tree, BASEDIR);
3165         talloc_free(mem_ctx);
3166
3167         return ret;
3168 }
3169
3170 /* Renaming a directory with open file, should work for OS X AAPL clients */
3171 static bool test_rename_dir_openfile(struct torture_context *torture,
3172                                      struct smb2_tree *tree)
3173 {
3174         bool ret = true;
3175         NTSTATUS status;
3176         union smb_open io;
3177         union smb_close cl;
3178         union smb_setfileinfo sinfo;
3179         struct smb2_handle d1, h1;
3180         const char *renamedir = BASEDIR "-new";
3181         bool server_is_osx = torture_setting_bool(torture, "osx", false);
3182
3183         smb2_deltree(tree, BASEDIR);
3184         smb2_util_rmdir(tree, BASEDIR);
3185         smb2_deltree(tree, renamedir);
3186
3187         ZERO_STRUCT(io.smb2);
3188         io.generic.level = RAW_OPEN_SMB2;
3189         io.smb2.in.create_flags = 0;
3190         io.smb2.in.desired_access = 0x0017019f;
3191         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
3192         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
3193         io.smb2.in.share_access = 0;
3194         io.smb2.in.alloc_size = 0;
3195         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
3196         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3197         io.smb2.in.security_flags = 0;
3198         io.smb2.in.fname = BASEDIR;
3199
3200         status = smb2_create(tree, torture, &(io.smb2));
3201         torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
3202         d1 = io.smb2.out.file.handle;
3203
3204         ZERO_STRUCT(io.smb2);
3205         io.generic.level = RAW_OPEN_SMB2;
3206         io.smb2.in.create_flags = 0;
3207         io.smb2.in.desired_access = 0x0017019f;
3208         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
3209         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3210         io.smb2.in.share_access = 0;
3211         io.smb2.in.alloc_size = 0;
3212         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
3213         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3214         io.smb2.in.security_flags = 0;
3215         io.smb2.in.fname = BASEDIR "\\file.txt";
3216
3217         status = smb2_create(tree, torture, &(io.smb2));
3218         torture_assert_ntstatus_ok(torture, status, "smb2_create file");
3219         h1 = io.smb2.out.file.handle;
3220
3221         if (!server_is_osx) {
3222                 torture_comment(torture, "Renaming directory without AAPL, must fail\n");
3223
3224                 ZERO_STRUCT(sinfo);
3225                 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
3226                 sinfo.rename_information.in.file.handle = d1;
3227                 sinfo.rename_information.in.overwrite = 0;
3228                 sinfo.rename_information.in.root_fid = 0;
3229                 sinfo.rename_information.in.new_name = renamedir;
3230                 status = smb2_setinfo_file(tree, &sinfo);
3231
3232                 torture_assert_ntstatus_equal(torture, status,
3233                                               NT_STATUS_ACCESS_DENIED,
3234                                               "smb2_setinfo_file");
3235         }
3236
3237         status = smb2_util_close(tree, d1);
3238         torture_assert_ntstatus_ok(torture, status, "smb2_util_close\n");
3239         ZERO_STRUCT(d1);
3240
3241         torture_comment(torture, "Enabling AAPL\n");
3242
3243         ret = enable_aapl(torture, tree);
3244         torture_assert(torture, ret == true, "enable_aapl failed");
3245
3246         torture_comment(torture, "Renaming directory with AAPL\n");
3247
3248         ZERO_STRUCT(io.smb2);
3249         io.generic.level = RAW_OPEN_SMB2;
3250         io.smb2.in.desired_access = 0x0017019f;
3251         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
3252         io.smb2.in.share_access = 0;
3253         io.smb2.in.alloc_size = 0;
3254         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
3255         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3256         io.smb2.in.security_flags = 0;
3257         io.smb2.in.fname = BASEDIR;
3258
3259         status = smb2_create(tree, torture, &(io.smb2));
3260         torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
3261         d1 = io.smb2.out.file.handle;
3262
3263         ZERO_STRUCT(sinfo);
3264         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
3265         sinfo.rename_information.in.file.handle = d1;
3266         sinfo.rename_information.in.overwrite = 0;
3267         sinfo.rename_information.in.root_fid = 0;
3268         sinfo.rename_information.in.new_name = renamedir;
3269
3270         status = smb2_setinfo_file(tree, &sinfo);
3271         torture_assert_ntstatus_ok(torture, status, "smb2_setinfo_file");
3272
3273         ZERO_STRUCT(cl.smb2);
3274         cl.smb2.level = RAW_CLOSE_SMB2;
3275         cl.smb2.in.file.handle = d1;
3276         status = smb2_close(tree, &(cl.smb2));
3277         torture_assert_ntstatus_ok(torture, status, "smb2_close");
3278         ZERO_STRUCT(d1);
3279
3280         cl.smb2.in.file.handle = h1;
3281         status = smb2_close(tree, &(cl.smb2));
3282         torture_assert_ntstatus_ok(torture, status, "smb2_close");
3283         ZERO_STRUCT(h1);
3284
3285         torture_comment(torture, "Cleaning up\n");
3286
3287         if (h1.data[0] || h1.data[1]) {
3288                 ZERO_STRUCT(cl.smb2);
3289                 cl.smb2.level = RAW_CLOSE_SMB2;
3290                 cl.smb2.in.file.handle = h1;
3291                 status = smb2_close(tree, &(cl.smb2));
3292         }
3293
3294         smb2_util_unlink(tree, BASEDIR "\\file.txt");
3295         smb2_util_unlink(tree, BASEDIR "-new\\file.txt");
3296         smb2_deltree(tree, renamedir);
3297         smb2_deltree(tree, BASEDIR);
3298         return ret;
3299 }
3300
3301 static bool test_afpinfo_enoent(struct torture_context *tctx,
3302                                 struct smb2_tree *tree)
3303 {
3304         bool ret = true;
3305         NTSTATUS status;
3306         struct smb2_create create;
3307         struct smb2_handle h1;
3308         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3309         const char *fname = BASEDIR "\\file";
3310         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3311
3312         torture_comment(tctx, "Opening file without AFP_AfpInfo\n");
3313
3314         smb2_deltree(tree, BASEDIR);
3315         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3316         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3317         smb2_util_close(tree, h1);
3318         ret = torture_setup_file(mem_ctx, tree, fname, false);
3319         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3320
3321         torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3322
3323         ZERO_STRUCT(create);
3324         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3325         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3326         create.in.fname = sname;
3327
3328         status = smb2_create(tree, mem_ctx, &create);
3329         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3330                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3331
3332 done:
3333         smb2_util_unlink(tree, fname);
3334         smb2_util_rmdir(tree, BASEDIR);
3335         return ret;
3336 }
3337
3338 static bool test_create_delete_on_close(struct torture_context *tctx,
3339                                         struct smb2_tree *tree)
3340 {
3341         bool ret = true;
3342         NTSTATUS status;
3343         struct smb2_create create;
3344         struct smb2_handle h1;
3345         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3346         const char *fname = BASEDIR "\\file";
3347         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3348         const char *type_creator = "SMB,OLE!";
3349         AfpInfo *info = NULL;
3350         const char *streams_basic[] = {
3351                 "::$DATA"
3352         };
3353         const char *streams_afpinfo[] = {
3354                 "::$DATA",
3355                 AFPINFO_STREAM
3356         };
3357
3358         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3359
3360         torture_comment(tctx, "Checking whether create with delete-on-close work with AFP_AfpInfo\n");
3361
3362         smb2_deltree(tree, BASEDIR);
3363         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3364         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3365         smb2_util_close(tree, h1);
3366         ret = torture_setup_file(mem_ctx, tree, fname, false);
3367         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3368
3369         torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3370
3371         ZERO_STRUCT(create);
3372         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3373         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3374         create.in.fname = sname;
3375
3376         status = smb2_create(tree, mem_ctx, &create);
3377         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3378                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3379
3380         ZERO_STRUCT(create);
3381         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3382         create.in.desired_access = SEC_FILE_ALL;
3383         create.in.fname = sname;
3384
3385         status = smb2_create(tree, mem_ctx, &create);
3386         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3387                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3388
3389         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3390         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3391
3392         torture_comment(tctx, "Deleting AFP_AfpInfo via create with delete-on-close\n");
3393
3394         info = torture_afpinfo_new(mem_ctx);
3395         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3396
3397         memcpy(info->afpi_FinderInfo, type_creator, 8);
3398         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3399         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3400
3401         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3402                            0, 60, 16, 8, type_creator);
3403         torture_assert_goto(tctx, ret == true, ret, done, "Bad type/creator in AFP_AfpInfo");
3404
3405         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3406         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3407
3408         ZERO_STRUCT(create);
3409         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3410         create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3411         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3412         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3413         create.in.fname = sname;
3414         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3415
3416         status = smb2_create(tree, mem_ctx, &create);
3417         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3418
3419         h1 = create.out.file.handle;
3420         smb2_util_close(tree, h1);
3421
3422         ZERO_STRUCT(create);
3423         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3424         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
3425         create.in.fname = sname;
3426         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3427         status = smb2_create(tree, mem_ctx, &create);
3428         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3429                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3430
3431         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3432         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3433
3434 done:
3435         smb2_util_unlink(tree, fname);
3436         smb2_util_rmdir(tree, BASEDIR);
3437         return ret;
3438 }
3439
3440 static bool test_setinfo_delete_on_close(struct torture_context *tctx,
3441                                          struct smb2_tree *tree)
3442 {
3443         bool ret = true;
3444         NTSTATUS status;
3445         struct smb2_create create;
3446         union smb_setfileinfo sfinfo;
3447         struct smb2_handle h1;
3448         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3449         const char *fname = BASEDIR "\\file";
3450         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3451         const char *type_creator = "SMB,OLE!";
3452         AfpInfo *info = NULL;
3453         const char *streams[] = {
3454                 AFPINFO_STREAM,
3455                 "::$DATA"
3456         };
3457         const char *streams_basic[] = {
3458                 "::$DATA"
3459         };
3460
3461         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3462
3463         torture_comment(tctx, "Deleting AFP_AfpInfo via setinfo with delete-on-close\n");
3464
3465         smb2_deltree(tree, BASEDIR);
3466         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3467         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3468         smb2_util_close(tree, h1);
3469         ret = torture_setup_file(mem_ctx, tree, fname, false);
3470         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3471
3472         info = torture_afpinfo_new(mem_ctx);
3473         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3474         memcpy(info->afpi_FinderInfo, type_creator, 8);
3475         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3476         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3477
3478         ZERO_STRUCT(create);
3479         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3480         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3481         create.in.fname = sname;
3482         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3483         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3484
3485         status = smb2_create(tree, mem_ctx, &create);
3486         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3487
3488         h1 = create.out.file.handle;
3489
3490         /* Delete stream via setinfo delete-on-close */
3491         ZERO_STRUCT(sfinfo);
3492         sfinfo.disposition_info.in.delete_on_close = 1;
3493         sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3494         sfinfo.generic.in.file.handle = h1;
3495         status = smb2_setinfo_file(tree, &sfinfo);
3496         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3497
3498         ret = check_stream_list(tree, tctx, fname, 2, streams, false);
3499         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3500
3501         ZERO_STRUCT(create);
3502         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3503         create.in.desired_access = SEC_FILE_ALL;
3504         create.in.fname = sname;
3505         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3506         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3507         status = smb2_create(tree, mem_ctx, &create);
3508         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_DELETE_PENDING,
3509                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3510
3511         smb2_util_close(tree, h1);
3512
3513         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3514         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3515
3516         ZERO_STRUCT(create);
3517         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3518         create.in.desired_access = SEC_FILE_ALL;
3519         create.in.fname = sname;
3520         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3521         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3522         status = smb2_create(tree, mem_ctx, &create);
3523         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3524                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3525
3526 done:
3527         smb2_util_unlink(tree, fname);
3528         smb2_util_rmdir(tree, BASEDIR);
3529         return ret;
3530 }
3531
3532 static bool test_setinfo_eof(struct torture_context *tctx,
3533                              struct smb2_tree *tree)
3534 {
3535         bool ret = true;
3536         NTSTATUS status;
3537         struct smb2_create create;
3538         union smb_setfileinfo sfinfo;
3539         struct smb2_handle h1;
3540         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3541         const char *fname = BASEDIR "\\file";
3542         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3543         const char *type_creator = "SMB,OLE!";
3544         AfpInfo *info = NULL;
3545         const char *streams_afpinfo[] = {
3546                 "::$DATA",
3547                 AFPINFO_STREAM
3548         };
3549
3550         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3551
3552         torture_comment(tctx, "Set AFP_AfpInfo EOF to 61, 1 and 0\n");
3553
3554         smb2_deltree(tree, BASEDIR);
3555         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3556         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3557         smb2_util_close(tree, h1);
3558         ret = torture_setup_file(mem_ctx, tree, fname, false);
3559         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3560
3561         info = torture_afpinfo_new(mem_ctx);
3562         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3563         memcpy(info->afpi_FinderInfo, type_creator, 8);
3564         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3565         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3566
3567         ZERO_STRUCT(create);
3568         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3569         create.in.desired_access = SEC_FILE_ALL;
3570         create.in.fname = sname;
3571         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3572         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3573
3574         status = smb2_create(tree, mem_ctx, &create);
3575         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3576
3577         h1 = create.out.file.handle;
3578
3579         torture_comment(tctx, "Set AFP_AfpInfo EOF to 61\n");
3580
3581         /* Test setinfo end-of-file info */
3582         ZERO_STRUCT(sfinfo);
3583         sfinfo.generic.in.file.handle = h1;
3584         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3585         sfinfo.position_information.in.position = 61;
3586         status = smb2_setinfo_file(tree, &sfinfo);
3587         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ALLOTTED_SPACE_EXCEEDED,
3588                                            ret, done, "set eof 61 failed");
3589
3590         torture_comment(tctx, "Set AFP_AfpInfo EOF to 1\n");
3591
3592         /* Truncation returns success, but has no effect */
3593         ZERO_STRUCT(sfinfo);
3594         sfinfo.generic.in.file.handle = h1;
3595         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3596         sfinfo.position_information.in.position = 1;
3597         status = smb2_setinfo_file(tree, &sfinfo);
3598         torture_assert_ntstatus_ok_goto(tctx, status,
3599                                         ret, done, "set eof 1 failed");
3600         smb2_util_close(tree, h1);
3601
3602         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3603         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3604
3605         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3606                            0, 60, 16, 8, type_creator);
3607         torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3608
3609         ZERO_STRUCT(create);
3610         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3611         create.in.desired_access = SEC_FILE_ALL;
3612         create.in.fname = sname;
3613         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3614         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3615
3616         status = smb2_create(tree, mem_ctx, &create);
3617         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3618
3619         h1 = create.out.file.handle;
3620
3621         /*
3622          * Delete stream via setinfo end-of-file info to 0, should
3623          * return success but stream MUST NOT deleted
3624          */
3625         ZERO_STRUCT(sfinfo);
3626         sfinfo.generic.in.file.handle = h1;
3627         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3628         sfinfo.position_information.in.position = 0;
3629         status = smb2_setinfo_file(tree, &sfinfo);
3630         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
3631
3632         smb2_util_close(tree, h1);
3633
3634         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3635         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3636
3637         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3638                            0, 60, 16, 8, type_creator);
3639         torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3640
3641 done:
3642         smb2_util_unlink(tree, fname);
3643         smb2_util_rmdir(tree, BASEDIR);
3644         return ret;
3645 }
3646
3647 static bool test_afpinfo_all0(struct torture_context *tctx,
3648                               struct smb2_tree *tree)
3649 {
3650         bool ret = true;
3651         NTSTATUS status;
3652         struct smb2_create create;
3653         struct smb2_handle h1 = {{0}};
3654         struct smb2_handle baseh = {{0}};
3655         union smb_setfileinfo setfinfo;
3656         union smb_fileinfo getfinfo;
3657         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3658         const char *fname = BASEDIR "\\file";
3659         const char *sname = BASEDIR "\\file" AFPINFO_STREAM;
3660         const char *type_creator = "SMB,OLE!";
3661         AfpInfo *info = NULL;
3662         char *infobuf = NULL;
3663         const char *streams_basic[] = {
3664                 "::$DATA"
3665         };
3666         const char *streams_afpinfo[] = {
3667                 "::$DATA",
3668                 AFPINFO_STREAM
3669         };
3670
3671         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3672
3673         torture_comment(tctx, "Write all 0 to AFP_AfpInfo and see what happens\n");
3674
3675         smb2_deltree(tree, BASEDIR);
3676         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3677         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3678         smb2_util_close(tree, h1);
3679         ret = torture_setup_file(mem_ctx, tree, fname, false);
3680         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3681
3682         info = torture_afpinfo_new(mem_ctx);
3683         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3684         memcpy(info->afpi_FinderInfo, type_creator, 8);
3685         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3686         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3687
3688         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3689         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3690
3691         /* Write all 0 to AFP_AfpInfo */
3692         memset(info->afpi_FinderInfo, 0, AFP_FinderSize);
3693         infobuf = torture_afpinfo_pack(mem_ctx, info);
3694         torture_assert_not_null_goto(tctx, infobuf, ret, done,
3695                                      "torture_afpinfo_pack failed\n");
3696
3697         ZERO_STRUCT(create);
3698         create.in.desired_access = SEC_FILE_ALL;
3699         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3700         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3701         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3702         create.in.fname = fname;
3703
3704         status = smb2_create(tree, mem_ctx, &create);
3705         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3706                                         "smb2_create failed\n");
3707         baseh = create.out.file.handle;
3708
3709         ZERO_STRUCT(create);
3710         create.in.desired_access = SEC_FILE_ALL;
3711         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3712         create.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
3713         create.in.fname = sname;
3714
3715         status = smb2_create(tree, mem_ctx, &create);
3716         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3717                                         "smb2_create failed\n");
3718         h1 = create.out.file.handle;
3719
3720         status = smb2_util_write(tree, h1, infobuf, 0, AFP_INFO_SIZE);
3721         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3722                                         "smb2_util_write failed\n");
3723
3724         /*
3725          * Get stream information on open handle, must return only default
3726          * stream, the AFP_AfpInfo stream must not be returned.
3727          */
3728
3729         ZERO_STRUCT(getfinfo);
3730         getfinfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
3731         getfinfo.generic.in.file.handle = baseh;
3732
3733         status = smb2_getinfo_file(tree, tctx, &getfinfo);
3734         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3735                                         "get stream info\n");
3736
3737         torture_assert_int_equal_goto(tctx, getfinfo.stream_info.out.num_streams,
3738                                       1, ret, done, "stream count");
3739
3740         smb2_util_close(tree, baseh);
3741         ZERO_STRUCT(baseh);
3742
3743         /*
3744          * Try to set some file-basic-info (time) on the stream. This catches
3745          * naive implementation mistakes that simply deleted the backing store
3746          * from the filesystem in the zero-out step.
3747          */
3748
3749         ZERO_STRUCT(setfinfo);
3750         unix_to_nt_time(&setfinfo.basic_info.in.write_time, time(NULL));
3751         setfinfo.basic_info.in.attrib = 0x20;
3752         setfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
3753         setfinfo.generic.in.file.handle = h1;
3754
3755         status = smb2_setinfo_file(tree, &setfinfo);
3756         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3757                                         "smb2_getinfo_file failed\n");
3758
3759         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3760         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
3761
3762         smb2_util_close(tree, h1);
3763         ZERO_STRUCT(h1);
3764
3765         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3766         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3767
3768 done:
3769         if (!smb2_util_handle_empty(h1)) {
3770                 smb2_util_close(tree, h1);
3771         }
3772         if (!smb2_util_handle_empty(baseh)) {
3773                 smb2_util_close(tree, baseh);
3774         }
3775         smb2_util_unlink(tree, fname);
3776         smb2_util_rmdir(tree, BASEDIR);
3777         return ret;
3778 }
3779
3780 static bool test_create_delete_on_close_resource(struct torture_context *tctx,
3781                                                  struct smb2_tree *tree)
3782 {
3783         bool ret = true;
3784         NTSTATUS status;
3785         struct smb2_create create;
3786         struct smb2_handle h1;
3787         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3788         const char *fname = BASEDIR "\\file";
3789         const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3790         const char *streams_basic[] = {
3791                 "::$DATA"
3792         };
3793         const char *streams_afpresource[] = {
3794                 "::$DATA",
3795                 AFPRESOURCE_STREAM
3796         };
3797
3798         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3799
3800         torture_comment(tctx, "Checking whether create with delete-on-close is ignored for AFP_AfpResource\n");
3801
3802         smb2_deltree(tree, BASEDIR);
3803         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3804         torture_assert_ntstatus_ok(tctx, status, "torture_smb2_testdir");
3805         smb2_util_close(tree, h1);
3806         ret = torture_setup_file(mem_ctx, tree, fname, false);
3807         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3808
3809         torture_comment(tctx, "Opening not existing AFP_AfpResource\n");
3810
3811         ZERO_STRUCT(create);
3812         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3813         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3814         create.in.fname = sname;
3815
3816         status = smb2_create(tree, mem_ctx, &create);
3817         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3818                                            ret, done, "Got unexpected AFP_AfpResource stream");
3819
3820         ZERO_STRUCT(create);
3821         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3822         create.in.desired_access = SEC_FILE_ALL;
3823         create.in.fname = sname;
3824
3825         status = smb2_create(tree, mem_ctx, &create);
3826         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3827                                            ret, done, "Got unexpected AFP_AfpResource stream");
3828
3829         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3830         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3831
3832         torture_comment(tctx, "Trying to delete AFP_AfpResource via create with delete-on-close\n");
3833
3834         ret = write_stream(tree, __location__, tctx, mem_ctx,
3835                            fname, AFPRESOURCE_STREAM_NAME,
3836                            0, 10, "1234567890");
3837         torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3838
3839         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3840                            0, 10, 0, 10, "1234567890");
3841         torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3842
3843         ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3844         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3845
3846         ZERO_STRUCT(create);
3847         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3848         create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3849         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3850         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3851         create.in.fname = sname;
3852         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3853
3854         status = smb2_create(tree, mem_ctx, &create);
3855         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3856
3857         h1 = create.out.file.handle;
3858         smb2_util_close(tree, h1);
3859
3860         ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3861         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3862
3863         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3864                            0, 10, 0, 10, "1234567890");
3865         torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3866
3867 done:
3868         smb2_util_unlink(tree, fname);
3869         smb2_util_rmdir(tree, BASEDIR);
3870         return ret;
3871 }
3872
3873 static bool test_setinfo_delete_on_close_resource(struct torture_context *tctx,
3874                                                   struct smb2_tree *tree)
3875 {
3876         bool ret = true;
3877         NTSTATUS status;
3878         struct smb2_create create;
3879         union smb_setfileinfo sfinfo;
3880         struct smb2_handle h1;
3881         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3882         const char *fname = BASEDIR "\\file";
3883         const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3884         const char *streams_afpresource[] = {
3885                 "::$DATA",
3886                 AFPRESOURCE_STREAM
3887         };
3888
3889         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3890
3891         torture_comment(tctx, "Trying to delete AFP_AfpResource via setinfo with delete-on-close\n");
3892
3893         smb2_deltree(tree, BASEDIR);
3894         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3895         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3896         smb2_util_close(tree, h1);
3897         ret = torture_setup_file(mem_ctx, tree, fname, false);
3898         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3899
3900         ret = write_stream(tree, __location__, tctx, mem_ctx,
3901                            fname, AFPRESOURCE_STREAM_NAME,
3902                            10, 10, "1234567890");
3903         torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3904
3905         ZERO_STRUCT(create);
3906         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3907         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3908         create.in.fname = sname;
3909         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3910         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3911
3912         status = smb2_create(tree, mem_ctx, &create);
3913         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3914
3915         h1 = create.out.file.handle;
3916
3917         /* Try to delete stream via setinfo delete-on-close */
3918         ZERO_STRUCT(sfinfo);
3919         sfinfo.disposition_info.in.delete_on_close = 1;
3920         sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3921         sfinfo.generic.in.file.handle = h1;
3922         status = smb2_setinfo_file(tree, &sfinfo);
3923         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3924
3925         smb2_util_close(tree, h1);
3926
3927         ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3928         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3929
3930         ZERO_STRUCT(create);
3931         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3932         create.in.desired_access = SEC_FILE_ALL;
3933         create.in.fname = sname;
3934         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3935         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3936         status = smb2_create(tree, mem_ctx, &create);
3937         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3938                                         "Got unexpected AFP_AfpResource stream");
3939
3940 done:
3941         smb2_util_unlink(tree, fname);
3942         smb2_util_rmdir(tree, BASEDIR);
3943         return ret;
3944 }
3945
3946 static bool test_setinfo_eof_resource(struct torture_context *tctx,
3947                                       struct smb2_tree *tree)
3948 {
3949         bool ret = true;
3950         NTSTATUS status;
3951         struct smb2_create create;
3952         union smb_setfileinfo sfinfo;
3953         union smb_fileinfo finfo;
3954         struct smb2_handle h1;
3955         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3956         const char *fname = BASEDIR "\\file";
3957         const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3958         const char *streams_basic[] = {
3959                 "::$DATA"
3960         };
3961
3962         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3963
3964         torture_comment(tctx, "Set AFP_AfpResource EOF to 1 and 0\n");
3965
3966         smb2_deltree(tree, BASEDIR);
3967         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3968         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3969         smb2_util_close(tree, h1);
3970         ret = torture_setup_file(mem_ctx, tree, fname, false);
3971         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3972
3973         ret = write_stream(tree, __location__, tctx, mem_ctx,
3974                            fname, AFPRESOURCE_STREAM_NAME,
3975                            10, 10, "1234567890");
3976         torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3977
3978         ZERO_STRUCT(create);
3979         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3980         create.in.desired_access = SEC_FILE_ALL;
3981         create.in.fname = sname;
3982         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3983         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3984
3985         status = smb2_create(tree, mem_ctx, &create);
3986         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3987
3988         h1 = create.out.file.handle;
3989
3990         torture_comment(tctx, "Set AFP_AfpResource EOF to 1\n");
3991
3992         /* Test setinfo end-of-file info */
3993         ZERO_STRUCT(sfinfo);
3994         sfinfo.generic.in.file.handle = h1;
3995         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3996         sfinfo.position_information.in.position = 1;
3997         status = smb2_setinfo_file(tree, &sfinfo);
3998         torture_assert_ntstatus_ok_goto(tctx, status,
3999                                         ret, done, "set eof 1 failed");
4000
4001         smb2_util_close(tree, h1);
4002
4003         /* Check size == 1 */
4004         ZERO_STRUCT(create);
4005         create.in.fname = sname;
4006         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4007         create.in.desired_access = SEC_FILE_ALL;
4008         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4009         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4010         status = smb2_create(tree, mem_ctx, &create);
4011         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4012
4013         h1 = create.out.file.handle;
4014
4015         ZERO_STRUCT(finfo);
4016         finfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
4017         finfo.generic.in.file.handle = h1;
4018         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
4019         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file failed");
4020
4021         smb2_util_close(tree, h1);
4022
4023         torture_assert_goto(tctx, finfo.all_info.out.size == 1, ret, done, "size != 1");
4024
4025         ZERO_STRUCT(create);
4026         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4027         create.in.desired_access = SEC_FILE_ALL;
4028         create.in.fname = sname;
4029         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4030         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4031
4032         status = smb2_create(tree, mem_ctx, &create);
4033         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4034
4035         h1 = create.out.file.handle;
4036
4037         /*
4038          * Delete stream via setinfo end-of-file info to 0, this
4039          * should delete the stream.
4040          */
4041         ZERO_STRUCT(sfinfo);
4042         sfinfo.generic.in.file.handle = h1;
4043         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
4044         sfinfo.position_information.in.position = 0;
4045         status = smb2_setinfo_file(tree, &sfinfo);
4046         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
4047
4048         smb2_util_close(tree, h1);
4049
4050         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
4051         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4052
4053         ZERO_STRUCT(create);
4054         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4055         create.in.desired_access = SEC_FILE_ALL;
4056         create.in.fname = sname;
4057         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4058         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4059
4060         status = smb2_create(tree, mem_ctx, &create);
4061         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4062                                            ret, done, "smb2_create failed");
4063
4064 done:
4065         smb2_util_unlink(tree, fname);
4066         smb2_util_rmdir(tree, BASEDIR);
4067         return ret;
4068 }
4069
4070 /*
4071  * This tests that right after creating the AFP_AfpInfo stream,
4072  * reading from the stream returns an empty, default metadata blob of
4073  * 60 bytes.
4074  *
4075  * NOTE: against OS X SMB server this only works if the read request
4076  * is compounded with the create that created the stream, is fails
4077  * otherwise. We don't care...
4078  */
4079 static bool test_null_afpinfo(struct torture_context *tctx,
4080                               struct smb2_tree *tree)
4081 {
4082         TALLOC_CTX *mem_ctx = talloc_new(tctx);
4083         const char *fname = "test_null_afpinfo";
4084         const char *sname = "test_null_afpinfo" AFPINFO_STREAM_NAME;
4085         NTSTATUS status;
4086         bool ret = true;
4087         struct smb2_request *req[3];
4088         struct smb2_handle handle;
4089         struct smb2_create create;
4090         struct smb2_read read;
4091         AfpInfo *afpinfo = NULL;
4092         char *afpinfo_buf = NULL;
4093         const char *type_creator = "SMB,OLE!";
4094         struct smb2_handle handle2;
4095         struct smb2_read r;
4096
4097         torture_comment(tctx, "Checking create of AfpInfo stream\n");
4098
4099         smb2_util_unlink(tree, fname);
4100
4101         ret = torture_setup_file(mem_ctx, tree, fname, false);
4102         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
4103
4104         ZERO_STRUCT(create);
4105         create.in.desired_access = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA;
4106         create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
4107         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4108         create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4109         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4110         create.in.fname = sname;
4111
4112         smb2_transport_compound_start(tree->session->transport, 2);
4113
4114         req[0] = smb2_create_send(tree, &create);
4115
4116         handle.data[0] = UINT64_MAX;
4117         handle.data[1] = UINT64_MAX;
4118
4119         smb2_transport_compound_set_related(tree->session->transport, true);
4120
4121         ZERO_STRUCT(read);
4122         read.in.file.handle = handle;
4123         read.in.length = AFP_INFO_SIZE;
4124         req[1] = smb2_read_send(tree, &read);
4125
4126         status = smb2_create_recv(req[0], tree, &create);
4127         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_recv failed");
4128
4129         handle = create.out.file.handle;
4130
4131         status = smb2_read_recv(req[1], tree, &read);
4132         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read_recv failed");
4133
4134         status = torture_smb2_testfile_access(tree, sname, &handle2,
4135                                               SEC_FILE_READ_DATA);
4136         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4137                                         "torture_smb2_testfile failed\n");
4138         r = (struct smb2_read) {
4139                 .in.file.handle = handle2,
4140                 .in.length      = AFP_INFO_SIZE,
4141         };
4142
4143         status = smb2_read(tree, tree, &r);
4144         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4145                                         "torture_smb2_testfile failed\n");
4146         smb2_util_close(tree, handle2);
4147
4148         afpinfo = torture_afpinfo_new(mem_ctx);
4149         torture_assert_goto(tctx, afpinfo != NULL, ret, done, "torture_afpinfo_new failed");
4150
4151         memcpy(afpinfo->afpi_FinderInfo, type_creator, 8);
4152
4153         afpinfo_buf = torture_afpinfo_pack(tctx, afpinfo);
4154         torture_assert_goto(tctx, afpinfo_buf != NULL, ret, done, "torture_afpinfo_new failed");
4155
4156         status = smb2_util_write(tree, handle, afpinfo_buf, 0, AFP_INFO_SIZE);
4157         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write failed");
4158
4159         smb2_util_close(tree, handle);
4160
4161         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
4162                            0, 60, 16, 8, type_creator);
4163         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
4164
4165 done:
4166         smb2_util_unlink(tree, fname);
4167         talloc_free(mem_ctx);
4168         return ret;
4169 }
4170
4171 static bool test_delete_file_with_rfork(struct torture_context *tctx,
4172                                         struct smb2_tree *tree)
4173 {
4174         const char *fname = "torture_write_rfork_io";
4175         const char *rfork_content = "1234567890";
4176         NTSTATUS status;
4177         bool ret = true;
4178
4179         smb2_util_unlink(tree, fname);
4180
4181         torture_comment(tctx, "Test deleting file with resource fork\n");
4182
4183         ret = torture_setup_file(tctx, tree, fname, false);
4184         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed\n");
4185
4186         ret = write_stream(tree, __location__, tctx, tctx,
4187                            fname, AFPRESOURCE_STREAM_NAME,
4188                            10, 10, rfork_content);
4189         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed\n");
4190
4191         ret = check_stream(tree, __location__, tctx, tctx,
4192                            fname, AFPRESOURCE_STREAM_NAME,
4193                            0, 20, 10, 10, rfork_content);
4194         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed\n");
4195
4196         status = smb2_util_unlink(tree, fname);
4197         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "check_stream failed\n");
4198
4199 done:
4200         return ret;
4201 }
4202
4203 static bool test_rename_and_read_rsrc(struct torture_context *tctx,
4204                                       struct smb2_tree *tree)
4205 {
4206         bool ret = true;
4207         NTSTATUS status;
4208         struct smb2_create create, create2;
4209         struct smb2_handle h1, h2;
4210         const char *fname = "test_rename_openfile";
4211         const char *sname = "test_rename_openfile" AFPRESOURCE_STREAM_NAME;
4212         const char *fname_renamed = "test_rename_openfile_renamed";
4213         const char *data = "1234567890";
4214         union smb_setfileinfo sinfo;
4215         bool server_is_macos = torture_setting_bool(tctx, "osx", false);
4216         NTSTATUS expected_status;
4217
4218         ret = enable_aapl(tctx, tree);
4219         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
4220
4221         torture_comment(tctx, "Create file with resource fork\n");
4222
4223         ret = torture_setup_file(tctx, tree, fname, false);
4224         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4225
4226         ret = write_stream(tree, __location__, tctx, tctx,
4227                            fname, AFPRESOURCE_STREAM_NAME, 0, 10, data);
4228         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4229
4230         torture_comment(tctx, "Open resource fork\n");
4231
4232         ZERO_STRUCT(create);
4233         create.in.desired_access = SEC_FILE_ALL;
4234         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4235         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4236         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4237         create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4238         create.in.fname = sname;
4239
4240         status = smb2_create(tree, tctx, &create);
4241         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4242
4243         h1 = create.out.file.handle;
4244
4245         torture_comment(tctx, "Rename base file\n");
4246
4247         ZERO_STRUCT(create2);
4248         create2.in.desired_access = SEC_FILE_ALL;
4249         create2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4250         create2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4251         create2.in.create_disposition = NTCREATEX_DISP_OPEN;
4252         create2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4253         create2.in.fname = fname;
4254
4255         status = smb2_create(tree, tctx, &create2);
4256         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4257
4258         h2 = create2.out.file.handle;
4259
4260         ZERO_STRUCT(sinfo);
4261         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
4262         sinfo.rename_information.in.file.handle = h2;
4263         sinfo.rename_information.in.overwrite = 0;
4264         sinfo.rename_information.in.root_fid = 0;
4265         sinfo.rename_information.in.new_name = fname_renamed;
4266
4267         if (server_is_macos) {
4268                 expected_status = NT_STATUS_SHARING_VIOLATION;
4269         } else {
4270                 expected_status = NT_STATUS_ACCESS_DENIED;
4271         }
4272
4273         status = smb2_setinfo_file(tree, &sinfo);
4274         torture_assert_ntstatus_equal_goto(
4275                 tctx, status, expected_status, ret, done,
4276                 "smb2_setinfo_file failed");
4277
4278         smb2_util_close(tree, h2);
4279
4280         status = smb2_util_write(tree, h1, "foo", 0, 3);
4281         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4282                                         "write failed\n");
4283
4284         smb2_util_close(tree, h1);
4285
4286 done:
4287         smb2_util_unlink(tree, fname);
4288         smb2_util_unlink(tree, fname_renamed);
4289
4290         return ret;
4291 }
4292
4293 static bool test_readdir_attr_illegal_ntfs(struct torture_context *tctx,
4294                                            struct smb2_tree *tree)
4295 {
4296         TALLOC_CTX *mem_ctx = talloc_new(tctx);
4297         const char *name = "test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
4298         const char *fname = BASEDIR "\\test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
4299         NTSTATUS status;
4300         struct smb2_handle testdirh;
4301         bool ret = true;
4302         struct smb2_create io;
4303         AfpInfo *info;
4304         const char *type_creator = "SMB,OLE!";
4305         struct smb2_find f;
4306         unsigned int count;
4307         union smb_search_data *d;
4308         uint64_t rfork_len;
4309         int i;
4310
4311         smb2_deltree(tree, BASEDIR);
4312
4313         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
4314         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
4315         smb2_util_close(tree, testdirh);
4316
4317         torture_comment(tctx, "Enabling AAPL\n");
4318
4319         ret = enable_aapl(tctx, tree);
4320         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
4321
4322         /*
4323          * Now that Requested AAPL extensions are enabled, setup some
4324          * Mac files with metadata and resource fork
4325          */
4326
4327         torture_comment(tctx, "Preparing file\n");
4328
4329         ret = torture_setup_file(mem_ctx, tree, fname, false);
4330         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
4331
4332         info = torture_afpinfo_new(mem_ctx);
4333         torture_assert_not_null_goto(tctx, info, ret, done, "torture_afpinfo_new failed");
4334
4335         memcpy(info->afpi_FinderInfo, type_creator, 8);
4336         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
4337         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
4338
4339         ret = write_stream(tree, __location__, tctx, mem_ctx,
4340                            fname, AFPRESOURCE_STREAM_NAME,
4341                            0, 3, "foo");
4342         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4343
4344         /*
4345          * Ok, file is prepared, now call smb2/find
4346          */
4347
4348         torture_comment(tctx, "Issue find\n");
4349
4350         ZERO_STRUCT(io);
4351         io.in.desired_access = SEC_RIGHTS_DIR_READ;
4352         io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
4353         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
4354         io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
4355                               NTCREATEX_SHARE_ACCESS_WRITE |
4356                               NTCREATEX_SHARE_ACCESS_DELETE);
4357         io.in.create_disposition = NTCREATEX_DISP_OPEN;
4358         io.in.fname = BASEDIR;
4359         status = smb2_create(tree, tctx, &io);
4360         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4361
4362         ZERO_STRUCT(f);
4363         f.in.file.handle        = io.out.file.handle;
4364         f.in.pattern            = "*";
4365         f.in.max_response_size  = 0x1000;
4366         f.in.level              = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
4367
4368         status = smb2_find_level(tree, tree, &f, &count, &d);
4369         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_level failed");
4370
4371         status = smb2_util_close(tree, io.out.file.handle);
4372         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close failed");
4373
4374         torture_comment(tctx, "Checking find response with enriched macOS metadata\n");
4375
4376         for (i = 0; i < count; i++) {
4377                 const char *found = d[i].id_both_directory_info.name.s;
4378
4379                 if (!strcmp(found, ".") || !strcmp(found, ".."))
4380                         continue;
4381                 if (strncmp(found, "._", 2) == 0) {
4382                         continue;
4383                 }
4384                 break;
4385         }
4386
4387         torture_assert_str_equal_goto(tctx,
4388                                       d[i].id_both_directory_info.name.s, name,
4389                                       ret, done, "bad name");
4390
4391         rfork_len = BVAL(d[i].id_both_directory_info.short_name_buf, 0);
4392         torture_assert_int_equal_goto(tctx, rfork_len, 3, ret, done, "bad resource fork length");
4393
4394         torture_assert_mem_equal_goto(tctx, type_creator,
4395                                       d[i].id_both_directory_info.short_name_buf + 8,
4396                                       8, ret, done, "Bad FinderInfo");
4397 done:
4398         smb2_util_unlink(tree, fname);
4399         smb2_deltree(tree, BASEDIR);
4400         talloc_free(mem_ctx);
4401         return ret;
4402 }
4403
4404 static bool test_invalid_afpinfo(struct torture_context *tctx,
4405                                  struct smb2_tree *tree1,
4406                                  struct smb2_tree *tree2)
4407 {
4408         const char *fname = "filtest_invalid_afpinfo";
4409         const char *sname = "filtest_invalid_afpinfo" AFPINFO_STREAM_NAME;
4410         struct smb2_create create;
4411         const char *streams_basic[] = {
4412                 "::$DATA"
4413         };
4414         const char *streams_afpinfo[] = {
4415                 "::$DATA",
4416                 AFPINFO_STREAM
4417         };
4418         NTSTATUS status;
4419         bool ret = true;
4420
4421         if (tree2 == NULL) {
4422                 torture_skip_goto(tctx, done, "need second share without fruit\n");
4423         }
4424
4425         torture_comment(tctx, "Testing invalid AFP_AfpInfo stream\n");
4426
4427         ret = torture_setup_file(tctx, tree2, fname, false);
4428         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4429
4430         ret = write_stream(tree2, __location__, tctx, tctx,
4431                            fname, AFPINFO_STREAM_NAME,
4432                            0, 3, "foo");
4433         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4434
4435         ret = check_stream_list(tree2, tctx, fname, 2, streams_afpinfo, false);
4436         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4437
4438         torture_comment(tctx, "Listing streams, bad AFPINFO stream must not be present\n");
4439
4440         ret = check_stream_list(tree1, tctx, fname, 1, streams_basic, false);
4441         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4442
4443         torture_comment(tctx, "Try to open AFPINFO stream, must fail\n");
4444
4445         ZERO_STRUCT(create);
4446         create.in.desired_access = SEC_FILE_ALL;
4447         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4448         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4449         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4450         create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4451         create.in.fname = sname;
4452
4453         status = smb2_create(tree1, tctx, &create);
4454         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4455                                            ret, done, "Stream still around?");
4456
4457 done:
4458         smb2_util_unlink(tree1, fname);
4459         return ret;
4460 }
4461
4462 static bool test_zero_file_id(struct torture_context *tctx,
4463                               struct smb2_tree *tree)
4464 {
4465         const char *fname = "filtest_file_id";
4466         struct smb2_create create = {0};
4467         NTSTATUS status;
4468         bool ret = true;
4469         uint8_t zero_file_id[8] = {0};
4470
4471         torture_comment(tctx, "Testing zero file id\n");
4472
4473         ret = torture_setup_file(tctx, tree, fname, false);
4474         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4475
4476         ZERO_STRUCT(create);
4477         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4478         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4479         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4480         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4481         create.in.fname = fname;
4482         create.in.query_on_disk_id = true;
4483
4484         status = smb2_create(tree, tctx, &create);
4485         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
4486                                            done,
4487                                            "test file could not be opened");
4488         torture_assert_mem_not_equal_goto(tctx, create.out.on_disk_id,
4489                                           zero_file_id, 8, ret, done,
4490                                           "unexpected zero file id");
4491
4492         smb2_util_close(tree, create.out.file.handle);
4493
4494         ret = enable_aapl(tctx, tree);
4495         torture_assert(tctx, ret == true, "enable_aapl failed");
4496
4497         ZERO_STRUCT(create);
4498         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4499         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4500         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4501         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4502         create.in.fname = fname;
4503         create.in.query_on_disk_id = true;
4504
4505         status = smb2_create(tree, tctx, &create);
4506         torture_assert_ntstatus_equal_goto(
4507             tctx, status, NT_STATUS_OK, ret, done,
4508             "test file could not be opened with AAPL");
4509         torture_assert_mem_equal_goto(tctx, create.out.on_disk_id, zero_file_id,
4510                                       8, ret, done, "non-zero file id");
4511
4512         smb2_util_close(tree, create.out.file.handle);
4513
4514 done:
4515         smb2_util_unlink(tree, fname);
4516         return ret;
4517 }
4518
4519 static bool copy_one_stream(struct torture_context *torture,
4520                             struct smb2_tree *tree,
4521                             TALLOC_CTX *tmp_ctx,
4522                             const char *src_sname,
4523                             const char *dst_sname)
4524 {
4525         struct smb2_handle src_h = {{0}};
4526         struct smb2_handle dest_h = {{0}};
4527         NTSTATUS status;
4528         union smb_ioctl io;
4529         struct srv_copychunk_copy cc_copy;
4530         struct srv_copychunk_rsp cc_rsp;
4531         enum ndr_err_code ndr_ret;
4532         bool ok = false;
4533
4534         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4535                                    1, /* 1 chunk */
4536                                    src_sname,
4537                                    &src_h, 256, /* fill 256 byte src file */
4538                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4539                                    dst_sname,
4540                                    &dest_h, 0,  /* 0 byte dest file */
4541                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4542                                    &cc_copy,
4543                                    &io);
4544         torture_assert_goto(torture, ok == true, ok, done,
4545                             "setup copy chunk error\n");
4546
4547         /* copy all src file data (via a single chunk desc) */
4548         cc_copy.chunks[0].source_off = 0;
4549         cc_copy.chunks[0].target_off = 0;
4550         cc_copy.chunks[0].length = 256;
4551
4552         ndr_ret = ndr_push_struct_blob(
4553                 &io.smb2.in.out, tmp_ctx, &cc_copy,
4554                 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4555
4556         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4557                                    "ndr_push_srv_copychunk_copy\n");
4558
4559         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4560         torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4561                                         "FSCTL_SRV_COPYCHUNK\n");
4562
4563         ndr_ret = ndr_pull_struct_blob(
4564                 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4565                 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4566
4567         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4568                                    "ndr_pull_srv_copychunk_rsp\n");
4569
4570         ok = check_copy_chunk_rsp(torture, &cc_rsp,
4571                                   1,    /* chunks written */
4572                                   0,    /* chunk bytes unsuccessfully written */
4573                                   256); /* total bytes written */
4574         torture_assert_goto(torture, ok == true, ok, done,
4575                             "bad copy chunk response data\n");
4576
4577         ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 256, 0);
4578         if (!ok) {
4579                 torture_fail(torture, "inconsistent file data\n");
4580         }
4581
4582 done:
4583         if (!smb2_util_handle_empty(src_h)) {
4584                 smb2_util_close(tree, src_h);
4585         }
4586         if (!smb2_util_handle_empty(dest_h)) {
4587                 smb2_util_close(tree, dest_h);
4588         }
4589
4590         return ok;
4591 }
4592
4593 static bool copy_finderinfo_stream(struct torture_context *torture,
4594                                    struct smb2_tree *tree,
4595                                    TALLOC_CTX *tmp_ctx,
4596                                    const char *src_name,
4597                                    const char *dst_name)
4598 {
4599         struct smb2_handle src_h = {{0}};
4600         struct smb2_handle dest_h = {{0}};
4601         NTSTATUS status;
4602         union smb_ioctl io;
4603         struct srv_copychunk_copy cc_copy;
4604         struct srv_copychunk_rsp cc_rsp;
4605         enum ndr_err_code ndr_ret;
4606         const char *type_creator = "SMB,OLE!";
4607         AfpInfo *info = NULL;
4608         const char *src_name_afpinfo = NULL;
4609         const char *dst_name_afpinfo = NULL;
4610         bool ok = false;
4611
4612         src_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", src_name,
4613                                            AFPINFO_STREAM);
4614         torture_assert_not_null_goto(torture, src_name_afpinfo, ok, done,
4615                                      "talloc_asprintf failed\n");
4616
4617         dst_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", dst_name,
4618                                            AFPINFO_STREAM);
4619         torture_assert_not_null_goto(torture, dst_name_afpinfo, ok, done,
4620                                      "talloc_asprintf failed\n");
4621
4622         info = torture_afpinfo_new(tmp_ctx);
4623         torture_assert_not_null_goto(torture, info, ok, done,
4624                                      "torture_afpinfo_new failed\n");
4625
4626         memcpy(info->afpi_FinderInfo, type_creator, 8);
4627         ok = torture_write_afpinfo(tree, torture, tmp_ctx, src_name, info);
4628         torture_assert_goto(torture, ok == true, ok, done,
4629                             "torture_write_afpinfo failed\n");
4630
4631         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4632                                    1, /* 1 chunk */
4633                                    src_name_afpinfo,
4634                                    &src_h, 0,
4635                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4636                                    dst_name_afpinfo,
4637                                    &dest_h, 0,
4638                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4639                                    &cc_copy,
4640                                    &io);
4641         torture_assert_goto(torture, ok == true, ok, done,
4642                             "setup copy chunk error\n");
4643
4644         /* copy all src file data (via a single chunk desc) */
4645         cc_copy.chunks[0].source_off = 0;
4646         cc_copy.chunks[0].target_off = 0;
4647         cc_copy.chunks[0].length = 60;
4648
4649         ndr_ret = ndr_push_struct_blob(
4650                 &io.smb2.in.out, tmp_ctx, &cc_copy,
4651                 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4652
4653         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4654                                    "ndr_push_srv_copychunk_copy\n");
4655
4656         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4657         torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4658                                         "FSCTL_SRV_COPYCHUNK\n");
4659
4660         ndr_ret = ndr_pull_struct_blob(
4661                 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4662                 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4663
4664         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4665                                    "ndr_pull_srv_copychunk_rsp\n");
4666
4667         smb2_util_close(tree, src_h);
4668         ZERO_STRUCT(src_h);
4669         smb2_util_close(tree, dest_h);
4670         ZERO_STRUCT(dest_h);
4671
4672         ok = check_copy_chunk_rsp(torture, &cc_rsp,
4673                                   1,    /* chunks written */
4674                                   0,    /* chunk bytes unsuccessfully written */
4675                                   60); /* total bytes written */
4676         torture_assert_goto(torture, ok == true, ok, done,
4677                             "bad copy chunk response data\n");
4678
4679         ok = check_stream(tree, __location__, torture, tmp_ctx,
4680                           dst_name, AFPINFO_STREAM,
4681                           0, 60, 16, 8, type_creator);
4682         torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
4683
4684 done:
4685         if (!smb2_util_handle_empty(src_h)) {
4686                 smb2_util_close(tree, src_h);
4687         }
4688         if (!smb2_util_handle_empty(dest_h)) {
4689                 smb2_util_close(tree, dest_h);
4690         }
4691
4692         return ok;
4693 }
4694
4695 static bool test_copy_chunk_streams(struct torture_context *torture,
4696                                     struct smb2_tree *tree)
4697 {
4698         const char *src_name = "src";
4699         const char *dst_name = "dst";
4700         struct names {
4701                 const char *src_sname;
4702                 const char *dst_sname;
4703         } names[] = {
4704                 { "src:foo", "dst:foo" },
4705                 { "src" AFPRESOURCE_STREAM, "dst" AFPRESOURCE_STREAM }
4706         };
4707         int i;
4708         TALLOC_CTX *tmp_ctx = NULL;
4709         bool ok = false;
4710
4711         tmp_ctx = talloc_new(tree);
4712         torture_assert_not_null_goto(torture, tmp_ctx, ok, done,
4713                                      "torture_setup_file\n");
4714
4715         smb2_util_unlink(tree, src_name);
4716         smb2_util_unlink(tree, dst_name);
4717
4718         ok = torture_setup_file(torture, tree, src_name, false);
4719         torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
4720         ok = torture_setup_file(torture, tree, dst_name, false);
4721         torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
4722
4723         for (i = 0; i < ARRAY_SIZE(names); i++) {
4724                 ok = copy_one_stream(torture, tree, tmp_ctx,
4725                                      names[i].src_sname,
4726                                      names[i].dst_sname);
4727                 torture_assert_goto(torture, ok == true, ok, done,
4728                                     "copy_one_stream failed\n");
4729         }
4730
4731         ok = copy_finderinfo_stream(torture, tree, tmp_ctx,
4732                                     src_name, dst_name);
4733         torture_assert_goto(torture, ok == true, ok, done,
4734                             "copy_finderinfo_stream failed\n");
4735
4736 done:
4737         smb2_util_unlink(tree, src_name);
4738         smb2_util_unlink(tree, dst_name);
4739         talloc_free(tmp_ctx);
4740         return ok;
4741 }
4742
4743 /*
4744  * Ensure this security descriptor has exactly one mode, uid
4745  * and gid.
4746  */
4747
4748 static NTSTATUS check_nfs_sd(const struct security_descriptor *psd)
4749 {
4750         uint32_t i;
4751         bool got_one_mode = false;
4752         bool got_one_uid = false;
4753         bool got_one_gid = false;
4754
4755         if (psd->dacl == NULL) {
4756                 return NT_STATUS_INVALID_SECURITY_DESCR;
4757         }
4758
4759         for (i = 0; i < psd->dacl->num_aces; i++) {
4760                 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Mode,
4761                                            &psd->dacl->aces[i].trustee) == 0) {
4762                         if (got_one_mode == true) {
4763                                 /* Can't have more than one. */
4764                                 return NT_STATUS_INVALID_SECURITY_DESCR;
4765                         }
4766                         got_one_mode = true;
4767                 }
4768         }
4769         for (i = 0; i < psd->dacl->num_aces; i++) {
4770                 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Users,
4771                                            &psd->dacl->aces[i].trustee) == 0) {
4772                         if (got_one_uid == true) {
4773                                 /* Can't have more than one. */
4774                                 return NT_STATUS_INVALID_SECURITY_DESCR;
4775                         }
4776                         got_one_uid = true;
4777                 }
4778         }
4779         for (i = 0; i < psd->dacl->num_aces; i++) {
4780                 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Groups,
4781                                            &psd->dacl->aces[i].trustee) == 0) {
4782                         if (got_one_gid == true) {
4783                                 /* Can't have more than one. */
4784                                 return NT_STATUS_INVALID_SECURITY_DESCR;
4785                         }
4786                         got_one_gid = true;
4787                 }
4788         }
4789         /* Must have at least one of each. */
4790         if (got_one_mode == false ||
4791                         got_one_uid == false ||
4792                         got_one_gid == false) {
4793                 return NT_STATUS_INVALID_SECURITY_DESCR;
4794         }
4795         return NT_STATUS_OK;
4796 }
4797
4798 static bool test_nfs_aces(struct torture_context *tctx,
4799                           struct smb2_tree *tree)
4800 {
4801         TALLOC_CTX *mem_ctx = talloc_new(tctx);
4802         struct security_ace ace;
4803         struct dom_sid sid;
4804         const char *fname = BASEDIR "\\nfs_aces.txt";
4805         struct smb2_handle h = {{0}};
4806         union smb_fileinfo finfo2;
4807         union smb_setfileinfo set;
4808         struct security_descriptor *psd = NULL;
4809         NTSTATUS status;
4810         bool ret = true;
4811         bool is_osx = torture_setting_bool(tctx, "osx", false);
4812
4813         if (is_osx) {
4814                 torture_skip(tctx, "Test only works with Samba\n");
4815         }
4816
4817         ret = enable_aapl(tctx, tree);
4818         torture_assert(tctx, ret == true, "enable_aapl failed");
4819
4820         /* clean slate ...*/
4821         smb2_util_unlink(tree, fname);
4822         smb2_deltree(tree, fname);
4823         smb2_deltree(tree, BASEDIR);
4824
4825         status = torture_smb2_testdir(tree, BASEDIR, &h);
4826         CHECK_STATUS(status, NT_STATUS_OK);
4827         smb2_util_close(tree, h);
4828
4829         /* Create a test file. */
4830         status = torture_smb2_testfile_access(tree,
4831                                 fname,
4832                                 &h,
4833                                 SEC_STD_READ_CONTROL |
4834                                 SEC_STD_WRITE_DAC |
4835                                 SEC_RIGHTS_FILE_ALL);
4836         CHECK_STATUS(status, NT_STATUS_OK);
4837
4838         /* Get the ACL. */
4839         finfo2.query_secdesc.in.secinfo_flags =
4840                 SECINFO_OWNER |
4841                 SECINFO_GROUP |
4842                 SECINFO_DACL;
4843         finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
4844         finfo2.generic.in.file.handle = h;
4845         status = smb2_getinfo_file(tree, tctx, &finfo2);
4846         CHECK_STATUS(status, NT_STATUS_OK);
4847
4848         psd = finfo2.query_secdesc.out.sd;
4849
4850         /* Ensure we have only single mode/uid/gid NFS entries. */
4851         status = check_nfs_sd(psd);
4852         if (!NT_STATUS_IS_OK(status)) {
4853                 NDR_PRINT_DEBUG(
4854                         security_descriptor,
4855                         discard_const_p(struct security_descriptor, psd));
4856         }
4857         CHECK_STATUS(status, NT_STATUS_OK);
4858
4859         /* Add a couple of extra NFS uids and gids. */
4860         sid_compose(&sid, &global_sid_Unix_NFS_Users, 27);
4861         init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
4862         status = security_descriptor_dacl_add(psd, &ace);
4863         CHECK_STATUS(status, NT_STATUS_OK);
4864         status = security_descriptor_dacl_add(psd, &ace);
4865         CHECK_STATUS(status, NT_STATUS_OK);
4866
4867         sid_compose(&sid, &global_sid_Unix_NFS_Groups, 300);
4868         init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
4869         status = security_descriptor_dacl_add(psd, &ace);
4870         CHECK_STATUS(status, NT_STATUS_OK);
4871         status = security_descriptor_dacl_add(psd, &ace);
4872         CHECK_STATUS(status, NT_STATUS_OK);
4873
4874         /* Now set on the file handle. */
4875         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
4876         set.set_secdesc.in.file.handle = h;
4877         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
4878         set.set_secdesc.in.sd = psd;
4879         status = smb2_setinfo_file(tree, &set);
4880         CHECK_STATUS(status, NT_STATUS_OK);
4881
4882         /* Get the ACL again. */
4883         finfo2.query_secdesc.in.secinfo_flags =
4884                 SECINFO_OWNER |
4885                 SECINFO_GROUP |
4886                 SECINFO_DACL;
4887         finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
4888         finfo2.generic.in.file.handle = h;
4889         status = smb2_getinfo_file(tree, tctx, &finfo2);
4890         CHECK_STATUS(status, NT_STATUS_OK);
4891
4892         psd = finfo2.query_secdesc.out.sd;
4893
4894         /* Ensure we have only single mode/uid/gid NFS entries. */
4895         status = check_nfs_sd(psd);
4896         if (!NT_STATUS_IS_OK(status)) {
4897                 NDR_PRINT_DEBUG(
4898                         security_descriptor,
4899                         discard_const_p(struct security_descriptor, psd));
4900         }
4901         CHECK_STATUS(status, NT_STATUS_OK);
4902
4903 done:
4904         if (!smb2_util_handle_empty(h)) {
4905                 smb2_util_close(tree, h);
4906         }
4907         smb2_util_unlink(tree, fname);
4908         smb2_deltree(tree, fname);
4909         smb2_deltree(tree, BASEDIR);
4910         talloc_free(mem_ctx);
4911         return ret;
4912 }
4913
4914 static bool test_setinfo_stream_eof(struct torture_context *tctx,
4915                                     struct smb2_tree *tree)
4916 {
4917         bool ret = true;
4918         NTSTATUS status;
4919         struct smb2_create create;
4920         union smb_setfileinfo sfinfo;
4921         union smb_fileinfo finfo;
4922         struct smb2_handle h1;
4923         TALLOC_CTX *mem_ctx = talloc_new(tctx);
4924         const char *fname = BASEDIR "\\file";
4925         const char *sname = BASEDIR "\\file:foo";
4926
4927         torture_assert_goto(tctx, mem_ctx != NULL, ret, done,
4928                             "talloc_new failed\n");
4929
4930         torture_comment(tctx, "Test setting EOF on a stream\n");
4931
4932         smb2_deltree(tree, BASEDIR);
4933         status = torture_smb2_testdir(tree, BASEDIR, &h1);
4934         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4935                                         "torture_smb2_testdir\n");
4936         smb2_util_close(tree, h1);
4937
4938         status = torture_smb2_testfile(tree, fname, &h1);
4939         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4940                                         "torture_smb2_testfile failed\n");
4941         smb2_util_close(tree, h1);
4942
4943         status = torture_smb2_testfile_access(tree, sname, &h1,
4944                                               SEC_FILE_WRITE_DATA);
4945         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4946                                         "torture_smb2_testfile failed\n");
4947
4948         status = smb2_util_write(tree, h1, "1234567890", 0, 10);
4949         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4950                                         "smb2_util_write failed\n");
4951         smb2_util_close(tree, h1);
4952
4953         /*
4954          * Test setting EOF to 21
4955          */
4956
4957         torture_comment(tctx, "Setting stream EOF to 21\n");
4958
4959         status = torture_smb2_testfile_access(tree, sname, &h1,
4960                                               SEC_FILE_WRITE_DATA);
4961         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4962                                         "torture_smb2_testfile failed\n");
4963
4964         ZERO_STRUCT(sfinfo);
4965         sfinfo.generic.in.file.handle = h1;
4966         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
4967         sfinfo.position_information.in.position = 21;
4968         status = smb2_setinfo_file(tree, &sfinfo);
4969         torture_assert_ntstatus_ok_goto(tctx, status,
4970                                         ret, done, "set EOF 21 failed\n");
4971
4972         smb2_util_close(tree, h1);
4973
4974         status = torture_smb2_testfile_access(tree, sname, &h1,
4975                                               SEC_FILE_WRITE_DATA);
4976         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4977                                         "torture_smb2_testfile failed\n");
4978
4979         ZERO_STRUCT(finfo);
4980         finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
4981         finfo.generic.in.file.handle = h1;
4982         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
4983         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4984                                         "smb2_getinfo_file failed");
4985
4986         smb2_util_close(tree, h1);
4987
4988         torture_assert_goto(tctx, finfo.standard_info.out.size == 21,
4989                             ret, done, "size != 21\n");
4990
4991         /*
4992          * Test setting EOF to 0
4993          */
4994
4995         torture_comment(tctx, "Setting stream EOF to 0\n");
4996
4997         status = torture_smb2_testfile_access(tree, sname, &h1,
4998                                               SEC_FILE_WRITE_DATA);
4999         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5000                                         "torture_smb2_testfile failed\n");
5001
5002         ZERO_STRUCT(sfinfo);
5003         sfinfo.generic.in.file.handle = h1;
5004         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5005         sfinfo.position_information.in.position = 0;
5006         status = smb2_setinfo_file(tree, &sfinfo);
5007         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5008                                         "set eof 0 failed\n");
5009
5010         smb2_util_close(tree, h1);
5011
5012         status = torture_smb2_testfile_access(tree, sname, &h1,
5013                                               SEC_FILE_WRITE_DATA);
5014         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5015                                         "torture_smb2_testfile failed\n");
5016
5017         ZERO_STRUCT(finfo);
5018         finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5019         finfo.generic.in.file.handle = h1;
5020         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5021         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5022                                         "smb2_getinfo_file failed\n");
5023
5024         smb2_util_close(tree, h1);
5025
5026         torture_assert_goto(tctx, finfo.standard_info.out.size == 0,
5027                             ret, done, "size != 0\n");
5028
5029         /*
5030          * Test setinfo end-of-file info to 1
5031          */
5032
5033         torture_comment(tctx, "Setting stream EOF to 1\n");
5034
5035         status = torture_smb2_testfile_access(tree, sname, &h1,
5036                                               SEC_FILE_WRITE_DATA);
5037         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5038                                         "torture_smb2_testfile failed\n");
5039
5040         ZERO_STRUCT(sfinfo);
5041         sfinfo.generic.in.file.handle = h1;
5042         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5043         sfinfo.position_information.in.position = 1;
5044         status = smb2_setinfo_file(tree, &sfinfo);
5045         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5046                                         "set EOF 1 failed\n");
5047
5048         smb2_util_close(tree, h1);
5049
5050         status = torture_smb2_testfile_access(tree, sname, &h1,
5051                                               SEC_FILE_WRITE_DATA);
5052         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5053                                         "torture_smb2_testfile failed\n");
5054
5055         ZERO_STRUCT(finfo);
5056         finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5057         finfo.generic.in.file.handle = h1;
5058         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5059         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5060                                         "smb2_getinfo_file failed\n");
5061
5062         smb2_util_close(tree, h1);
5063
5064         torture_assert_goto(tctx, finfo.standard_info.out.size == 1,
5065                             ret, done, "size != 1\n");
5066
5067         /*
5068          * Test setting EOF to 0 with AAPL enabled, should delete stream
5069          */
5070
5071         torture_comment(tctx, "Enabling AAPL extensions\n");
5072
5073         ret = enable_aapl(tctx, tree);
5074         torture_assert(tctx, ret == true, "enable_aapl failed\n");
5075
5076         torture_comment(tctx, "Setting stream EOF to 0\n");
5077         status = torture_smb2_testfile_access(tree, sname, &h1,
5078                                               SEC_FILE_WRITE_DATA);
5079         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5080                                         "torture_smb2_testfile failed\n");
5081
5082         ZERO_STRUCT(sfinfo);
5083         sfinfo.generic.in.file.handle = h1;
5084         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5085         sfinfo.position_information.in.position = 0;
5086         status = smb2_setinfo_file(tree, &sfinfo);
5087         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5088                                         "set eof 0 failed\n");
5089
5090         smb2_util_close(tree, h1);
5091
5092         ZERO_STRUCT(create);
5093         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5094         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5095         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5096         create.in.create_disposition = NTCREATEX_DISP_OPEN;
5097         create.in.fname = sname;
5098
5099         status = smb2_create(tree, tctx, &create);
5100         torture_assert_ntstatus_equal_goto(
5101                 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5102                 "Unexpected status\n");
5103
5104         torture_comment(
5105                 tctx, "Setting main file EOF to 1 to force 0-truncate\n");
5106
5107         status = torture_smb2_testfile_access(
5108                 tree,
5109                 fname,
5110                 &h1,
5111                 SEC_FILE_WRITE_DATA);
5112         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5113                                         "torture_smb2_testfile failed\n");
5114
5115         ZERO_STRUCT(sfinfo);
5116         sfinfo.generic.in.file.handle = h1;
5117         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5118         sfinfo.position_information.in.position = 1;
5119         status = smb2_setinfo_file(tree, &sfinfo);
5120         torture_assert_ntstatus_ok_goto(
5121                 tctx,
5122                 status,
5123                 ret,
5124                 done,
5125                 "set eof 1 failed\n");
5126
5127         sfinfo.position_information.in.position = 0;
5128         status = smb2_setinfo_file(tree, &sfinfo);
5129         torture_assert_ntstatus_ok_goto(
5130                 tctx,
5131                 status,
5132                 ret,
5133                 done,
5134                 "set eof 0 failed\n");
5135
5136         smb2_util_close(tree, h1);
5137
5138         ZERO_STRUCT(create);
5139         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5140         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5141         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5142         create.in.create_disposition = NTCREATEX_DISP_OPEN;
5143         create.in.fname = fname;
5144
5145         status = smb2_create(tree, tctx, &create);
5146         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5147                                         "torture_smb2_testfile failed\n");
5148         smb2_util_close(tree, h1);
5149 done:
5150         smb2_util_unlink(tree, fname);
5151         smb2_util_rmdir(tree, BASEDIR);
5152         return ret;
5153 }
5154
5155 /*
5156  * Note: This test depends on "vfs objects = catia fruit streams_xattr".  For
5157  * some tests torture must be run on the host it tests and takes an additional
5158  * argument with the local path to the share:
5159  * "--option=torture:localdir=<SHAREPATH>".
5160  *
5161  * When running against an OS X SMB server add "--option=torture:osx=true"
5162  */
5163 struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx)
5164 {
5165         struct torture_suite *suite = torture_suite_create(
5166                 ctx, "fruit");
5167
5168         suite->description = talloc_strdup(suite, "vfs_fruit tests");
5169
5170         torture_suite_add_1smb2_test(suite, "copyfile", test_copyfile);
5171         torture_suite_add_1smb2_test(suite, "read metadata", test_read_afpinfo);
5172         torture_suite_add_1smb2_test(suite, "write metadata", test_write_atalk_metadata);
5173         torture_suite_add_1smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io);
5174         torture_suite_add_1smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl);
5175         torture_suite_add_1smb2_test(suite, "stream names", test_stream_names);
5176         torture_suite_add_1smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate);
5177         torture_suite_add_1smb2_test(suite, "opening and creating resource fork", test_rfork_create);
5178         torture_suite_add_1smb2_test(suite, "rename_dir_openfile", test_rename_dir_openfile);
5179         torture_suite_add_1smb2_test(suite, "File without AFP_AfpInfo", test_afpinfo_enoent);
5180         torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpInfo", test_create_delete_on_close);
5181         torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpInfo", test_setinfo_delete_on_close);
5182         torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpInfo", test_setinfo_eof);
5183         torture_suite_add_1smb2_test(suite, "delete AFP_AfpInfo by writing all 0", test_afpinfo_all0);
5184         torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpResource", test_create_delete_on_close_resource);
5185         torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpResource", test_setinfo_delete_on_close_resource);
5186         torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpResource", test_setinfo_eof_resource);
5187         torture_suite_add_1smb2_test(suite, "setinfo eof stream", test_setinfo_stream_eof);
5188         torture_suite_add_1smb2_test(suite, "null afpinfo", test_null_afpinfo);
5189         torture_suite_add_1smb2_test(suite, "delete", test_delete_file_with_rfork);
5190         torture_suite_add_1smb2_test(suite, "read open rsrc after rename", test_rename_and_read_rsrc);
5191         torture_suite_add_1smb2_test(suite, "readdir_attr with names with illegal ntfs characters", test_readdir_attr_illegal_ntfs);
5192         torture_suite_add_2ns_smb2_test(suite, "invalid AFP_AfpInfo", test_invalid_afpinfo);
5193         torture_suite_add_1smb2_test(suite, "creating rsrc with read-only access", test_rfork_create_ro);
5194         torture_suite_add_1smb2_test(suite, "copy-chunk streams", test_copy_chunk_streams);
5195         torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
5196         torture_suite_add_1smb2_test(suite, "NFS ACE entries", test_nfs_aces);
5197         torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion without embedded xattr", test_adouble_conversion_wo_xattr);
5198
5199         return suite;
5200 }
5201
5202 static bool test_stream_names_local(struct torture_context *tctx,
5203                                     struct smb2_tree *tree)
5204 {
5205         TALLOC_CTX *mem_ctx = talloc_new(tctx);
5206         NTSTATUS status;
5207         struct smb2_create create;
5208         struct smb2_handle h;
5209         const char *fname = BASEDIR "\\stream_names.txt";
5210         const char *sname1;
5211         bool ret;
5212         /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
5213         const char *streams[] = {
5214                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
5215                 ":bar" "\xef\x80\xa2" "baz:$DATA", /* "bar:baz:$DATA" */
5216                 "::$DATA"
5217         };
5218         const char *localdir = NULL;
5219
5220         localdir = torture_setting_string(tctx, "localdir", NULL);
5221         if (localdir == NULL) {
5222                 torture_skip(tctx, "Need localdir for test");
5223         }
5224
5225         sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
5226
5227         /* clean slate ...*/
5228         smb2_util_unlink(tree, fname);
5229         smb2_deltree(tree, fname);
5230         smb2_deltree(tree, BASEDIR);
5231
5232         status = torture_smb2_testdir(tree, BASEDIR, &h);
5233         CHECK_STATUS(status, NT_STATUS_OK);
5234         smb2_util_close(tree, h);
5235
5236         torture_comment(tctx, "(%s) testing stream names\n", __location__);
5237         ZERO_STRUCT(create);
5238         create.in.desired_access = SEC_FILE_WRITE_DATA;
5239         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5240         create.in.share_access =
5241                 NTCREATEX_SHARE_ACCESS_DELETE|
5242                 NTCREATEX_SHARE_ACCESS_READ|
5243                 NTCREATEX_SHARE_ACCESS_WRITE;
5244         create.in.create_disposition = NTCREATEX_DISP_CREATE;
5245         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
5246         create.in.fname = sname1;
5247
5248         status = smb2_create(tree, mem_ctx, &create);
5249         CHECK_STATUS(status, NT_STATUS_OK);
5250         smb2_util_close(tree, create.out.file.handle);
5251
5252         ret = torture_setup_local_xattr(tctx, "localdir", BASEDIR "/stream_names.txt",
5253                                         "user.DosStream.bar:baz:$DATA",
5254                                         "data", strlen("data"));
5255         CHECK_VALUE(ret, true);
5256
5257         ret = check_stream_list(tree, tctx, fname, 3, streams, false);
5258         CHECK_VALUE(ret, true);
5259
5260 done:
5261         status = smb2_util_unlink(tree, fname);
5262         smb2_deltree(tree, BASEDIR);
5263         talloc_free(mem_ctx);
5264
5265         return ret;
5266 }
5267
5268 static bool test_fruit_locking_conflict(struct torture_context *tctx,
5269                                         struct smb2_tree *tree)
5270 {
5271         TALLOC_CTX *mem_ctx;
5272         struct smb2_create create;
5273         struct smb2_handle h;
5274         struct smb2_lock lck;
5275         struct smb2_lock_element el;
5276         const char *fname = BASEDIR "\\locking_conflict.txt";
5277         NTSTATUS status;
5278         bool ret = false;
5279
5280         mem_ctx = talloc_new(tctx);
5281         torture_assert_not_null(tctx, mem_ctx, "talloc_new failed");
5282
5283         /* clean slate ...*/
5284         smb2_util_unlink(tree, fname);
5285         smb2_deltree(tree, fname);
5286         smb2_deltree(tree, BASEDIR);
5287
5288         status = torture_smb2_testdir(tree, BASEDIR, &h);
5289         CHECK_STATUS(status, NT_STATUS_OK);
5290         smb2_util_close(tree, h);
5291
5292         create = (struct smb2_create) {
5293                 .in.desired_access = SEC_RIGHTS_FILE_READ,
5294                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
5295                 .in.share_access =
5296                 NTCREATEX_SHARE_ACCESS_READ|
5297                 NTCREATEX_SHARE_ACCESS_WRITE,
5298                 .in.create_disposition = NTCREATEX_DISP_CREATE,
5299                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
5300                 .in.fname = fname,
5301         };
5302
5303         status = smb2_create(tree, mem_ctx, &create);
5304         CHECK_STATUS(status, NT_STATUS_OK);
5305         h = create.out.file.handle;
5306
5307         el = (struct smb2_lock_element) {
5308                 .offset = 0xfffffffffffffffc,
5309                 .length = 1,
5310                 .flags = SMB2_LOCK_FLAG_EXCLUSIVE,
5311         };
5312         lck = (struct smb2_lock) {
5313                 .in.lock_count = 1,
5314                 .in.file.handle = h,
5315                 .in.locks = &el,
5316         };
5317
5318         status = smb2_lock(tree, &lck);
5319         CHECK_STATUS(status, NT_STATUS_OK);
5320
5321         el = (struct smb2_lock_element) {
5322                 .offset = 0,
5323                 .length = 0x7fffffffffffffff,
5324                 .flags = SMB2_LOCK_FLAG_EXCLUSIVE,
5325         };
5326         status = smb2_lock(tree, &lck);
5327         CHECK_STATUS(status, NT_STATUS_OK);
5328
5329         create = (struct smb2_create) {
5330                 .in.desired_access =
5331                 SEC_RIGHTS_FILE_READ|SEC_RIGHTS_FILE_WRITE,
5332                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
5333                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
5334                 .in.create_disposition = NTCREATEX_DISP_OPEN,
5335                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
5336                 .in.fname = fname,
5337         };
5338
5339         status = smb2_create(tree, mem_ctx, &create);
5340         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
5341
5342         {
5343                 struct smb2_close cl = {
5344                         .level = RAW_CLOSE_SMB2,
5345                         .in.file.handle = h,
5346                 };
5347                 smb2_close(tree, &cl);
5348         }
5349
5350         ret = true;
5351 done:
5352         return ret;
5353 }
5354
5355 struct torture_suite *torture_vfs_fruit_netatalk(TALLOC_CTX *ctx)
5356 {
5357         struct torture_suite *suite = torture_suite_create(
5358                 ctx, "fruit_netatalk");
5359
5360         suite->description = talloc_strdup(suite, "vfs_fruit tests for Netatalk interop that require fruit:metadata=netatalk");
5361
5362         torture_suite_add_1smb2_test(suite, "read netatalk metadata", test_read_netatalk_metadata);
5363         torture_suite_add_1smb2_test(suite, "stream names with locally created xattr", test_stream_names_local);
5364         torture_suite_add_1smb2_test(
5365                 suite, "locking conflict", test_fruit_locking_conflict);
5366
5367         return suite;
5368 }
5369
5370 struct torture_suite *torture_vfs_fruit_file_id(TALLOC_CTX *ctx)
5371 {
5372         struct torture_suite *suite =
5373             torture_suite_create(ctx, "fruit_file_id");
5374
5375         suite->description =
5376             talloc_strdup(suite, "vfs_fruit tests for on-disk file ID that "
5377                                  "require fruit:zero_file_id=yes");
5378
5379         torture_suite_add_1smb2_test(suite, "zero file id if AAPL negotiated",
5380                                      test_zero_file_id);
5381
5382         return suite;
5383 }
5384
5385 static bool test_timemachine_volsize(struct torture_context *tctx,
5386                                      struct smb2_tree *tree)
5387 {
5388         TALLOC_CTX *mem_ctx = talloc_new(tctx);
5389         struct smb2_handle h = {{0}};
5390         union smb_fsinfo fsinfo;
5391         NTSTATUS status;
5392         bool ok = true;
5393         const char *info_plist =
5394                 "<dict>\n"
5395                 "        <key>band-size</key>\n"
5396                 "        <integer>8192</integer>\n"
5397                 "</dict>\n";
5398
5399         smb2_deltree(tree, "test.sparsebundle");
5400
5401         ok = enable_aapl(tctx, tree);
5402         torture_assert_goto(tctx, ok, ok, done, "enable_aapl failed");
5403
5404         status = smb2_util_mkdir(tree, "test.sparsebundle");
5405         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
5406                                         "smb2_util_mkdir\n");
5407
5408         ok = write_stream(tree, __location__, tctx, mem_ctx,
5409                           "test.sparsebundle/Info.plist", NULL,
5410                            0, strlen(info_plist), info_plist);
5411         torture_assert_goto(tctx, ok, ok, done, "write_stream failed\n");
5412
5413         status = smb2_util_mkdir(tree, "test.sparsebundle/bands");
5414         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
5415                                         "smb2_util_mkdir\n");
5416
5417         ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/1", false);
5418         torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
5419
5420         ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/2", false);
5421         torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
5422
5423         status = smb2_util_roothandle(tree, &h);
5424         torture_assert_ntstatus_ok(tctx, status, "Unable to create root handle");
5425
5426         ZERO_STRUCT(fsinfo);
5427         fsinfo.generic.level = RAW_QFS_SIZE_INFORMATION;
5428         fsinfo.generic.handle = h;
5429
5430         status = smb2_getinfo_fs(tree, tree, &fsinfo);
5431         torture_assert_ntstatus_ok(tctx, status, "smb2_getinfo_fs failed");
5432
5433         torture_comment(tctx, "sectors_per_unit: %" PRIu32"\n"
5434                         "bytes_per_sector: %" PRIu32"\n"
5435                         "total_alloc_units: %" PRIu64"\n"
5436                         "avail_alloc_units: %" PRIu64"\n",
5437                         fsinfo.size_info.out.sectors_per_unit,
5438                         fsinfo.size_info.out.bytes_per_sector,
5439                         fsinfo.size_info.out.total_alloc_units,
5440                         fsinfo.size_info.out.avail_alloc_units);
5441
5442         /*
5443          * Let me explain the numbers:
5444          *
5445          * - the share is set to "fruit:time machine max size = 32K"
5446          * - we've faked a bandsize of 8 K in the Info.plist file
5447          * - we've created two bands files
5448          * - one allocation unit is made of two sectors with 512 B each
5449          * => we've consumed 16 allocation units, there should be 16 free
5450          */
5451
5452         torture_assert_goto(tctx, fsinfo.size_info.out.sectors_per_unit == 2,
5453                             ok, done, "Bad sectors_per_unit");
5454
5455         torture_assert_goto(tctx, fsinfo.size_info.out.bytes_per_sector == 512,
5456                             ok, done, "Bad bytes_per_sector");
5457
5458         torture_assert_goto(tctx, fsinfo.size_info.out.total_alloc_units == 32,
5459                             ok, done, "Bad total_alloc_units");
5460
5461         torture_assert_goto(tctx, fsinfo.size_info.out.avail_alloc_units == 16,
5462                             ok, done, "Bad avail_alloc_units");
5463
5464 done:
5465         if (!smb2_util_handle_empty(h)) {
5466                 smb2_util_close(tree, h);
5467         }
5468         smb2_deltree(tree, "test.sparsebundle");
5469         talloc_free(mem_ctx);
5470         return ok;
5471 }
5472
5473 struct torture_suite *torture_vfs_fruit_timemachine(TALLOC_CTX *ctx)
5474 {
5475         struct torture_suite *suite = torture_suite_create(
5476                 ctx, "fruit_timemachine");
5477
5478         suite->description = talloc_strdup(
5479                 suite, "vfs_fruit tests for TimeMachine");
5480
5481         torture_suite_add_1smb2_test(suite, "Timemachine-volsize",
5482                                      test_timemachine_volsize);
5483
5484         return suite;
5485 }
5486
5487 static bool test_convert_xattr_and_empty_rfork_then_delete(
5488         struct torture_context *tctx,
5489         struct smb2_tree *tree1,
5490         struct smb2_tree *tree2)
5491 {
5492         TALLOC_CTX *mem_ctx = talloc_new(tctx);
5493         const char *fname = BASEDIR "\\test_adouble_conversion";
5494         const char *adname = BASEDIR "/._test_adouble_conversion";
5495         const char *rfork = BASEDIR "\\test_adouble_conversion" AFPRESOURCE_STREAM_NAME;
5496         NTSTATUS status;
5497         struct smb2_handle testdirh;
5498         bool ret = true;
5499         const char *streams[] = {
5500                 "::$DATA",
5501                 AFPINFO_STREAM,
5502                 ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
5503                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
5504         };
5505         struct smb2_create create;
5506         struct smb2_find find;
5507         unsigned int count;
5508         union smb_search_data *d;
5509         bool delete_empty_adfiles;
5510         int expected_num_files;
5511
5512         delete_empty_adfiles = torture_setting_bool(tctx,
5513                                                     "delete_empty_adfiles",
5514                                                     false);
5515
5516         smb2_deltree(tree1, BASEDIR);
5517
5518         status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
5519         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5520                                         "torture_smb2_testdir failed\n");
5521         smb2_util_close(tree1, testdirh);
5522
5523         ret = torture_setup_file(tctx, tree1, fname, false);
5524         torture_assert_goto(tctx, ret == true, ret, done,
5525                             "torture_setup_file failed\n");
5526
5527         ret = torture_setup_file(tctx, tree1, adname, false);
5528         torture_assert_goto(tctx, ret == true, ret, done,
5529                             "torture_setup_file failed\n");
5530
5531         ret = write_stream(tree1, __location__, tctx, mem_ctx,
5532                            adname, NULL,
5533                            0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr);
5534         torture_assert_goto(tctx, ret == true, ret, done,
5535                             "write_stream failed\n");
5536
5537         ret = enable_aapl(tctx, tree2);
5538         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
5539
5540         /*
5541          * Issue a smb2_find(), this triggers the server-side conversion
5542          */
5543
5544         create = (struct smb2_create) {
5545                 .in.desired_access = SEC_RIGHTS_DIR_READ,
5546                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
5547                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
5548                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
5549                 .in.create_disposition = NTCREATEX_DISP_OPEN,
5550                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
5551                 .in.fname = BASEDIR,
5552         };
5553
5554         status = smb2_create(tree2, tctx, &create);
5555         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5556                                         "smb2_create failed\n");
5557
5558         find = (struct smb2_find) {
5559                 .in.file.handle = create.out.file.handle,
5560                 .in.pattern = "*",
5561                 .in.max_response_size = 0x1000,
5562                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
5563         };
5564
5565         status = smb2_find_level(tree2, tree2, &find, &count, &d);
5566         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5567                                         "smb2_find_level failed\n");
5568
5569         status = smb2_util_close(tree2, create.out.file.handle);
5570         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5571                                         "smb2_util_close failed");
5572
5573         /*
5574          * Check number of streams
5575          */
5576
5577         ret = check_stream_list(tree2, tctx, fname, 4, streams, false);
5578         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
5579
5580         /*
5581          * Check Resource Fork is gone
5582          */
5583
5584         create = (struct smb2_create) {
5585                 .in.desired_access = SEC_RIGHTS_FILE_READ|SEC_RIGHTS_FILE_WRITE,
5586                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
5587                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
5588                 .in.create_disposition = NTCREATEX_DISP_OPEN,
5589                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
5590                 .in.fname = rfork,
5591         };
5592
5593         status = smb2_create(tree2, mem_ctx, &create);
5594         torture_assert_ntstatus_equal_goto(
5595                 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
5596                 ret, done, "Bad smb2_create return\n");
5597
5598         /*
5599          * Check xattr data has been migrated from the AppleDouble file to
5600          * streams.
5601          */
5602
5603         ret = check_stream(tree2, __location__, tctx, mem_ctx,
5604                            fname, AFPINFO_STREAM,
5605                            0, 60, 16, 8, "TESTSLOW");
5606         torture_assert_goto(tctx, ret == true, ret, done,
5607                             "check AFPINFO_STREAM failed\n");
5608
5609         ret = check_stream(tree2, __location__, tctx, mem_ctx,
5610                            fname, ":foo" "\xef\x80\xa2" "bar", /* foo:bar */
5611                            0, 3, 0, 3, "baz");
5612         torture_assert_goto(tctx, ret == true, ret, done,
5613                             "check foo stream failed\n");
5614
5615         /*
5616          * Now check number of files. If delete_empty_adfiles is set, the
5617          * AppleDouble files should have been deleted.
5618          */
5619
5620         create = (struct smb2_create) {
5621                 .in.desired_access = SEC_RIGHTS_DIR_READ,
5622                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
5623                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
5624                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
5625                 .in.create_disposition = NTCREATEX_DISP_OPEN,
5626                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
5627                 .in.fname = BASEDIR,
5628         };
5629
5630         status = smb2_create(tree2, tctx, &create);
5631         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5632                                         "smb2_create failed\n");
5633
5634         find = (struct smb2_find) {
5635                 .in.file.handle = create.out.file.handle,
5636                 .in.pattern = "*",
5637                 .in.max_response_size = 0x1000,
5638                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
5639         };
5640
5641         status = smb2_find_level(tree2, tree2, &find, &count, &d);
5642         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5643                                         "smb2_find_level failed\n");
5644
5645         status = smb2_util_close(tree2, create.out.file.handle);
5646         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5647                                         "smb2_util_close failed");
5648
5649         if (delete_empty_adfiles) {
5650                 expected_num_files = 3;
5651         } else {
5652                 expected_num_files = 4;
5653         }
5654         torture_assert_int_equal_goto(tctx, count, expected_num_files, ret, done,
5655                                       "Wrong number of files\n");
5656
5657 done:
5658         smb2_deltree(tree1, BASEDIR);
5659         talloc_free(mem_ctx);
5660         return ret;
5661 }
5662
5663 struct torture_suite *torture_vfs_fruit_conversion(TALLOC_CTX *ctx)
5664 {
5665         struct torture_suite *suite = torture_suite_create(
5666                 ctx, "fruit_conversion");
5667
5668         suite->description = talloc_strdup(
5669                 suite, "vfs_fruit conversion tests");
5670
5671         torture_suite_add_2ns_smb2_test(
5672                 suite, "convert_xattr_and_empty_rfork_then_delete",
5673                 test_convert_xattr_and_empty_rfork_then_delete);
5674
5675         return suite;
5676 }