s4:libcli/smb2: align struct smb_ioctl.smb2 to [MS-SMB2] names
[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_output_response = 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_output_response = 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_writing_afpinfo(struct torture_context *tctx,
4506                                  struct smb2_tree *tree)
4507 {
4508         const char *fname = "filtest_invalid_afpinfo";
4509         const char *sname = "filtest_invalid_afpinfo" AFPINFO_STREAM;
4510         const char *streams_afpinfo[] = {
4511                 "::$DATA",
4512                 AFPINFO_STREAM
4513         };
4514         bool ret = true;
4515         static AfpInfo *afpi = NULL;
4516         char *buf = NULL;
4517         char *afpi_buf = NULL;
4518         char *zero_buf = NULL;
4519         bool broken_osx = torture_setting_bool(tctx, "broken_osx_45759458", false);
4520         off_t min_offset_for_2streams = 16;
4521         int i;
4522         NTSTATUS status;
4523         struct test_sizes {
4524                 off_t offset;
4525                 size_t size;
4526                 bool expected_result;
4527         } test_sizes[] = {
4528                 { 0, 1, false},
4529                 { 0, 2, false},
4530                 { 0, 3, true},
4531                 { 0, 4, true},
4532                 { 0, 14, true},
4533                 { 0, 15, true},
4534                 { 0, 16, true},
4535                 { 0, 24, true},
4536                 { 0, 34, true},
4537                 { 0, 44, true},
4538                 { 0, 54, true},
4539                 { 0, 55, true},
4540                 { 0, 56, true},
4541                 { 0, 57, true},
4542                 { 0, 58, true},
4543                 { 0, 59, true},
4544                 { 0, 60, true},
4545                 { 0, 61, true},
4546                 { 0, 64, true},
4547                 { 0, 1024, true},
4548                 { 0, 10064, true},
4549
4550                 { 1, 1, false},
4551                 { 1, 2, false},
4552                 { 1, 3, false},
4553                 { 1, 4, false},
4554                 { 1, 14, false},
4555                 { 1, 15, false},
4556                 { 1, 16, false},
4557                 { 1, 24, false},
4558                 { 1, 34, false},
4559                 { 1, 44, false},
4560                 { 1, 54, false},
4561                 { 1, 55, false},
4562                 { 1, 56, false},
4563                 { 1, 57, false},
4564                 { 1, 58, false},
4565                 { 1, 59, false},
4566                 { 1, 60, true},
4567                 { 1, 61, true},
4568                 { 1, 1024, true},
4569                 { 1, 10064, true},
4570
4571                 { 30, 1, false},
4572                 { 30, 2, false},
4573                 { 30, 3, false},
4574                 { 30, 4, false},
4575                 { 30, 14, false},
4576                 { 30, 15, false},
4577                 { 30, 16, false},
4578                 { 30, 24, false},
4579                 { 30, 34, false},
4580                 { 30, 44, false},
4581                 { 30, 54, false},
4582                 { 30, 55, false},
4583                 { 30, 56, false},
4584                 { 30, 57, false},
4585                 { 30, 58, false},
4586                 { 30, 59, false},
4587                 { 30, 60, true},
4588                 { 30, 61, true},
4589                 { 30, 1024, true},
4590                 { 30, 10064, true},
4591
4592                 { 58, 1, false},
4593                 { 58, 2, false},
4594                 { 58, 3, false},
4595                 { 58, 4, false},
4596                 { 58, 14, false},
4597                 { 58, 15, false},
4598                 { 58, 16, false},
4599                 { 58, 24, false},
4600                 { 58, 34, false},
4601                 { 58, 44, false},
4602                 { 58, 54, false},
4603                 { 58, 55, false},
4604                 { 58, 56, false},
4605                 { 58, 57, false},
4606                 { 58, 58, false},
4607                 { 58, 59, false},
4608                 { 58, 60, true},
4609                 { 58, 61, true},
4610                 { 58, 1024, true},
4611                 { 58, 10064, true},
4612
4613                 { 59, 1, false},
4614                 { 59, 2, false},
4615                 { 59, 3, false},
4616                 { 59, 4, false},
4617                 { 59, 14, false},
4618                 { 59, 15, false},
4619                 { 59, 16, false},
4620                 { 59, 24, false},
4621                 { 59, 34, false},
4622                 { 59, 44, false},
4623                 { 59, 54, false},
4624                 { 59, 55, false},
4625                 { 59, 56, false},
4626                 { 59, 57, false},
4627                 { 59, 58, false},
4628                 { 59, 59, false},
4629                 { 59, 60, true},
4630                 { 59, 61, true},
4631                 { 59, 1024, true},
4632                 { 59, 10064, true},
4633
4634                 { 60, 1, false},
4635                 { 60, 2, false},
4636                 { 60, 3, false},
4637                 { 60, 4, false},
4638                 { 60, 14, false},
4639                 { 60, 15, false},
4640                 { 60, 16, false},
4641                 { 60, 24, false},
4642                 { 60, 34, false},
4643                 { 60, 44, false},
4644                 { 60, 54, false},
4645                 { 60, 55, false},
4646                 { 60, 56, false},
4647                 { 60, 57, false},
4648                 { 60, 58, false},
4649                 { 60, 59, false},
4650                 { 60, 60, true},
4651                 { 60, 61, true},
4652                 { 60, 1024, true},
4653                 { 60, 10064, true},
4654
4655                 { 61, 1, false},
4656                 { 61, 2, false},
4657                 { 61, 3, false},
4658                 { 61, 4, false},
4659                 { 61, 14, false},
4660                 { 61, 15, false},
4661                 { 61, 16, false},
4662                 { 61, 24, false},
4663                 { 61, 34, false},
4664                 { 61, 44, false},
4665                 { 61, 54, false},
4666                 { 61, 55, false},
4667                 { 61, 56, false},
4668                 { 61, 57, false},
4669                 { 61, 58, false},
4670                 { 61, 59, false},
4671                 { 61, 60, true},
4672                 { 61, 61, true},
4673                 { 61, 1024, true},
4674                 { 61, 10064, true},
4675
4676                 { 10000, 1, false},
4677                 { 10000, 2, false},
4678                 { 10000, 3, false},
4679                 { 10000, 4, false},
4680                 { 10000, 14, false},
4681                 { 10000, 15, false},
4682                 { 10000, 16, false},
4683                 { 10000, 24, false},
4684                 { 10000, 34, false},
4685                 { 10000, 44, false},
4686                 { 10000, 54, false},
4687                 { 10000, 55, false},
4688                 { 10000, 56, false},
4689                 { 10000, 57, false},
4690                 { 10000, 58, false},
4691                 { 10000, 59, false},
4692                 { 10000, 60, true},
4693                 { 10000, 61, true},
4694                 { 10000, 1024, true},
4695                 { 10000, 10064, true},
4696
4697                 { -1, 0, false},
4698         };
4699
4700         afpi = torture_afpinfo_new(tctx);
4701         torture_assert_not_null_goto(tctx, afpi, ret, done,
4702                                      "torture_afpinfo_new failed\n");
4703
4704         memcpy(afpi->afpi_FinderInfo, "FOO BAR ", 8);
4705
4706         buf = torture_afpinfo_pack(afpi, afpi);
4707         torture_assert_not_null_goto(tctx, buf, ret, done,
4708                                      "torture_afpinfo_pack failed\n");
4709
4710         afpi_buf = talloc_zero_array(tctx, char, 10064);
4711         torture_assert_not_null_goto(tctx, afpi_buf, ret, done,
4712                                      "talloc_zero_array failed\n");
4713         memcpy(afpi_buf, buf, 60);
4714
4715         zero_buf = talloc_zero_array(tctx, char, 10064);
4716         torture_assert_not_null_goto(tctx, zero_buf, ret, done,
4717                                      "talloc_zero_array failed\n");
4718
4719         ret = torture_setup_file(tctx, tree, fname, false);
4720         torture_assert_goto(tctx, ret == true, ret, done,
4721                             "torture_setup_file\n");
4722
4723         for (i = 0; test_sizes[i].offset != -1; i++) {
4724                 struct smb2_handle h;
4725                 struct smb2_create c;
4726                 int expected_num_streams;
4727                 size_t fi_check_size;
4728
4729                 torture_comment(tctx,
4730                                 "Test %d: offset=%jd size=%zu result=%s\n",
4731                                 i,
4732                                 (intmax_t)test_sizes[i].offset,
4733                                 test_sizes[i].size,
4734                                 test_sizes[i].expected_result ? "true":"false");
4735
4736
4737                 c = (struct smb2_create) {
4738                         .in.desired_access = SEC_FILE_WRITE_DATA,
4739                         .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
4740                         .in.create_disposition = NTCREATEX_DISP_OPEN_IF,
4741                         .in.fname = sname,
4742                 };
4743
4744                 status = smb2_create(tree, tree, &c);
4745                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4746                                                 "smb2_create\n");
4747                 h = c.out.file.handle;
4748
4749                 status = smb2_util_write(tree,
4750                                          h,
4751                                          zero_buf,
4752                                          test_sizes[i].offset,
4753                                          test_sizes[i].size);
4754                 torture_assert_ntstatus_equal_goto(
4755                         tctx, status, NT_STATUS_INVALID_PARAMETER,
4756                         ret, done, "smb2_util_write\n");
4757
4758                 status = smb2_util_write(tree,
4759                                          h,
4760                                          afpi_buf,
4761                                          test_sizes[i].offset,
4762                                          test_sizes[i].size);
4763                 smb2_util_close(tree, h);
4764                 if (test_sizes[i].expected_result == true) {
4765                         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4766                                                         "smb2_util_write\n");
4767                 } else {
4768                         torture_assert_ntstatus_equal_goto(
4769                                 tctx, status, NT_STATUS_INVALID_PARAMETER,
4770                                 ret, done, "smb2_util_write\n");
4771                 }
4772
4773                 if (broken_osx) {
4774                         /*
4775                          * Currently macOS has a bug (Radar #45759458) where it
4776                          * writes more bytes then requested from uninitialized
4777                          * memory to the filesystem. That means it will likely
4778                          * write data to FinderInfo so the stream is not empty
4779                          * and thus listed when the number of streams is
4780                          * queried.
4781                          */
4782                         min_offset_for_2streams = 2;
4783                 }
4784
4785                 if ((test_sizes[i].expected_result == true) &&
4786                     (test_sizes[i].size > min_offset_for_2streams))
4787                 {
4788                         expected_num_streams = 2;
4789                 } else {
4790                         expected_num_streams = 1;
4791                 }
4792
4793                 ret = check_stream_list(tree, tctx, fname,
4794                                         expected_num_streams,
4795                                         streams_afpinfo, false);
4796                 torture_assert_goto(tctx, ret == true, ret, done,
4797                                     "Bad streams\n");
4798
4799                 if (test_sizes[i].expected_result == false) {
4800                         continue;
4801                 }
4802
4803                 if (test_sizes[i].size <= 16) {
4804                         /*
4805                          * FinderInfo with the "FOO BAR " string we wrote above
4806                          * would start at offset 16. Check whether this test
4807                          * wrote 1 byte or more.
4808                          */
4809                         goto next;
4810                 }
4811
4812                 fi_check_size = test_sizes[i].size - 16;
4813                 fi_check_size = MIN(fi_check_size, 8);
4814
4815                 ret = check_stream(tree, __location__,
4816                                    tctx, tctx,
4817                                    fname, AFPINFO_STREAM,
4818                                    0, 60, 16, fi_check_size, "FOO BAR ");
4819                 torture_assert_goto(tctx, ret == true, ret, done,
4820                                     "Bad streams\n");
4821
4822 next:
4823                 status = smb2_util_unlink(tree, sname);
4824                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4825                         bool missing_ok;
4826
4827                         missing_ok = test_sizes[i].expected_result == false;
4828                         missing_ok |= test_sizes[i].size <= 16;
4829
4830                         torture_assert_goto(tctx, missing_ok,
4831                                             ret, done, "smb2_util_unlink\n");
4832                 }
4833         }
4834
4835 done:
4836         smb2_util_unlink(tree, fname);
4837         return ret;
4838 }
4839
4840 static bool test_zero_file_id(struct torture_context *tctx,
4841                               struct smb2_tree *tree)
4842 {
4843         const char *fname = "filtest_file_id";
4844         struct smb2_create create = {0};
4845         NTSTATUS status;
4846         bool ret = true;
4847         uint8_t zero_file_id[8] = {0};
4848
4849         torture_comment(tctx, "Testing zero file id\n");
4850
4851         ret = torture_setup_file(tctx, tree, fname, false);
4852         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4853
4854         ZERO_STRUCT(create);
4855         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4856         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4857         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4858         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4859         create.in.fname = fname;
4860         create.in.query_on_disk_id = true;
4861
4862         status = smb2_create(tree, tctx, &create);
4863         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
4864                                            done,
4865                                            "test file could not be opened");
4866         torture_assert_mem_not_equal_goto(tctx, create.out.on_disk_id,
4867                                           zero_file_id, 8, ret, done,
4868                                           "unexpected zero file id");
4869
4870         smb2_util_close(tree, create.out.file.handle);
4871
4872         ret = enable_aapl(tctx, tree);
4873         torture_assert(tctx, ret == true, "enable_aapl failed");
4874
4875         ZERO_STRUCT(create);
4876         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4877         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4878         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4879         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4880         create.in.fname = fname;
4881         create.in.query_on_disk_id = true;
4882
4883         status = smb2_create(tree, tctx, &create);
4884         torture_assert_ntstatus_equal_goto(
4885             tctx, status, NT_STATUS_OK, ret, done,
4886             "test file could not be opened with AAPL");
4887         torture_assert_mem_equal_goto(tctx, create.out.on_disk_id, zero_file_id,
4888                                       8, ret, done, "non-zero file id");
4889
4890         smb2_util_close(tree, create.out.file.handle);
4891
4892 done:
4893         smb2_util_unlink(tree, fname);
4894         return ret;
4895 }
4896
4897 static bool copy_one_stream(struct torture_context *torture,
4898                             struct smb2_tree *tree,
4899                             TALLOC_CTX *tmp_ctx,
4900                             const char *src_sname,
4901                             const char *dst_sname)
4902 {
4903         struct smb2_handle src_h = {{0}};
4904         struct smb2_handle dest_h = {{0}};
4905         NTSTATUS status;
4906         union smb_ioctl io;
4907         struct srv_copychunk_copy cc_copy;
4908         struct srv_copychunk_rsp cc_rsp;
4909         enum ndr_err_code ndr_ret;
4910         bool ok = false;
4911
4912         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4913                                    1, /* 1 chunk */
4914                                    src_sname,
4915                                    &src_h, 256, /* fill 256 byte src file */
4916                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4917                                    dst_sname,
4918                                    &dest_h, 0,  /* 0 byte dest file */
4919                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4920                                    &cc_copy,
4921                                    &io);
4922         torture_assert_goto(torture, ok == true, ok, done,
4923                             "setup copy chunk error\n");
4924
4925         /* copy all src file data (via a single chunk desc) */
4926         cc_copy.chunks[0].source_off = 0;
4927         cc_copy.chunks[0].target_off = 0;
4928         cc_copy.chunks[0].length = 256;
4929
4930         ndr_ret = ndr_push_struct_blob(
4931                 &io.smb2.in.out, tmp_ctx, &cc_copy,
4932                 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4933
4934         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4935                                    "ndr_push_srv_copychunk_copy\n");
4936
4937         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4938         torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4939                                         "FSCTL_SRV_COPYCHUNK\n");
4940
4941         ndr_ret = ndr_pull_struct_blob(
4942                 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4943                 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4944
4945         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4946                                    "ndr_pull_srv_copychunk_rsp\n");
4947
4948         ok = check_copy_chunk_rsp(torture, &cc_rsp,
4949                                   1,    /* chunks written */
4950                                   0,    /* chunk bytes unsuccessfully written */
4951                                   256); /* total bytes written */
4952         torture_assert_goto(torture, ok == true, ok, done,
4953                             "bad copy chunk response data\n");
4954
4955         ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 256, 0);
4956         if (!ok) {
4957                 torture_fail(torture, "inconsistent file data\n");
4958         }
4959
4960 done:
4961         if (!smb2_util_handle_empty(src_h)) {
4962                 smb2_util_close(tree, src_h);
4963         }
4964         if (!smb2_util_handle_empty(dest_h)) {
4965                 smb2_util_close(tree, dest_h);
4966         }
4967
4968         return ok;
4969 }
4970
4971 static bool copy_finderinfo_stream(struct torture_context *torture,
4972                                    struct smb2_tree *tree,
4973                                    TALLOC_CTX *tmp_ctx,
4974                                    const char *src_name,
4975                                    const char *dst_name)
4976 {
4977         struct smb2_handle src_h = {{0}};
4978         struct smb2_handle dest_h = {{0}};
4979         NTSTATUS status;
4980         union smb_ioctl io;
4981         struct srv_copychunk_copy cc_copy;
4982         struct srv_copychunk_rsp cc_rsp;
4983         enum ndr_err_code ndr_ret;
4984         const char *type_creator = "SMB,OLE!";
4985         AfpInfo *info = NULL;
4986         const char *src_name_afpinfo = NULL;
4987         const char *dst_name_afpinfo = NULL;
4988         bool ok = false;
4989
4990         src_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", src_name,
4991                                            AFPINFO_STREAM);
4992         torture_assert_not_null_goto(torture, src_name_afpinfo, ok, done,
4993                                      "talloc_asprintf failed\n");
4994
4995         dst_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", dst_name,
4996                                            AFPINFO_STREAM);
4997         torture_assert_not_null_goto(torture, dst_name_afpinfo, ok, done,
4998                                      "talloc_asprintf failed\n");
4999
5000         info = torture_afpinfo_new(tmp_ctx);
5001         torture_assert_not_null_goto(torture, info, ok, done,
5002                                      "torture_afpinfo_new failed\n");
5003
5004         memcpy(info->afpi_FinderInfo, type_creator, 8);
5005         ok = torture_write_afpinfo(tree, torture, tmp_ctx, src_name, info);
5006         torture_assert_goto(torture, ok == true, ok, done,
5007                             "torture_write_afpinfo failed\n");
5008
5009         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
5010                                    1, /* 1 chunk */
5011                                    src_name_afpinfo,
5012                                    &src_h, 0,
5013                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
5014                                    dst_name_afpinfo,
5015                                    &dest_h, 0,
5016                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
5017                                    &cc_copy,
5018                                    &io);
5019         torture_assert_goto(torture, ok == true, ok, done,
5020                             "setup copy chunk error\n");
5021
5022         /* copy all src file data (via a single chunk desc) */
5023         cc_copy.chunks[0].source_off = 0;
5024         cc_copy.chunks[0].target_off = 0;
5025         cc_copy.chunks[0].length = 60;
5026
5027         ndr_ret = ndr_push_struct_blob(
5028                 &io.smb2.in.out, tmp_ctx, &cc_copy,
5029                 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
5030
5031         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
5032                                    "ndr_push_srv_copychunk_copy\n");
5033
5034         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
5035         torture_assert_ntstatus_ok_goto(torture, status, ok, done,
5036                                         "FSCTL_SRV_COPYCHUNK\n");
5037
5038         ndr_ret = ndr_pull_struct_blob(
5039                 &io.smb2.out.out, tmp_ctx, &cc_rsp,
5040                 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
5041
5042         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
5043                                    "ndr_pull_srv_copychunk_rsp\n");
5044
5045         smb2_util_close(tree, src_h);
5046         ZERO_STRUCT(src_h);
5047         smb2_util_close(tree, dest_h);
5048         ZERO_STRUCT(dest_h);
5049
5050         ok = check_copy_chunk_rsp(torture, &cc_rsp,
5051                                   1,    /* chunks written */
5052                                   0,    /* chunk bytes unsuccessfully written */
5053                                   60); /* total bytes written */
5054         torture_assert_goto(torture, ok == true, ok, done,
5055                             "bad copy chunk response data\n");
5056
5057         ok = check_stream(tree, __location__, torture, tmp_ctx,
5058                           dst_name, AFPINFO_STREAM,
5059                           0, 60, 16, 8, type_creator);
5060         torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
5061
5062 done:
5063         if (!smb2_util_handle_empty(src_h)) {
5064                 smb2_util_close(tree, src_h);
5065         }
5066         if (!smb2_util_handle_empty(dest_h)) {
5067                 smb2_util_close(tree, dest_h);
5068         }
5069
5070         return ok;
5071 }
5072
5073 static bool test_copy_chunk_streams(struct torture_context *torture,
5074                                     struct smb2_tree *tree)
5075 {
5076         const char *src_name = "src";
5077         const char *dst_name = "dst";
5078         struct names {
5079                 const char *src_sname;
5080                 const char *dst_sname;
5081         } names[] = {
5082                 { "src:foo", "dst:foo" },
5083                 { "src" AFPRESOURCE_STREAM, "dst" AFPRESOURCE_STREAM }
5084         };
5085         int i;
5086         TALLOC_CTX *tmp_ctx = NULL;
5087         bool ok = false;
5088
5089         tmp_ctx = talloc_new(tree);
5090         torture_assert_not_null_goto(torture, tmp_ctx, ok, done,
5091                                      "torture_setup_file\n");
5092
5093         smb2_util_unlink(tree, src_name);
5094         smb2_util_unlink(tree, dst_name);
5095
5096         ok = torture_setup_file(torture, tree, src_name, false);
5097         torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
5098         ok = torture_setup_file(torture, tree, dst_name, false);
5099         torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
5100
5101         for (i = 0; i < ARRAY_SIZE(names); i++) {
5102                 ok = copy_one_stream(torture, tree, tmp_ctx,
5103                                      names[i].src_sname,
5104                                      names[i].dst_sname);
5105                 torture_assert_goto(torture, ok == true, ok, done,
5106                                     "copy_one_stream failed\n");
5107         }
5108
5109         ok = copy_finderinfo_stream(torture, tree, tmp_ctx,
5110                                     src_name, dst_name);
5111         torture_assert_goto(torture, ok == true, ok, done,
5112                             "copy_finderinfo_stream failed\n");
5113
5114 done:
5115         smb2_util_unlink(tree, src_name);
5116         smb2_util_unlink(tree, dst_name);
5117         talloc_free(tmp_ctx);
5118         return ok;
5119 }
5120
5121 /*
5122  * Ensure this security descriptor has exactly one mode, uid
5123  * and gid.
5124  */
5125
5126 static NTSTATUS check_nfs_sd(const struct security_descriptor *psd)
5127 {
5128         uint32_t i;
5129         bool got_one_mode = false;
5130         bool got_one_uid = false;
5131         bool got_one_gid = false;
5132
5133         if (psd->dacl == NULL) {
5134                 return NT_STATUS_INVALID_SECURITY_DESCR;
5135         }
5136
5137         for (i = 0; i < psd->dacl->num_aces; i++) {
5138                 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Mode,
5139                                            &psd->dacl->aces[i].trustee) == 0) {
5140                         if (got_one_mode == true) {
5141                                 /* Can't have more than one. */
5142                                 return NT_STATUS_INVALID_SECURITY_DESCR;
5143                         }
5144                         got_one_mode = true;
5145                 }
5146         }
5147         for (i = 0; i < psd->dacl->num_aces; i++) {
5148                 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Users,
5149                                            &psd->dacl->aces[i].trustee) == 0) {
5150                         if (got_one_uid == true) {
5151                                 /* Can't have more than one. */
5152                                 return NT_STATUS_INVALID_SECURITY_DESCR;
5153                         }
5154                         got_one_uid = true;
5155                 }
5156         }
5157         for (i = 0; i < psd->dacl->num_aces; i++) {
5158                 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Groups,
5159                                            &psd->dacl->aces[i].trustee) == 0) {
5160                         if (got_one_gid == true) {
5161                                 /* Can't have more than one. */
5162                                 return NT_STATUS_INVALID_SECURITY_DESCR;
5163                         }
5164                         got_one_gid = true;
5165                 }
5166         }
5167         /* Must have at least one of each. */
5168         if (got_one_mode == false ||
5169                         got_one_uid == false ||
5170                         got_one_gid == false) {
5171                 return NT_STATUS_INVALID_SECURITY_DESCR;
5172         }
5173         return NT_STATUS_OK;
5174 }
5175
5176 static bool test_nfs_aces(struct torture_context *tctx,
5177                           struct smb2_tree *tree)
5178 {
5179         TALLOC_CTX *mem_ctx = talloc_new(tctx);
5180         struct security_ace ace;
5181         struct dom_sid sid;
5182         const char *fname = BASEDIR "\\nfs_aces.txt";
5183         struct smb2_handle h = {{0}};
5184         union smb_fileinfo finfo2;
5185         union smb_setfileinfo set;
5186         struct security_descriptor *psd = NULL;
5187         NTSTATUS status;
5188         bool ret = true;
5189         bool is_osx = torture_setting_bool(tctx, "osx", false);
5190
5191         if (is_osx) {
5192                 torture_skip(tctx, "Test only works with Samba\n");
5193         }
5194
5195         ret = enable_aapl(tctx, tree);
5196         torture_assert(tctx, ret == true, "enable_aapl failed");
5197
5198         /* clean slate ...*/
5199         smb2_util_unlink(tree, fname);
5200         smb2_deltree(tree, fname);
5201         smb2_deltree(tree, BASEDIR);
5202
5203         status = torture_smb2_testdir(tree, BASEDIR, &h);
5204         CHECK_STATUS(status, NT_STATUS_OK);
5205         smb2_util_close(tree, h);
5206
5207         /* Create a test file. */
5208         status = torture_smb2_testfile_access(tree,
5209                                 fname,
5210                                 &h,
5211                                 SEC_STD_READ_CONTROL |
5212                                 SEC_STD_WRITE_DAC |
5213                                 SEC_RIGHTS_FILE_ALL);
5214         CHECK_STATUS(status, NT_STATUS_OK);
5215
5216         /* Get the ACL. */
5217         finfo2.query_secdesc.in.secinfo_flags =
5218                 SECINFO_OWNER |
5219                 SECINFO_GROUP |
5220                 SECINFO_DACL;
5221         finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
5222         finfo2.generic.in.file.handle = h;
5223         status = smb2_getinfo_file(tree, tctx, &finfo2);
5224         CHECK_STATUS(status, NT_STATUS_OK);
5225
5226         psd = finfo2.query_secdesc.out.sd;
5227
5228         /* Ensure we have only single mode/uid/gid NFS entries. */
5229         status = check_nfs_sd(psd);
5230         if (!NT_STATUS_IS_OK(status)) {
5231                 NDR_PRINT_DEBUG(
5232                         security_descriptor,
5233                         discard_const_p(struct security_descriptor, psd));
5234         }
5235         CHECK_STATUS(status, NT_STATUS_OK);
5236
5237         /* Add a couple of extra NFS uids and gids. */
5238         sid_compose(&sid, &global_sid_Unix_NFS_Users, 27);
5239         init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
5240         status = security_descriptor_dacl_add(psd, &ace);
5241         CHECK_STATUS(status, NT_STATUS_OK);
5242         status = security_descriptor_dacl_add(psd, &ace);
5243         CHECK_STATUS(status, NT_STATUS_OK);
5244
5245         sid_compose(&sid, &global_sid_Unix_NFS_Groups, 300);
5246         init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
5247         status = security_descriptor_dacl_add(psd, &ace);
5248         CHECK_STATUS(status, NT_STATUS_OK);
5249         status = security_descriptor_dacl_add(psd, &ace);
5250         CHECK_STATUS(status, NT_STATUS_OK);
5251
5252         /* Now set on the file handle. */
5253         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
5254         set.set_secdesc.in.file.handle = h;
5255         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
5256         set.set_secdesc.in.sd = psd;
5257         status = smb2_setinfo_file(tree, &set);
5258         CHECK_STATUS(status, NT_STATUS_OK);
5259
5260         /* Get the ACL again. */
5261         finfo2.query_secdesc.in.secinfo_flags =
5262                 SECINFO_OWNER |
5263                 SECINFO_GROUP |
5264                 SECINFO_DACL;
5265         finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
5266         finfo2.generic.in.file.handle = h;
5267         status = smb2_getinfo_file(tree, tctx, &finfo2);
5268         CHECK_STATUS(status, NT_STATUS_OK);
5269
5270         psd = finfo2.query_secdesc.out.sd;
5271
5272         /* Ensure we have only single mode/uid/gid NFS entries. */
5273         status = check_nfs_sd(psd);
5274         if (!NT_STATUS_IS_OK(status)) {
5275                 NDR_PRINT_DEBUG(
5276                         security_descriptor,
5277                         discard_const_p(struct security_descriptor, psd));
5278         }
5279         CHECK_STATUS(status, NT_STATUS_OK);
5280
5281 done:
5282         if (!smb2_util_handle_empty(h)) {
5283                 smb2_util_close(tree, h);
5284         }
5285         smb2_util_unlink(tree, fname);
5286         smb2_deltree(tree, fname);
5287         smb2_deltree(tree, BASEDIR);
5288         talloc_free(mem_ctx);
5289         return ret;
5290 }
5291
5292 static bool test_setinfo_stream_eof(struct torture_context *tctx,
5293                                     struct smb2_tree *tree)
5294 {
5295         bool ret = true;
5296         NTSTATUS status;
5297         struct smb2_create create;
5298         union smb_setfileinfo sfinfo;
5299         union smb_fileinfo finfo;
5300         struct smb2_handle h1;
5301         TALLOC_CTX *mem_ctx = talloc_new(tctx);
5302         const char *fname = BASEDIR "\\file";
5303         const char *sname = BASEDIR "\\file:foo";
5304
5305         torture_assert_goto(tctx, mem_ctx != NULL, ret, done,
5306                             "talloc_new failed\n");
5307
5308         ret = enable_aapl(tctx, tree);
5309         torture_assert(tctx, ret == true, "enable_aapl failed");
5310
5311         torture_comment(tctx, "Test setting EOF on a stream\n");
5312
5313         smb2_deltree(tree, BASEDIR);
5314         status = torture_smb2_testdir(tree, BASEDIR, &h1);
5315         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5316                                         "torture_smb2_testdir\n");
5317         smb2_util_close(tree, h1);
5318
5319         status = torture_smb2_testfile(tree, fname, &h1);
5320         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5321                                         "torture_smb2_testfile failed\n");
5322         smb2_util_close(tree, h1);
5323
5324         status = torture_smb2_testfile_access(tree, sname, &h1,
5325                                               SEC_FILE_WRITE_DATA);
5326         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5327                                         "torture_smb2_testfile failed\n");
5328
5329         status = smb2_util_write(tree, h1, "1234567890", 0, 10);
5330         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5331                                         "smb2_util_write failed\n");
5332         smb2_util_close(tree, h1);
5333
5334         /*
5335          * Test setting EOF to 21
5336          */
5337
5338         torture_comment(tctx, "Setting stream EOF to 21\n");
5339
5340         status = torture_smb2_testfile_access(tree, sname, &h1,
5341                                               SEC_FILE_WRITE_DATA);
5342         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5343                                         "torture_smb2_testfile failed\n");
5344
5345         ZERO_STRUCT(sfinfo);
5346         sfinfo.generic.in.file.handle = h1;
5347         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5348         sfinfo.position_information.in.position = 21;
5349         status = smb2_setinfo_file(tree, &sfinfo);
5350         torture_assert_ntstatus_ok_goto(tctx, status,
5351                                         ret, done, "set EOF 21 failed\n");
5352
5353         smb2_util_close(tree, h1);
5354
5355         status = torture_smb2_testfile_access(tree, sname, &h1,
5356                                               SEC_FILE_WRITE_DATA);
5357         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5358                                         "torture_smb2_testfile failed\n");
5359
5360         ZERO_STRUCT(finfo);
5361         finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5362         finfo.generic.in.file.handle = h1;
5363         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5364         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5365                                         "smb2_getinfo_file failed");
5366
5367         smb2_util_close(tree, h1);
5368
5369         torture_assert_goto(tctx, finfo.standard_info.out.size == 21,
5370                             ret, done, "size != 21\n");
5371
5372         /*
5373          * Test setting EOF to 0
5374          */
5375
5376         torture_comment(tctx, "Setting stream EOF to 0\n");
5377
5378         status = torture_smb2_testfile_access(tree, sname, &h1,
5379                                               SEC_FILE_WRITE_DATA);
5380         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5381                                         "torture_smb2_testfile failed\n");
5382
5383         ZERO_STRUCT(sfinfo);
5384         sfinfo.generic.in.file.handle = h1;
5385         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5386         sfinfo.position_information.in.position = 0;
5387         status = smb2_setinfo_file(tree, &sfinfo);
5388         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5389                                         "set eof 0 failed\n");
5390
5391         ZERO_STRUCT(create);
5392         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5393         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5394         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5395         create.in.create_disposition = NTCREATEX_DISP_OPEN;
5396         create.in.fname = sname;
5397
5398         status = smb2_create(tree, tctx, &create);
5399         torture_assert_ntstatus_equal_goto(
5400                 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5401                 "Unexpected status\n");
5402
5403         smb2_util_close(tree, h1);
5404
5405         ZERO_STRUCT(create);
5406         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5407         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5408         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5409         create.in.create_disposition = NTCREATEX_DISP_OPEN;
5410         create.in.fname = sname;
5411
5412         status = smb2_create(tree, tctx, &create);
5413         torture_assert_ntstatus_equal_goto(
5414                 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5415                 "Unexpected status\n");
5416
5417         status = torture_smb2_testfile_access(tree, sname, &h1,
5418                                               SEC_FILE_WRITE_DATA);
5419         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5420                                         "torture_smb2_testfile failed\n");
5421
5422         ZERO_STRUCT(finfo);
5423         finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5424         finfo.generic.in.file.handle = h1;
5425         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5426         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5427                                         "smb2_getinfo_file failed\n");
5428
5429         smb2_util_close(tree, h1);
5430
5431         torture_assert_goto(tctx, finfo.standard_info.out.size == 0,
5432                             ret, done, "size != 0\n");
5433
5434         /*
5435          * Test setinfo end-of-file info to 1
5436          */
5437
5438         torture_comment(tctx, "Setting stream EOF to 1\n");
5439
5440         status = torture_smb2_testfile_access(tree, sname, &h1,
5441                                               SEC_FILE_WRITE_DATA);
5442         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5443                                         "torture_smb2_testfile failed\n");
5444
5445         ZERO_STRUCT(sfinfo);
5446         sfinfo.generic.in.file.handle = h1;
5447         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5448         sfinfo.position_information.in.position = 1;
5449         status = smb2_setinfo_file(tree, &sfinfo);
5450         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5451                                         "set EOF 1 failed\n");
5452
5453         smb2_util_close(tree, h1);
5454
5455         status = torture_smb2_testfile_access(tree, sname, &h1,
5456                                               SEC_FILE_WRITE_DATA);
5457         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5458                                         "torture_smb2_testfile failed\n");
5459
5460         ZERO_STRUCT(finfo);
5461         finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5462         finfo.generic.in.file.handle = h1;
5463         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5464         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5465                                         "smb2_getinfo_file failed\n");
5466
5467         smb2_util_close(tree, h1);
5468
5469         torture_assert_goto(tctx, finfo.standard_info.out.size == 1,
5470                             ret, done, "size != 1\n");
5471
5472         /*
5473          * Test setting EOF to 0 with AAPL enabled, should delete stream
5474          */
5475
5476         torture_comment(tctx, "Enabling AAPL extensions\n");
5477
5478         ret = enable_aapl(tctx, tree);
5479         torture_assert(tctx, ret == true, "enable_aapl failed\n");
5480
5481         torture_comment(tctx, "Setting stream EOF to 0\n");
5482         status = torture_smb2_testfile_access(tree, sname, &h1,
5483                                               SEC_FILE_WRITE_DATA);
5484         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5485                                         "torture_smb2_testfile failed\n");
5486
5487         ZERO_STRUCT(sfinfo);
5488         sfinfo.generic.in.file.handle = h1;
5489         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5490         sfinfo.position_information.in.position = 0;
5491         status = smb2_setinfo_file(tree, &sfinfo);
5492         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5493                                         "set eof 0 failed\n");
5494
5495         ZERO_STRUCT(create);
5496         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5497         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5498         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5499         create.in.create_disposition = NTCREATEX_DISP_OPEN;
5500         create.in.fname = sname;
5501
5502         status = smb2_create(tree, tctx, &create);
5503         torture_assert_ntstatus_equal_goto(
5504                 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5505                 "Unexpected status\n");
5506
5507         smb2_util_close(tree, h1);
5508
5509         ZERO_STRUCT(create);
5510         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5511         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5512         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5513         create.in.create_disposition = NTCREATEX_DISP_OPEN;
5514         create.in.fname = sname;
5515
5516         status = smb2_create(tree, tctx, &create);
5517         torture_assert_ntstatus_equal_goto(
5518                 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5519                 "Unexpected status\n");
5520
5521         torture_comment(
5522                 tctx, "Setting main file EOF to 1 to force 0-truncate\n");
5523
5524         status = torture_smb2_testfile_access(
5525                 tree,
5526                 fname,
5527                 &h1,
5528                 SEC_FILE_WRITE_DATA);
5529         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5530                                         "torture_smb2_testfile failed\n");
5531
5532         ZERO_STRUCT(sfinfo);
5533         sfinfo.generic.in.file.handle = h1;
5534         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5535         sfinfo.position_information.in.position = 1;
5536         status = smb2_setinfo_file(tree, &sfinfo);
5537         torture_assert_ntstatus_ok_goto(
5538                 tctx,
5539                 status,
5540                 ret,
5541                 done,
5542                 "set eof 1 failed\n");
5543
5544         sfinfo.position_information.in.position = 0;
5545         status = smb2_setinfo_file(tree, &sfinfo);
5546         torture_assert_ntstatus_ok_goto(
5547                 tctx,
5548                 status,
5549                 ret,
5550                 done,
5551                 "set eof 0 failed\n");
5552
5553         smb2_util_close(tree, h1);
5554
5555         ZERO_STRUCT(create);
5556         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5557         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5558         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5559         create.in.create_disposition = NTCREATEX_DISP_OPEN;
5560         create.in.fname = fname;
5561
5562         status = smb2_create(tree, tctx, &create);
5563         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5564                                         "torture_smb2_testfile failed\n");
5565         smb2_util_close(tree, h1);
5566
5567         torture_comment(tctx, "Writing to stream after setting EOF to 0\n");
5568         status = torture_smb2_testfile_access(tree, sname, &h1,
5569                                               SEC_FILE_WRITE_DATA);
5570         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5571                                         "torture_smb2_testfile failed\n");
5572
5573         status = smb2_util_write(tree, h1, "1234567890", 0, 10);
5574         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5575                                         "smb2_util_write failed\n");
5576
5577         ZERO_STRUCT(sfinfo);
5578         sfinfo.generic.in.file.handle = h1;
5579         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5580         sfinfo.position_information.in.position = 0;
5581         status = smb2_setinfo_file(tree, &sfinfo);
5582         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5583                                         "set eof 0 failed\n");
5584
5585         status = smb2_util_write(tree, h1, "1234567890", 0, 10);
5586         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5587                                         "smb2_util_write failed\n");
5588
5589         smb2_util_close(tree, h1);
5590
5591 done:
5592         smb2_util_unlink(tree, fname);
5593         smb2_util_rmdir(tree, BASEDIR);
5594         return ret;
5595 }
5596
5597 #define MAX_STREAMS 16
5598
5599 struct tcase {
5600         const char *name;
5601         uint32_t access;
5602         const char *write_data;
5603         size_t write_size;
5604         struct tcase_results {
5605                 size_t size;
5606                 NTSTATUS initial_status;
5607                 NTSTATUS final_status;
5608                 int num_streams_open_handle;
5609                 const char *streams_open_handle[MAX_STREAMS];
5610                 int num_streams_closed_handle;
5611                 const char *streams_closed_handle[MAX_STREAMS];
5612         } create, write, overwrite, eof, doc;
5613 };
5614
5615 typedef enum {T_CREATE, T_WRITE, T_OVERWRITE, T_EOF, T_DOC} subtcase_t;
5616
5617 static bool test_empty_stream_do_checks(
5618         struct torture_context *tctx,
5619         struct smb2_tree *tree,
5620         struct smb2_tree *tree2,
5621         struct tcase *tcase,
5622         TALLOC_CTX *mem_ctx,
5623         struct smb2_handle baseh,
5624         struct smb2_handle streamh,
5625         subtcase_t subcase)
5626 {
5627         bool ret = false;
5628         NTSTATUS status;
5629         struct smb2_handle h1;
5630         union smb_fileinfo finfo;
5631         struct tcase_results *tcase_results = NULL;
5632
5633         switch (subcase) {
5634         case T_CREATE:
5635                 tcase_results = &tcase->create;
5636                 break;
5637         case T_OVERWRITE:
5638                 tcase_results = &tcase->overwrite;
5639                 break;
5640         case T_WRITE:
5641                 tcase_results = &tcase->write;
5642                 break;
5643         case T_EOF:
5644                 tcase_results = &tcase->eof;
5645                 break;
5646         case T_DOC:
5647                 tcase_results = &tcase->doc;
5648                 break;
5649         }
5650
5651         finfo = (union smb_fileinfo) {
5652                 .generic.level = RAW_FILEINFO_STANDARD_INFORMATION,
5653                 .generic.in.file.handle = streamh,
5654         };
5655
5656         /*
5657          * Test: check size, same client
5658          */
5659
5660         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5661         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5662                                         "torture_smb2_testfile failed\n");
5663
5664         torture_assert_int_equal_goto(tctx, finfo.standard_info.out.size,
5665                                       tcase_results->size,
5666                                       ret, done, "Wrong size\n");
5667
5668         /*
5669          * Test: open, same client
5670          */
5671
5672         status = torture_smb2_open(tree, tcase->name,
5673                                    SEC_FILE_READ_ATTRIBUTE, &h1);
5674         torture_assert_ntstatus_equal_goto(tctx, status,
5675                                            tcase_results->initial_status,
5676                                            ret, done,
5677                                            "smb2_create failed\n");
5678         if (NT_STATUS_IS_OK(status)) {
5679                 status = smb2_util_close(tree, h1);
5680                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5681                                                 "smb2_util_close failed\n");
5682         }
5683
5684         /*
5685          * Test: check streams, same client
5686          */
5687
5688         ret = check_stream_list_handle(tree, tctx, baseh,
5689                                        tcase_results->num_streams_open_handle,
5690                                        tcase_results->streams_open_handle,
5691                                        false);
5692         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
5693
5694         /*
5695          * Test: open, different client
5696          */
5697
5698         status = torture_smb2_open(tree2, tcase->name,
5699                                    SEC_FILE_READ_ATTRIBUTE, &h1);
5700         torture_assert_ntstatus_equal_goto(tctx, status,
5701                                            tcase_results->initial_status,
5702                                            ret, done,
5703                                            "smb2_create failed\n");
5704         if (NT_STATUS_IS_OK(status)) {
5705                 finfo = (union smb_fileinfo) {
5706                         .generic.level = RAW_FILEINFO_STANDARD_INFORMATION,
5707                         .generic.in.file.handle = h1,
5708                 };
5709
5710                 /*
5711                  * Test: check size, different client
5712                  */
5713
5714                 status = smb2_getinfo_file(tree2, mem_ctx, &finfo);
5715                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5716                                                 "smb2_getinfo_file failed\n");
5717
5718                 torture_assert_int_equal_goto(tctx, finfo.standard_info.out.size,
5719                                               tcase_results->size,
5720                                               ret, done, "Wrong size\n");
5721
5722                 /*
5723                  * Test: check streams, different client
5724                  */
5725
5726                 ret = check_stream_list(tree2, tctx, BASEDIR "\\file",
5727                                         tcase_results->num_streams_open_handle,
5728                                         tcase_results->streams_open_handle,
5729                                         false);
5730                 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
5731
5732                 status = smb2_util_close(tree2, h1);
5733                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5734                                                 "smb2_util_close failed\n");
5735         }
5736
5737         status = smb2_util_close(tree, streamh);
5738         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5739                                         "smb2_util_close failed\n");
5740
5741         /*
5742          * Test: open after close, same client
5743          */
5744
5745         status = torture_smb2_open(tree, tcase->name,
5746                                    SEC_FILE_READ_DATA, &h1);
5747         torture_assert_ntstatus_equal_goto(tctx, status,
5748                                            tcase_results->final_status,
5749                                            ret, done,
5750                                            "smb2_create failed\n");
5751         if (NT_STATUS_IS_OK(status)) {
5752                 status = smb2_util_close(tree, h1);
5753                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5754                                                 "smb2_util_close failed\n");
5755         }
5756
5757         /*
5758          * Test: open after close, different client
5759          */
5760
5761         status = torture_smb2_open(tree2, tcase->name,
5762                                    SEC_FILE_READ_DATA, &h1);
5763         torture_assert_ntstatus_equal_goto(tctx, status,
5764                                            tcase_results->final_status,
5765                                            ret, done,
5766                                            "smb2_create failed\n");
5767         if (NT_STATUS_IS_OK(status)) {
5768                 status = smb2_util_close(tree2, h1);
5769                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5770                                                 "smb2_util_close failed\n");
5771         }
5772
5773         /*
5774          * Test: check streams after close, same client
5775          */
5776
5777         ret = check_stream_list_handle(tree, tctx, baseh,
5778                                        tcase_results->num_streams_closed_handle,
5779                                        tcase_results->streams_closed_handle,
5780                                        false);
5781         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
5782
5783         ret = true;
5784
5785 done:
5786         smb2_util_close(tree, streamh);
5787         smb2_util_close(tree, baseh);
5788         return ret;
5789 }
5790
5791 static bool test_empty_stream_do_one(
5792         struct torture_context *tctx,
5793         struct smb2_tree *tree,
5794         struct smb2_tree *tree2,
5795         struct tcase *tcase)
5796 {
5797         bool ret = false;
5798         NTSTATUS status;
5799         struct smb2_handle baseh = {{0}};
5800         struct smb2_handle streamh;
5801         struct smb2_create create;
5802         union smb_setfileinfo sfinfo;
5803         TALLOC_CTX *mem_ctx = talloc_new(tctx);
5804
5805         torture_comment(tctx, "Testing stream [%s]\n", tcase->name);
5806
5807         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new\n");
5808
5809         /*
5810          * Subtest: create
5811          */
5812         torture_comment(tctx, "Subtest: T_CREATE\n");
5813
5814         status = smb2_util_unlink(tree, BASEDIR "\\file");
5815         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5816                                         "smb2_util_unlink failed\n");
5817
5818         status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5819                                               &baseh, SEC_FILE_ALL);
5820         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5821                                         "torture_smb2_testfile_access failed\n");
5822
5823         status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5824                                               tcase->access);
5825         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5826                                         "torture_smb2_testfile_access failed\n");
5827
5828         ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5829                                           mem_ctx, baseh, streamh, T_CREATE);
5830         torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5831
5832         if (!(tcase->access & SEC_FILE_WRITE_DATA)) {
5833                 /*
5834                  * All subsequent tests require write access
5835                  */
5836                 ret = true;
5837                 goto done;
5838         }
5839
5840         /*
5841          * Subtest: create and write
5842          */
5843         torture_comment(tctx, "Subtest: T_WRITE\n");
5844
5845         status = smb2_util_unlink(tree, BASEDIR "\\file");
5846         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5847                                         "smb2_util_unlink failed\n");
5848
5849         status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5850                                               &baseh, SEC_FILE_ALL);
5851         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5852                                         "torture_smb2_testfile_access failed\n");
5853
5854         status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5855                                               tcase->access);
5856         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5857                                         "torture_smb2_testfile_access failed\n");
5858
5859         status = smb2_util_write(tree, streamh, tcase->write_data, 0,
5860                                  tcase->write_size);
5861         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5862                                         "torture_smb2_open failed\n");
5863
5864         ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5865                                           mem_ctx, baseh, streamh, T_WRITE);
5866         torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5867
5868         /*
5869          * Subtest: overwrite
5870          */
5871         torture_comment(tctx, "Subtest: T_OVERWRITE\n");
5872
5873         status = smb2_util_unlink(tree, BASEDIR "\\file");
5874         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5875                                         "smb2_util_unlink failed\n");
5876
5877         status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5878                                               &baseh, SEC_FILE_ALL);
5879         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5880                                         "torture_smb2_testfile_access failed\n");
5881
5882         create = (struct smb2_create) {
5883                 .in.desired_access = SEC_FILE_ALL,
5884                 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
5885                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
5886                 .in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF,
5887                 .in.fname = tcase->name,
5888         };
5889
5890         status = smb2_create(tree, tctx, &create);
5891         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5892                                         "torture_smb2_testfile failed\n");
5893         streamh = create.out.file.handle;
5894
5895         ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5896                                           mem_ctx, baseh, streamh, T_OVERWRITE);
5897         torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5898
5899         /*
5900          * Subtest: setinfo EOF 0
5901          */
5902         torture_comment(tctx, "Subtest: T_EOF\n");
5903
5904         status = smb2_util_unlink(tree, BASEDIR "\\file");
5905         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5906                                         "smb2_util_unlink failed\n");
5907
5908         status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5909                                               &baseh, SEC_FILE_ALL);
5910         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5911                                         "torture_smb2_testfile_access failed\n");
5912
5913         status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5914                                               tcase->access);
5915         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5916                                         "torture_smb2_testfile_access failed\n");
5917
5918         status = smb2_util_write(tree, streamh, tcase->write_data, 0,
5919                                  tcase->write_size);
5920         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5921                                         "torture_smb2_open failed\n");
5922
5923         sfinfo = (union smb_setfileinfo) {
5924                 .end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION,
5925                 .end_of_file_info.in.file.handle = streamh,
5926                 .end_of_file_info.in.size = 0,
5927         };
5928         status = smb2_setinfo_file(tree, &sfinfo);
5929         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5930                                         "set eof 0 failed\n");
5931
5932         ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5933                                           mem_ctx, baseh, streamh, T_EOF);
5934         torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5935
5936         /*
5937          * Subtest: delete-on-close
5938          */
5939         torture_comment(tctx, "Subtest: T_DOC\n");
5940
5941         status = smb2_util_unlink(tree, BASEDIR "\\file");
5942         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5943                                         "smb2_util_unlink failed\n");
5944
5945         status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5946                                               &baseh, SEC_FILE_ALL);
5947         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5948                                         "torture_smb2_testfile_access failed\n");
5949
5950         status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5951                                               tcase->access);
5952         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5953                                         "torture_smb2_testfile_access failed\n");
5954
5955         status = smb2_util_write(tree, streamh, tcase->write_data, 0,
5956                                  tcase->write_size);
5957         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5958                                         "torture_smb2_open failed\n");
5959
5960         sfinfo = (union smb_setfileinfo) {
5961                 .disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFORMATION,
5962                 .disposition_info.in.file.handle = streamh,
5963                 .disposition_info.in.delete_on_close = true,
5964         };
5965         status = smb2_setinfo_file(tree, &sfinfo);
5966         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5967                                         "set eof 0 failed\n");
5968
5969         ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5970                                           mem_ctx, baseh, streamh,
5971                                           T_DOC);
5972         torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5973
5974         ret = true;
5975
5976 done:
5977         smb2_util_close(tree, baseh);
5978         TALLOC_FREE(mem_ctx);
5979         return ret;
5980 }
5981
5982 static bool test_empty_stream(struct torture_context *tctx,
5983                               struct smb2_tree *tree)
5984 {
5985         struct smb2_tree *tree2 = NULL;
5986         struct tcase *tcase = NULL;
5987         const char *fname = BASEDIR "\\file";
5988         struct smb2_handle h1;
5989         bool ret = true;
5990         NTSTATUS status;
5991         AfpInfo ai = (AfpInfo) {
5992                 .afpi_Signature = AFP_Signature,
5993                 .afpi_Version = AFP_Version,
5994                 .afpi_BackupTime = AFP_BackupTime,
5995                 .afpi_FinderInfo = "FOO BAR ",
5996         };
5997         char *ai_blob = torture_afpinfo_pack(tctx, &ai);
5998         struct tcase tcase_afpinfo_ro = (struct tcase) {
5999                 .name = BASEDIR "\\file" AFPINFO_STREAM,
6000                 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
6001                 .create = {
6002                         .size = 60,
6003                         .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6004                         .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6005                         .num_streams_open_handle = 1,
6006                         .num_streams_closed_handle = 1,
6007                         .streams_open_handle = {"::$DATA"},
6008                         .streams_closed_handle = {"::$DATA"},
6009                 },
6010         };
6011         struct tcase tcase_afpinfo_rw = (struct tcase) {
6012                 .name = BASEDIR "\\file" AFPINFO_STREAM,
6013                 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
6014                 .write_data = ai_blob,
6015                 .write_size = AFP_INFO_SIZE,
6016                 .create = {
6017                         .size = 60,
6018                         .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6019                         .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6020                         .num_streams_open_handle = 1,
6021                         .num_streams_closed_handle = 1,
6022                         .streams_open_handle = {"::$DATA"},
6023                         .streams_closed_handle = {"::$DATA"},
6024                 },
6025                 .write = {
6026                         .size = 60,
6027                         .initial_status = NT_STATUS_OK,
6028                         .final_status = NT_STATUS_OK,
6029                         .num_streams_open_handle = 2,
6030                         .num_streams_closed_handle = 2,
6031                         .streams_open_handle = {"::$DATA", AFPINFO_STREAM},
6032                         .streams_closed_handle = {"::$DATA", AFPINFO_STREAM},
6033                 },
6034                 .overwrite = {
6035                         .size = 60,
6036                         .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6037                         .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6038                         .num_streams_open_handle = 1,
6039                         .num_streams_closed_handle = 1,
6040                         .streams_open_handle = {"::$DATA"},
6041                         .streams_closed_handle = {"::$DATA"},
6042                 },
6043                 .eof = {
6044                         .size = 60,
6045                         .initial_status = NT_STATUS_OK,
6046                         .final_status = NT_STATUS_OK,
6047                         .num_streams_open_handle = 2,
6048                         .num_streams_closed_handle = 2,
6049                         .streams_open_handle = {"::$DATA", AFPINFO_STREAM},
6050                         .streams_closed_handle = {"::$DATA", AFPINFO_STREAM},
6051                 },
6052                 .doc = {
6053                         .size = 60,
6054                         .initial_status = NT_STATUS_DELETE_PENDING,
6055                         .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6056                         .num_streams_open_handle = 2,
6057                         .num_streams_closed_handle = 1,
6058                         .streams_open_handle = {"::$DATA", AFPINFO_STREAM},
6059                         .streams_closed_handle = {"::$DATA"},
6060                 },
6061         };
6062
6063         struct tcase tcase_afpresource_ro = (struct tcase) {
6064                 .name = BASEDIR "\\file" AFPRESOURCE_STREAM,
6065                 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
6066                 .create = {
6067                         .size = 0,
6068                         .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6069                         .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6070                         .num_streams_open_handle = 1,
6071                         .num_streams_closed_handle = 1,
6072                         .streams_open_handle = {"::$DATA"},
6073                         .streams_closed_handle = {"::$DATA"},
6074                 },
6075         };
6076         struct tcase tcase_afpresource_rw = (struct tcase) {
6077                 .name = BASEDIR "\\file" AFPRESOURCE_STREAM,
6078                 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
6079                 .write_data = "foo",
6080                 .write_size = 3,
6081                 .create = {
6082                         .size = 0,
6083                         .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6084                         .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6085                         .num_streams_open_handle = 1,
6086                         .num_streams_closed_handle = 1,
6087                         .streams_open_handle = {"::$DATA"},
6088                         .streams_closed_handle = {"::$DATA"},
6089                 },
6090                 .write = {
6091                         .size = 3,
6092                         .initial_status = NT_STATUS_OK,
6093                         .final_status = NT_STATUS_OK,
6094                         .num_streams_open_handle = 2,
6095                         .num_streams_closed_handle = 2,
6096                         .streams_open_handle = {"::$DATA", AFPRESOURCE_STREAM},
6097                         .streams_closed_handle = {"::$DATA", AFPRESOURCE_STREAM},
6098                 },
6099                 .overwrite = {
6100                         .size = 0,
6101                         .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6102                         .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6103                         .num_streams_open_handle = 1,
6104                         .num_streams_closed_handle = 1,
6105                         .streams_open_handle = {"::$DATA"},
6106                         .streams_closed_handle = {"::$DATA"},
6107                 },
6108                 .eof = {
6109                         .size = 0,
6110                         .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6111                         .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6112                         .num_streams_open_handle = 1,
6113                         .num_streams_closed_handle = 1,
6114                         .streams_open_handle = {"::$DATA"},
6115                         .streams_closed_handle = {"::$DATA"},
6116                 },
6117                 .doc = {
6118                         .size = 3,
6119                         .initial_status = NT_STATUS_DELETE_PENDING,
6120                         .final_status = NT_STATUS_OK,
6121                         .num_streams_open_handle = 2,
6122                         .num_streams_closed_handle = 2,
6123                         .streams_open_handle = {"::$DATA", AFPRESOURCE_STREAM},
6124                         .streams_closed_handle = {"::$DATA", AFPRESOURCE_STREAM},
6125                 },
6126         };
6127
6128         struct tcase tcase_foo_ro = (struct tcase) {
6129                 .name = BASEDIR "\\file:foo",
6130                 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
6131                 .write_data = "foo",
6132                 .write_size = 3,
6133                 .create = {
6134                         .size = 0,
6135                         .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6136                         .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6137                         .num_streams_open_handle = 1,
6138                         .num_streams_closed_handle = 1,
6139                         .streams_open_handle = {"::$DATA"},
6140                         .streams_closed_handle = {"::$DATA"},
6141                 },
6142         };
6143
6144         struct tcase tcase_foo_rw = (struct tcase) {
6145                 .name = BASEDIR "\\file:foo",
6146                 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
6147                 .write_data = "foo",
6148                 .write_size = 3,
6149                 .create = {
6150                         .size = 0,
6151                         .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6152                         .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6153                         .num_streams_open_handle = 1,
6154                         .num_streams_closed_handle = 1,
6155                         .streams_open_handle = {"::$DATA"},
6156                         .streams_closed_handle = {"::$DATA"},
6157                 },
6158                 .write = {
6159                         .size = 3,
6160                         .initial_status = NT_STATUS_OK,
6161                         .final_status = NT_STATUS_OK,
6162                         .num_streams_open_handle = 2,
6163                         .num_streams_closed_handle = 2,
6164                         .streams_open_handle = {"::$DATA", ":foo:$DATA"},
6165                         .streams_closed_handle = {"::$DATA", ":foo:$DATA"},
6166                 },
6167                 .overwrite = {
6168                         .size = 0,
6169                         .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6170                         .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6171                         .num_streams_open_handle = 1,
6172                         .num_streams_closed_handle = 1,
6173                         .streams_open_handle = {"::$DATA"},
6174                         .streams_closed_handle = {"::$DATA"},
6175                 },
6176                 .eof = {
6177                         .size = 0,
6178                         .initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6179                         .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6180                         .num_streams_open_handle = 1,
6181                         .num_streams_closed_handle = 1,
6182                         .streams_open_handle = {"::$DATA"},
6183                         .streams_closed_handle = {"::$DATA"},
6184                 },
6185                 .doc = {
6186                         .size = 3,
6187                         .initial_status = NT_STATUS_DELETE_PENDING,
6188                         .final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
6189                         .num_streams_open_handle = 2,
6190                         .num_streams_closed_handle = 1,
6191                         .streams_open_handle = {"::$DATA", ":foo:$DATA"},
6192                         .streams_closed_handle = {"::$DATA"},
6193                 },
6194         };
6195
6196         struct tcase tcases[] = {
6197                 tcase_afpinfo_ro,
6198                 tcase_afpinfo_rw,
6199                 tcase_afpresource_ro,
6200                 tcase_afpresource_rw,
6201                 tcase_foo_ro,
6202                 tcase_foo_rw,
6203                 {NULL}
6204         };
6205
6206         ret = torture_smb2_connection(tctx, &tree2);
6207         torture_assert_goto(tctx, ret == true, ret, done,
6208                             "torture_smb2_connection failed\n");
6209
6210         ret = enable_aapl(tctx, tree);
6211         torture_assert(tctx, ret == true, "enable_aapl failed\n");
6212
6213         ret = enable_aapl(tctx, tree2);
6214         torture_assert(tctx, ret == true, "enable_aapl failed\n");
6215
6216         smb2_deltree(tree, BASEDIR);
6217
6218         status = torture_smb2_testdir(tree, BASEDIR, &h1);
6219         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6220                                         "torture_smb2_testdir\n");
6221         smb2_util_close(tree, h1);
6222
6223         for (tcase = &tcases[0]; tcase->name != NULL; tcase++) {
6224                 ret = torture_setup_file(tctx, tree, fname, false);
6225                 torture_assert_goto(tctx, ret == true, ret, done,
6226                                     "torture_setup_file failed\n");
6227
6228                 ret = test_empty_stream_do_one(tctx, tree, tree2, tcase);
6229                 torture_assert_goto(tctx, ret == true, ret, done,
6230                                     "subtest failed\n");
6231
6232                 status = smb2_util_unlink(tree, fname);
6233                 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6234                                                 "smb2_util_unlink failed\n");
6235         }
6236
6237 done:
6238         smb2_deltree(tree, BASEDIR);
6239         TALLOC_FREE(tree2);
6240         return ret;
6241 }
6242
6243 /*
6244  * Note: This test depends on "vfs objects = catia fruit streams_xattr".  For
6245  * some tests torture must be run on the host it tests and takes an additional
6246  * argument with the local path to the share:
6247  * "--option=torture:localdir=<SHAREPATH>".
6248  *
6249  * When running against an OS X SMB server add "--option=torture:osx=true"
6250  */
6251 struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx)
6252 {
6253         struct torture_suite *suite = torture_suite_create(
6254                 ctx, "fruit");
6255
6256         suite->description = talloc_strdup(suite, "vfs_fruit tests");
6257
6258         torture_suite_add_1smb2_test(suite, "copyfile", test_copyfile);
6259         torture_suite_add_1smb2_test(suite, "read metadata", test_read_afpinfo);
6260         torture_suite_add_1smb2_test(suite, "write metadata", test_write_atalk_metadata);
6261         torture_suite_add_1smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io);
6262         torture_suite_add_1smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl);
6263         torture_suite_add_1smb2_test(suite, "stream names", test_stream_names);
6264         torture_suite_add_1smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate);
6265         torture_suite_add_1smb2_test(suite, "opening and creating resource fork", test_rfork_create);
6266         torture_suite_add_1smb2_test(suite, "rename_dir_openfile", test_rename_dir_openfile);
6267         torture_suite_add_1smb2_test(suite, "File without AFP_AfpInfo", test_afpinfo_enoent);
6268         torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpInfo", test_create_delete_on_close);
6269         torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpInfo", test_setinfo_delete_on_close);
6270         torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpInfo", test_setinfo_eof);
6271         torture_suite_add_1smb2_test(suite, "delete AFP_AfpInfo by writing all 0", test_afpinfo_all0);
6272         torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpResource", test_create_delete_on_close_resource);
6273         torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpResource", test_setinfo_delete_on_close_resource);
6274         torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpResource", test_setinfo_eof_resource);
6275         torture_suite_add_1smb2_test(suite, "setinfo eof stream", test_setinfo_stream_eof);
6276         torture_suite_add_1smb2_test(suite, "null afpinfo", test_null_afpinfo);
6277         torture_suite_add_1smb2_test(suite, "delete", test_delete_file_with_rfork);
6278         torture_suite_add_1smb2_test(suite, "read open rsrc after rename", test_rename_and_read_rsrc);
6279         torture_suite_add_1smb2_test(suite, "readdir_attr with names with illegal ntfs characters", test_readdir_attr_illegal_ntfs);
6280         torture_suite_add_2ns_smb2_test(suite, "invalid AFP_AfpInfo", test_invalid_afpinfo);
6281         torture_suite_add_1smb2_test(suite, "creating rsrc with read-only access", test_rfork_create_ro);
6282         torture_suite_add_1smb2_test(suite, "copy-chunk streams", test_copy_chunk_streams);
6283         torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
6284         torture_suite_add_1smb2_test(suite, "NFS ACE entries", test_nfs_aces);
6285         torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion without embedded xattr", test_adouble_conversion_wo_xattr);
6286         torture_suite_add_1smb2_test(suite, "empty_stream", test_empty_stream);
6287         torture_suite_add_1smb2_test(suite, "writing_afpinfo", test_writing_afpinfo);
6288
6289         return suite;
6290 }
6291
6292 static bool test_stream_names_local(struct torture_context *tctx,
6293                                     struct smb2_tree *tree)
6294 {
6295         TALLOC_CTX *mem_ctx = talloc_new(tctx);
6296         NTSTATUS status;
6297         struct smb2_create create;
6298         struct smb2_handle h;
6299         const char *fname = BASEDIR "\\stream_names.txt";
6300         const char *sname1;
6301         bool ret;
6302         /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
6303         const char *streams[] = {
6304                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
6305                 ":bar" "\xef\x80\xa2" "baz:$DATA", /* "bar:baz:$DATA" */
6306                 "::$DATA"
6307         };
6308         const char *localdir = NULL;
6309
6310         localdir = torture_setting_string(tctx, "localdir", NULL);
6311         if (localdir == NULL) {
6312                 torture_skip(tctx, "Need localdir for test");
6313         }
6314
6315         sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
6316
6317         /* clean slate ...*/
6318         smb2_util_unlink(tree, fname);
6319         smb2_deltree(tree, fname);
6320         smb2_deltree(tree, BASEDIR);
6321
6322         status = torture_smb2_testdir(tree, BASEDIR, &h);
6323         CHECK_STATUS(status, NT_STATUS_OK);
6324         smb2_util_close(tree, h);
6325
6326         torture_comment(tctx, "(%s) testing stream names\n", __location__);
6327         ZERO_STRUCT(create);
6328         create.in.desired_access = SEC_FILE_WRITE_DATA;
6329         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
6330         create.in.share_access =
6331                 NTCREATEX_SHARE_ACCESS_DELETE|
6332                 NTCREATEX_SHARE_ACCESS_READ|
6333                 NTCREATEX_SHARE_ACCESS_WRITE;
6334         create.in.create_disposition = NTCREATEX_DISP_CREATE;
6335         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
6336         create.in.fname = sname1;
6337
6338         status = smb2_create(tree, mem_ctx, &create);
6339         CHECK_STATUS(status, NT_STATUS_OK);
6340
6341         status = smb2_util_write(tree, create.out.file.handle, "foo", 0, 3);
6342         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6343                                         "smb2_util_write failed\n");
6344
6345         smb2_util_close(tree, create.out.file.handle);
6346
6347         ret = torture_setup_local_xattr(tctx, "localdir", BASEDIR "/stream_names.txt",
6348                                         "user.DosStream.bar:baz:$DATA",
6349                                         "data", strlen("data"));
6350         CHECK_VALUE(ret, true);
6351
6352         ret = check_stream_list(tree, tctx, fname, 3, streams, false);
6353         CHECK_VALUE(ret, true);
6354
6355 done:
6356         status = smb2_util_unlink(tree, fname);
6357         smb2_deltree(tree, BASEDIR);
6358         talloc_free(mem_ctx);
6359
6360         return ret;
6361 }
6362
6363 static bool test_fruit_locking_conflict(struct torture_context *tctx,
6364                                         struct smb2_tree *tree,
6365                                         struct smb2_tree *tree2)
6366 {
6367         TALLOC_CTX *mem_ctx;
6368         struct smb2_create create;
6369         struct smb2_handle h;
6370         struct smb2_lock lck;
6371         struct smb2_lock_element el;
6372         const char *fname = BASEDIR "\\locking_conflict.txt";
6373         NTSTATUS status;
6374         bool ret = false;
6375
6376         mem_ctx = talloc_new(tctx);
6377         torture_assert_not_null(tctx, mem_ctx, "talloc_new failed");
6378
6379         /* clean slate ...*/
6380         smb2_util_unlink(tree, fname);
6381         smb2_deltree(tree, fname);
6382         smb2_deltree(tree, BASEDIR);
6383
6384         status = torture_smb2_testdir(tree, BASEDIR, &h);
6385         CHECK_STATUS(status, NT_STATUS_OK);
6386         smb2_util_close(tree, h);
6387
6388         create = (struct smb2_create) {
6389                 .in.desired_access = SEC_RIGHTS_FILE_READ,
6390                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
6391                 .in.share_access =
6392                 NTCREATEX_SHARE_ACCESS_READ|
6393                 NTCREATEX_SHARE_ACCESS_WRITE,
6394                 .in.create_disposition = NTCREATEX_DISP_CREATE,
6395                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6396                 .in.fname = fname,
6397         };
6398
6399         status = smb2_create(tree, mem_ctx, &create);
6400         CHECK_STATUS(status, NT_STATUS_OK);
6401         h = create.out.file.handle;
6402
6403         /* Add AD_FILELOCK_RSRC_DENY_WR lock. */
6404         el = (struct smb2_lock_element) {
6405                 .offset = 0xfffffffffffffffc,
6406                 .length = 1,
6407                 .flags = SMB2_LOCK_FLAG_EXCLUSIVE,
6408         };
6409         lck = (struct smb2_lock) {
6410                 .in.lock_count = 1,
6411                 .in.file.handle = h,
6412                 .in.locks = &el,
6413         };
6414
6415         /*
6416          * Lock up to and including:
6417          * AD_FILELOCK_OPEN_WR
6418          * AD_FILELOCK_OPEN_RD
6419          * This is designed to cause a NetAtalk
6420          * locking conflict on the next open,
6421          * even though the share modes are
6422          * compatible.
6423          */
6424         status = smb2_lock(tree, &lck);
6425         CHECK_STATUS(status, NT_STATUS_OK);
6426
6427         el = (struct smb2_lock_element) {
6428                 .offset = 0,
6429                 .length = 0x7ffffffffffffff7,
6430                 .flags = SMB2_LOCK_FLAG_EXCLUSIVE,
6431         };
6432         status = smb2_lock(tree, &lck);
6433         CHECK_STATUS(status, NT_STATUS_OK);
6434
6435         create = (struct smb2_create) {
6436                 .in.desired_access =
6437                 SEC_RIGHTS_FILE_READ|SEC_RIGHTS_FILE_WRITE,
6438                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
6439                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6440                 .in.create_disposition = NTCREATEX_DISP_OPEN,
6441                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6442                 .in.fname = fname,
6443         };
6444
6445         /*
6446          * Open on the second tree - ensure we are
6447          * emulating trying to access with a NetATalk
6448          * process with an existing open/deny mode.
6449          */
6450         status = smb2_create(tree2, mem_ctx, &create);
6451         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
6452
6453         {
6454                 struct smb2_close cl = {
6455                         .level = RAW_CLOSE_SMB2,
6456                         .in.file.handle = h,
6457                 };
6458                 smb2_close(tree, &cl);
6459         }
6460
6461         ret = true;
6462 done:
6463         return ret;
6464 }
6465
6466 struct torture_suite *torture_vfs_fruit_netatalk(TALLOC_CTX *ctx)
6467 {
6468         struct torture_suite *suite = torture_suite_create(
6469                 ctx, "fruit_netatalk");
6470
6471         suite->description = talloc_strdup(suite, "vfs_fruit tests for Netatalk interop that require fruit:metadata=netatalk");
6472
6473         torture_suite_add_1smb2_test(suite, "read netatalk metadata", test_read_netatalk_metadata);
6474         torture_suite_add_1smb2_test(suite, "stream names with locally created xattr", test_stream_names_local);
6475         torture_suite_add_2smb2_test(
6476                 suite, "locking conflict", test_fruit_locking_conflict);
6477
6478         return suite;
6479 }
6480
6481 struct torture_suite *torture_vfs_fruit_file_id(TALLOC_CTX *ctx)
6482 {
6483         struct torture_suite *suite =
6484             torture_suite_create(ctx, "fruit_file_id");
6485
6486         suite->description =
6487             talloc_strdup(suite, "vfs_fruit tests for on-disk file ID that "
6488                                  "require fruit:zero_file_id=yes");
6489
6490         torture_suite_add_1smb2_test(suite, "zero file id if AAPL negotiated",
6491                                      test_zero_file_id);
6492
6493         return suite;
6494 }
6495
6496 static bool test_timemachine_volsize(struct torture_context *tctx,
6497                                      struct smb2_tree *tree)
6498 {
6499         TALLOC_CTX *mem_ctx = talloc_new(tctx);
6500         struct smb2_handle h = {{0}};
6501         union smb_fsinfo fsinfo;
6502         NTSTATUS status;
6503         bool ok = true;
6504         const char *info_plist =
6505                 "<dict>\n"
6506                 "        <key>band-size</key>\n"
6507                 "        <integer>8192</integer>\n"
6508                 "</dict>\n";
6509
6510         smb2_deltree(tree, "test.sparsebundle");
6511
6512         ok = enable_aapl(tctx, tree);
6513         torture_assert_goto(tctx, ok, ok, done, "enable_aapl failed");
6514
6515         status = smb2_util_mkdir(tree, "test.sparsebundle");
6516         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
6517                                         "smb2_util_mkdir\n");
6518
6519         ok = write_stream(tree, __location__, tctx, mem_ctx,
6520                           "test.sparsebundle/Info.plist", NULL,
6521                            0, strlen(info_plist), info_plist);
6522         torture_assert_goto(tctx, ok, ok, done, "write_stream failed\n");
6523
6524         status = smb2_util_mkdir(tree, "test.sparsebundle/bands");
6525         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
6526                                         "smb2_util_mkdir\n");
6527
6528         ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/1", false);
6529         torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
6530
6531         ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/2", false);
6532         torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
6533
6534         status = smb2_util_roothandle(tree, &h);
6535         torture_assert_ntstatus_ok(tctx, status, "Unable to create root handle");
6536
6537         ZERO_STRUCT(fsinfo);
6538         fsinfo.generic.level = RAW_QFS_SIZE_INFORMATION;
6539         fsinfo.generic.handle = h;
6540
6541         status = smb2_getinfo_fs(tree, tree, &fsinfo);
6542         torture_assert_ntstatus_ok(tctx, status, "smb2_getinfo_fs failed");
6543
6544         torture_comment(tctx, "sectors_per_unit: %" PRIu32"\n"
6545                         "bytes_per_sector: %" PRIu32"\n"
6546                         "total_alloc_units: %" PRIu64"\n"
6547                         "avail_alloc_units: %" PRIu64"\n",
6548                         fsinfo.size_info.out.sectors_per_unit,
6549                         fsinfo.size_info.out.bytes_per_sector,
6550                         fsinfo.size_info.out.total_alloc_units,
6551                         fsinfo.size_info.out.avail_alloc_units);
6552
6553         /*
6554          * Let me explain the numbers:
6555          *
6556          * - the share is set to "fruit:time machine max size = 32K"
6557          * - we've faked a bandsize of 8 K in the Info.plist file
6558          * - we've created two bands files
6559          * - one allocation unit is made of two sectors with 512 B each
6560          * => we've consumed 16 allocation units, there should be 16 free
6561          */
6562
6563         torture_assert_goto(tctx, fsinfo.size_info.out.sectors_per_unit == 2,
6564                             ok, done, "Bad sectors_per_unit");
6565
6566         torture_assert_goto(tctx, fsinfo.size_info.out.bytes_per_sector == 512,
6567                             ok, done, "Bad bytes_per_sector");
6568
6569         torture_assert_goto(tctx, fsinfo.size_info.out.total_alloc_units == 32,
6570                             ok, done, "Bad total_alloc_units");
6571
6572         torture_assert_goto(tctx, fsinfo.size_info.out.avail_alloc_units == 16,
6573                             ok, done, "Bad avail_alloc_units");
6574
6575 done:
6576         if (!smb2_util_handle_empty(h)) {
6577                 smb2_util_close(tree, h);
6578         }
6579         smb2_deltree(tree, "test.sparsebundle");
6580         talloc_free(mem_ctx);
6581         return ok;
6582 }
6583
6584 struct torture_suite *torture_vfs_fruit_timemachine(TALLOC_CTX *ctx)
6585 {
6586         struct torture_suite *suite = torture_suite_create(
6587                 ctx, "fruit_timemachine");
6588
6589         suite->description = talloc_strdup(
6590                 suite, "vfs_fruit tests for TimeMachine");
6591
6592         torture_suite_add_1smb2_test(suite, "Timemachine-volsize",
6593                                      test_timemachine_volsize);
6594
6595         return suite;
6596 }
6597
6598 static bool test_convert_xattr_and_empty_rfork_then_delete(
6599         struct torture_context *tctx,
6600         struct smb2_tree *tree1,
6601         struct smb2_tree *tree2)
6602 {
6603         TALLOC_CTX *mem_ctx = talloc_new(tctx);
6604         const char *fname = BASEDIR "\\test_adouble_conversion";
6605         const char *adname = BASEDIR "/._test_adouble_conversion";
6606         const char *rfork = BASEDIR "\\test_adouble_conversion" AFPRESOURCE_STREAM_NAME;
6607         NTSTATUS status;
6608         struct smb2_handle testdirh;
6609         bool ret = true;
6610         const char *streams[] = {
6611                 "::$DATA",
6612                 AFPINFO_STREAM,
6613                 ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
6614                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
6615         };
6616         struct smb2_create create;
6617         struct smb2_find find;
6618         unsigned int count;
6619         union smb_search_data *d;
6620         bool delete_empty_adfiles;
6621         int expected_num_files;
6622
6623         delete_empty_adfiles = torture_setting_bool(tctx,
6624                                                     "delete_empty_adfiles",
6625                                                     false);
6626
6627         smb2_deltree(tree1, BASEDIR);
6628
6629         status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
6630         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6631                                         "torture_smb2_testdir failed\n");
6632         smb2_util_close(tree1, testdirh);
6633
6634         ret = torture_setup_file(tctx, tree1, fname, false);
6635         torture_assert_goto(tctx, ret == true, ret, done,
6636                             "torture_setup_file failed\n");
6637
6638         ret = torture_setup_file(tctx, tree1, adname, false);
6639         torture_assert_goto(tctx, ret == true, ret, done,
6640                             "torture_setup_file failed\n");
6641
6642         ret = write_stream(tree1, __location__, tctx, mem_ctx,
6643                            adname, NULL,
6644                            0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr);
6645         torture_assert_goto(tctx, ret == true, ret, done,
6646                             "write_stream failed\n");
6647
6648         ret = enable_aapl(tctx, tree2);
6649         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
6650
6651         /*
6652          * Issue a smb2_find(), this triggers the server-side conversion
6653          */
6654
6655         create = (struct smb2_create) {
6656                 .in.desired_access = SEC_RIGHTS_DIR_READ,
6657                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
6658                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
6659                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6660                 .in.create_disposition = NTCREATEX_DISP_OPEN,
6661                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6662                 .in.fname = BASEDIR,
6663         };
6664
6665         status = smb2_create(tree2, tctx, &create);
6666         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6667                                         "smb2_create failed\n");
6668
6669         find = (struct smb2_find) {
6670                 .in.file.handle = create.out.file.handle,
6671                 .in.pattern = "*",
6672                 .in.max_response_size = 0x1000,
6673                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
6674         };
6675
6676         status = smb2_find_level(tree2, tree2, &find, &count, &d);
6677         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6678                                         "smb2_find_level failed\n");
6679
6680         status = smb2_util_close(tree2, create.out.file.handle);
6681         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6682                                         "smb2_util_close failed");
6683
6684         /*
6685          * Check number of streams
6686          */
6687
6688         ret = check_stream_list(tree2, tctx, fname, 4, streams, false);
6689         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
6690
6691         /*
6692          * Check Resource Fork is gone
6693          */
6694
6695         create = (struct smb2_create) {
6696                 .in.desired_access = SEC_RIGHTS_FILE_READ|SEC_RIGHTS_FILE_WRITE,
6697                 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
6698                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6699                 .in.create_disposition = NTCREATEX_DISP_OPEN,
6700                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6701                 .in.fname = rfork,
6702         };
6703
6704         status = smb2_create(tree2, mem_ctx, &create);
6705         torture_assert_ntstatus_equal_goto(
6706                 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
6707                 ret, done, "Bad smb2_create return\n");
6708
6709         /*
6710          * Check xattr data has been migrated from the AppleDouble file to
6711          * streams.
6712          */
6713
6714         ret = check_stream(tree2, __location__, tctx, mem_ctx,
6715                            fname, AFPINFO_STREAM,
6716                            0, 60, 16, 8, "TESTSLOW");
6717         torture_assert_goto(tctx, ret == true, ret, done,
6718                             "check AFPINFO_STREAM failed\n");
6719
6720         ret = check_stream(tree2, __location__, tctx, mem_ctx,
6721                            fname, ":foo" "\xef\x80\xa2" "bar", /* foo:bar */
6722                            0, 3, 0, 3, "baz");
6723         torture_assert_goto(tctx, ret == true, ret, done,
6724                             "check foo stream failed\n");
6725
6726         /*
6727          * Now check number of files. If delete_empty_adfiles is set, the
6728          * AppleDouble files should have been deleted.
6729          */
6730
6731         create = (struct smb2_create) {
6732                 .in.desired_access = SEC_RIGHTS_DIR_READ,
6733                 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
6734                 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
6735                 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6736                 .in.create_disposition = NTCREATEX_DISP_OPEN,
6737                 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6738                 .in.fname = BASEDIR,
6739         };
6740
6741         status = smb2_create(tree2, tctx, &create);
6742         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6743                                         "smb2_create failed\n");
6744
6745         find = (struct smb2_find) {
6746                 .in.file.handle = create.out.file.handle,
6747                 .in.pattern = "*",
6748                 .in.max_response_size = 0x1000,
6749                 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
6750         };
6751
6752         status = smb2_find_level(tree2, tree2, &find, &count, &d);
6753         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6754                                         "smb2_find_level failed\n");
6755
6756         status = smb2_util_close(tree2, create.out.file.handle);
6757         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6758                                         "smb2_util_close failed");
6759
6760         if (delete_empty_adfiles) {
6761                 expected_num_files = 3;
6762         } else {
6763                 expected_num_files = 4;
6764         }
6765         torture_assert_int_equal_goto(tctx, count, expected_num_files, ret, done,
6766                                       "Wrong number of files\n");
6767
6768 done:
6769         smb2_deltree(tree1, BASEDIR);
6770         talloc_free(mem_ctx);
6771         return ret;
6772 }
6773
6774 struct torture_suite *torture_vfs_fruit_conversion(TALLOC_CTX *ctx)
6775 {
6776         struct torture_suite *suite = torture_suite_create(
6777                 ctx, "fruit_conversion");
6778
6779         suite->description = talloc_strdup(
6780                 suite, "vfs_fruit conversion tests");
6781
6782         torture_suite_add_2ns_smb2_test(
6783                 suite, "convert_xattr_and_empty_rfork_then_delete",
6784                 test_convert_xattr_and_empty_rfork_then_delete);
6785
6786         return suite;
6787 }