s4:torture/vfs/fruit: add test "empty_stream"
[amitay/samba.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         ret = enable_aapl(tctx, tree);
1814         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
1815
1816         smb2_util_unlink(tree, fname);
1817
1818         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1819         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1820         smb2_util_close(tree, testdirh);
1821
1822         ret = torture_setup_file(mem_ctx, tree, fname, false);
1823         if (ret == false) {
1824                 goto done;
1825         }
1826
1827         ret &= write_stream(tree, __location__, tctx, mem_ctx,
1828                             fname, AFPRESOURCE_STREAM,
1829                             10, 10, rfork_content);
1830
1831         /* Truncate back to size 0, further access MUST return ENOENT */
1832
1833         torture_comment(tctx, "(%s) truncate resource fork to size 0\n",
1834                         __location__);
1835
1836         ZERO_STRUCT(create);
1837         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1838         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1839         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1840         create.in.fname               = fname;
1841         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1842                 NTCREATEX_SHARE_ACCESS_READ |
1843                 NTCREATEX_SHARE_ACCESS_WRITE;
1844         status = smb2_create(tree, mem_ctx, &create);
1845         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1846         fh1 = create.out.file.handle;
1847
1848         ZERO_STRUCT(create);
1849         create.in.create_disposition  = NTCREATEX_DISP_OPEN_IF;
1850         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1851         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1852         create.in.fname               = rfork;
1853         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1854                 NTCREATEX_SHARE_ACCESS_READ |
1855                 NTCREATEX_SHARE_ACCESS_WRITE;
1856         status = smb2_create(tree, mem_ctx, &create);
1857         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1858         fh2 = create.out.file.handle;
1859
1860         ZERO_STRUCT(sinfo);
1861         sinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1862         sinfo.end_of_file_info.in.file.handle = fh2;
1863         sinfo.end_of_file_info.in.size = 0;
1864         status = smb2_setinfo_file(tree, &sinfo);
1865         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file");
1866
1867         /*
1868          * Now check size, we should get OBJECT_NAME_NOT_FOUND (!)
1869          */
1870         ZERO_STRUCT(create);
1871         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1872         create.in.desired_access      = SEC_FILE_ALL;
1873         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1874         create.in.fname               = rfork;
1875         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1876                 NTCREATEX_SHARE_ACCESS_READ |
1877                 NTCREATEX_SHARE_ACCESS_WRITE;
1878         status = smb2_create(tree, mem_ctx, &create);
1879         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1880
1881         /*
1882          * Do another open on the rfork and write to the new handle. A
1883          * naive server might unlink the AppleDouble resource fork
1884          * file when its truncated to 0 bytes above, so in case both
1885          * open handles share the same underlying fd, the unlink would
1886          * cause the below write to be lost.
1887          */
1888         ZERO_STRUCT(create);
1889         create.in.create_disposition  = NTCREATEX_DISP_OPEN_IF;
1890         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1891         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1892         create.in.fname               = rfork;
1893         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1894                 NTCREATEX_SHARE_ACCESS_READ |
1895                 NTCREATEX_SHARE_ACCESS_WRITE;
1896         status = smb2_create(tree, mem_ctx, &create);
1897         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1898         fh3 = create.out.file.handle;
1899
1900         status = smb2_util_write(tree, fh3, "foo", 0, 3);
1901         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write");
1902
1903         smb2_util_close(tree, fh3);
1904         smb2_util_close(tree, fh2);
1905         smb2_util_close(tree, fh1);
1906
1907         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM,
1908                            0, 3, 0, 3, "foo");
1909         torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
1910
1911 done:
1912         smb2_util_unlink(tree, fname);
1913         smb2_deltree(tree, BASEDIR);
1914         talloc_free(mem_ctx);
1915         return ret;
1916 }
1917
1918 static bool test_rfork_create(struct torture_context *tctx,
1919                               struct smb2_tree *tree)
1920 {
1921         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1922         const char *fname = BASEDIR "\\torture_rfork_create";
1923         const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
1924         NTSTATUS status;
1925         struct smb2_handle testdirh;
1926         bool ret = true;
1927         struct smb2_create create;
1928         struct smb2_handle fh1;
1929         const char *streams[] = {
1930                 "::$DATA"
1931         };
1932         union smb_fileinfo finfo;
1933
1934         ret = enable_aapl(tctx, tree);
1935         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
1936
1937         smb2_util_unlink(tree, fname);
1938
1939         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1940         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1941         smb2_util_close(tree, testdirh);
1942
1943         ret = torture_setup_file(mem_ctx, tree, fname, false);
1944         if (ret == false) {
1945                 goto done;
1946         }
1947
1948         torture_comment(tctx, "(%s) open rfork, should return ENOENT\n",
1949                         __location__);
1950
1951         ZERO_STRUCT(create);
1952         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1953         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1954         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1955         create.in.fname               = rfork;
1956         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1957                 NTCREATEX_SHARE_ACCESS_READ |
1958                 NTCREATEX_SHARE_ACCESS_WRITE;
1959         status = smb2_create(tree, mem_ctx, &create);
1960         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1961
1962         torture_comment(tctx, "(%s) create resource fork\n", __location__);
1963
1964         ZERO_STRUCT(create);
1965         create.in.create_disposition  = NTCREATEX_DISP_OPEN_IF;
1966         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1967         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1968         create.in.fname               = rfork;
1969         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1970                 NTCREATEX_SHARE_ACCESS_READ |
1971                 NTCREATEX_SHARE_ACCESS_WRITE;
1972         status = smb2_create(tree, mem_ctx, &create);
1973         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1974         fh1 = create.out.file.handle;
1975
1976         torture_comment(tctx, "(%s) getinfo on create handle\n",
1977                         __location__);
1978
1979         ZERO_STRUCT(finfo);
1980         finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1981         finfo.generic.in.file.handle = fh1;
1982         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1983         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file");
1984         if (finfo.all_info.out.size != 0) {
1985                 torture_result(tctx, TORTURE_FAIL,
1986                                "(%s) Incorrect resource fork size\n",
1987                                __location__);
1988                 ret = false;
1989                 smb2_util_close(tree, fh1);
1990                 goto done;
1991         }
1992
1993         torture_comment(tctx, "(%s) open rfork, should still return ENOENT\n",
1994                         __location__);
1995
1996         ZERO_STRUCT(create);
1997         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1998         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1999         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
2000         create.in.fname               = rfork;
2001         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
2002                 NTCREATEX_SHARE_ACCESS_READ |
2003                 NTCREATEX_SHARE_ACCESS_WRITE;
2004         status = smb2_create(tree, mem_ctx, &create);
2005         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
2006
2007         ret = check_stream_list(tree, tctx, fname, 1, streams, false);
2008         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2009
2010         torture_comment(tctx, "(%s) close empty created rfork, open should return ENOENT\n",
2011                         __location__);
2012
2013         ZERO_STRUCT(create);
2014         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
2015         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
2016         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
2017         create.in.fname               = rfork;
2018         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
2019                 NTCREATEX_SHARE_ACCESS_READ |
2020                 NTCREATEX_SHARE_ACCESS_WRITE;
2021         status = smb2_create(tree, mem_ctx, &create);
2022         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
2023
2024 done:
2025         smb2_util_unlink(tree, fname);
2026         smb2_deltree(tree, BASEDIR);
2027         talloc_free(mem_ctx);
2028         return ret;
2029 }
2030
2031 static bool test_rfork_create_ro(struct torture_context *tctx,
2032                                  struct smb2_tree *tree)
2033 {
2034         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2035         const char *fname = BASEDIR "\\torture_rfork_create";
2036         const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
2037         NTSTATUS status;
2038         struct smb2_handle testdirh;
2039         bool ret = true;
2040         struct smb2_create create;
2041
2042         smb2_util_unlink(tree, fname);
2043         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2044         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2045                 "torture_smb2_testdir\n");
2046         smb2_util_close(tree, testdirh);
2047
2048         ret = torture_setup_file(mem_ctx, tree, fname, false);
2049         if (ret == false) {
2050                 goto done;
2051         }
2052
2053         torture_comment(tctx, "(%s) Try opening read-only with "
2054                         "open_if create disposition, should work\n",
2055                         __location__);
2056
2057         ZERO_STRUCT(create);
2058         create.in.fname = rfork;
2059         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2060         create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
2061         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2062         create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
2063         status = smb2_create(tree, mem_ctx, &(create));
2064         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2065                 "smb2_create failed\n");
2066
2067         smb2_util_close(tree, create.out.file.handle);
2068
2069 done:
2070         smb2_util_unlink(tree, fname);
2071         smb2_deltree(tree, BASEDIR);
2072         talloc_free(mem_ctx);
2073         return ret;
2074 }
2075
2076 static bool test_adouble_conversion(struct torture_context *tctx,
2077                                     struct smb2_tree *tree)
2078 {
2079         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2080         const char *fname = BASEDIR "\\test_adouble_conversion";
2081         const char *adname = BASEDIR "/._test_adouble_conversion";
2082         NTSTATUS status;
2083         struct smb2_handle testdirh;
2084         bool ret = true;
2085         const char *data = "This resource fork intentionally left blank";
2086         size_t datalen = strlen(data);
2087         const char *streams[] = {
2088                 "::$DATA",
2089                 AFPINFO_STREAM,
2090                 AFPRESOURCE_STREAM,
2091                 ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
2092                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2093         };
2094         bool is_osx = torture_setting_bool(tctx, "osx", false);
2095
2096         if (is_osx) {
2097                 torture_skip(tctx, "Test only works with Samba\n");
2098         }
2099
2100         smb2_deltree(tree, BASEDIR);
2101
2102         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2103         CHECK_STATUS(status, NT_STATUS_OK);
2104         smb2_util_close(tree, testdirh);
2105
2106         ret = torture_setup_file(tctx, tree, fname, false);
2107         torture_assert_goto(tctx, ret == true, ret, done,
2108                             "torture_setup_file failed\n");
2109
2110         ret = torture_setup_file(tctx, tree, adname, false);
2111         torture_assert_goto(tctx, ret == true, ret, done,
2112                             "torture_setup_file failed\n");
2113
2114         ret = write_stream(tree, __location__, tctx, mem_ctx,
2115                            adname, NULL,
2116                            0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr);
2117         torture_assert_goto(tctx, ret == true, ret, done,
2118                             "write_stream failed\n");
2119
2120         torture_comment(tctx, "(%s) test OS X AppleDouble conversion\n",
2121             __location__);
2122
2123         ret = check_stream(tree, __location__, tctx, mem_ctx,
2124                            fname, AFPRESOURCE_STREAM,
2125                            16, datalen, 0, datalen, data);
2126         torture_assert_goto(tctx, ret == true, ret, done,
2127                             "check AFPRESOURCE_STREAM failed\n");
2128
2129         ret = check_stream(tree, __location__, tctx, mem_ctx,
2130                            fname, AFPINFO_STREAM,
2131                            0, 60, 16, 8, "TESTSLOW");
2132         torture_assert_goto(tctx, ret == true, ret, done,
2133                             "check AFPINFO_STREAM failed\n");
2134
2135         ret = check_stream(tree, __location__, tctx, mem_ctx, fname,
2136                            ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2137                            0, 3, 0, 3, "baz");
2138         torture_assert_goto(tctx, ret == true, ret, done,
2139                             "check foo:bar stream failed\n");
2140
2141         ret = check_stream_list(tree, tctx, fname, 5, streams, false);
2142         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2143
2144 done:
2145         smb2_deltree(tree, BASEDIR);
2146         talloc_free(mem_ctx);
2147         return ret;
2148 }
2149
2150 /*
2151  * Test conversion of AppleDouble file without embedded xattr data
2152  */
2153 static bool test_adouble_conversion_wo_xattr(struct torture_context *tctx,
2154                                              struct smb2_tree *tree)
2155 {
2156         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2157         const char *fname = BASEDIR "\\test_adouble_conversion";
2158         const char *adname = BASEDIR "/._test_adouble_conversion";
2159         NTSTATUS status;
2160         struct smb2_handle testdirh;
2161         bool ret = true;
2162         const char *streams[] = {
2163                 "::$DATA",
2164                 AFPINFO_STREAM,
2165                 AFPRESOURCE_STREAM
2166         };
2167         struct smb2_create create;
2168         struct smb2_find find;
2169         unsigned int count;
2170         union smb_search_data *d;
2171         const char *data = "This resource fork intentionally left blank";
2172         size_t datalen = strlen(data);
2173         bool is_osx = torture_setting_bool(tctx, "osx", false);
2174
2175         if (is_osx) {
2176                 torture_skip(tctx, "Test only works with Samba\n");
2177         }
2178
2179         smb2_deltree(tree, BASEDIR);
2180
2181         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2182         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2183                                         "torture_smb2_testdir failed\n");
2184         smb2_util_close(tree, testdirh);
2185
2186         ret = torture_setup_file(tctx, tree, fname, false);
2187         torture_assert_goto(tctx, ret == true, ret, done,
2188                             "torture_setup_file failed\n");
2189
2190         ret = torture_setup_file(tctx, tree, adname, false);
2191         torture_assert_goto(tctx, ret == true, ret, done,
2192                             "torture_setup_file failed\n");
2193
2194         ret = write_stream(tree, __location__, tctx, mem_ctx,
2195                            adname, NULL, 0,
2196                            sizeof(osx_adouble_without_xattr),
2197                            osx_adouble_without_xattr);
2198         torture_assert_goto(tctx, ret == true, ret, done,
2199                             "write_stream failed\n");
2200
2201         ret = enable_aapl(tctx, tree);
2202         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
2203
2204         /*
2205          * Issue a smb2_find(), this triggers the server-side conversion
2206          */
2207
2208         create = (struct smb2_create) {
2209                 .in.desired_access = SEC_RIGHTS_DIR_READ,
2210                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
2211                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
2212                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
2213                 .in.create_disposition = NTCREATEX_DISP_OPEN,
2214                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
2215                 .in.fname = BASEDIR,
2216         };
2217
2218         status = smb2_create(tree, tctx, &create);
2219         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2220                                         "smb2_create failed\n");
2221
2222         find = (struct smb2_find) {
2223                 .in.file.handle = create.out.file.handle,
2224                 .in.pattern = "*",
2225                 .in.max_response_size = 0x1000,
2226                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
2227         };
2228
2229         status = smb2_find_level(tree, tree, &find, &count, &d);
2230         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2231                                         "smb2_find_level failed\n");
2232
2233         status = smb2_util_close(tree, create.out.file.handle);
2234         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2235                                         "smb2_util_close failed");
2236
2237         /*
2238          * Check number of streams
2239          */
2240
2241         ret = check_stream_list(tree, tctx, fname, 3, streams, false);
2242         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2243
2244
2245         /*
2246          * Check Resourcefork data can be read.
2247          */
2248
2249         ret = check_stream(tree, __location__, tctx, mem_ctx,
2250                            fname, AFPRESOURCE_STREAM,
2251                            16, datalen, 0, datalen, data);
2252         torture_assert_goto(tctx, ret == true, ret, done,
2253                             "check AFPRESOURCE_STREAM failed\n");
2254
2255         /*
2256          * Check FinderInfo data has been migrated to stream.
2257          */
2258
2259         ret = check_stream(tree, __location__, tctx, mem_ctx,
2260                            fname, AFPINFO_STREAM,
2261                            0, 60, 16, 8, "WAVEPTul");
2262         torture_assert_goto(tctx, ret == true, ret, done,
2263                             "check AFPINFO_STREAM failed\n");
2264
2265 done:
2266         smb2_deltree(tree, BASEDIR);
2267         talloc_free(mem_ctx);
2268         return ret;
2269 }
2270
2271 static bool test_aapl(struct torture_context *tctx,
2272                       struct smb2_tree *tree)
2273 {
2274         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2275         const char *fname = BASEDIR "\\test_aapl";
2276         NTSTATUS status;
2277         struct smb2_handle testdirh;
2278         bool ret = true;
2279         struct smb2_create io;
2280         DATA_BLOB data;
2281         struct smb2_create_blob *aapl = NULL;
2282         AfpInfo *info;
2283         const char *type_creator = "SMB,OLE!";
2284         char type_creator_buf[9];
2285         uint32_t aapl_cmd;
2286         uint32_t aapl_reply_bitmap;
2287         uint32_t aapl_server_caps;
2288         uint32_t aapl_vol_caps;
2289         uint32_t expected_vol_caps = 0;
2290         char *model;
2291         struct smb2_find f;
2292         unsigned int count;
2293         union smb_search_data *d;
2294         uint64_t rfork_len;
2295         bool is_osx_server = torture_setting_bool(tctx, "osx", false);
2296
2297         smb2_deltree(tree, BASEDIR);
2298
2299         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2300         CHECK_STATUS(status, NT_STATUS_OK);
2301         smb2_util_close(tree, testdirh);
2302
2303         ZERO_STRUCT(io);
2304         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
2305         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
2306         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2307         io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2308                               NTCREATEX_SHARE_ACCESS_READ |
2309                               NTCREATEX_SHARE_ACCESS_WRITE);
2310         io.in.fname = fname;
2311
2312         /*
2313          * Issuing an SMB2/CREATE with a suitably formed AAPL context,
2314          * controls behaviour of Apple's SMB2 extensions for the whole
2315          * session!
2316          */
2317
2318         data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2319         SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2320         SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2321                              SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2322                              SMB2_CRTCTX_AAPL_MODEL_INFO));
2323         SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2324                               SMB2_CRTCTX_AAPL_UNIX_BASED |
2325                               SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
2326
2327         torture_comment(tctx, "Testing SMB2 create context AAPL\n");
2328         status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2329         CHECK_STATUS(status, NT_STATUS_OK);
2330
2331         status = smb2_create(tree, tctx, &io);
2332         CHECK_STATUS(status, NT_STATUS_OK);
2333         status = smb2_util_close(tree, io.out.file.handle);
2334         CHECK_STATUS(status, NT_STATUS_OK);
2335
2336         /*
2337          * Now check returned AAPL context
2338          */
2339         torture_comment(tctx, "Comparing returned AAPL capabilities\n");
2340
2341         aapl = smb2_create_blob_find(&io.out.blobs,
2342                                      SMB2_CREATE_TAG_AAPL);
2343
2344         if (aapl == NULL) {
2345                 torture_result(tctx, TORTURE_FAIL,
2346                                "(%s) unexpectedly no AAPL capabilities were returned.",
2347                                __location__);
2348                 ret = false;
2349                 goto done;
2350         }
2351
2352         if (!is_osx_server) {
2353                 size_t expected_aapl_ctx_size;
2354                 bool size_ok;
2355
2356                 /*
2357                  * uint32_t CommandCode = kAAPL_SERVER_QUERY
2358                  * uint32_t Reserved = 0;
2359                  * uint64_t ReplyBitmap = kAAPL_SERVER_CAPS |
2360                  *                        kAAPL_VOLUME_CAPS |
2361                  *                        kAAPL_MODEL_INFO;
2362                  * uint64_t ServerCaps = kAAPL_SUPPORTS_READDIR_ATTR |
2363                  *                       kAAPL_SUPPORTS_OSX_COPYFILE;
2364                  * uint64_t VolumeCaps = kAAPL_SUPPORT_RESOLVE_ID |
2365                  *                       kAAPL_CASE_SENSITIVE;
2366                  * uint32_t Pad2 = 0;
2367                  * uint32_t ModelStringLen = 10;
2368                  * ucs2_t ModelString[5] = "MacSamba";
2369                  */
2370                 expected_aapl_ctx_size = strlen("MacSamba") * 2 + 40;
2371
2372                 size_ok = aapl->data.length == expected_aapl_ctx_size;
2373                 torture_assert_goto(tctx, size_ok, ret, done, "bad AAPL size");
2374         }
2375
2376         aapl_cmd = IVAL(aapl->data.data, 0);
2377         if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2378                 torture_result(tctx, TORTURE_FAIL,
2379                                "(%s) unexpected cmd: %d",
2380                                __location__, (int)aapl_cmd);
2381                 ret = false;
2382                 goto done;
2383         }
2384
2385         aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2386         if (aapl_reply_bitmap != (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2387                                   SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2388                                   SMB2_CRTCTX_AAPL_MODEL_INFO)) {
2389                 torture_result(tctx, TORTURE_FAIL,
2390                                "(%s) unexpected reply_bitmap: %d",
2391                                __location__, (int)aapl_reply_bitmap);
2392                 ret = false;
2393                 goto done;
2394         }
2395
2396         aapl_server_caps = BVAL(aapl->data.data, 16);
2397         if (aapl_server_caps != (SMB2_CRTCTX_AAPL_UNIX_BASED |
2398                                  SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2399                                  SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
2400                                  SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE)) {
2401                 torture_result(tctx, TORTURE_FAIL,
2402                                "(%s) unexpected server_caps: %d",
2403                                __location__, (int)aapl_server_caps);
2404                 ret = false;
2405                 goto done;
2406         }
2407
2408         if (is_osx_server) {
2409                 expected_vol_caps = 5;
2410         }
2411         aapl_vol_caps = BVAL(aapl->data.data, 24);
2412         if (aapl_vol_caps != expected_vol_caps) {
2413                 /* this will fail on a case insensitive fs ... */
2414                 torture_result(tctx, TORTURE_FAIL,
2415                                 "(%s) unexpected vol_caps: %d",
2416                                 __location__, (int)aapl_vol_caps);
2417         }
2418
2419         ret = convert_string_talloc(mem_ctx,
2420                                     CH_UTF16LE, CH_UNIX,
2421                                     aapl->data.data + 40, 10,
2422                                     &model, NULL);
2423         if (ret == false) {
2424                 torture_result(tctx, TORTURE_FAIL,
2425                                "(%s) convert_string_talloc() failed",
2426                                __location__);
2427                 goto done;
2428         }
2429         torture_comment(tctx, "Got server model: \"%s\"\n", model);
2430
2431         /*
2432          * Now that Requested AAPL extensions are enabled, setup some
2433          * Mac files with metadata and resource fork
2434          */
2435         ret = torture_setup_file(mem_ctx, tree, fname, false);
2436         if (ret == false) {
2437                 torture_result(tctx, TORTURE_FAIL,
2438                                "(%s) torture_setup_file() failed",
2439                                __location__);
2440                 goto done;
2441         }
2442
2443         info = torture_afpinfo_new(mem_ctx);
2444         if (info == NULL) {
2445                 torture_result(tctx, TORTURE_FAIL,
2446                                "(%s) torture_afpinfo_new() failed",
2447                                __location__);
2448                 ret = false;
2449                 goto done;
2450         }
2451
2452         memcpy(info->afpi_FinderInfo, type_creator, 8);
2453         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
2454         if (ret == false) {
2455                 torture_result(tctx, TORTURE_FAIL,
2456                                "(%s) torture_write_afpinfo() failed",
2457                                __location__);
2458                 goto done;
2459         }
2460
2461         ret = write_stream(tree, __location__, tctx, mem_ctx,
2462                            fname, AFPRESOURCE_STREAM_NAME,
2463                            0, 3, "foo");
2464         if (ret == false) {
2465                 torture_result(tctx, TORTURE_FAIL,
2466                                "(%s) write_stream() failed",
2467                                __location__);
2468                 goto done;
2469         }
2470
2471         /*
2472          * Ok, file is prepared, now call smb2/find
2473          */
2474
2475         ZERO_STRUCT(io);
2476         io.in.desired_access = SEC_RIGHTS_DIR_READ;
2477         io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2478         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2479         io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
2480                               NTCREATEX_SHARE_ACCESS_WRITE |
2481                               NTCREATEX_SHARE_ACCESS_DELETE);
2482         io.in.create_disposition = NTCREATEX_DISP_OPEN;
2483         io.in.fname = BASEDIR;
2484         status = smb2_create(tree, tctx, &io);
2485         CHECK_STATUS(status, NT_STATUS_OK);
2486
2487         ZERO_STRUCT(f);
2488         f.in.file.handle        = io.out.file.handle;
2489         f.in.pattern            = "test_aapl";
2490         f.in.continue_flags     = SMB2_CONTINUE_FLAG_SINGLE;
2491         f.in.max_response_size  = 0x1000;
2492         f.in.level              = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
2493
2494         status = smb2_find_level(tree, tree, &f, &count, &d);
2495         CHECK_STATUS(status, NT_STATUS_OK);
2496
2497         status = smb2_util_close(tree, io.out.file.handle);
2498         CHECK_STATUS(status, NT_STATUS_OK);
2499
2500         if (strcmp(d[0].id_both_directory_info.name.s, "test_aapl") != 0) {
2501                 torture_result(tctx, TORTURE_FAIL,
2502                                "(%s) write_stream() failed",
2503                                __location__);
2504                 ret = false;
2505                 goto done;
2506         }
2507
2508         if (d[0].id_both_directory_info.short_name.private_length != 24) {
2509                 torture_result(tctx, TORTURE_FAIL,
2510                                "(%s) bad short_name length %" PRIu32 ", expected 24",
2511                                __location__, d[0].id_both_directory_info.short_name.private_length);
2512                 ret = false;
2513                 goto done;
2514         }
2515
2516         torture_comment(tctx, "short_name buffer:\n");
2517         dump_data(0, d[0].id_both_directory_info.short_name_buf, 24);
2518
2519         /*
2520          * Extract data as specified by the AAPL extension:
2521          * - ea_size contains max_access
2522          * - short_name contains resource fork length + FinderInfo
2523          * - reserved2 contains the unix mode
2524          */
2525         torture_comment(tctx, "mac_access: %" PRIx32 "\n",
2526                         d[0].id_both_directory_info.ea_size);
2527
2528         rfork_len = BVAL(d[0].id_both_directory_info.short_name_buf, 0);
2529         if (rfork_len != 3) {
2530                 torture_result(tctx, TORTURE_FAIL,
2531                                "(%s) expected resource fork length 3, got: %" PRIu64,
2532                                __location__, rfork_len);
2533                 ret = false;
2534                 goto done;
2535         }
2536
2537         memcpy(type_creator_buf, d[0].id_both_directory_info.short_name_buf + 8, 8);
2538         type_creator_buf[8] = 0;
2539         if (strcmp(type_creator, type_creator_buf) != 0) {
2540                 torture_result(tctx, TORTURE_FAIL,
2541                                "(%s) expected type/creator \"%s\" , got: %s",
2542                                __location__, type_creator, type_creator_buf);
2543                 ret = false;
2544                 goto done;
2545         }
2546
2547 done:
2548         smb2_util_unlink(tree, fname);
2549         smb2_deltree(tree, BASEDIR);
2550         talloc_free(mem_ctx);
2551         return ret;
2552 }
2553
2554 static uint64_t patt_hash(uint64_t off)
2555 {
2556         return off;
2557 }
2558
2559 static bool write_pattern(struct torture_context *torture,
2560                           struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2561                           struct smb2_handle h, uint64_t off, uint64_t len,
2562                           uint64_t patt_off)
2563 {
2564         NTSTATUS status;
2565         uint64_t i;
2566         uint8_t *buf;
2567         uint64_t io_sz = MIN(1024 * 64, len);
2568
2569         if (len == 0) {
2570                 return true;
2571         }
2572
2573         torture_assert(torture, (len % 8) == 0, "invalid write len");
2574
2575         buf = talloc_zero_size(mem_ctx, io_sz);
2576         torture_assert(torture, (buf != NULL), "no memory for file data buf");
2577
2578         while (len > 0) {
2579                 for (i = 0; i <= io_sz - 8; i += 8) {
2580                         SBVAL(buf, i, patt_hash(patt_off));
2581                         patt_off += 8;
2582                 }
2583
2584                 status = smb2_util_write(tree, h,
2585                                          buf, off, io_sz);
2586                 torture_assert_ntstatus_ok(torture, status, "file write");
2587
2588                 len -= io_sz;
2589                 off += io_sz;
2590         }
2591
2592         talloc_free(buf);
2593
2594         return true;
2595 }
2596
2597 static bool check_pattern(struct torture_context *torture,
2598                           struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2599                           struct smb2_handle h, uint64_t off, uint64_t len,
2600                           uint64_t patt_off)
2601 {
2602         if (len == 0) {
2603                 return true;
2604         }
2605
2606         torture_assert(torture, (len % 8) == 0, "invalid read len");
2607
2608         while (len > 0) {
2609                 uint64_t i;
2610                 struct smb2_read r;
2611                 NTSTATUS status;
2612                 uint64_t io_sz = MIN(1024 * 64, len);
2613
2614                 ZERO_STRUCT(r);
2615                 r.in.file.handle = h;
2616                 r.in.length      = io_sz;
2617                 r.in.offset      = off;
2618                 status = smb2_read(tree, mem_ctx, &r);
2619                 torture_assert_ntstatus_ok(torture, status, "read");
2620
2621                 torture_assert_u64_equal(torture, r.out.data.length, io_sz,
2622                                          "read data len mismatch");
2623
2624                 for (i = 0; i <= io_sz - 8; i += 8, patt_off += 8) {
2625                         uint64_t data = BVAL(r.out.data.data, i);
2626                         torture_assert_u64_equal(torture, data, patt_hash(patt_off),
2627                                                  talloc_asprintf(torture, "read data "
2628                                                                  "pattern bad at %llu\n",
2629                                                                  (unsigned long long)off + i));
2630                 }
2631                 talloc_free(r.out.data.data);
2632                 len -= io_sz;
2633                 off += io_sz;
2634         }
2635
2636         return true;
2637 }
2638
2639 static bool test_setup_open(struct torture_context *torture,
2640                             struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2641                             const char *fname,
2642                             struct smb2_handle *fh,
2643                             uint32_t desired_access,
2644                             uint32_t file_attributes)
2645 {
2646         struct smb2_create io;
2647         NTSTATUS status;
2648
2649         ZERO_STRUCT(io);
2650         io.in.desired_access = desired_access;
2651         io.in.file_attributes = file_attributes;
2652         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2653         io.in.share_access =
2654                 NTCREATEX_SHARE_ACCESS_DELETE|
2655                 NTCREATEX_SHARE_ACCESS_READ|
2656                 NTCREATEX_SHARE_ACCESS_WRITE;
2657         if (file_attributes & FILE_ATTRIBUTE_DIRECTORY) {
2658                 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2659         }
2660         io.in.fname = fname;
2661
2662         status = smb2_create(tree, mem_ctx, &io);
2663         torture_assert_ntstatus_ok(torture, status, "file create");
2664
2665         *fh = io.out.file.handle;
2666
2667         return true;
2668 }
2669
2670 static bool test_setup_create_fill(struct torture_context *torture,
2671                                    struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2672                                    const char *fname,
2673                                    struct smb2_handle *fh,
2674                                    uint64_t size,
2675                                    uint32_t desired_access,
2676                                    uint32_t file_attributes)
2677 {
2678         bool ok;
2679
2680         ok = test_setup_open(torture, tree, mem_ctx,
2681                              fname,
2682                              fh,
2683                              desired_access,
2684                              file_attributes);
2685         torture_assert(torture, ok, "file open");
2686
2687         if (size > 0) {
2688                 ok = write_pattern(torture, tree, mem_ctx, *fh, 0, size, 0);
2689                 torture_assert(torture, ok, "write pattern");
2690         }
2691         return true;
2692 }
2693
2694 static bool test_setup_copy_chunk(struct torture_context *torture,
2695                                   struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2696                                   uint32_t nchunks,
2697                                   const char *src_name,
2698                                   struct smb2_handle *src_h,
2699                                   uint64_t src_size,
2700                                   uint32_t src_desired_access,
2701                                   const char *dst_name,
2702                                   struct smb2_handle *dest_h,
2703                                   uint64_t dest_size,
2704                                   uint32_t dest_desired_access,
2705                                   struct srv_copychunk_copy *cc_copy,
2706                                   union smb_ioctl *io)
2707 {
2708         struct req_resume_key_rsp res_key;
2709         bool ok;
2710         NTSTATUS status;
2711         enum ndr_err_code ndr_ret;
2712
2713         ok = test_setup_create_fill(torture, tree, mem_ctx, src_name,
2714                                     src_h, src_size, src_desired_access,
2715                                     FILE_ATTRIBUTE_NORMAL);
2716         torture_assert(torture, ok, "src file create fill");
2717
2718         ok = test_setup_create_fill(torture, tree, mem_ctx, dst_name,
2719                                     dest_h, dest_size, dest_desired_access,
2720                                     FILE_ATTRIBUTE_NORMAL);
2721         torture_assert(torture, ok, "dest file create fill");
2722
2723         ZERO_STRUCTPN(io);
2724         io->smb2.level = RAW_IOCTL_SMB2;
2725         io->smb2.in.file.handle = *src_h;
2726         io->smb2.in.function = FSCTL_SRV_REQUEST_RESUME_KEY;
2727         /* Allow for Key + ContextLength + Context */
2728         io->smb2.in.max_response_size = 32;
2729         io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2730
2731         status = smb2_ioctl(tree, mem_ctx, &io->smb2);
2732         torture_assert_ntstatus_ok(torture, status,
2733                                    "FSCTL_SRV_REQUEST_RESUME_KEY");
2734
2735         ndr_ret = ndr_pull_struct_blob(&io->smb2.out.out, mem_ctx, &res_key,
2736                         (ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
2737
2738         torture_assert_ndr_success(torture, ndr_ret,
2739                                    "ndr_pull_req_resume_key_rsp");
2740
2741         ZERO_STRUCTPN(io);
2742         io->smb2.level = RAW_IOCTL_SMB2;
2743         io->smb2.in.file.handle = *dest_h;
2744         io->smb2.in.function = FSCTL_SRV_COPYCHUNK;
2745         io->smb2.in.max_response_size = sizeof(struct srv_copychunk_rsp);
2746         io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2747
2748         ZERO_STRUCTPN(cc_copy);
2749         memcpy(cc_copy->source_key, res_key.resume_key, ARRAY_SIZE(cc_copy->source_key));
2750         cc_copy->chunk_count = nchunks;
2751         cc_copy->chunks = talloc_zero_array(mem_ctx, struct srv_copychunk, nchunks);
2752         torture_assert(torture, (cc_copy->chunks != NULL), "no memory for chunks");
2753
2754         return true;
2755 }
2756
2757
2758 static bool check_copy_chunk_rsp(struct torture_context *torture,
2759                                  struct srv_copychunk_rsp *cc_rsp,
2760                                  uint32_t ex_chunks_written,
2761                                  uint32_t ex_chunk_bytes_written,
2762                                  uint32_t ex_total_bytes_written)
2763 {
2764         torture_assert_int_equal(torture, cc_rsp->chunks_written,
2765                                  ex_chunks_written, "num chunks");
2766         torture_assert_int_equal(torture, cc_rsp->chunk_bytes_written,
2767                                  ex_chunk_bytes_written, "chunk bytes written");
2768         torture_assert_int_equal(torture, cc_rsp->total_bytes_written,
2769                                  ex_total_bytes_written, "chunk total bytes");
2770         return true;
2771 }
2772
2773 static bool neg_aapl_copyfile(struct torture_context *tctx,
2774                               struct smb2_tree *tree,
2775                               uint64_t flags)
2776 {
2777         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2778         const char *fname = "aapl";
2779         NTSTATUS status;
2780         struct smb2_create io;
2781         DATA_BLOB data;
2782         struct smb2_create_blob *aapl = NULL;
2783         uint32_t aapl_cmd;
2784         uint32_t aapl_reply_bitmap;
2785         uint32_t aapl_server_caps;
2786         bool ret = true;
2787
2788         ZERO_STRUCT(io);
2789         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
2790         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
2791         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2792         io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2793                               NTCREATEX_SHARE_ACCESS_READ |
2794                               NTCREATEX_SHARE_ACCESS_WRITE);
2795         io.in.fname = fname;
2796
2797         data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2798         SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2799         SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS));
2800         SBVAL(data.data, 16, flags);
2801
2802         status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2803         CHECK_STATUS(status, NT_STATUS_OK);
2804
2805         status = smb2_create(tree, tctx, &io);
2806         CHECK_STATUS(status, NT_STATUS_OK);
2807
2808         aapl = smb2_create_blob_find(&io.out.blobs,
2809                                      SMB2_CREATE_TAG_AAPL);
2810         if (aapl == NULL) {
2811                 ret = false;
2812                 goto done;
2813
2814         }
2815         if (aapl->data.length < 24) {
2816                 ret = false;
2817                 goto done;
2818         }
2819
2820         aapl_cmd = IVAL(aapl->data.data, 0);
2821         if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2822                 torture_result(tctx, TORTURE_FAIL,
2823                                "(%s) unexpected cmd: %d",
2824                                __location__, (int)aapl_cmd);
2825                 ret = false;
2826                 goto done;
2827         }
2828
2829         aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2830         if (!(aapl_reply_bitmap & SMB2_CRTCTX_AAPL_SERVER_CAPS)) {
2831                 torture_result(tctx, TORTURE_FAIL,
2832                                "(%s) unexpected reply_bitmap: %d",
2833                                __location__, (int)aapl_reply_bitmap);
2834                 ret = false;
2835                 goto done;
2836         }
2837
2838         aapl_server_caps = BVAL(aapl->data.data, 16);
2839         if (!(aapl_server_caps & flags)) {
2840                 torture_result(tctx, TORTURE_FAIL,
2841                                "(%s) unexpected server_caps: %d",
2842                                __location__, (int)aapl_server_caps);
2843                 ret = false;
2844                 goto done;
2845         }
2846
2847 done:
2848         status = smb2_util_close(tree, io.out.file.handle);
2849         CHECK_STATUS(status, NT_STATUS_OK);
2850
2851         smb2_util_unlink(tree, "aapl");
2852         talloc_free(mem_ctx);
2853         return ret;
2854 }
2855
2856 static bool test_copyfile(struct torture_context *torture,
2857                           struct smb2_tree *tree)
2858 {
2859         struct smb2_handle src_h;
2860         struct smb2_handle dest_h;
2861         NTSTATUS status;
2862         union smb_ioctl io;
2863         TALLOC_CTX *tmp_ctx = talloc_new(tree);
2864         struct srv_copychunk_copy cc_copy;
2865         struct srv_copychunk_rsp cc_rsp;
2866         enum ndr_err_code ndr_ret;
2867         bool ok;
2868         const char *sname = ":foo" "\xef\x80\xa2" "bar:$DATA";
2869
2870         /*
2871          * First test a copy_chunk with a 0 chunk count without having
2872          * enabled this via AAPL. The request must not fail and the
2873          * copied length in the response must be 0. This is verified
2874          * against Windows 2008r2.
2875          */
2876
2877         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2878                                    0, /* 0 chunks, copyfile semantics */
2879                                    FNAME_CC_SRC,
2880                                    &src_h, 4096, /* fill 4096 byte src file */
2881                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2882                                    FNAME_CC_DST,
2883                                    &dest_h, 0,  /* 0 byte dest file */
2884                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2885                                    &cc_copy,
2886                                    &io);
2887         if (!ok) {
2888                 torture_fail_goto(torture, done, "setup copy chunk error");
2889         }
2890
2891         ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2892                                        &cc_copy,
2893                         (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2894         torture_assert_ndr_success(torture, ndr_ret,
2895                                    "ndr_push_srv_copychunk_copy");
2896
2897         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2898         torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2899
2900         ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2901                                        &cc_rsp,
2902                         (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2903         torture_assert_ndr_success(torture, ndr_ret,
2904                                    "ndr_pull_srv_copychunk_rsp");
2905
2906         ok = check_copy_chunk_rsp(torture, &cc_rsp,
2907                                   0,    /* chunks written */
2908                                   0,    /* chunk bytes unsuccessfully written */
2909                                   0); /* total bytes written */
2910         if (!ok) {
2911                 torture_fail_goto(torture, done, "bad copy chunk response data");
2912         }
2913
2914         /*
2915          * Now enable AAPL copyfile and test again, the file and the
2916          * stream must be copied by the server.
2917          */
2918         ok = neg_aapl_copyfile(torture, tree,
2919                                SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
2920         if (!ok) {
2921                 torture_skip_goto(torture, done, "missing AAPL copyfile");
2922                 goto done;
2923         }
2924
2925         smb2_util_close(tree, src_h);
2926         smb2_util_close(tree, dest_h);
2927         smb2_util_unlink(tree, FNAME_CC_SRC);
2928         smb2_util_unlink(tree, FNAME_CC_DST);
2929
2930         ok = torture_setup_file(tmp_ctx, tree, FNAME_CC_SRC, false);
2931         if (!ok) {
2932                 torture_fail(torture, "setup file error");
2933         }
2934         ok = write_stream(tree, __location__, torture, tmp_ctx,
2935                             FNAME_CC_SRC, AFPRESOURCE_STREAM,
2936                             10, 10, "1234567890");
2937         if (!ok) {
2938                 torture_fail(torture, "setup stream error");
2939         }
2940
2941         ok = write_stream(tree, __location__, torture, tmp_ctx,
2942                             FNAME_CC_SRC, sname,
2943                             10, 10, "abcdefghij");
2944         torture_assert_goto(torture, ok == true, ok, done, "write_stream failed\n");
2945
2946         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2947                                    0, /* 0 chunks, copyfile semantics */
2948                                    FNAME_CC_SRC,
2949                                    &src_h, 4096, /* fill 4096 byte src file */
2950                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2951                                    FNAME_CC_DST,
2952                                    &dest_h, 0,  /* 0 byte dest file */
2953                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2954                                    &cc_copy,
2955                                    &io);
2956         if (!ok) {
2957                 torture_fail_goto(torture, done, "setup copy chunk error");
2958         }
2959
2960         ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2961                                        &cc_copy,
2962                         (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2963         torture_assert_ndr_success(torture, ndr_ret,
2964                                    "ndr_push_srv_copychunk_copy");
2965
2966         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2967         torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2968
2969         ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2970                                        &cc_rsp,
2971                         (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2972         torture_assert_ndr_success(torture, ndr_ret,
2973                                    "ndr_pull_srv_copychunk_rsp");
2974
2975         ok = check_copy_chunk_rsp(torture, &cc_rsp,
2976                                   0,    /* chunks written */
2977                                   0,    /* chunk bytes unsuccessfully written */
2978                                   4096); /* total bytes written */
2979         if (!ok) {
2980                 torture_fail_goto(torture, done, "bad copy chunk response data");
2981         }
2982
2983         ok = test_setup_open(torture, tree, tmp_ctx, FNAME_CC_DST, &dest_h,
2984                              SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL);
2985         if (!ok) {
2986                 torture_fail_goto(torture, done,"open failed");
2987         }
2988         ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 4096, 0);
2989         if (!ok) {
2990                 torture_fail_goto(torture, done, "inconsistent file data");
2991         }
2992
2993         ok = check_stream(tree, __location__, torture, tmp_ctx,
2994                             FNAME_CC_DST, AFPRESOURCE_STREAM,
2995                             0, 20, 10, 10, "1234567890");
2996         if (!ok) {
2997                 torture_fail_goto(torture, done, "inconsistent stream data");
2998         }
2999
3000         ok = check_stream(tree, __location__, torture, tmp_ctx,
3001                             FNAME_CC_DST, sname,
3002                             0, 20, 10, 10, "abcdefghij");
3003         torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
3004
3005 done:
3006         smb2_util_close(tree, src_h);
3007         smb2_util_close(tree, dest_h);
3008         smb2_util_unlink(tree, FNAME_CC_SRC);
3009         smb2_util_unlink(tree, FNAME_CC_DST);
3010         talloc_free(tmp_ctx);
3011         return true;
3012 }
3013
3014 static bool check_stream_list(struct smb2_tree *tree,
3015                               struct torture_context *tctx,
3016                               const char *fname,
3017                               int num_exp,
3018                               const char **exp,
3019                               bool is_dir)
3020 {
3021         bool ret = true;
3022         union smb_fileinfo finfo;
3023         NTSTATUS status;
3024         int i;
3025         TALLOC_CTX *tmp_ctx = talloc_new(tctx);
3026         char **exp_sort;
3027         struct stream_struct *stream_sort;
3028         struct smb2_create create;
3029         struct smb2_handle h;
3030
3031         ZERO_STRUCT(h);
3032         torture_assert_goto(tctx, tmp_ctx != NULL, ret, done, "talloc_new failed");
3033
3034         ZERO_STRUCT(create);
3035         create.in.fname = fname;
3036         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3037         create.in.desired_access = SEC_FILE_ALL;
3038         create.in.create_options = is_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
3039         create.in.file_attributes = is_dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
3040         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3041         status = smb2_create(tree, tmp_ctx, &create);
3042         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
3043         h = create.out.file.handle;
3044
3045         finfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
3046         finfo.generic.in.file.handle = h;
3047
3048         status = smb2_getinfo_file(tree, tctx, &finfo);
3049         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "get stream info");
3050
3051         smb2_util_close(tree, h);
3052
3053         torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams, num_exp,
3054                                       ret, done, "stream count");
3055
3056         if (num_exp == 0) {
3057                 TALLOC_FREE(tmp_ctx);
3058                 goto done;
3059         }
3060
3061         exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
3062         torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
3063
3064         TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
3065
3066         stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
3067                                     finfo.stream_info.out.num_streams *
3068                                     sizeof(*stream_sort));
3069         torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
3070
3071         TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
3072
3073         for (i=0; i<num_exp; i++) {
3074                 torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
3075                                 i, exp_sort[i], stream_sort[i].stream_name.s);
3076                 torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s, exp_sort[i],
3077                                               ret, done, "stream name");
3078         }
3079
3080 done:
3081         TALLOC_FREE(tmp_ctx);
3082         return ret;
3083 }
3084
3085 static bool check_stream_list_handle(struct smb2_tree *tree,
3086                                      struct torture_context *tctx,
3087                                      struct smb2_handle h,
3088                                      int num_exp,
3089                                      const char **exp,
3090                                      bool is_dir)
3091 {
3092         bool ret = true;
3093         union smb_fileinfo finfo;
3094         NTSTATUS status;
3095         int i;
3096         TALLOC_CTX *tmp_ctx = talloc_new(tctx);
3097         char **exp_sort;
3098         struct stream_struct *stream_sort;
3099
3100         torture_assert_goto(tctx, tmp_ctx != NULL, ret, done,
3101                             "talloc_new failed\n");
3102
3103         finfo = (union smb_fileinfo) {
3104                 .stream_info.level = RAW_FILEINFO_STREAM_INFORMATION,
3105                 .stream_info.in.file.handle = h,
3106         };
3107
3108         status = smb2_getinfo_file(tree, tctx, &finfo);
3109         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3110                                         "get stream info\n");
3111
3112         torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams,
3113                                       num_exp, ret, done, "stream count\n");
3114
3115         if (num_exp == 0) {
3116                 TALLOC_FREE(tmp_ctx);
3117                 goto done;
3118         }
3119
3120         exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
3121         torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
3122
3123         TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
3124
3125         stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
3126                                     finfo.stream_info.out.num_streams *
3127                                     sizeof(*stream_sort));
3128         torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
3129
3130         TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
3131
3132         for (i=0; i<num_exp; i++) {
3133                 torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
3134                                 i, exp_sort[i], stream_sort[i].stream_name.s);
3135                 torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s,
3136                                               exp_sort[i], ret, done,
3137                                               "stream name\n");
3138         }
3139
3140 done:
3141         TALLOC_FREE(tmp_ctx);
3142         return ret;
3143 }
3144
3145 /*
3146   test stream names
3147 */
3148 static bool test_stream_names(struct torture_context *tctx,
3149                               struct smb2_tree *tree)
3150 {
3151         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3152         NTSTATUS status;
3153         struct smb2_create create;
3154         struct smb2_handle h;
3155         const char *fname = BASEDIR "\\stream_names.txt";
3156         const char *sname1;
3157         bool ret;
3158         /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
3159         const char *streams[] = {
3160                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
3161                 "::$DATA"
3162         };
3163
3164         sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
3165
3166         /* clean slate ...*/
3167         smb2_util_unlink(tree, fname);
3168         smb2_deltree(tree, fname);
3169         smb2_deltree(tree, BASEDIR);
3170
3171         status = torture_smb2_testdir(tree, BASEDIR, &h);
3172         CHECK_STATUS(status, NT_STATUS_OK);
3173         smb2_util_close(tree, h);
3174
3175         ret = torture_setup_file(mem_ctx, tree, fname, false);
3176         torture_assert_goto(tctx, ret, ret, done, "torture_setup_file");
3177
3178         torture_comment(tctx, "(%s) testing stream names\n", __location__);
3179         ZERO_STRUCT(create);
3180         create.in.desired_access = SEC_FILE_WRITE_DATA;
3181         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3182         create.in.share_access =
3183                 NTCREATEX_SHARE_ACCESS_DELETE|
3184                 NTCREATEX_SHARE_ACCESS_READ|
3185                 NTCREATEX_SHARE_ACCESS_WRITE;
3186         create.in.create_disposition = NTCREATEX_DISP_CREATE;
3187         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3188         create.in.fname = sname1;
3189
3190         status = smb2_create(tree, mem_ctx, &create);
3191         CHECK_STATUS(status, NT_STATUS_OK);
3192
3193         status = smb2_util_write(tree, create.out.file.handle, "foo", 0, 3);
3194         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3195                                         "smb2_util_write failed\n");
3196
3197         smb2_util_close(tree, create.out.file.handle);
3198
3199         ret = check_stream_list(tree, tctx, fname, 2, streams, false);
3200         CHECK_VALUE(ret, true);
3201
3202 done:
3203         status = smb2_util_unlink(tree, fname);
3204         smb2_deltree(tree, BASEDIR);
3205         talloc_free(mem_ctx);
3206
3207         return ret;
3208 }
3209
3210 /* Renaming a directory with open file, should work for OS X AAPL clients */
3211 static bool test_rename_dir_openfile(struct torture_context *torture,
3212                                      struct smb2_tree *tree)
3213 {
3214         bool ret = true;
3215         NTSTATUS status;
3216         union smb_open io;
3217         union smb_close cl;
3218         union smb_setfileinfo sinfo;
3219         struct smb2_handle d1, h1;
3220         const char *renamedir = BASEDIR "-new";
3221         bool server_is_osx = torture_setting_bool(torture, "osx", false);
3222
3223         smb2_deltree(tree, BASEDIR);
3224         smb2_util_rmdir(tree, BASEDIR);
3225         smb2_deltree(tree, renamedir);
3226
3227         ZERO_STRUCT(io.smb2);
3228         io.generic.level = RAW_OPEN_SMB2;
3229         io.smb2.in.create_flags = 0;
3230         io.smb2.in.desired_access = 0x0017019f;
3231         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
3232         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
3233         io.smb2.in.share_access = 0;
3234         io.smb2.in.alloc_size = 0;
3235         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
3236         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3237         io.smb2.in.security_flags = 0;
3238         io.smb2.in.fname = BASEDIR;
3239
3240         status = smb2_create(tree, torture, &(io.smb2));
3241         torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
3242         d1 = io.smb2.out.file.handle;
3243
3244         ZERO_STRUCT(io.smb2);
3245         io.generic.level = RAW_OPEN_SMB2;
3246         io.smb2.in.create_flags = 0;
3247         io.smb2.in.desired_access = 0x0017019f;
3248         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
3249         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3250         io.smb2.in.share_access = 0;
3251         io.smb2.in.alloc_size = 0;
3252         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
3253         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3254         io.smb2.in.security_flags = 0;
3255         io.smb2.in.fname = BASEDIR "\\file.txt";
3256
3257         status = smb2_create(tree, torture, &(io.smb2));
3258         torture_assert_ntstatus_ok(torture, status, "smb2_create file");
3259         h1 = io.smb2.out.file.handle;
3260
3261         if (!server_is_osx) {
3262                 torture_comment(torture, "Renaming directory without AAPL, must fail\n");
3263
3264                 ZERO_STRUCT(sinfo);
3265                 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
3266                 sinfo.rename_information.in.file.handle = d1;
3267                 sinfo.rename_information.in.overwrite = 0;
3268                 sinfo.rename_information.in.root_fid = 0;
3269                 sinfo.rename_information.in.new_name = renamedir;
3270                 status = smb2_setinfo_file(tree, &sinfo);
3271
3272                 torture_assert_ntstatus_equal(torture, status,
3273                                               NT_STATUS_ACCESS_DENIED,
3274                                               "smb2_setinfo_file");
3275         }
3276
3277         status = smb2_util_close(tree, d1);
3278         torture_assert_ntstatus_ok(torture, status, "smb2_util_close\n");
3279         ZERO_STRUCT(d1);
3280
3281         torture_comment(torture, "Enabling AAPL\n");
3282
3283         ret = enable_aapl(torture, tree);
3284         torture_assert(torture, ret == true, "enable_aapl failed");
3285
3286         torture_comment(torture, "Renaming directory with AAPL\n");
3287
3288         ZERO_STRUCT(io.smb2);
3289         io.generic.level = RAW_OPEN_SMB2;
3290         io.smb2.in.desired_access = 0x0017019f;
3291         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
3292         io.smb2.in.share_access = 0;
3293         io.smb2.in.alloc_size = 0;
3294         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
3295         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3296         io.smb2.in.security_flags = 0;
3297         io.smb2.in.fname = BASEDIR;
3298
3299         status = smb2_create(tree, torture, &(io.smb2));
3300         torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
3301         d1 = io.smb2.out.file.handle;
3302
3303         ZERO_STRUCT(sinfo);
3304         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
3305         sinfo.rename_information.in.file.handle = d1;
3306         sinfo.rename_information.in.overwrite = 0;
3307         sinfo.rename_information.in.root_fid = 0;
3308         sinfo.rename_information.in.new_name = renamedir;
3309
3310         status = smb2_setinfo_file(tree, &sinfo);
3311         torture_assert_ntstatus_ok(torture, status, "smb2_setinfo_file");
3312
3313         ZERO_STRUCT(cl.smb2);
3314         cl.smb2.level = RAW_CLOSE_SMB2;
3315         cl.smb2.in.file.handle = d1;
3316         status = smb2_close(tree, &(cl.smb2));
3317         torture_assert_ntstatus_ok(torture, status, "smb2_close");
3318         ZERO_STRUCT(d1);
3319
3320         cl.smb2.in.file.handle = h1;
3321         status = smb2_close(tree, &(cl.smb2));
3322         torture_assert_ntstatus_ok(torture, status, "smb2_close");
3323         ZERO_STRUCT(h1);
3324
3325         torture_comment(torture, "Cleaning up\n");
3326
3327         if (h1.data[0] || h1.data[1]) {
3328                 ZERO_STRUCT(cl.smb2);
3329                 cl.smb2.level = RAW_CLOSE_SMB2;
3330                 cl.smb2.in.file.handle = h1;
3331                 status = smb2_close(tree, &(cl.smb2));
3332         }
3333
3334         smb2_util_unlink(tree, BASEDIR "\\file.txt");
3335         smb2_util_unlink(tree, BASEDIR "-new\\file.txt");
3336         smb2_deltree(tree, renamedir);
3337         smb2_deltree(tree, BASEDIR);
3338         return ret;
3339 }
3340
3341 static bool test_afpinfo_enoent(struct torture_context *tctx,
3342                                 struct smb2_tree *tree)
3343 {
3344         bool ret = true;
3345         NTSTATUS status;
3346         struct smb2_create create;
3347         struct smb2_handle h1;
3348         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3349         const char *fname = BASEDIR "\\file";
3350         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3351
3352         torture_comment(tctx, "Opening file without AFP_AfpInfo\n");
3353
3354         smb2_deltree(tree, BASEDIR);
3355         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3356         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3357         smb2_util_close(tree, h1);
3358         ret = torture_setup_file(mem_ctx, tree, fname, false);
3359         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3360
3361         torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3362
3363         ZERO_STRUCT(create);
3364         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3365         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3366         create.in.fname = sname;
3367
3368         status = smb2_create(tree, mem_ctx, &create);
3369         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3370                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3371
3372 done:
3373         smb2_util_unlink(tree, fname);
3374         smb2_util_rmdir(tree, BASEDIR);
3375         return ret;
3376 }
3377
3378 static bool test_create_delete_on_close(struct torture_context *tctx,
3379                                         struct smb2_tree *tree)
3380 {
3381         bool ret = true;
3382         NTSTATUS status;
3383         struct smb2_create create;
3384         struct smb2_handle h1;
3385         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3386         const char *fname = BASEDIR "\\file";
3387         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3388         const char *type_creator = "SMB,OLE!";
3389         AfpInfo *info = NULL;
3390         const char *streams_basic[] = {
3391                 "::$DATA"
3392         };
3393         const char *streams_afpinfo[] = {
3394                 "::$DATA",
3395                 AFPINFO_STREAM
3396         };
3397
3398         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3399
3400         torture_comment(tctx, "Checking whether create with delete-on-close work with AFP_AfpInfo\n");
3401
3402         smb2_deltree(tree, BASEDIR);
3403         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3404         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3405         smb2_util_close(tree, h1);
3406         ret = torture_setup_file(mem_ctx, tree, fname, false);
3407         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3408
3409         torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3410
3411         ZERO_STRUCT(create);
3412         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3413         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3414         create.in.fname = sname;
3415
3416         status = smb2_create(tree, mem_ctx, &create);
3417         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3418                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3419
3420         ZERO_STRUCT(create);
3421         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3422         create.in.desired_access = SEC_FILE_ALL;
3423         create.in.fname = sname;
3424
3425         status = smb2_create(tree, mem_ctx, &create);
3426         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3427                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3428
3429         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3430         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3431
3432         torture_comment(tctx, "Deleting AFP_AfpInfo via create with delete-on-close\n");
3433
3434         info = torture_afpinfo_new(mem_ctx);
3435         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3436
3437         memcpy(info->afpi_FinderInfo, type_creator, 8);
3438         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3439         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3440
3441         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3442                            0, 60, 16, 8, type_creator);
3443         torture_assert_goto(tctx, ret == true, ret, done, "Bad type/creator in AFP_AfpInfo");
3444
3445         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3446         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3447
3448         ZERO_STRUCT(create);
3449         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3450         create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3451         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3452         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3453         create.in.fname = sname;
3454         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3455
3456         status = smb2_create(tree, mem_ctx, &create);
3457         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3458
3459         h1 = create.out.file.handle;
3460         smb2_util_close(tree, h1);
3461
3462         ZERO_STRUCT(create);
3463         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3464         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
3465         create.in.fname = sname;
3466         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3467         status = smb2_create(tree, mem_ctx, &create);
3468         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3469                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3470
3471         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3472         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3473
3474 done:
3475         smb2_util_unlink(tree, fname);
3476         smb2_util_rmdir(tree, BASEDIR);
3477         return ret;
3478 }
3479
3480 static bool test_setinfo_delete_on_close(struct torture_context *tctx,
3481                                          struct smb2_tree *tree)
3482 {
3483         bool ret = true;
3484         NTSTATUS status;
3485         struct smb2_create create;
3486         union smb_setfileinfo sfinfo;
3487         struct smb2_handle h1;
3488         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3489         const char *fname = BASEDIR "\\file";
3490         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3491         const char *type_creator = "SMB,OLE!";
3492         AfpInfo *info = NULL;
3493         const char *streams[] = {
3494                 AFPINFO_STREAM,
3495                 "::$DATA"
3496         };
3497         const char *streams_basic[] = {
3498                 "::$DATA"
3499         };
3500
3501         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3502
3503         torture_comment(tctx, "Deleting AFP_AfpInfo via setinfo with delete-on-close\n");
3504
3505         smb2_deltree(tree, BASEDIR);
3506         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3507         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3508         smb2_util_close(tree, h1);
3509         ret = torture_setup_file(mem_ctx, tree, fname, false);
3510         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3511
3512         info = torture_afpinfo_new(mem_ctx);
3513         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3514         memcpy(info->afpi_FinderInfo, type_creator, 8);
3515         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3516         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3517
3518         ZERO_STRUCT(create);
3519         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3520         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3521         create.in.fname = sname;
3522         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3523         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3524
3525         status = smb2_create(tree, mem_ctx, &create);
3526         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3527
3528         h1 = create.out.file.handle;
3529
3530         /* Delete stream via setinfo delete-on-close */
3531         ZERO_STRUCT(sfinfo);
3532         sfinfo.disposition_info.in.delete_on_close = 1;
3533         sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3534         sfinfo.generic.in.file.handle = h1;
3535         status = smb2_setinfo_file(tree, &sfinfo);
3536         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3537
3538         ret = check_stream_list(tree, tctx, fname, 2, streams, false);
3539         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3540
3541         ZERO_STRUCT(create);
3542         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3543         create.in.desired_access = SEC_FILE_ALL;
3544         create.in.fname = sname;
3545         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3546         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3547         status = smb2_create(tree, mem_ctx, &create);
3548         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_DELETE_PENDING,
3549                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3550
3551         smb2_util_close(tree, h1);
3552
3553         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3554         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3555
3556         ZERO_STRUCT(create);
3557         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3558         create.in.desired_access = SEC_FILE_ALL;
3559         create.in.fname = sname;
3560         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3561         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3562         status = smb2_create(tree, mem_ctx, &create);
3563         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3564                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3565
3566 done:
3567         smb2_util_unlink(tree, fname);
3568         smb2_util_rmdir(tree, BASEDIR);
3569         return ret;
3570 }
3571
3572 static bool test_setinfo_eof(struct torture_context *tctx,
3573                              struct smb2_tree *tree)
3574 {
3575         bool ret = true;
3576         NTSTATUS status;
3577         struct smb2_create create;
3578         union smb_setfileinfo sfinfo;
3579         struct smb2_handle h1;
3580         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3581         const char *fname = BASEDIR "\\file";
3582         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3583         const char *type_creator = "SMB,OLE!";
3584         AfpInfo *info = NULL;
3585         const char *streams_afpinfo[] = {
3586                 "::$DATA",
3587                 AFPINFO_STREAM
3588         };
3589
3590         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3591
3592         torture_comment(tctx, "Set AFP_AfpInfo EOF to 61, 1 and 0\n");
3593
3594         smb2_deltree(tree, BASEDIR);
3595         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3596         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3597         smb2_util_close(tree, h1);
3598         ret = torture_setup_file(mem_ctx, tree, fname, false);
3599         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3600
3601         info = torture_afpinfo_new(mem_ctx);
3602         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3603         memcpy(info->afpi_FinderInfo, type_creator, 8);
3604         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3605         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3606
3607         ZERO_STRUCT(create);
3608         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3609         create.in.desired_access = SEC_FILE_ALL;
3610         create.in.fname = sname;
3611         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3612         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3613
3614         status = smb2_create(tree, mem_ctx, &create);
3615         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3616
3617         h1 = create.out.file.handle;
3618
3619         torture_comment(tctx, "Set AFP_AfpInfo EOF to 61\n");
3620
3621         /* Test setinfo end-of-file info */
3622         ZERO_STRUCT(sfinfo);
3623         sfinfo.generic.in.file.handle = h1;
3624         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3625         sfinfo.position_information.in.position = 61;
3626         status = smb2_setinfo_file(tree, &sfinfo);
3627         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ALLOTTED_SPACE_EXCEEDED,
3628                                            ret, done, "set eof 61 failed");
3629
3630         torture_comment(tctx, "Set AFP_AfpInfo EOF to 1\n");
3631
3632         /* Truncation returns success, but has no effect */
3633         ZERO_STRUCT(sfinfo);
3634         sfinfo.generic.in.file.handle = h1;
3635         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3636         sfinfo.position_information.in.position = 1;
3637         status = smb2_setinfo_file(tree, &sfinfo);
3638         torture_assert_ntstatus_ok_goto(tctx, status,
3639                                         ret, done, "set eof 1 failed");
3640         smb2_util_close(tree, h1);
3641
3642         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3643         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3644
3645         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3646                            0, 60, 16, 8, type_creator);
3647         torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3648
3649         ZERO_STRUCT(create);
3650         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3651         create.in.desired_access = SEC_FILE_ALL;
3652         create.in.fname = sname;
3653         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3654         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3655
3656         status = smb2_create(tree, mem_ctx, &create);
3657         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3658
3659         h1 = create.out.file.handle;
3660
3661         /*
3662          * Delete stream via setinfo end-of-file info to 0, should
3663          * return success but stream MUST NOT deleted
3664          */
3665         ZERO_STRUCT(sfinfo);
3666         sfinfo.generic.in.file.handle = h1;
3667         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3668         sfinfo.position_information.in.position = 0;
3669         status = smb2_setinfo_file(tree, &sfinfo);
3670         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
3671
3672         smb2_util_close(tree, h1);
3673
3674         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3675         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3676
3677         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3678                            0, 60, 16, 8, type_creator);
3679         torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3680
3681 done:
3682         smb2_util_unlink(tree, fname);
3683         smb2_util_rmdir(tree, BASEDIR);
3684         return ret;
3685 }
3686
3687 static bool test_afpinfo_all0(struct torture_context *tctx,
3688                               struct smb2_tree *tree)
3689 {
3690         bool ret = true;
3691         NTSTATUS status;
3692         struct smb2_create create;
3693         struct smb2_handle h1 = {{0}};
3694         struct smb2_handle baseh = {{0}};
3695         union smb_setfileinfo setfinfo;
3696         union smb_fileinfo getfinfo;
3697         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3698         const char *fname = BASEDIR "\\file";
3699         const char *sname = BASEDIR "\\file" AFPINFO_STREAM;
3700         const char *type_creator = "SMB,OLE!";
3701         AfpInfo *info = NULL;
3702         char *infobuf = NULL;
3703         const char *streams_basic[] = {
3704                 "::$DATA"
3705         };
3706         const char *streams_afpinfo[] = {
3707                 "::$DATA",
3708                 AFPINFO_STREAM
3709         };
3710
3711         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3712
3713         torture_comment(tctx, "Write all 0 to AFP_AfpInfo and see what happens\n");
3714
3715         smb2_deltree(tree, BASEDIR);
3716         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3717         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3718         smb2_util_close(tree, h1);
3719         ret = torture_setup_file(mem_ctx, tree, fname, false);
3720         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3721
3722         info = torture_afpinfo_new(mem_ctx);
3723         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3724         memcpy(info->afpi_FinderInfo, type_creator, 8);
3725         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3726         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3727
3728         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3729         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3730
3731         /* Write all 0 to AFP_AfpInfo */
3732         memset(info->afpi_FinderInfo, 0, AFP_FinderSize);
3733         infobuf = torture_afpinfo_pack(mem_ctx, info);
3734         torture_assert_not_null_goto(tctx, infobuf, ret, done,
3735                                      "torture_afpinfo_pack failed\n");
3736
3737         ZERO_STRUCT(create);
3738         create.in.desired_access = SEC_FILE_ALL;
3739         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3740         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3741         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3742         create.in.fname = fname;
3743
3744         status = smb2_create(tree, mem_ctx, &create);
3745         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3746                                         "smb2_create failed\n");
3747         baseh = create.out.file.handle;
3748
3749         ZERO_STRUCT(create);
3750         create.in.desired_access = SEC_FILE_ALL;
3751         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3752         create.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
3753         create.in.fname = sname;
3754
3755         status = smb2_create(tree, mem_ctx, &create);
3756         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3757                                         "smb2_create failed\n");
3758         h1 = create.out.file.handle;
3759
3760         status = smb2_util_write(tree, h1, infobuf, 0, AFP_INFO_SIZE);
3761         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3762                                         "smb2_util_write failed\n");
3763
3764         /*
3765          * Get stream information on open handle, must return only default
3766          * stream, the AFP_AfpInfo stream must not be returned.
3767          */
3768
3769         ZERO_STRUCT(getfinfo);
3770         getfinfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
3771         getfinfo.generic.in.file.handle = baseh;
3772
3773         status = smb2_getinfo_file(tree, tctx, &getfinfo);
3774         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3775                                         "get stream info\n");
3776
3777         torture_assert_int_equal_goto(tctx, getfinfo.stream_info.out.num_streams,
3778                                       1, ret, done, "stream count");
3779
3780         smb2_util_close(tree, baseh);
3781         ZERO_STRUCT(baseh);
3782
3783         /*
3784          * Try to set some file-basic-info (time) on the stream. This catches
3785          * naive implementation mistakes that simply deleted the backing store
3786          * from the filesystem in the zero-out step.
3787          */
3788
3789         ZERO_STRUCT(setfinfo);
3790         unix_to_nt_time(&setfinfo.basic_info.in.write_time, time(NULL));
3791         setfinfo.basic_info.in.attrib = 0x20;
3792         setfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
3793         setfinfo.generic.in.file.handle = h1;
3794
3795         status = smb2_setinfo_file(tree, &setfinfo);
3796         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3797                                         "smb2_getinfo_file failed\n");
3798
3799         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3800         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
3801
3802         smb2_util_close(tree, h1);
3803         ZERO_STRUCT(h1);
3804
3805         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3806         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3807
3808 done:
3809         if (!smb2_util_handle_empty(h1)) {
3810                 smb2_util_close(tree, h1);
3811         }
3812         if (!smb2_util_handle_empty(baseh)) {
3813                 smb2_util_close(tree, baseh);
3814         }
3815         smb2_util_unlink(tree, fname);
3816         smb2_util_rmdir(tree, BASEDIR);
3817         return ret;
3818 }
3819
3820 static bool test_create_delete_on_close_resource(struct torture_context *tctx,
3821                                                  struct smb2_tree *tree)
3822 {
3823         bool ret = true;
3824         NTSTATUS status;
3825         struct smb2_create create;
3826         struct smb2_handle h1;
3827         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3828         const char *fname = BASEDIR "\\file";
3829         const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3830         const char *streams_basic[] = {
3831                 "::$DATA"
3832         };
3833         const char *streams_afpresource[] = {
3834                 "::$DATA",
3835                 AFPRESOURCE_STREAM
3836         };
3837
3838         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3839
3840         torture_comment(tctx, "Checking whether create with delete-on-close is ignored for AFP_AfpResource\n");
3841
3842         smb2_deltree(tree, BASEDIR);
3843         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3844         torture_assert_ntstatus_ok(tctx, status, "torture_smb2_testdir");
3845         smb2_util_close(tree, h1);
3846         ret = torture_setup_file(mem_ctx, tree, fname, false);
3847         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3848
3849         torture_comment(tctx, "Opening not existing AFP_AfpResource\n");
3850
3851         ZERO_STRUCT(create);
3852         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3853         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3854         create.in.fname = sname;
3855
3856         status = smb2_create(tree, mem_ctx, &create);
3857         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3858                                            ret, done, "Got unexpected AFP_AfpResource stream");
3859
3860         ZERO_STRUCT(create);
3861         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3862         create.in.desired_access = SEC_FILE_ALL;
3863         create.in.fname = sname;
3864
3865         status = smb2_create(tree, mem_ctx, &create);
3866         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3867                                            ret, done, "Got unexpected AFP_AfpResource stream");
3868
3869         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3870         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3871
3872         torture_comment(tctx, "Trying to delete AFP_AfpResource via create with delete-on-close\n");
3873
3874         ret = write_stream(tree, __location__, tctx, mem_ctx,
3875                            fname, AFPRESOURCE_STREAM_NAME,
3876                            0, 10, "1234567890");
3877         torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3878
3879         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3880                            0, 10, 0, 10, "1234567890");
3881         torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3882
3883         ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3884         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3885
3886         ZERO_STRUCT(create);
3887         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3888         create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3889         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3890         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3891         create.in.fname = sname;
3892         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3893
3894         status = smb2_create(tree, mem_ctx, &create);
3895         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3896
3897         h1 = create.out.file.handle;
3898         smb2_util_close(tree, h1);
3899
3900         ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3901         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3902
3903         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3904                            0, 10, 0, 10, "1234567890");
3905         torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3906
3907 done:
3908         smb2_util_unlink(tree, fname);
3909         smb2_util_rmdir(tree, BASEDIR);
3910         return ret;
3911 }
3912
3913 static bool test_setinfo_delete_on_close_resource(struct torture_context *tctx,
3914                                                   struct smb2_tree *tree)
3915 {
3916         bool ret = true;
3917         NTSTATUS status;
3918         struct smb2_create create;
3919         union smb_setfileinfo sfinfo;
3920         struct smb2_handle h1;
3921         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3922         const char *fname = BASEDIR "\\file";
3923         const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3924         const char *streams_afpresource[] = {
3925                 "::$DATA",
3926                 AFPRESOURCE_STREAM
3927         };
3928
3929         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3930
3931         torture_comment(tctx, "Trying to delete AFP_AfpResource via setinfo with delete-on-close\n");
3932
3933         smb2_deltree(tree, BASEDIR);
3934         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3935         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3936         smb2_util_close(tree, h1);
3937         ret = torture_setup_file(mem_ctx, tree, fname, false);
3938         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3939
3940         ret = write_stream(tree, __location__, tctx, mem_ctx,
3941                            fname, AFPRESOURCE_STREAM_NAME,
3942                            10, 10, "1234567890");
3943         torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3944
3945         ZERO_STRUCT(create);
3946         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3947         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3948         create.in.fname = sname;
3949         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3950         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3951
3952         status = smb2_create(tree, mem_ctx, &create);
3953         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3954
3955         h1 = create.out.file.handle;
3956
3957         /* Try to delete stream via setinfo delete-on-close */
3958         ZERO_STRUCT(sfinfo);
3959         sfinfo.disposition_info.in.delete_on_close = 1;
3960         sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3961         sfinfo.generic.in.file.handle = h1;
3962         status = smb2_setinfo_file(tree, &sfinfo);
3963         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3964
3965         smb2_util_close(tree, h1);
3966
3967         ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3968         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3969
3970         ZERO_STRUCT(create);
3971         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3972         create.in.desired_access = SEC_FILE_ALL;
3973         create.in.fname = sname;
3974         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3975         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3976         status = smb2_create(tree, mem_ctx, &create);
3977         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3978                                         "Got unexpected AFP_AfpResource stream");
3979
3980 done:
3981         smb2_util_unlink(tree, fname);
3982         smb2_util_rmdir(tree, BASEDIR);
3983         return ret;
3984 }
3985
3986 static bool test_setinfo_eof_resource(struct torture_context *tctx,
3987                                       struct smb2_tree *tree)
3988 {
3989         bool ret = true;
3990         NTSTATUS status;
3991         struct smb2_create create;
3992         union smb_setfileinfo sfinfo;
3993         union smb_fileinfo finfo;
3994         struct smb2_handle h1;
3995         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3996         const char *fname = BASEDIR "\\file";
3997         const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3998         const char *streams_basic[] = {
3999                 "::$DATA"
4000         };
4001
4002         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
4003
4004         ret = enable_aapl(tctx, tree);
4005         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
4006
4007         torture_comment(tctx, "Set AFP_AfpResource EOF to 1 and 0\n");
4008
4009         smb2_deltree(tree, BASEDIR);
4010         status = torture_smb2_testdir(tree, BASEDIR, &h1);
4011         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
4012         smb2_util_close(tree, h1);
4013         ret = torture_setup_file(mem_ctx, tree, fname, false);
4014         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4015
4016         ret = write_stream(tree, __location__, tctx, mem_ctx,
4017                            fname, AFPRESOURCE_STREAM_NAME,
4018                            10, 10, "1234567890");
4019         torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
4020
4021         ZERO_STRUCT(create);
4022         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4023         create.in.desired_access = SEC_FILE_ALL;
4024         create.in.fname = sname;
4025         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4026         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4027
4028         status = smb2_create(tree, mem_ctx, &create);
4029         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4030
4031         h1 = create.out.file.handle;
4032
4033         torture_comment(tctx, "Set AFP_AfpResource EOF to 1\n");
4034
4035         /* Test setinfo end-of-file info */
4036         ZERO_STRUCT(sfinfo);
4037         sfinfo.generic.in.file.handle = h1;
4038         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
4039         sfinfo.position_information.in.position = 1;
4040         status = smb2_setinfo_file(tree, &sfinfo);
4041         torture_assert_ntstatus_ok_goto(tctx, status,
4042                                         ret, done, "set eof 1 failed");
4043
4044         smb2_util_close(tree, h1);
4045
4046         /* Check size == 1 */
4047         ZERO_STRUCT(create);
4048         create.in.fname = sname;
4049         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4050         create.in.desired_access = SEC_FILE_ALL;
4051         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4052         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4053         status = smb2_create(tree, mem_ctx, &create);
4054         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4055
4056         h1 = create.out.file.handle;
4057
4058         ZERO_STRUCT(finfo);
4059         finfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
4060         finfo.generic.in.file.handle = h1;
4061         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
4062         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file failed");
4063
4064         smb2_util_close(tree, h1);
4065
4066         torture_assert_goto(tctx, finfo.all_info.out.size == 1, ret, done, "size != 1");
4067
4068         ZERO_STRUCT(create);
4069         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4070         create.in.desired_access = SEC_FILE_ALL;
4071         create.in.fname = sname;
4072         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4073         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4074
4075         status = smb2_create(tree, mem_ctx, &create);
4076         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4077
4078         h1 = create.out.file.handle;
4079
4080         /*
4081          * Delete stream via setinfo end-of-file info to 0, this
4082          * should delete the stream.
4083          */
4084         ZERO_STRUCT(sfinfo);
4085         sfinfo.generic.in.file.handle = h1;
4086         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
4087         sfinfo.position_information.in.position = 0;
4088         status = smb2_setinfo_file(tree, &sfinfo);
4089         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
4090
4091         smb2_util_close(tree, h1);
4092
4093         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
4094         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4095
4096         ZERO_STRUCT(create);
4097         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4098         create.in.desired_access = SEC_FILE_ALL;
4099         create.in.fname = sname;
4100         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4101         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4102
4103         status = smb2_create(tree, mem_ctx, &create);
4104         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4105                                            ret, done, "smb2_create failed");
4106
4107 done:
4108         smb2_util_unlink(tree, fname);
4109         smb2_util_rmdir(tree, BASEDIR);
4110         return ret;
4111 }
4112
4113 /*
4114  * This tests that right after creating the AFP_AfpInfo stream,
4115  * reading from the stream returns an empty, default metadata blob of
4116  * 60 bytes.
4117  *
4118  * NOTE: against OS X SMB server this only works if the read request
4119  * is compounded with the create that created the stream, is fails
4120  * otherwise. We don't care...
4121  */
4122 static bool test_null_afpinfo(struct torture_context *tctx,
4123                               struct smb2_tree *tree)
4124 {
4125         TALLOC_CTX *mem_ctx = talloc_new(tctx);
4126         const char *fname = "test_null_afpinfo";
4127         const char *sname = "test_null_afpinfo" AFPINFO_STREAM_NAME;
4128         NTSTATUS status;
4129         bool ret = true;
4130         struct smb2_request *req[3];
4131         struct smb2_handle handle;
4132         struct smb2_create create;
4133         struct smb2_read read;
4134         AfpInfo *afpinfo = NULL;
4135         char *afpinfo_buf = NULL;
4136         const char *type_creator = "SMB,OLE!";
4137         struct smb2_handle handle2;
4138         struct smb2_read r;
4139
4140         torture_comment(tctx, "Checking create of AfpInfo stream\n");
4141
4142         smb2_util_unlink(tree, fname);
4143
4144         ret = torture_setup_file(mem_ctx, tree, fname, false);
4145         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
4146
4147         ZERO_STRUCT(create);
4148         create.in.desired_access = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA;
4149         create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
4150         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4151         create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4152         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4153         create.in.fname = sname;
4154
4155         smb2_transport_compound_start(tree->session->transport, 2);
4156
4157         req[0] = smb2_create_send(tree, &create);
4158
4159         handle.data[0] = UINT64_MAX;
4160         handle.data[1] = UINT64_MAX;
4161
4162         smb2_transport_compound_set_related(tree->session->transport, true);
4163
4164         ZERO_STRUCT(read);
4165         read.in.file.handle = handle;
4166         read.in.length = AFP_INFO_SIZE;
4167         req[1] = smb2_read_send(tree, &read);
4168
4169         status = smb2_create_recv(req[0], tree, &create);
4170         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_recv failed");
4171
4172         handle = create.out.file.handle;
4173
4174         status = smb2_read_recv(req[1], tree, &read);
4175         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read_recv failed");
4176
4177         status = torture_smb2_testfile_access(tree, sname, &handle2,
4178                                               SEC_FILE_READ_DATA);
4179         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4180                                         "torture_smb2_testfile failed\n");
4181         r = (struct smb2_read) {
4182                 .in.file.handle = handle2,
4183                 .in.length      = AFP_INFO_SIZE,
4184         };
4185
4186         status = smb2_read(tree, tree, &r);
4187         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4188                                         "torture_smb2_testfile failed\n");
4189         smb2_util_close(tree, handle2);
4190
4191         afpinfo = torture_afpinfo_new(mem_ctx);
4192         torture_assert_goto(tctx, afpinfo != NULL, ret, done, "torture_afpinfo_new failed");
4193
4194         memcpy(afpinfo->afpi_FinderInfo, type_creator, 8);
4195
4196         afpinfo_buf = torture_afpinfo_pack(tctx, afpinfo);
4197         torture_assert_goto(tctx, afpinfo_buf != NULL, ret, done, "torture_afpinfo_new failed");
4198
4199         status = smb2_util_write(tree, handle, afpinfo_buf, 0, AFP_INFO_SIZE);
4200         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write failed");
4201
4202         smb2_util_close(tree, handle);
4203
4204         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
4205                            0, 60, 16, 8, type_creator);
4206         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
4207
4208 done:
4209         smb2_util_unlink(tree, fname);
4210         talloc_free(mem_ctx);
4211         return ret;
4212 }
4213
4214 static bool test_delete_file_with_rfork(struct torture_context *tctx,
4215                                         struct smb2_tree *tree)
4216 {
4217         const char *fname = "torture_write_rfork_io";
4218         const char *rfork_content = "1234567890";
4219         NTSTATUS status;
4220         bool ret = true;
4221
4222         smb2_util_unlink(tree, fname);
4223
4224         torture_comment(tctx, "Test deleting file with resource fork\n");
4225
4226         ret = torture_setup_file(tctx, tree, fname, false);
4227         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed\n");
4228
4229         ret = write_stream(tree, __location__, tctx, tctx,
4230                            fname, AFPRESOURCE_STREAM_NAME,
4231                            10, 10, rfork_content);
4232         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed\n");
4233
4234         ret = check_stream(tree, __location__, tctx, tctx,
4235                            fname, AFPRESOURCE_STREAM_NAME,
4236                            0, 20, 10, 10, rfork_content);
4237         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed\n");
4238
4239         status = smb2_util_unlink(tree, fname);
4240         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "check_stream failed\n");
4241
4242 done:
4243         return ret;
4244 }
4245
4246 static bool test_rename_and_read_rsrc(struct torture_context *tctx,
4247                                       struct smb2_tree *tree)
4248 {
4249         bool ret = true;
4250         NTSTATUS status;
4251         struct smb2_create create, create2;
4252         struct smb2_handle h1, h2;
4253         const char *fname = "test_rename_openfile";
4254         const char *sname = "test_rename_openfile" AFPRESOURCE_STREAM_NAME;
4255         const char *fname_renamed = "test_rename_openfile_renamed";
4256         const char *data = "1234567890";
4257         union smb_setfileinfo sinfo;
4258         bool server_is_macos = torture_setting_bool(tctx, "osx", false);
4259         NTSTATUS expected_status;
4260
4261         ret = enable_aapl(tctx, tree);
4262         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
4263
4264         torture_comment(tctx, "Create file with resource fork\n");
4265
4266         ret = torture_setup_file(tctx, tree, fname, false);
4267         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4268
4269         ret = write_stream(tree, __location__, tctx, tctx,
4270                            fname, AFPRESOURCE_STREAM_NAME, 0, 10, data);
4271         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4272
4273         torture_comment(tctx, "Open resource fork\n");
4274
4275         ZERO_STRUCT(create);
4276         create.in.desired_access = SEC_FILE_ALL;
4277         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4278         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4279         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4280         create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4281         create.in.fname = sname;
4282
4283         status = smb2_create(tree, tctx, &create);
4284         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4285
4286         h1 = create.out.file.handle;
4287
4288         torture_comment(tctx, "Rename base file\n");
4289
4290         ZERO_STRUCT(create2);
4291         create2.in.desired_access = SEC_FILE_ALL;
4292         create2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4293         create2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4294         create2.in.create_disposition = NTCREATEX_DISP_OPEN;
4295         create2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4296         create2.in.fname = fname;
4297
4298         status = smb2_create(tree, tctx, &create2);
4299         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4300
4301         h2 = create2.out.file.handle;
4302
4303         ZERO_STRUCT(sinfo);
4304         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
4305         sinfo.rename_information.in.file.handle = h2;
4306         sinfo.rename_information.in.overwrite = 0;
4307         sinfo.rename_information.in.root_fid = 0;
4308         sinfo.rename_information.in.new_name = fname_renamed;
4309
4310         if (server_is_macos) {
4311                 expected_status = NT_STATUS_SHARING_VIOLATION;
4312         } else {
4313                 expected_status = NT_STATUS_ACCESS_DENIED;
4314         }
4315
4316         status = smb2_setinfo_file(tree, &sinfo);
4317         torture_assert_ntstatus_equal_goto(
4318                 tctx, status, expected_status, ret, done,
4319                 "smb2_setinfo_file failed");
4320
4321         smb2_util_close(tree, h2);
4322
4323         status = smb2_util_write(tree, h1, "foo", 0, 3);
4324         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4325                                         "write failed\n");
4326
4327         smb2_util_close(tree, h1);
4328
4329 done:
4330         smb2_util_unlink(tree, fname);
4331         smb2_util_unlink(tree, fname_renamed);
4332
4333         return ret;
4334 }
4335
4336 static bool test_readdir_attr_illegal_ntfs(struct torture_context *tctx,
4337                                            struct smb2_tree *tree)
4338 {
4339         TALLOC_CTX *mem_ctx = talloc_new(tctx);
4340         const char *name = "test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
4341         const char *fname = BASEDIR "\\test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
4342         NTSTATUS status;
4343         struct smb2_handle testdirh;
4344         bool ret = true;
4345         struct smb2_create io;
4346         AfpInfo *info;
4347         const char *type_creator = "SMB,OLE!";
4348         struct smb2_find f;
4349         unsigned int count;
4350         union smb_search_data *d;
4351         uint64_t rfork_len;
4352         int i;
4353
4354         smb2_deltree(tree, BASEDIR);
4355
4356         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
4357         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
4358         smb2_util_close(tree, testdirh);
4359
4360         torture_comment(tctx, "Enabling AAPL\n");
4361
4362         ret = enable_aapl(tctx, tree);
4363         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
4364
4365         /*
4366          * Now that Requested AAPL extensions are enabled, setup some
4367          * Mac files with metadata and resource fork
4368          */
4369
4370         torture_comment(tctx, "Preparing file\n");
4371
4372         ret = torture_setup_file(mem_ctx, tree, fname, false);
4373         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
4374
4375         info = torture_afpinfo_new(mem_ctx);
4376         torture_assert_not_null_goto(tctx, info, ret, done, "torture_afpinfo_new failed");
4377
4378         memcpy(info->afpi_FinderInfo, type_creator, 8);
4379         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
4380         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
4381
4382         ret = write_stream(tree, __location__, tctx, mem_ctx,
4383                            fname, AFPRESOURCE_STREAM_NAME,
4384                            0, 3, "foo");
4385         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4386
4387         /*
4388          * Ok, file is prepared, now call smb2/find
4389          */
4390
4391         torture_comment(tctx, "Issue find\n");
4392
4393         ZERO_STRUCT(io);
4394         io.in.desired_access = SEC_RIGHTS_DIR_READ;
4395         io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
4396         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
4397         io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
4398                               NTCREATEX_SHARE_ACCESS_WRITE |
4399                               NTCREATEX_SHARE_ACCESS_DELETE);
4400         io.in.create_disposition = NTCREATEX_DISP_OPEN;
4401         io.in.fname = BASEDIR;
4402         status = smb2_create(tree, tctx, &io);
4403         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4404
4405         ZERO_STRUCT(f);
4406         f.in.file.handle        = io.out.file.handle;
4407         f.in.pattern            = "*";
4408         f.in.max_response_size  = 0x1000;
4409         f.in.level              = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
4410
4411         status = smb2_find_level(tree, tree, &f, &count, &d);
4412         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_level failed");
4413
4414         status = smb2_util_close(tree, io.out.file.handle);
4415         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close failed");
4416
4417         torture_comment(tctx, "Checking find response with enriched macOS metadata\n");
4418
4419         for (i = 0; i < count; i++) {
4420                 const char *found = d[i].id_both_directory_info.name.s;
4421
4422                 if (!strcmp(found, ".") || !strcmp(found, ".."))
4423                         continue;
4424                 if (strncmp(found, "._", 2) == 0) {
4425                         continue;
4426                 }
4427                 break;
4428         }
4429
4430         torture_assert_str_equal_goto(tctx,
4431                                       d[i].id_both_directory_info.name.s, name,
4432                                       ret, done, "bad name");
4433
4434         rfork_len = BVAL(d[i].id_both_directory_info.short_name_buf, 0);
4435         torture_assert_int_equal_goto(tctx, rfork_len, 3, ret, done, "bad resource fork length");
4436
4437         torture_assert_mem_equal_goto(tctx, type_creator,
4438                                       d[i].id_both_directory_info.short_name_buf + 8,
4439                                       8, ret, done, "Bad FinderInfo");
4440 done:
4441         smb2_util_unlink(tree, fname);
4442         smb2_deltree(tree, BASEDIR);
4443         talloc_free(mem_ctx);
4444         return ret;
4445 }
4446
4447 static bool test_invalid_afpinfo(struct torture_context *tctx,
4448                                  struct smb2_tree *tree1,
4449                                  struct smb2_tree *tree2)
4450 {
4451         const char *fname = "filtest_invalid_afpinfo";
4452         const char *sname = "filtest_invalid_afpinfo" AFPINFO_STREAM_NAME;
4453         struct smb2_create create;
4454         const char *streams_basic[] = {
4455                 "::$DATA"
4456         };
4457         const char *streams_afpinfo[] = {
4458                 "::$DATA",
4459                 AFPINFO_STREAM
4460         };
4461         NTSTATUS status;
4462         bool ret = true;
4463
4464         if (tree2 == NULL) {
4465                 torture_skip_goto(tctx, done, "need second share without fruit\n");
4466         }
4467
4468         torture_comment(tctx, "Testing invalid AFP_AfpInfo stream\n");
4469
4470         ret = torture_setup_file(tctx, tree2, fname, false);
4471         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4472
4473         ret = write_stream(tree2, __location__, tctx, tctx,
4474                            fname, AFPINFO_STREAM_NAME,
4475                            0, 3, "foo");
4476         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4477
4478         ret = check_stream_list(tree2, tctx, fname, 2, streams_afpinfo, false);
4479         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4480
4481         torture_comment(tctx, "Listing streams, bad AFPINFO stream must not be present\n");
4482
4483         ret = check_stream_list(tree1, tctx, fname, 1, streams_basic, false);
4484         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4485
4486         torture_comment(tctx, "Try to open AFPINFO stream, must fail\n");
4487
4488         ZERO_STRUCT(create);
4489         create.in.desired_access = SEC_FILE_ALL;
4490         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4491         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4492         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4493         create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4494         create.in.fname = sname;
4495
4496         status = smb2_create(tree1, tctx, &create);
4497         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4498                                            ret, done, "Stream still around?");
4499
4500 done:
4501         smb2_util_unlink(tree1, fname);
4502         return ret;
4503 }
4504
4505 static bool test_zero_file_id(struct torture_context *tctx,
4506                               struct smb2_tree *tree)
4507 {
4508         const char *fname = "filtest_file_id";
4509         struct smb2_create create = {0};
4510         NTSTATUS status;
4511         bool ret = true;
4512         uint8_t zero_file_id[8] = {0};
4513
4514         torture_comment(tctx, "Testing zero file id\n");
4515
4516         ret = torture_setup_file(tctx, tree, fname, false);
4517         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4518
4519         ZERO_STRUCT(create);
4520         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4521         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4522         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4523         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4524         create.in.fname = fname;
4525         create.in.query_on_disk_id = true;
4526
4527         status = smb2_create(tree, tctx, &create);
4528         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
4529                                            done,
4530                                            "test file could not be opened");
4531         torture_assert_mem_not_equal_goto(tctx, create.out.on_disk_id,
4532                                           zero_file_id, 8, ret, done,
4533                                           "unexpected zero file id");
4534
4535         smb2_util_close(tree, create.out.file.handle);
4536
4537         ret = enable_aapl(tctx, tree);
4538         torture_assert(tctx, ret == true, "enable_aapl failed");
4539
4540         ZERO_STRUCT(create);
4541         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4542         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4543         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4544         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4545         create.in.fname = fname;
4546         create.in.query_on_disk_id = true;
4547
4548         status = smb2_create(tree, tctx, &create);
4549         torture_assert_ntstatus_equal_goto(
4550             tctx, status, NT_STATUS_OK, ret, done,
4551             "test file could not be opened with AAPL");
4552         torture_assert_mem_equal_goto(tctx, create.out.on_disk_id, zero_file_id,
4553                                       8, ret, done, "non-zero file id");
4554
4555         smb2_util_close(tree, create.out.file.handle);
4556
4557 done:
4558         smb2_util_unlink(tree, fname);
4559         return ret;
4560 }
4561
4562 static bool copy_one_stream(struct torture_context *torture,
4563                             struct smb2_tree *tree,
4564                             TALLOC_CTX *tmp_ctx,
4565                             const char *src_sname,
4566                             const char *dst_sname)
4567 {
4568         struct smb2_handle src_h = {{0}};
4569         struct smb2_handle dest_h = {{0}};
4570         NTSTATUS status;
4571         union smb_ioctl io;
4572         struct srv_copychunk_copy cc_copy;
4573         struct srv_copychunk_rsp cc_rsp;
4574         enum ndr_err_code ndr_ret;
4575         bool ok = false;
4576
4577         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4578                                    1, /* 1 chunk */
4579                                    src_sname,
4580                                    &src_h, 256, /* fill 256 byte src file */
4581                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4582                                    dst_sname,
4583                                    &dest_h, 0,  /* 0 byte dest file */
4584                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4585                                    &cc_copy,
4586                                    &io);
4587         torture_assert_goto(torture, ok == true, ok, done,
4588                             "setup copy chunk error\n");
4589
4590         /* copy all src file data (via a single chunk desc) */
4591         cc_copy.chunks[0].source_off = 0;
4592         cc_copy.chunks[0].target_off = 0;
4593         cc_copy.chunks[0].length = 256;
4594
4595         ndr_ret = ndr_push_struct_blob(
4596                 &io.smb2.in.out, tmp_ctx, &cc_copy,
4597                 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4598
4599         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4600                                    "ndr_push_srv_copychunk_copy\n");
4601
4602         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4603         torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4604                                         "FSCTL_SRV_COPYCHUNK\n");
4605
4606         ndr_ret = ndr_pull_struct_blob(
4607                 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4608                 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4609
4610         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4611                                    "ndr_pull_srv_copychunk_rsp\n");
4612
4613         ok = check_copy_chunk_rsp(torture, &cc_rsp,
4614                                   1,    /* chunks written */
4615                                   0,    /* chunk bytes unsuccessfully written */
4616                                   256); /* total bytes written */
4617         torture_assert_goto(torture, ok == true, ok, done,
4618                             "bad copy chunk response data\n");
4619
4620         ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 256, 0);
4621         if (!ok) {
4622                 torture_fail(torture, "inconsistent file data\n");
4623         }
4624
4625 done:
4626         if (!smb2_util_handle_empty(src_h)) {
4627                 smb2_util_close(tree, src_h);
4628         }
4629         if (!smb2_util_handle_empty(dest_h)) {
4630                 smb2_util_close(tree, dest_h);
4631         }
4632
4633         return ok;
4634 }
4635
4636 static bool copy_finderinfo_stream(struct torture_context *torture,
4637                                    struct smb2_tree *tree,
4638                                    TALLOC_CTX *tmp_ctx,
4639                                    const char *src_name,
4640                                    const char *dst_name)
4641 {
4642         struct smb2_handle src_h = {{0}};
4643         struct smb2_handle dest_h = {{0}};
4644         NTSTATUS status;
4645         union smb_ioctl io;
4646         struct srv_copychunk_copy cc_copy;
4647         struct srv_copychunk_rsp cc_rsp;
4648         enum ndr_err_code ndr_ret;
4649         const char *type_creator = "SMB,OLE!";
4650         AfpInfo *info = NULL;
4651         const char *src_name_afpinfo = NULL;
4652         const char *dst_name_afpinfo = NULL;
4653         bool ok = false;
4654
4655         src_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", src_name,
4656                                            AFPINFO_STREAM);
4657         torture_assert_not_null_goto(torture, src_name_afpinfo, ok, done,
4658                                      "talloc_asprintf failed\n");
4659
4660         dst_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", dst_name,
4661                                            AFPINFO_STREAM);
4662         torture_assert_not_null_goto(torture, dst_name_afpinfo, ok, done,
4663                                      "talloc_asprintf failed\n");
4664
4665         info = torture_afpinfo_new(tmp_ctx);
4666         torture_assert_not_null_goto(torture, info, ok, done,
4667                                      "torture_afpinfo_new failed\n");
4668
4669         memcpy(info->afpi_FinderInfo, type_creator, 8);
4670         ok = torture_write_afpinfo(tree, torture, tmp_ctx, src_name, info);
4671         torture_assert_goto(torture, ok == true, ok, done,
4672                             "torture_write_afpinfo failed\n");
4673
4674         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4675                                    1, /* 1 chunk */
4676                                    src_name_afpinfo,
4677                                    &src_h, 0,
4678                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4679                                    dst_name_afpinfo,
4680                                    &dest_h, 0,
4681                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4682                                    &cc_copy,
4683                                    &io);
4684         torture_assert_goto(torture, ok == true, ok, done,
4685                             "setup copy chunk error\n");
4686
4687         /* copy all src file data (via a single chunk desc) */
4688         cc_copy.chunks[0].source_off = 0;
4689         cc_copy.chunks[0].target_off = 0;
4690         cc_copy.chunks[0].length = 60;
4691
4692         ndr_ret = ndr_push_struct_blob(
4693                 &io.smb2.in.out, tmp_ctx, &cc_copy,
4694                 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4695
4696         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4697                                    "ndr_push_srv_copychunk_copy\n");
4698
4699         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4700         torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4701                                         "FSCTL_SRV_COPYCHUNK\n");
4702
4703         ndr_ret = ndr_pull_struct_blob(
4704                 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4705                 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4706
4707         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4708                                    "ndr_pull_srv_copychunk_rsp\n");
4709
4710         smb2_util_close(tree, src_h);
4711         ZERO_STRUCT(src_h);
4712         smb2_util_close(tree, dest_h);
4713         ZERO_STRUCT(dest_h);
4714
4715         ok = check_copy_chunk_rsp(torture, &cc_rsp,
4716                                   1,    /* chunks written */
4717                                   0,    /* chunk bytes unsuccessfully written */
4718                                   60); /* total bytes written */
4719         torture_assert_goto(torture, ok == true, ok, done,
4720                             "bad copy chunk response data\n");
4721
4722         ok = check_stream(tree, __location__, torture, tmp_ctx,
4723                           dst_name, AFPINFO_STREAM,
4724                           0, 60, 16, 8, type_creator);
4725         torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
4726
4727 done:
4728         if (!smb2_util_handle_empty(src_h)) {
4729                 smb2_util_close(tree, src_h);
4730         }
4731         if (!smb2_util_handle_empty(dest_h)) {
4732                 smb2_util_close(tree, dest_h);
4733         }
4734
4735         return ok;
4736 }
4737
4738 static bool test_copy_chunk_streams(struct torture_context *torture,
4739                                     struct smb2_tree *tree)
4740 {
4741         const char *src_name = "src";
4742         const char *dst_name = "dst";
4743         struct names {
4744                 const char *src_sname;
4745                 const char *dst_sname;
4746         } names[] = {
4747                 { "src:foo", "dst:foo" },
4748                 { "src" AFPRESOURCE_STREAM, "dst" AFPRESOURCE_STREAM }
4749         };
4750         int i;
4751         TALLOC_CTX *tmp_ctx = NULL;
4752         bool ok = false;
4753
4754         tmp_ctx = talloc_new(tree);
4755         torture_assert_not_null_goto(torture, tmp_ctx, ok, done,
4756                                      "torture_setup_file\n");
4757
4758         smb2_util_unlink(tree, src_name);
4759         smb2_util_unlink(tree, dst_name);
4760
4761         ok = torture_setup_file(torture, tree, src_name, false);
4762         torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
4763         ok = torture_setup_file(torture, tree, dst_name, false);
4764         torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
4765
4766         for (i = 0; i < ARRAY_SIZE(names); i++) {
4767                 ok = copy_one_stream(torture, tree, tmp_ctx,
4768                                      names[i].src_sname,
4769                                      names[i].dst_sname);
4770                 torture_assert_goto(torture, ok == true, ok, done,
4771                                     "copy_one_stream failed\n");
4772         }
4773
4774         ok = copy_finderinfo_stream(torture, tree, tmp_ctx,
4775                                     src_name, dst_name);
4776         torture_assert_goto(torture, ok == true, ok, done,
4777                             "copy_finderinfo_stream failed\n");
4778
4779 done:
4780         smb2_util_unlink(tree, src_name);
4781         smb2_util_unlink(tree, dst_name);
4782         talloc_free(tmp_ctx);
4783         return ok;
4784 }
4785
4786 /*
4787  * Ensure this security descriptor has exactly one mode, uid
4788  * and gid.
4789  */
4790
4791 static NTSTATUS check_nfs_sd(const struct security_descriptor *psd)
4792 {
4793         uint32_t i;
4794         bool got_one_mode = false;
4795         bool got_one_uid = false;
4796         bool got_one_gid = false;
4797
4798         if (psd->dacl == NULL) {
4799                 return NT_STATUS_INVALID_SECURITY_DESCR;
4800         }
4801
4802         for (i = 0; i < psd->dacl->num_aces; i++) {
4803                 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Mode,
4804                                            &psd->dacl->aces[i].trustee) == 0) {
4805                         if (got_one_mode == true) {
4806                                 /* Can't have more than one. */
4807                                 return NT_STATUS_INVALID_SECURITY_DESCR;
4808                         }
4809                         got_one_mode = true;
4810                 }
4811         }
4812         for (i = 0; i < psd->dacl->num_aces; i++) {
4813                 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Users,
4814                                            &psd->dacl->aces[i].trustee) == 0) {
4815                         if (got_one_uid == true) {
4816                                 /* Can't have more than one. */
4817                                 return NT_STATUS_INVALID_SECURITY_DESCR;
4818                         }
4819                         got_one_uid = true;
4820                 }
4821         }
4822         for (i = 0; i < psd->dacl->num_aces; i++) {
4823                 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Groups,
4824                                            &psd->dacl->aces[i].trustee) == 0) {
4825                         if (got_one_gid == true) {
4826                                 /* Can't have more than one. */
4827                                 return NT_STATUS_INVALID_SECURITY_DESCR;
4828                         }
4829                         got_one_gid = true;
4830                 }
4831         }
4832         /* Must have at least one of each. */
4833         if (got_one_mode == false ||
4834                         got_one_uid == false ||
4835                         got_one_gid == false) {
4836                 return NT_STATUS_INVALID_SECURITY_DESCR;
4837         }
4838         return NT_STATUS_OK;
4839 }
4840
4841 static bool test_nfs_aces(struct torture_context *tctx,
4842                           struct smb2_tree *tree)
4843 {
4844         TALLOC_CTX *mem_ctx = talloc_new(tctx);
4845         struct security_ace ace;
4846         struct dom_sid sid;
4847         const char *fname = BASEDIR "\\nfs_aces.txt";
4848         struct smb2_handle h = {{0}};
4849         union smb_fileinfo finfo2;
4850         union smb_setfileinfo set;
4851         struct security_descriptor *psd = NULL;
4852         NTSTATUS status;
4853         bool ret = true;
4854         bool is_osx = torture_setting_bool(tctx, "osx", false);
4855
4856         if (is_osx) {
4857                 torture_skip(tctx, "Test only works with Samba\n");
4858         }
4859
4860         ret = enable_aapl(tctx, tree);
4861         torture_assert(tctx, ret == true, "enable_aapl failed");
4862
4863         /* clean slate ...*/
4864         smb2_util_unlink(tree, fname);
4865         smb2_deltree(tree, fname);
4866         smb2_deltree(tree, BASEDIR);
4867
4868         status = torture_smb2_testdir(tree, BASEDIR, &h);
4869         CHECK_STATUS(status, NT_STATUS_OK);
4870         smb2_util_close(tree, h);
4871
4872         /* Create a test file. */
4873         status = torture_smb2_testfile_access(tree,
4874                                 fname,
4875                                 &h,
4876                                 SEC_STD_READ_CONTROL |
4877                                 SEC_STD_WRITE_DAC |
4878                                 SEC_RIGHTS_FILE_ALL);
4879         CHECK_STATUS(status, NT_STATUS_OK);
4880
4881         /* Get the ACL. */
4882         finfo2.query_secdesc.in.secinfo_flags =
4883                 SECINFO_OWNER |
4884                 SECINFO_GROUP |
4885                 SECINFO_DACL;
4886         finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
4887         finfo2.generic.in.file.handle = h;
4888         status = smb2_getinfo_file(tree, tctx, &finfo2);
4889         CHECK_STATUS(status, NT_STATUS_OK);
4890
4891         psd = finfo2.query_secdesc.out.sd;
4892
4893         /* Ensure we have only single mode/uid/gid NFS entries. */
4894         status = check_nfs_sd(psd);
4895         if (!NT_STATUS_IS_OK(status)) {
4896                 NDR_PRINT_DEBUG(
4897                         security_descriptor,
4898                         discard_const_p(struct security_descriptor, psd));
4899         }
4900         CHECK_STATUS(status, NT_STATUS_OK);
4901
4902         /* Add a couple of extra NFS uids and gids. */
4903         sid_compose(&sid, &global_sid_Unix_NFS_Users, 27);
4904         init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
4905         status = security_descriptor_dacl_add(psd, &ace);
4906         CHECK_STATUS(status, NT_STATUS_OK);
4907         status = security_descriptor_dacl_add(psd, &ace);
4908         CHECK_STATUS(status, NT_STATUS_OK);
4909
4910         sid_compose(&sid, &global_sid_Unix_NFS_Groups, 300);
4911         init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
4912         status = security_descriptor_dacl_add(psd, &ace);
4913         CHECK_STATUS(status, NT_STATUS_OK);
4914         status = security_descriptor_dacl_add(psd, &ace);
4915         CHECK_STATUS(status, NT_STATUS_OK);
4916
4917         /* Now set on the file handle. */
4918         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
4919         set.set_secdesc.in.file.handle = h;
4920         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
4921         set.set_secdesc.in.sd = psd;
4922         status = smb2_setinfo_file(tree, &set);
4923         CHECK_STATUS(status, NT_STATUS_OK);
4924
4925         /* Get the ACL again. */
4926         finfo2.query_secdesc.in.secinfo_flags =
4927                 SECINFO_OWNER |
4928                 SECINFO_GROUP |
4929                 SECINFO_DACL;
4930         finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
4931         finfo2.generic.in.file.handle = h;
4932         status = smb2_getinfo_file(tree, tctx, &finfo2);
4933         CHECK_STATUS(status, NT_STATUS_OK);
4934
4935         psd = finfo2.query_secdesc.out.sd;
4936
4937         /* Ensure we have only single mode/uid/gid NFS entries. */
4938         status = check_nfs_sd(psd);
4939         if (!NT_STATUS_IS_OK(status)) {
4940                 NDR_PRINT_DEBUG(
4941                         security_descriptor,
4942                         discard_const_p(struct security_descriptor, psd));
4943         }
4944         CHECK_STATUS(status, NT_STATUS_OK);
4945
4946 done:
4947         if (!smb2_util_handle_empty(h)) {
4948                 smb2_util_close(tree, h);
4949         }
4950         smb2_util_unlink(tree, fname);
4951         smb2_deltree(tree, fname);
4952         smb2_deltree(tree, BASEDIR);
4953         talloc_free(mem_ctx);
4954         return ret;
4955 }
4956
4957 static bool test_setinfo_stream_eof(struct torture_context *tctx,
4958                                     struct smb2_tree *tree)
4959 {
4960         bool ret = true;
4961         NTSTATUS status;
4962         struct smb2_create create;
4963         union smb_setfileinfo sfinfo;
4964         union smb_fileinfo finfo;
4965         struct smb2_handle h1;
4966         TALLOC_CTX *mem_ctx = talloc_new(tctx);
4967         const char *fname = BASEDIR "\\file";
4968         const char *sname = BASEDIR "\\file:foo";
4969
4970         torture_assert_goto(tctx, mem_ctx != NULL, ret, done,
4971                             "talloc_new failed\n");
4972
4973         ret = enable_aapl(tctx, tree);
4974         torture_assert(tctx, ret == true, "enable_aapl failed");
4975
4976         torture_comment(tctx, "Test setting EOF on a stream\n");
4977
4978         smb2_deltree(tree, BASEDIR);
4979         status = torture_smb2_testdir(tree, BASEDIR, &h1);
4980         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4981                                         "torture_smb2_testdir\n");
4982         smb2_util_close(tree, h1);
4983
4984         status = torture_smb2_testfile(tree, fname, &h1);
4985         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4986                                         "torture_smb2_testfile failed\n");
4987         smb2_util_close(tree, h1);
4988
4989         status = torture_smb2_testfile_access(tree, sname, &h1,
4990                                               SEC_FILE_WRITE_DATA);
4991         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4992                                         "torture_smb2_testfile failed\n");
4993
4994         status = smb2_util_write(tree, h1, "1234567890", 0, 10);
4995         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4996                                         "smb2_util_write failed\n");
4997         smb2_util_close(tree, h1);
4998
4999         /*
5000          * Test setting EOF to 21
5001          */
5002
5003         torture_comment(tctx, "Setting stream EOF to 21\n");
5004
5005         status = torture_smb2_testfile_access(tree, sname, &h1,
5006                                               SEC_FILE_WRITE_DATA);
5007         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5008                                         "torture_smb2_testfile failed\n");
5009
5010         ZERO_STRUCT(sfinfo);
5011         sfinfo.generic.in.file.handle = h1;
5012         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5013         sfinfo.position_information.in.position = 21;
5014         status = smb2_setinfo_file(tree, &sfinfo);
5015         torture_assert_ntstatus_ok_goto(tctx, status,
5016                                         ret, done, "set EOF 21 failed\n");
5017
5018         smb2_util_close(tree, h1);
5019
5020         status = torture_smb2_testfile_access(tree, sname, &h1,
5021                                               SEC_FILE_WRITE_DATA);
5022         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5023                                         "torture_smb2_testfile failed\n");
5024
5025         ZERO_STRUCT(finfo);
5026         finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5027         finfo.generic.in.file.handle = h1;
5028         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5029         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5030                                         "smb2_getinfo_file failed");
5031
5032         smb2_util_close(tree, h1);
5033
5034         torture_assert_goto(tctx, finfo.standard_info.out.size == 21,
5035                             ret, done, "size != 21\n");
5036
5037         /*
5038          * Test setting EOF to 0
5039          */
5040
5041         torture_comment(tctx, "Setting stream EOF to 0\n");
5042
5043         status = torture_smb2_testfile_access(tree, sname, &h1,
5044                                               SEC_FILE_WRITE_DATA);
5045         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5046                                         "torture_smb2_testfile failed\n");
5047
5048         ZERO_STRUCT(sfinfo);
5049         sfinfo.generic.in.file.handle = h1;
5050         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5051         sfinfo.position_information.in.position = 0;
5052         status = smb2_setinfo_file(tree, &sfinfo);
5053         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5054                                         "set eof 0 failed\n");
5055
5056         ZERO_STRUCT(create);
5057         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5058         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5059         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5060         create.in.create_disposition = NTCREATEX_DISP_OPEN;
5061         create.in.fname = sname;
5062
5063         status = smb2_create(tree, tctx, &create);
5064         torture_assert_ntstatus_equal_goto(
5065                 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5066                 "Unexpected status\n");
5067
5068         smb2_util_close(tree, h1);
5069
5070         ZERO_STRUCT(create);
5071         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5072         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5073         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5074         create.in.create_disposition = NTCREATEX_DISP_OPEN;
5075         create.in.fname = sname;
5076
5077         status = smb2_create(tree, tctx, &create);
5078         torture_assert_ntstatus_equal_goto(
5079                 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5080                 "Unexpected status\n");
5081
5082         status = torture_smb2_testfile_access(tree, sname, &h1,
5083                                               SEC_FILE_WRITE_DATA);
5084         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5085                                         "torture_smb2_testfile failed\n");
5086
5087         ZERO_STRUCT(finfo);
5088         finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5089         finfo.generic.in.file.handle = h1;
5090         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5091         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5092                                         "smb2_getinfo_file failed\n");
5093
5094         smb2_util_close(tree, h1);
5095
5096         torture_assert_goto(tctx, finfo.standard_info.out.size == 0,
5097                             ret, done, "size != 0\n");
5098
5099         /*
5100          * Test setinfo end-of-file info to 1
5101          */
5102
5103         torture_comment(tctx, "Setting stream EOF to 1\n");
5104
5105         status = torture_smb2_testfile_access(tree, sname, &h1,
5106                                               SEC_FILE_WRITE_DATA);
5107         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5108                                         "torture_smb2_testfile failed\n");
5109
5110         ZERO_STRUCT(sfinfo);
5111         sfinfo.generic.in.file.handle = h1;
5112         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5113         sfinfo.position_information.in.position = 1;
5114         status = smb2_setinfo_file(tree, &sfinfo);
5115         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5116                                         "set EOF 1 failed\n");
5117
5118         smb2_util_close(tree, h1);
5119
5120         status = torture_smb2_testfile_access(tree, sname, &h1,
5121                                               SEC_FILE_WRITE_DATA);
5122         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5123                                         "torture_smb2_testfile failed\n");
5124
5125         ZERO_STRUCT(finfo);
5126         finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5127         finfo.generic.in.file.handle = h1;
5128         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5129         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5130                                         "smb2_getinfo_file failed\n");
5131
5132         smb2_util_close(tree, h1);
5133
5134         torture_assert_goto(tctx, finfo.standard_info.out.size == 1,
5135                             ret, done, "size != 1\n");
5136
5137         /*
5138          * Test setting EOF to 0 with AAPL enabled, should delete stream
5139          */
5140
5141         torture_comment(tctx, "Enabling AAPL extensions\n");
5142
5143         ret = enable_aapl(tctx, tree);
5144         torture_assert(tctx, ret == true, "enable_aapl failed\n");
5145
5146         torture_comment(tctx, "Setting stream EOF to 0\n");
5147         status = torture_smb2_testfile_access(tree, sname, &h1,
5148                                               SEC_FILE_WRITE_DATA);
5149         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5150                                         "torture_smb2_testfile failed\n");
5151
5152         ZERO_STRUCT(sfinfo);
5153         sfinfo.generic.in.file.handle = h1;
5154         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5155         sfinfo.position_information.in.position = 0;
5156         status = smb2_setinfo_file(tree, &sfinfo);
5157         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5158                                         "set eof 0 failed\n");
5159
5160         ZERO_STRUCT(create);
5161         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5162         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5163         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5164         create.in.create_disposition = NTCREATEX_DISP_OPEN;
5165         create.in.fname = sname;
5166
5167         status = smb2_create(tree, tctx, &create);
5168         torture_assert_ntstatus_equal_goto(
5169                 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5170                 "Unexpected status\n");
5171
5172         smb2_util_close(tree, h1);
5173
5174         ZERO_STRUCT(create);
5175         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5176         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5177         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5178         create.in.create_disposition = NTCREATEX_DISP_OPEN;
5179         create.in.fname = sname;
5180
5181         status = smb2_create(tree, tctx, &create);
5182         torture_assert_ntstatus_equal_goto(
5183                 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5184                 "Unexpected status\n");
5185
5186         torture_comment(
5187                 tctx, "Setting main file EOF to 1 to force 0-truncate\n");
5188
5189         status = torture_smb2_testfile_access(
5190                 tree,
5191                 fname,
5192                 &h1,
5193                 SEC_FILE_WRITE_DATA);
5194         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5195                                         "torture_smb2_testfile failed\n");
5196
5197         ZERO_STRUCT(sfinfo);
5198         sfinfo.generic.in.file.handle = h1;
5199         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5200         sfinfo.position_information.in.position = 1;
5201         status = smb2_setinfo_file(tree, &sfinfo);
5202         torture_assert_ntstatus_ok_goto(
5203                 tctx,
5204                 status,
5205                 ret,
5206                 done,
5207                 "set eof 1 failed\n");
5208
5209         sfinfo.position_information.in.position = 0;
5210         status = smb2_setinfo_file(tree, &sfinfo);
5211         torture_assert_ntstatus_ok_goto(
5212                 tctx,
5213                 status,
5214                 ret,
5215                 done,
5216                 "set eof 0 failed\n");
5217
5218         smb2_util_close(tree, h1);
5219
5220         ZERO_STRUCT(create);
5221         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5222         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5223         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5224         create.in.create_disposition = NTCREATEX_DISP_OPEN;
5225         create.in.fname = fname;
5226
5227         status = smb2_create(tree, tctx, &create);
5228         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5229                                         "torture_smb2_testfile failed\n");
5230         smb2_util_close(tree, h1);
5231
5232         torture_comment(tctx, "Writing to stream after setting EOF to 0\n");
5233         status = torture_smb2_testfile_access(tree, sname, &h1,
5234                                               SEC_FILE_WRITE_DATA);
5235         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5236                                         "torture_smb2_testfile failed\n");
5237
5238         status = smb2_util_write(tree, h1, "1234567890", 0, 10);
5239         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5240                                         "smb2_util_write failed\n");
5241
5242         ZERO_STRUCT(sfinfo);
5243         sfinfo.generic.in.file.handle = h1;
5244         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5245         sfinfo.position_information.in.position = 0;
5246         status = smb2_setinfo_file(tree, &sfinfo);
5247         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5248                                         "set eof 0 failed\n");
5249
5250         status = smb2_util_write(tree, h1, "1234567890", 0, 10);
5251         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5252                                         "smb2_util_write failed\n");
5253
5254         smb2_util_close(tree, h1);
5255
5256 done:
5257         smb2_util_unlink(tree, fname);
5258         smb2_util_rmdir(tree, BASEDIR);
5259         return ret;
5260 }
5261
5262 #define MAX_STREAMS 16
5263
5264 struct tcase {
5265         const char *name;
5266         uint32_t access;
5267         const char *write_data;
5268         size_t write_size;
5269         struct tcase_results {
5270                 size_t size;
5271                 NTSTATUS initial_status;
5272                 NTSTATUS final_status;
5273                 int num_streams_open_handle;
5274                 const char *streams_open_handle[MAX_STREAMS];
5275                 int num_streams_closed_handle;
5276                 const char *streams_closed_handle[MAX_STREAMS];
5277         } create, write, overwrite, eof, doc;
5278 };
5279
5280 typedef enum {T_CREATE, T_WRITE, T_OVERWRITE, T_EOF, T_DOC} subtcase_t;
5281
5282 static bool test_empty_stream_do_checks(
5283         struct torture_context *tctx,
5284         struct smb2_tree *tree,
5285         struct smb2_tree *tree2,
5286         struct tcase *tcase,
5287         TALLOC_CTX *mem_ctx,
5288         struct smb2_handle baseh,
5289         struct smb2_handle streamh,
5290         subtcase_t subcase)
5291 {
5292         bool ret = false;
5293         NTSTATUS status;
5294         struct smb2_handle h1;
5295         union smb_fileinfo finfo;
5296         struct tcase_results *tcase_results = NULL;
5297
5298         switch (subcase) {
5299         case T_CREATE:
5300                 tcase_results = &tcase->create;
5301                 break;
5302         case T_OVERWRITE:
5303                 tcase_results = &tcase->overwrite;
5304                 break;
5305         case T_WRITE:
5306                 tcase_results = &tcase->write;
5307                 break;
5308         case T_EOF:
5309                 tcase_results = &tcase->eof;
5310                 break;
5311         case T_DOC:
5312                 tcase_results = &tcase->doc;
5313                 break;
5314         }
5315
5316         finfo = (union smb_fileinfo) {
5317                 .generic.level = RAW_FILEINFO_STANDARD_INFORMATION,
5318                 .generic.in.file.handle = streamh,
5319         };
5320
5321         /*
5322          * Test: check size, same client
5323          */
5324
5325         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5326         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5327                                         "torture_smb2_testfile failed\n");
5328
5329         torture_assert_int_equal_goto(tctx, finfo.standard_info.out.size,
5330                                       tcase_results->size,
5331                                       ret, done, "Wrong size\n");
5332
5333         /*
5334          * Test: open, same client
5335          */
5336
5337         status = torture_smb2_open(tree, tcase->name,
5338                                    SEC_FILE_READ_ATTRIBUTE, &h1);
5339         torture_assert_ntstatus_equal_goto(tctx, status,
5340                                            tcase_results->initial_status,
5341                                            ret, done,
5342                                            "smb2_create failed\n");
5343         if (NT_STATUS_IS_OK(status)) {
5344                 status = smb2_util_close(tree, h1);
5345                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5346                                                 "smb2_util_close failed\n");
5347         }
5348
5349         /*
5350          * Test: check streams, same client
5351          */
5352
5353         ret = check_stream_list_handle(tree, tctx, baseh,
5354                                        tcase_results->num_streams_open_handle,
5355                                        tcase_results->streams_open_handle,
5356                                        false);
5357         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
5358
5359         /*
5360          * Test: open, different client
5361          */
5362
5363         status = torture_smb2_open(tree2, tcase->name,
5364                                    SEC_FILE_READ_ATTRIBUTE, &h1);
5365         torture_assert_ntstatus_equal_goto(tctx, status,
5366                                            tcase_results->initial_status,
5367                                            ret, done,
5368                                            "smb2_create failed\n");
5369         if (NT_STATUS_IS_OK(status)) {
5370                 finfo = (union smb_fileinfo) {
5371                         .generic.level = RAW_FILEINFO_STANDARD_INFORMATION,
5372                         .generic.in.file.handle = h1,
5373                 };
5374
5375                 /*
5376                  * Test: check size, different client
5377                  */
5378
5379                 status = smb2_getinfo_file(tree2, mem_ctx, &finfo);
5380                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5381                                                 "smb2_getinfo_file failed\n");
5382
5383                 torture_assert_int_equal_goto(tctx, finfo.standard_info.out.size,
5384                                               tcase_results->size,
5385                                               ret, done, "Wrong size\n");
5386
5387                 /*
5388                  * Test: check streams, different client
5389                  */
5390
5391                 ret = check_stream_list(tree2, tctx, BASEDIR "\\file",
5392                                         tcase_results->num_streams_open_handle,
5393                                         tcase_results->streams_open_handle,
5394                                         false);
5395                 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
5396
5397                 status = smb2_util_close(tree2, h1);
5398                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5399                                                 "smb2_util_close failed\n");
5400         }
5401
5402         status = smb2_util_close(tree, streamh);
5403         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5404                                         "smb2_util_close failed\n");
5405
5406         /*
5407          * Test: open after close, same client
5408          */
5409
5410         status = torture_smb2_open(tree, tcase->name,
5411                                    SEC_FILE_READ_DATA, &h1);
5412         torture_assert_ntstatus_equal_goto(tctx, status,
5413                                            tcase_results->final_status,
5414                                            ret, done,
5415                                            "smb2_create failed\n");
5416         if (NT_STATUS_IS_OK(status)) {
5417                 status = smb2_util_close(tree, h1);
5418                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5419                                                 "smb2_util_close failed\n");
5420         }
5421
5422         /*
5423          * Test: open after close, different client
5424          */
5425
5426         status = torture_smb2_open(tree2, tcase->name,
5427                                    SEC_FILE_READ_DATA, &h1);
5428         torture_assert_ntstatus_equal_goto(tctx, status,
5429                                            tcase_results->final_status,
5430                                            ret, done,
5431                                            "smb2_create failed\n");
5432         if (NT_STATUS_IS_OK(status)) {
5433                 status = smb2_util_close(tree2, h1);
5434                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5435                                                 "smb2_util_close failed\n");
5436         }
5437
5438         /*
5439          * Test: check streams after close, same client
5440          */
5441
5442         ret = check_stream_list_handle(tree, tctx, baseh,
5443                                        tcase_results->num_streams_closed_handle,
5444                                        tcase_results->streams_closed_handle,
5445                                        false);
5446         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
5447
5448         ret = true;
5449
5450 done:
5451         smb2_util_close(tree, streamh);
5452         smb2_util_close(tree, baseh);
5453         return ret;
5454 }
5455
5456 static bool test_empty_stream_do_one(
5457         struct torture_context *tctx,
5458         struct smb2_tree *tree,
5459         struct smb2_tree *tree2,
5460         struct tcase *tcase)
5461 {
5462         bool ret = false;
5463         NTSTATUS status;
5464         struct smb2_handle baseh;
5465         struct smb2_handle streamh;
5466         struct smb2_create create;
5467         union smb_setfileinfo sfinfo;
5468         TALLOC_CTX *mem_ctx = talloc_new(tctx);
5469
5470         torture_comment(tctx, "Testing stream [%s]\n", tcase->name);
5471
5472         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new\n");
5473
5474         /*
5475          * Subtest: create
5476          */
5477         torture_comment(tctx, "Subtest: T_CREATE\n");
5478
5479         status = smb2_util_unlink(tree, BASEDIR "\\file");
5480         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5481                                         "smb2_util_unlink failed\n");
5482
5483         status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5484                                               &baseh, SEC_FILE_ALL);
5485         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5486                                         "torture_smb2_testfile_access failed\n");
5487
5488         status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5489                                               tcase->access);
5490         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5491                                         "torture_smb2_testfile_access failed\n");
5492
5493         ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5494                                           mem_ctx, baseh, streamh, T_CREATE);
5495         torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5496
5497         if (!(tcase->access & SEC_FILE_WRITE_DATA)) {
5498                 /*
5499                  * All subsequent tests require write access
5500                  */
5501                 ret = true;
5502                 goto done;
5503         }
5504
5505         /*
5506          * Subtest: create and write
5507          */
5508         torture_comment(tctx, "Subtest: T_WRITE\n");
5509
5510         status = smb2_util_unlink(tree, BASEDIR "\\file");
5511         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5512                                         "smb2_util_unlink failed\n");
5513
5514         status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5515                                               &baseh, SEC_FILE_ALL);
5516         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5517                                         "torture_smb2_testfile_access failed\n");
5518
5519         status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5520                                               tcase->access);
5521         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5522                                         "torture_smb2_testfile_access failed\n");
5523
5524         status = smb2_util_write(tree, streamh, tcase->write_data, 0,
5525                                  tcase->write_size);
5526         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5527                                         "torture_smb2_open failed\n");
5528
5529         ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5530                                           mem_ctx, baseh, streamh, T_WRITE);
5531         torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5532
5533         /*
5534          * Subtest: overwrite
5535          */
5536         torture_comment(tctx, "Subtest: T_OVERWRITE\n");
5537
5538         status = smb2_util_unlink(tree, BASEDIR "\\file");
5539         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5540                                         "smb2_util_unlink failed\n");
5541
5542         status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5543                                               &baseh, SEC_FILE_ALL);
5544         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5545                                         "torture_smb2_testfile_access failed\n");
5546
5547         create = (struct smb2_create) {
5548                 .in.desired_access = SEC_FILE_ALL,
5549                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
5550                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
5551                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF,
5552                 .in.fname = tcase->name,
5553         };
5554
5555         status = smb2_create(tree, tctx, &create);
5556         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5557                                         "torture_smb2_testfile failed\n");
5558         streamh = create.out.file.handle;
5559
5560         ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5561                                           mem_ctx, baseh, streamh, T_OVERWRITE);
5562         torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5563
5564         /*
5565          * Subtest: setinfo EOF 0
5566          */
5567         torture_comment(tctx, "Subtest: T_EOF\n");
5568
5569         status = smb2_util_unlink(tree, BASEDIR "\\file");
5570         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5571                                         "smb2_util_unlink failed\n");
5572
5573         status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5574                                               &baseh, SEC_FILE_ALL);
5575         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5576                                         "torture_smb2_testfile_access failed\n");
5577
5578         status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5579                                               tcase->access);
5580         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5581                                         "torture_smb2_testfile_access failed\n");
5582
5583         status = smb2_util_write(tree, streamh, tcase->write_data, 0,
5584                                  tcase->write_size);
5585         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5586                                         "torture_smb2_open failed\n");
5587
5588         sfinfo = (union smb_setfileinfo) {
5589                 .end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION,
5590                 .end_of_file_info.in.file.handle = streamh,
5591                 .end_of_file_info.in.size = 0,
5592         };
5593         status = smb2_setinfo_file(tree, &sfinfo);
5594         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5595                                         "set eof 0 failed\n");
5596
5597         ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5598                                           mem_ctx, baseh, streamh, T_EOF);
5599         torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5600
5601         /*
5602          * Subtest: delete-on-close
5603          */
5604         torture_comment(tctx, "Subtest: T_DOC\n");
5605
5606         status = smb2_util_unlink(tree, BASEDIR "\\file");
5607         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5608                                         "smb2_util_unlink failed\n");
5609
5610         status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5611                                               &baseh, SEC_FILE_ALL);
5612         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5613                                         "torture_smb2_testfile_access failed\n");
5614
5615         status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5616                                               tcase->access);
5617         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5618                                         "torture_smb2_testfile_access failed\n");
5619
5620         status = smb2_util_write(tree, streamh, tcase->write_data, 0,
5621                                  tcase->write_size);
5622         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5623                                         "torture_smb2_open failed\n");
5624
5625         sfinfo = (union smb_setfileinfo) {
5626                 .disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFORMATION,
5627                 .disposition_info.in.file.handle = streamh,
5628                 .disposition_info.in.delete_on_close = true,
5629         };
5630         status = smb2_setinfo_file(tree, &sfinfo);
5631         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5632                                         "set eof 0 failed\n");
5633
5634         ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5635                                           mem_ctx, baseh, streamh,
5636                                           T_DOC);
5637         torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5638
5639         ret = true;
5640
5641 done:
5642         smb2_util_close(tree, baseh);
5643         TALLOC_FREE(mem_ctx);
5644         return ret;
5645 }
5646
5647 static bool test_empty_stream(struct torture_context *tctx,
5648                               struct smb2_tree *tree)
5649 {
5650         struct smb2_tree *tree2 = NULL;
5651         struct tcase *tcase = NULL;
5652         const char *fname = BASEDIR "\\file";
5653         struct smb2_handle h1;
5654         bool ret = true;
5655         NTSTATUS status;
5656         AfpInfo ai = (AfpInfo) {
5657                 .afpi_Signature = AFP_Signature,
5658                 .afpi_Version = AFP_Version,
5659                 .afpi_BackupTime = AFP_BackupTime,
5660                 .afpi_FinderInfo = "FOO BAR ",
5661         };
5662         char *ai_blob = torture_afpinfo_pack(tctx, &ai);
5663         struct tcase tcase_afpinfo_ro = (struct tcase) {
5664                 .name = BASEDIR "\\file" AFPINFO_STREAM,
5665                 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
5666                 .create.size = 60,
5667                 .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5668                 .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5669                 .create.num_streams_open_handle = 1,
5670                 .create.num_streams_closed_handle = 1,
5671                 .create.streams_open_handle = {"::$DATA"},
5672                 .create.streams_closed_handle = {"::$DATA"},
5673         };
5674         struct tcase tcase_afpinfo_rw = (struct tcase) {
5675                 .name = BASEDIR "\\file" AFPINFO_STREAM,
5676                 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
5677                 .write_data = ai_blob,
5678                 .write_size = AFP_INFO_SIZE,
5679                 .create.size = 60,
5680                 .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5681                 .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5682                 .create.num_streams_open_handle = 1,
5683                 .create.num_streams_closed_handle = 1,
5684                 .create.streams_open_handle = {"::$DATA"},
5685                 .create.streams_closed_handle = {"::$DATA"},
5686                 .write.size = 60,
5687                 .write.initial_status = NT_STATUS_OK,
5688                 .write.final_status = NT_STATUS_OK,
5689                 .write.num_streams_open_handle = 2,
5690                 .write.num_streams_closed_handle = 2,
5691                 .write.streams_open_handle = {"::$DATA", AFPINFO_STREAM},
5692                 .write.streams_closed_handle = {"::$DATA", AFPINFO_STREAM},
5693                 .overwrite.size = 60,
5694                 .overwrite.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5695                 .overwrite.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5696                 .overwrite.num_streams_open_handle = 1,
5697                 .overwrite.num_streams_closed_handle = 1,
5698                 .overwrite.streams_open_handle = {"::$DATA"},
5699                 .overwrite.streams_closed_handle = {"::$DATA"},
5700                 .eof.size = 60,
5701                 .eof.initial_status = NT_STATUS_OK,
5702                 .eof.final_status = NT_STATUS_OK,
5703                 .eof.num_streams_open_handle = 2,
5704                 .eof.num_streams_closed_handle = 2,
5705                 .eof.streams_open_handle = {"::$DATA", AFPINFO_STREAM},
5706                 .eof.streams_closed_handle = {"::$DATA", AFPINFO_STREAM},
5707                 .doc.size = 60,
5708                 .doc.initial_status = NT_STATUS_DELETE_PENDING,
5709                 .doc.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5710                 .doc.num_streams_open_handle = 2,
5711                 .doc.num_streams_closed_handle = 1,
5712                 .doc.streams_open_handle = {"::$DATA", AFPINFO_STREAM},
5713                 .doc.streams_closed_handle = {"::$DATA"},
5714         };
5715
5716         struct tcase tcase_afpresource_ro = (struct tcase) {
5717                 .name = BASEDIR "\\file" AFPRESOURCE_STREAM,
5718                 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
5719                 .create.size = 0,
5720                 .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5721                 .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5722                 .create.num_streams_open_handle = 1,
5723                 .create.num_streams_closed_handle = 1,
5724                 .create.streams_open_handle = {"::$DATA"},
5725                 .create.streams_closed_handle = {"::$DATA"},
5726         };
5727         struct tcase tcase_afpresource_rw = (struct tcase) {
5728                 .name = BASEDIR "\\file" AFPRESOURCE_STREAM,
5729                 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
5730                 .write_data = "foo",
5731                 .write_size = 3,
5732                 .create.size = 0,
5733                 .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5734                 .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5735                 .create.num_streams_open_handle = 1,
5736                 .create.num_streams_closed_handle = 1,
5737                 .create.streams_open_handle = {"::$DATA"},
5738                 .create.streams_closed_handle = {"::$DATA"},
5739                 .write.size = 3,
5740                 .write.initial_status = NT_STATUS_OK,
5741                 .write.final_status = NT_STATUS_OK,
5742                 .write.num_streams_open_handle = 2,
5743                 .write.num_streams_closed_handle = 2,
5744                 .write.streams_open_handle = {"::$DATA", AFPRESOURCE_STREAM},
5745                 .write.streams_closed_handle = {"::$DATA", AFPRESOURCE_STREAM},
5746                 .overwrite.size = 0,
5747                 .overwrite.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5748                 .overwrite.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5749                 .overwrite.num_streams_open_handle = 1,
5750                 .overwrite.num_streams_closed_handle = 1,
5751                 .overwrite.streams_open_handle = {"::$DATA"},
5752                 .overwrite.streams_closed_handle = {"::$DATA"},
5753                 .eof.size = 0,
5754                 .eof.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5755                 .eof.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5756                 .eof.num_streams_open_handle = 1,
5757                 .eof.num_streams_closed_handle = 1,
5758                 .eof.streams_open_handle = {"::$DATA"},
5759                 .eof.streams_closed_handle = {"::$DATA"},
5760                 .doc.size = 3,
5761                 .doc.initial_status = NT_STATUS_DELETE_PENDING,
5762                 .doc.final_status = NT_STATUS_OK,
5763                 .doc.num_streams_open_handle = 2,
5764                 .doc.num_streams_closed_handle = 2,
5765                 .doc.streams_open_handle = {"::$DATA", AFPRESOURCE_STREAM},
5766                 .doc.streams_closed_handle = {"::$DATA", AFPRESOURCE_STREAM},
5767         };
5768
5769         struct tcase tcase_foo_ro = (struct tcase) {
5770                 .name = BASEDIR "\\file:foo",
5771                 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
5772                 .write_data = "foo",
5773                 .write_size = 3,
5774                 .create.size = 0,
5775                 .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5776                 .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5777                 .create.num_streams_open_handle = 1,
5778                 .create.num_streams_closed_handle = 1,
5779                 .create.streams_open_handle = {"::$DATA"},
5780                 .create.streams_closed_handle = {"::$DATA"},
5781         };
5782
5783         struct tcase tcase_foo_rw = (struct tcase) {
5784                 .name = BASEDIR "\\file:foo",
5785                 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
5786                 .write_data = "foo",
5787                 .write_size = 3,
5788                 .create.size = 0,
5789                 .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5790                 .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5791                 .create.num_streams_open_handle = 1,
5792                 .create.num_streams_closed_handle = 1,
5793                 .create.streams_open_handle = {"::$DATA"},
5794                 .create.streams_closed_handle = {"::$DATA"},
5795                 .write.size = 3,
5796                 .write.initial_status = NT_STATUS_OK,
5797                 .write.final_status = NT_STATUS_OK,
5798                 .write.num_streams_open_handle = 2,
5799                 .write.num_streams_closed_handle = 2,
5800                 .write.streams_open_handle = {"::$DATA", ":foo:$DATA"},
5801                 .write.streams_closed_handle = {"::$DATA", ":foo:$DATA"},
5802                 .overwrite.size = 0,
5803                 .overwrite.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5804                 .overwrite.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5805                 .overwrite.num_streams_open_handle = 1,
5806                 .overwrite.num_streams_closed_handle = 1,
5807                 .overwrite.streams_open_handle = {"::$DATA"},
5808                 .overwrite.streams_closed_handle = {"::$DATA"},
5809                 .eof.size = 0,
5810                 .eof.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5811                 .eof.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5812                 .eof.num_streams_open_handle = 1,
5813                 .eof.num_streams_closed_handle = 1,
5814                 .eof.streams_open_handle = {"::$DATA"},
5815                 .eof.streams_closed_handle = {"::$DATA"},
5816                 .doc.size = 3,
5817                 .doc.initial_status = NT_STATUS_DELETE_PENDING,
5818                 .doc.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5819                 .doc.num_streams_open_handle = 2,
5820                 .doc.num_streams_closed_handle = 1,
5821                 .doc.streams_open_handle = {"::$DATA", ":foo:$DATA"},
5822                 .doc.streams_closed_handle = {"::$DATA"},
5823         };
5824
5825         struct tcase tcases[] = {
5826                 tcase_afpinfo_ro,
5827                 tcase_afpinfo_rw,
5828                 tcase_afpresource_ro,
5829                 tcase_afpresource_rw,
5830                 tcase_foo_ro,
5831                 tcase_foo_rw,
5832                 {NULL}
5833         };
5834
5835         ret = torture_smb2_connection(tctx, &tree2);
5836         torture_assert_goto(tctx, ret == true, ret, done,
5837                             "torture_smb2_connection failed\n");
5838
5839         ret = enable_aapl(tctx, tree);
5840         torture_assert(tctx, ret == true, "enable_aapl failed\n");
5841
5842         ret = enable_aapl(tctx, tree2);
5843         torture_assert(tctx, ret == true, "enable_aapl failed\n");
5844
5845         smb2_deltree(tree, BASEDIR);
5846
5847         status = torture_smb2_testdir(tree, BASEDIR, &h1);
5848         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5849                                         "torture_smb2_testdir\n");
5850         smb2_util_close(tree, h1);
5851
5852         for (tcase = &tcases[0]; tcase->name != NULL; tcase++) {
5853                 ret = torture_setup_file(tctx, tree, fname, false);
5854                 torture_assert_goto(tctx, ret == true, ret, done,
5855                                     "torture_setup_file failed\n");
5856
5857                 ret = test_empty_stream_do_one(tctx, tree, tree2, tcase);
5858                 torture_assert_goto(tctx, ret == true, ret, done,
5859                                     "subtest failed\n");
5860
5861                 status = smb2_util_unlink(tree, fname);
5862                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5863                                                 "smb2_util_unlink failed\n");
5864         }
5865
5866 done:
5867         smb2_deltree(tree, BASEDIR);
5868         TALLOC_FREE(tree2);
5869         return ret;
5870 }
5871
5872 /*
5873  * Note: This test depends on "vfs objects = catia fruit streams_xattr".  For
5874  * some tests torture must be run on the host it tests and takes an additional
5875  * argument with the local path to the share:
5876  * "--option=torture:localdir=<SHAREPATH>".
5877  *
5878  * When running against an OS X SMB server add "--option=torture:osx=true"
5879  */
5880 struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx)
5881 {
5882         struct torture_suite *suite = torture_suite_create(
5883                 ctx, "fruit");
5884
5885         suite->description = talloc_strdup(suite, "vfs_fruit tests");
5886
5887         torture_suite_add_1smb2_test(suite, "copyfile", test_copyfile);
5888         torture_suite_add_1smb2_test(suite, "read metadata", test_read_afpinfo);
5889         torture_suite_add_1smb2_test(suite, "write metadata", test_write_atalk_metadata);
5890         torture_suite_add_1smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io);
5891         torture_suite_add_1smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl);
5892         torture_suite_add_1smb2_test(suite, "stream names", test_stream_names);
5893         torture_suite_add_1smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate);
5894         torture_suite_add_1smb2_test(suite, "opening and creating resource fork", test_rfork_create);
5895         torture_suite_add_1smb2_test(suite, "rename_dir_openfile", test_rename_dir_openfile);
5896         torture_suite_add_1smb2_test(suite, "File without AFP_AfpInfo", test_afpinfo_enoent);
5897         torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpInfo", test_create_delete_on_close);
5898         torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpInfo", test_setinfo_delete_on_close);
5899         torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpInfo", test_setinfo_eof);
5900         torture_suite_add_1smb2_test(suite, "delete AFP_AfpInfo by writing all 0", test_afpinfo_all0);
5901         torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpResource", test_create_delete_on_close_resource);
5902         torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpResource", test_setinfo_delete_on_close_resource);
5903         torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpResource", test_setinfo_eof_resource);
5904         torture_suite_add_1smb2_test(suite, "setinfo eof stream", test_setinfo_stream_eof);
5905         torture_suite_add_1smb2_test(suite, "null afpinfo", test_null_afpinfo);
5906         torture_suite_add_1smb2_test(suite, "delete", test_delete_file_with_rfork);
5907         torture_suite_add_1smb2_test(suite, "read open rsrc after rename", test_rename_and_read_rsrc);
5908         torture_suite_add_1smb2_test(suite, "readdir_attr with names with illegal ntfs characters", test_readdir_attr_illegal_ntfs);
5909         torture_suite_add_2ns_smb2_test(suite, "invalid AFP_AfpInfo", test_invalid_afpinfo);
5910         torture_suite_add_1smb2_test(suite, "creating rsrc with read-only access", test_rfork_create_ro);
5911         torture_suite_add_1smb2_test(suite, "copy-chunk streams", test_copy_chunk_streams);
5912         torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
5913         torture_suite_add_1smb2_test(suite, "NFS ACE entries", test_nfs_aces);
5914         torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion without embedded xattr", test_adouble_conversion_wo_xattr);
5915         torture_suite_add_1smb2_test(suite, "empty_stream", test_empty_stream);
5916
5917         return suite;
5918 }
5919
5920 static bool test_stream_names_local(struct torture_context *tctx,
5921                                     struct smb2_tree *tree)
5922 {
5923         TALLOC_CTX *mem_ctx = talloc_new(tctx);
5924         NTSTATUS status;
5925         struct smb2_create create;
5926         struct smb2_handle h;
5927         const char *fname = BASEDIR "\\stream_names.txt";
5928         const char *sname1;
5929         bool ret;
5930         /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
5931         const char *streams[] = {
5932                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
5933                 ":bar" "\xef\x80\xa2" "baz:$DATA", /* "bar:baz:$DATA" */
5934                 "::$DATA"
5935         };
5936         const char *localdir = NULL;
5937
5938         localdir = torture_setting_string(tctx, "localdir", NULL);
5939         if (localdir == NULL) {
5940                 torture_skip(tctx, "Need localdir for test");
5941         }
5942
5943         sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
5944
5945         /* clean slate ...*/
5946         smb2_util_unlink(tree, fname);
5947         smb2_deltree(tree, fname);
5948         smb2_deltree(tree, BASEDIR);
5949
5950         status = torture_smb2_testdir(tree, BASEDIR, &h);
5951         CHECK_STATUS(status, NT_STATUS_OK);
5952         smb2_util_close(tree, h);
5953
5954         torture_comment(tctx, "(%s) testing stream names\n", __location__);
5955         ZERO_STRUCT(create);
5956         create.in.desired_access = SEC_FILE_WRITE_DATA;
5957         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5958         create.in.share_access =
5959                 NTCREATEX_SHARE_ACCESS_DELETE|
5960                 NTCREATEX_SHARE_ACCESS_READ|
5961                 NTCREATEX_SHARE_ACCESS_WRITE;
5962         create.in.create_disposition = NTCREATEX_DISP_CREATE;
5963         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
5964         create.in.fname = sname1;
5965
5966         status = smb2_create(tree, mem_ctx, &create);
5967         CHECK_STATUS(status, NT_STATUS_OK);
5968
5969         status = smb2_util_write(tree, create.out.file.handle, "foo", 0, 3);
5970         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5971                                         "smb2_util_write failed\n");
5972
5973         smb2_util_close(tree, create.out.file.handle);
5974
5975         ret = torture_setup_local_xattr(tctx, "localdir", BASEDIR "/stream_names.txt",
5976                                         "user.DosStream.bar:baz:$DATA",
5977                                         "data", strlen("data"));
5978         CHECK_VALUE(ret, true);
5979
5980         ret = check_stream_list(tree, tctx, fname, 3, streams, false);
5981         CHECK_VALUE(ret, true);
5982
5983 done:
5984         status = smb2_util_unlink(tree, fname);
5985         smb2_deltree(tree, BASEDIR);
5986         talloc_free(mem_ctx);
5987
5988         return ret;
5989 }
5990
5991 static bool test_fruit_locking_conflict(struct torture_context *tctx,
5992                                         struct smb2_tree *tree)
5993 {
5994         TALLOC_CTX *mem_ctx;
5995         struct smb2_create create;
5996         struct smb2_handle h;
5997         struct smb2_lock lck;
5998         struct smb2_lock_element el;
5999         const char *fname = BASEDIR "\\locking_conflict.txt";
6000         NTSTATUS status;
6001         bool ret = false;
6002
6003         mem_ctx = talloc_new(tctx);
6004         torture_assert_not_null(tctx, mem_ctx, "talloc_new failed");
6005
6006         /* clean slate ...*/
6007         smb2_util_unlink(tree, fname);
6008         smb2_deltree(tree, fname);
6009         smb2_deltree(tree, BASEDIR);
6010
6011         status = torture_smb2_testdir(tree, BASEDIR, &h);
6012         CHECK_STATUS(status, NT_STATUS_OK);
6013         smb2_util_close(tree, h);
6014
6015         create = (struct smb2_create) {
6016                 .in.desired_access = SEC_RIGHTS_FILE_READ,
6017                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
6018                 .in.share_access =
6019                 NTCREATEX_SHARE_ACCESS_READ|
6020                 NTCREATEX_SHARE_ACCESS_WRITE,
6021                 .in.create_disposition = NTCREATEX_DISP_CREATE,
6022                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6023                 .in.fname = fname,
6024         };
6025
6026         status = smb2_create(tree, mem_ctx, &create);
6027         CHECK_STATUS(status, NT_STATUS_OK);
6028         h = create.out.file.handle;
6029
6030         el = (struct smb2_lock_element) {
6031                 .offset = 0xfffffffffffffffc,
6032                 .length = 1,
6033                 .flags = SMB2_LOCK_FLAG_EXCLUSIVE,
6034         };
6035         lck = (struct smb2_lock) {
6036                 .in.lock_count = 1,
6037                 .in.file.handle = h,
6038                 .in.locks = &el,
6039         };
6040
6041         status = smb2_lock(tree, &lck);
6042         CHECK_STATUS(status, NT_STATUS_OK);
6043
6044         el = (struct smb2_lock_element) {
6045                 .offset = 0,
6046                 .length = 0x7fffffffffffffff,
6047                 .flags = SMB2_LOCK_FLAG_EXCLUSIVE,
6048         };
6049         status = smb2_lock(tree, &lck);
6050         CHECK_STATUS(status, NT_STATUS_OK);
6051
6052         create = (struct smb2_create) {
6053                 .in.desired_access =
6054                 SEC_RIGHTS_FILE_READ|SEC_RIGHTS_FILE_WRITE,
6055                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
6056                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6057                 .in.create_disposition = NTCREATEX_DISP_OPEN,
6058                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6059                 .in.fname = fname,
6060         };
6061
6062         status = smb2_create(tree, mem_ctx, &create);
6063         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
6064
6065         {
6066                 struct smb2_close cl = {
6067                         .level = RAW_CLOSE_SMB2,
6068                         .in.file.handle = h,
6069                 };
6070                 smb2_close(tree, &cl);
6071         }
6072
6073         ret = true;
6074 done:
6075         return ret;
6076 }
6077
6078 struct torture_suite *torture_vfs_fruit_netatalk(TALLOC_CTX *ctx)
6079 {
6080         struct torture_suite *suite = torture_suite_create(
6081                 ctx, "fruit_netatalk");
6082
6083         suite->description = talloc_strdup(suite, "vfs_fruit tests for Netatalk interop that require fruit:metadata=netatalk");
6084
6085         torture_suite_add_1smb2_test(suite, "read netatalk metadata", test_read_netatalk_metadata);
6086         torture_suite_add_1smb2_test(suite, "stream names with locally created xattr", test_stream_names_local);
6087         torture_suite_add_1smb2_test(
6088                 suite, "locking conflict", test_fruit_locking_conflict);
6089
6090         return suite;
6091 }
6092
6093 struct torture_suite *torture_vfs_fruit_file_id(TALLOC_CTX *ctx)
6094 {
6095         struct torture_suite *suite =
6096             torture_suite_create(ctx, "fruit_file_id");
6097
6098         suite->description =
6099             talloc_strdup(suite, "vfs_fruit tests for on-disk file ID that "
6100                                  "require fruit:zero_file_id=yes");
6101
6102         torture_suite_add_1smb2_test(suite, "zero file id if AAPL negotiated",
6103                                      test_zero_file_id);
6104
6105         return suite;
6106 }
6107
6108 static bool test_timemachine_volsize(struct torture_context *tctx,
6109                                      struct smb2_tree *tree)
6110 {
6111         TALLOC_CTX *mem_ctx = talloc_new(tctx);
6112         struct smb2_handle h = {{0}};
6113         union smb_fsinfo fsinfo;
6114         NTSTATUS status;
6115         bool ok = true;
6116         const char *info_plist =
6117                 "<dict>\n"
6118                 "        <key>band-size</key>\n"
6119                 "        <integer>8192</integer>\n"
6120                 "</dict>\n";
6121
6122         smb2_deltree(tree, "test.sparsebundle");
6123
6124         ok = enable_aapl(tctx, tree);
6125         torture_assert_goto(tctx, ok, ok, done, "enable_aapl failed");
6126
6127         status = smb2_util_mkdir(tree, "test.sparsebundle");
6128         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
6129                                         "smb2_util_mkdir\n");
6130
6131         ok = write_stream(tree, __location__, tctx, mem_ctx,
6132                           "test.sparsebundle/Info.plist", NULL,
6133                            0, strlen(info_plist), info_plist);
6134         torture_assert_goto(tctx, ok, ok, done, "write_stream failed\n");
6135
6136         status = smb2_util_mkdir(tree, "test.sparsebundle/bands");
6137         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
6138                                         "smb2_util_mkdir\n");
6139
6140         ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/1", false);
6141         torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
6142
6143         ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/2", false);
6144         torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
6145
6146         status = smb2_util_roothandle(tree, &h);
6147         torture_assert_ntstatus_ok(tctx, status, "Unable to create root handle");
6148
6149         ZERO_STRUCT(fsinfo);
6150         fsinfo.generic.level = RAW_QFS_SIZE_INFORMATION;
6151         fsinfo.generic.handle = h;
6152
6153         status = smb2_getinfo_fs(tree, tree, &fsinfo);
6154         torture_assert_ntstatus_ok(tctx, status, "smb2_getinfo_fs failed");
6155
6156         torture_comment(tctx, "sectors_per_unit: %" PRIu32"\n"
6157                         "bytes_per_sector: %" PRIu32"\n"
6158                         "total_alloc_units: %" PRIu64"\n"
6159                         "avail_alloc_units: %" PRIu64"\n",
6160                         fsinfo.size_info.out.sectors_per_unit,
6161                         fsinfo.size_info.out.bytes_per_sector,
6162                         fsinfo.size_info.out.total_alloc_units,
6163                         fsinfo.size_info.out.avail_alloc_units);
6164
6165         /*
6166          * Let me explain the numbers:
6167          *
6168          * - the share is set to "fruit:time machine max size = 32K"
6169          * - we've faked a bandsize of 8 K in the Info.plist file
6170          * - we've created two bands files
6171          * - one allocation unit is made of two sectors with 512 B each
6172          * => we've consumed 16 allocation units, there should be 16 free
6173          */
6174
6175         torture_assert_goto(tctx, fsinfo.size_info.out.sectors_per_unit == 2,
6176                             ok, done, "Bad sectors_per_unit");
6177
6178         torture_assert_goto(tctx, fsinfo.size_info.out.bytes_per_sector == 512,
6179                             ok, done, "Bad bytes_per_sector");
6180
6181         torture_assert_goto(tctx, fsinfo.size_info.out.total_alloc_units == 32,
6182                             ok, done, "Bad total_alloc_units");
6183
6184         torture_assert_goto(tctx, fsinfo.size_info.out.avail_alloc_units == 16,
6185                             ok, done, "Bad avail_alloc_units");
6186
6187 done:
6188         if (!smb2_util_handle_empty(h)) {
6189                 smb2_util_close(tree, h);
6190         }
6191         smb2_deltree(tree, "test.sparsebundle");
6192         talloc_free(mem_ctx);
6193         return ok;
6194 }
6195
6196 struct torture_suite *torture_vfs_fruit_timemachine(TALLOC_CTX *ctx)
6197 {
6198         struct torture_suite *suite = torture_suite_create(
6199                 ctx, "fruit_timemachine");
6200
6201         suite->description = talloc_strdup(
6202                 suite, "vfs_fruit tests for TimeMachine");
6203
6204         torture_suite_add_1smb2_test(suite, "Timemachine-volsize",
6205                                      test_timemachine_volsize);
6206
6207         return suite;
6208 }
6209
6210 static bool test_convert_xattr_and_empty_rfork_then_delete(
6211         struct torture_context *tctx,
6212         struct smb2_tree *tree1,
6213         struct smb2_tree *tree2)
6214 {
6215         TALLOC_CTX *mem_ctx = talloc_new(tctx);
6216         const char *fname = BASEDIR "\\test_adouble_conversion";
6217         const char *adname = BASEDIR "/._test_adouble_conversion";
6218         const char *rfork = BASEDIR "\\test_adouble_conversion" AFPRESOURCE_STREAM_NAME;
6219         NTSTATUS status;
6220         struct smb2_handle testdirh;
6221         bool ret = true;
6222         const char *streams[] = {
6223                 "::$DATA",
6224                 AFPINFO_STREAM,
6225                 ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
6226                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
6227         };
6228         struct smb2_create create;
6229         struct smb2_find find;
6230         unsigned int count;
6231         union smb_search_data *d;
6232         bool delete_empty_adfiles;
6233         int expected_num_files;
6234
6235         delete_empty_adfiles = torture_setting_bool(tctx,
6236                                                     "delete_empty_adfiles",
6237                                                     false);
6238
6239         smb2_deltree(tree1, BASEDIR);
6240
6241         status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
6242         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6243                                         "torture_smb2_testdir failed\n");
6244         smb2_util_close(tree1, testdirh);
6245
6246         ret = torture_setup_file(tctx, tree1, fname, false);
6247         torture_assert_goto(tctx, ret == true, ret, done,
6248                             "torture_setup_file failed\n");
6249
6250         ret = torture_setup_file(tctx, tree1, adname, false);
6251         torture_assert_goto(tctx, ret == true, ret, done,
6252                             "torture_setup_file failed\n");
6253
6254         ret = write_stream(tree1, __location__, tctx, mem_ctx,
6255                            adname, NULL,
6256                            0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr);
6257         torture_assert_goto(tctx, ret == true, ret, done,
6258                             "write_stream failed\n");
6259
6260         ret = enable_aapl(tctx, tree2);
6261         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
6262
6263         /*
6264          * Issue a smb2_find(), this triggers the server-side conversion
6265          */
6266
6267         create = (struct smb2_create) {
6268                 .in.desired_access = SEC_RIGHTS_DIR_READ,
6269                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
6270                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
6271                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6272                 .in.create_disposition = NTCREATEX_DISP_OPEN,
6273                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6274                 .in.fname = BASEDIR,
6275         };
6276
6277         status = smb2_create(tree2, tctx, &create);
6278         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6279                                         "smb2_create failed\n");
6280
6281         find = (struct smb2_find) {
6282                 .in.file.handle = create.out.file.handle,
6283                 .in.pattern = "*",
6284                 .in.max_response_size = 0x1000,
6285                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
6286         };
6287
6288         status = smb2_find_level(tree2, tree2, &find, &count, &d);
6289         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6290                                         "smb2_find_level failed\n");
6291
6292         status = smb2_util_close(tree2, create.out.file.handle);
6293         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6294                                         "smb2_util_close failed");
6295
6296         /*
6297          * Check number of streams
6298          */
6299
6300         ret = check_stream_list(tree2, tctx, fname, 4, streams, false);
6301         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
6302
6303         /*
6304          * Check Resource Fork is gone
6305          */
6306
6307         create = (struct smb2_create) {
6308                 .in.desired_access = SEC_RIGHTS_FILE_READ|SEC_RIGHTS_FILE_WRITE,
6309                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
6310                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6311                 .in.create_disposition = NTCREATEX_DISP_OPEN,
6312                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6313                 .in.fname = rfork,
6314         };
6315
6316         status = smb2_create(tree2, mem_ctx, &create);
6317         torture_assert_ntstatus_equal_goto(
6318                 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
6319                 ret, done, "Bad smb2_create return\n");
6320
6321         /*
6322          * Check xattr data has been migrated from the AppleDouble file to
6323          * streams.
6324          */
6325
6326         ret = check_stream(tree2, __location__, tctx, mem_ctx,
6327                            fname, AFPINFO_STREAM,
6328                            0, 60, 16, 8, "TESTSLOW");
6329         torture_assert_goto(tctx, ret == true, ret, done,
6330                             "check AFPINFO_STREAM failed\n");
6331
6332         ret = check_stream(tree2, __location__, tctx, mem_ctx,
6333                            fname, ":foo" "\xef\x80\xa2" "bar", /* foo:bar */
6334                            0, 3, 0, 3, "baz");
6335         torture_assert_goto(tctx, ret == true, ret, done,
6336                             "check foo stream failed\n");
6337
6338         /*
6339          * Now check number of files. If delete_empty_adfiles is set, the
6340          * AppleDouble files should have been deleted.
6341          */
6342
6343         create = (struct smb2_create) {
6344                 .in.desired_access = SEC_RIGHTS_DIR_READ,
6345                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
6346                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
6347                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6348                 .in.create_disposition = NTCREATEX_DISP_OPEN,
6349                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6350                 .in.fname = BASEDIR,
6351         };
6352
6353         status = smb2_create(tree2, tctx, &create);
6354         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6355                                         "smb2_create failed\n");
6356
6357         find = (struct smb2_find) {
6358                 .in.file.handle = create.out.file.handle,
6359                 .in.pattern = "*",
6360                 .in.max_response_size = 0x1000,
6361                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
6362         };
6363
6364         status = smb2_find_level(tree2, tree2, &find, &count, &d);
6365         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6366                                         "smb2_find_level failed\n");
6367
6368         status = smb2_util_close(tree2, create.out.file.handle);
6369         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6370                                         "smb2_util_close failed");
6371
6372         if (delete_empty_adfiles) {
6373                 expected_num_files = 3;
6374         } else {
6375                 expected_num_files = 4;
6376         }
6377         torture_assert_int_equal_goto(tctx, count, expected_num_files, ret, done,
6378                                       "Wrong number of files\n");
6379
6380 done:
6381         smb2_deltree(tree1, BASEDIR);
6382         talloc_free(mem_ctx);
6383         return ret;
6384 }
6385
6386 struct torture_suite *torture_vfs_fruit_conversion(TALLOC_CTX *ctx)
6387 {
6388         struct torture_suite *suite = torture_suite_create(
6389                 ctx, "fruit_conversion");
6390
6391         suite->description = talloc_strdup(
6392                 suite, "vfs_fruit conversion tests");
6393
6394         torture_suite_add_2ns_smb2_test(
6395                 suite, "convert_xattr_and_empty_rfork_then_delete",
6396                 test_convert_xattr_and_empty_rfork_then_delete);
6397
6398         return suite;
6399 }