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