s4:torture/vfs/fruit: decrease large resource fork size in test from 1 GB to 64 MB
[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  * talloc and intialize an AfpInfo
891  **/
892 static AfpInfo *torture_afpinfo_new(TALLOC_CTX *mem_ctx)
893 {
894         AfpInfo *info;
895
896         info = talloc_zero(mem_ctx, AfpInfo);
897         if (info == NULL) {
898                 return NULL;
899         }
900
901         info->afpi_Signature = AFP_Signature;
902         info->afpi_Version = AFP_Version;
903         info->afpi_BackupTime = AFP_BackupTime;
904
905         return info;
906 }
907
908 /**
909  * Pack AfpInfo into a talloced buffer
910  **/
911 static char *torture_afpinfo_pack(TALLOC_CTX *mem_ctx,
912                                   AfpInfo *info)
913 {
914         char *buf;
915
916         buf = talloc_zero_array(mem_ctx, char, AFP_INFO_SIZE);
917         if (buf == NULL) {
918                 return NULL;
919         }
920
921         RSIVAL(buf, 0, info->afpi_Signature);
922         RSIVAL(buf, 4, info->afpi_Version);
923         RSIVAL(buf, 12, info->afpi_BackupTime);
924         memcpy(buf + 16, info->afpi_FinderInfo, sizeof(info->afpi_FinderInfo));
925
926         return buf;
927 }
928
929 /**
930  * Unpack AfpInfo
931  **/
932 #if 0
933 static void torture_afpinfo_unpack(AfpInfo *info, char *data)
934 {
935         info->afpi_Signature = RIVAL(data, 0);
936         info->afpi_Version = RIVAL(data, 4);
937         info->afpi_BackupTime = RIVAL(data, 12);
938         memcpy(info->afpi_FinderInfo, (const char *)data + 16,
939                sizeof(info->afpi_FinderInfo));
940 }
941 #endif
942
943 static bool torture_write_afpinfo(struct smb2_tree *tree,
944                                   struct torture_context *tctx,
945                                   TALLOC_CTX *mem_ctx,
946                                   const char *fname,
947                                   AfpInfo *info)
948 {
949         struct smb2_handle handle;
950         struct smb2_create io;
951         NTSTATUS status;
952         const char *full_name;
953         char *infobuf;
954         bool ret = true;
955
956         full_name = talloc_asprintf(mem_ctx, "%s%s", fname, AFPINFO_STREAM_NAME);
957         if (full_name == NULL) {
958             torture_comment(tctx, "talloc_asprintf error\n");
959             return false;
960         }
961         ZERO_STRUCT(io);
962         io.in.desired_access = SEC_FILE_WRITE_DATA;
963         io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
964         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
965         io.in.create_options = 0;
966         io.in.fname = full_name;
967
968         status = smb2_create(tree, mem_ctx, &io);
969         CHECK_STATUS(status, NT_STATUS_OK);
970
971         handle = io.out.file.handle;
972
973         infobuf = torture_afpinfo_pack(mem_ctx, info);
974         if (infobuf == NULL) {
975                 return false;
976         }
977
978         status = smb2_util_write(tree, handle, infobuf, 0, AFP_INFO_SIZE);
979         CHECK_STATUS(status, NT_STATUS_OK);
980
981         smb2_util_close(tree, handle);
982
983 done:
984         return ret;
985 }
986
987 /**
988  * Read 'count' bytes at 'offset' from stream 'fname:sname' and
989  * compare against buffer 'value'
990  **/
991 static bool check_stream(struct smb2_tree *tree,
992                          const char *location,
993                          struct torture_context *tctx,
994                          TALLOC_CTX *mem_ctx,
995                          const char *fname,
996                          const char *sname,
997                          off_t read_offset,
998                          size_t read_count,
999                          off_t comp_offset,
1000                          size_t comp_count,
1001                          const char *value)
1002 {
1003         struct smb2_handle handle;
1004         struct smb2_create create;
1005         struct smb2_read r;
1006         NTSTATUS status;
1007         char *full_name;
1008         bool ret = true;
1009
1010         full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
1011         if (full_name == NULL) {
1012             torture_comment(tctx, "talloc_asprintf error\n");
1013             return false;
1014         }
1015         ZERO_STRUCT(create);
1016         create.in.desired_access = SEC_FILE_READ_DATA;
1017         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1018         create.in.create_disposition = NTCREATEX_DISP_OPEN;
1019         create.in.fname = full_name;
1020
1021         torture_comment(tctx, "Open stream %s\n", full_name);
1022
1023         status = smb2_create(tree, mem_ctx, &create);
1024         if (!NT_STATUS_IS_OK(status)) {
1025                 TALLOC_FREE(full_name);
1026                 if (value == NULL) {
1027                         return true;
1028                 }
1029                 torture_comment(tctx, "Unable to open stream %s\n", full_name);
1030                 return false;
1031         }
1032
1033         handle = create.out.file.handle;
1034         if (value == NULL) {
1035                 TALLOC_FREE(full_name);
1036                 smb2_util_close(tree, handle);
1037                 return true;
1038         }
1039
1040         ZERO_STRUCT(r);
1041         r.in.file.handle = handle;
1042         r.in.length      = read_count;
1043         r.in.offset      = read_offset;
1044
1045         status = smb2_read(tree, tree, &r);
1046
1047         torture_assert_ntstatus_ok_goto(
1048                 tctx, status, ret, done,
1049                 talloc_asprintf(tctx, "(%s) Failed to read %lu bytes from stream '%s'\n",
1050                                 location, (long)strlen(value), full_name));
1051
1052         torture_assert_goto(tctx, r.out.data.length == read_count, ret, done,
1053                             talloc_asprintf(tctx, "smb2_read returned %jd bytes, expected %jd\n",
1054                                             (intmax_t)r.out.data.length, (intmax_t)read_count));
1055
1056         torture_assert_goto(
1057                 tctx, memcmp(r.out.data.data + comp_offset, value, comp_count) == 0,
1058                 ret, done,
1059                 talloc_asprintf(tctx, "(%s) Bad data in stream\n", location));
1060
1061 done:
1062         TALLOC_FREE(full_name);
1063         smb2_util_close(tree, handle);
1064         return ret;
1065 }
1066
1067 /**
1068  * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1069  * compare against buffer 'value'
1070  **/
1071 static ssize_t read_stream(struct smb2_tree *tree,
1072                            const char *location,
1073                            struct torture_context *tctx,
1074                            TALLOC_CTX *mem_ctx,
1075                            const char *fname,
1076                            const char *sname,
1077                            off_t read_offset,
1078                            size_t read_count)
1079 {
1080         struct smb2_handle handle;
1081         struct smb2_create create;
1082         struct smb2_read r;
1083         NTSTATUS status;
1084         const char *full_name;
1085         bool ret = true;
1086
1087         full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
1088         if (full_name == NULL) {
1089             torture_comment(tctx, "talloc_asprintf error\n");
1090             return -1;
1091         }
1092         ZERO_STRUCT(create);
1093         create.in.desired_access = SEC_FILE_READ_DATA;
1094         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1095         create.in.create_disposition = NTCREATEX_DISP_OPEN;
1096         create.in.fname = full_name;
1097
1098         torture_comment(tctx, "Open stream %s\n", full_name);
1099
1100         status = smb2_create(tree, mem_ctx, &create);
1101         if (!NT_STATUS_IS_OK(status)) {
1102                 torture_comment(tctx, "Unable to open stream %s\n",
1103                                 full_name);
1104                 return -1;
1105         }
1106
1107         handle = create.out.file.handle;
1108
1109         ZERO_STRUCT(r);
1110         r.in.file.handle = handle;
1111         r.in.length      = read_count;
1112         r.in.offset      = read_offset;
1113
1114         status = smb2_read(tree, tree, &r);
1115         if (!NT_STATUS_IS_OK(status)) {
1116                 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
1117         }
1118
1119         smb2_util_close(tree, handle);
1120
1121 done:
1122         if (ret == false) {
1123                 return -1;
1124         }
1125         return r.out.data.length;
1126 }
1127
1128 /**
1129  * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1130  * compare against buffer 'value'
1131  **/
1132 static bool write_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 offset,
1139                          size_t size,
1140                          const char *value)
1141 {
1142         struct smb2_handle handle;
1143         struct smb2_create create;
1144         NTSTATUS status;
1145         const char *full_name;
1146
1147         full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname ? sname : "");
1148         if (full_name == NULL) {
1149             torture_comment(tctx, "talloc_asprintf error\n");
1150             return false;
1151         }
1152         ZERO_STRUCT(create);
1153         create.in.desired_access = SEC_FILE_WRITE_DATA;
1154         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1155         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1156         create.in.fname = full_name;
1157
1158         status = smb2_create(tree, mem_ctx, &create);
1159         if (!NT_STATUS_IS_OK(status)) {
1160                 if (value == NULL) {
1161                         return true;
1162                 } else {
1163                         torture_comment(tctx, "Unable to open stream %s\n",
1164                             full_name);
1165                         sleep(10000000);
1166                         return false;
1167                 }
1168         }
1169
1170         handle = create.out.file.handle;
1171         if (value == NULL) {
1172                 return true;
1173         }
1174
1175         status = smb2_util_write(tree, handle, value, offset, size);
1176
1177         if (!NT_STATUS_IS_OK(status)) {
1178                 torture_comment(tctx, "(%s) Failed to write %lu bytes to "
1179                     "stream '%s'\n", location, (long)size, full_name);
1180                 return false;
1181         }
1182
1183         smb2_util_close(tree, handle);
1184         return true;
1185 }
1186
1187 static bool torture_setup_local_xattr(struct torture_context *tctx,
1188                                       const char *path_option,
1189                                       const char *name,
1190                                       const char *xattr,
1191                                       const char *metadata,
1192                                       size_t size)
1193 {
1194         int ret = true;
1195         int result;
1196         const char *spath;
1197         char *path;
1198
1199         spath = torture_setting_string(tctx, path_option, NULL);
1200         if (spath == NULL) {
1201                 printf("No sharepath for option %s\n", path_option);
1202                 return false;
1203         }
1204
1205         path = talloc_asprintf(tctx, "%s/%s", spath, name);
1206
1207         result = setxattr(path, xattr, metadata, size, 0);
1208         if (result != 0) {
1209                 ret = false;
1210         }
1211
1212         TALLOC_FREE(path);
1213
1214         return ret;
1215 }
1216
1217 /**
1218  * Create a file or directory
1219  **/
1220 static bool torture_setup_file(TALLOC_CTX *mem_ctx, struct smb2_tree *tree,
1221                                const char *name, bool dir)
1222 {
1223         struct smb2_create io;
1224         NTSTATUS status;
1225
1226         smb2_util_unlink(tree, name);
1227         ZERO_STRUCT(io);
1228         io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1229         io.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
1230         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1231         io.in.share_access =
1232                 NTCREATEX_SHARE_ACCESS_DELETE|
1233                 NTCREATEX_SHARE_ACCESS_READ|
1234                 NTCREATEX_SHARE_ACCESS_WRITE;
1235         io.in.create_options = 0;
1236         io.in.fname = name;
1237         if (dir) {
1238                 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1239                 io.in.share_access &= ~NTCREATEX_SHARE_ACCESS_DELETE;
1240                 io.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
1241                 io.in.create_disposition = NTCREATEX_DISP_CREATE;
1242         }
1243
1244         status = smb2_create(tree, mem_ctx, &io);
1245         if (!NT_STATUS_IS_OK(status)) {
1246                 return false;
1247         }
1248
1249         status = smb2_util_close(tree, io.out.file.handle);
1250         if (!NT_STATUS_IS_OK(status)) {
1251                 return false;
1252         }
1253
1254         return true;
1255 }
1256
1257 static bool enable_aapl(struct torture_context *tctx,
1258                         struct smb2_tree *tree)
1259 {
1260         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1261         NTSTATUS status;
1262         bool ret = true;
1263         struct smb2_create io;
1264         DATA_BLOB data;
1265         struct smb2_create_blob *aapl = NULL;
1266         uint32_t aapl_server_caps;
1267         uint32_t expected_scaps = (SMB2_CRTCTX_AAPL_UNIX_BASED |
1268                                    SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
1269                                    SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
1270                                    SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
1271         bool is_osx_server = torture_setting_bool(tctx, "osx", false);
1272
1273         ZERO_STRUCT(io);
1274         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
1275         io.in.file_attributes    = FILE_ATTRIBUTE_DIRECTORY;
1276         io.in.create_disposition = NTCREATEX_DISP_OPEN;
1277         io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
1278                               NTCREATEX_SHARE_ACCESS_READ |
1279                               NTCREATEX_SHARE_ACCESS_WRITE);
1280         io.in.fname = "";
1281
1282         /*
1283          * Issuing an SMB2/CREATE with a suitably formed AAPL context,
1284          * controls behaviour of Apple's SMB2 extensions for the whole
1285          * session!
1286          */
1287
1288         data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
1289         SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
1290         SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
1291                              SMB2_CRTCTX_AAPL_VOLUME_CAPS |
1292                              SMB2_CRTCTX_AAPL_MODEL_INFO));
1293         SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
1294                               SMB2_CRTCTX_AAPL_UNIX_BASED |
1295                               SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
1296
1297         status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
1298         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_blob_add");
1299
1300         status = smb2_create(tree, tctx, &io);
1301         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1302
1303         status = smb2_util_close(tree, io.out.file.handle);
1304         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close");
1305
1306         /*
1307          * Now check returned AAPL context
1308          */
1309         torture_comment(tctx, "Comparing returned AAPL capabilities\n");
1310
1311         aapl = smb2_create_blob_find(&io.out.blobs,
1312                                      SMB2_CREATE_TAG_AAPL);
1313         torture_assert_goto(tctx, aapl != NULL, ret, done, "missing AAPL context");
1314
1315         if (!is_osx_server) {
1316                 size_t expected_aapl_ctx_size;
1317
1318                 expected_aapl_ctx_size = strlen("MacSamba") * 2 + 40;
1319
1320                 torture_assert_goto(
1321                         tctx, aapl->data.length == expected_aapl_ctx_size,
1322                         ret, done, "bad AAPL size");
1323         }
1324
1325         aapl_server_caps = BVAL(aapl->data.data, 16);
1326         torture_assert_goto(tctx, aapl_server_caps == expected_scaps,
1327                             ret, done, "bad AAPL caps");
1328
1329 done:
1330         talloc_free(mem_ctx);
1331         return ret;
1332 }
1333
1334 static bool test_read_netatalk_metadata(struct torture_context *tctx,
1335                                         struct smb2_tree *tree)
1336 {
1337         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1338         const char *fname = BASEDIR "\\torture_read_metadata";
1339         NTSTATUS status;
1340         struct smb2_handle testdirh;
1341         bool ret = true;
1342         ssize_t len;
1343         const char *localdir = NULL;
1344
1345         torture_comment(tctx, "Checking metadata access\n");
1346
1347         localdir = torture_setting_string(tctx, "localdir", NULL);
1348         if (localdir == NULL) {
1349                 torture_skip(tctx, "Need localdir for test");
1350         }
1351
1352         smb2_util_unlink(tree, fname);
1353
1354         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1355         CHECK_STATUS(status, NT_STATUS_OK);
1356         smb2_util_close(tree, testdirh);
1357
1358         ret = torture_setup_file(mem_ctx, tree, fname, false);
1359         if (ret == false) {
1360                 goto done;
1361         }
1362
1363         ret = torture_setup_local_xattr(tctx, "localdir",
1364                                         BASEDIR "/torture_read_metadata",
1365                                         AFPINFO_EA_NETATALK,
1366                                         metadata_xattr, sizeof(metadata_xattr));
1367         if (ret == false) {
1368                 goto done;
1369         }
1370
1371         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1372                            0, 60, 0, 4, "AFP");
1373         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1374
1375         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1376                            0, 60, 16, 8, "BARRFOOO");
1377         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1378
1379         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1380                            16, 8, 0, 3, "AFP");
1381         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1382
1383         /* Check reading offset and read size > sizeof(AFPINFO_STREAM) */
1384
1385         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1386                           AFPINFO_STREAM, 0, 61);
1387         CHECK_VALUE(len, 60);
1388
1389         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1390                           AFPINFO_STREAM, 59, 2);
1391         CHECK_VALUE(len, 2);
1392
1393         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1394                           AFPINFO_STREAM, 60, 1);
1395         CHECK_VALUE(len, 1);
1396
1397         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1398                           AFPINFO_STREAM, 61, 1);
1399         CHECK_VALUE(len, 0);
1400
1401 done:
1402         smb2_deltree(tree, BASEDIR);
1403         talloc_free(mem_ctx);
1404         return ret;
1405 }
1406
1407 static bool test_read_afpinfo(struct torture_context *tctx,
1408                               struct smb2_tree *tree)
1409 {
1410         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1411         const char *fname = BASEDIR "\\torture_read_metadata";
1412         NTSTATUS status;
1413         struct smb2_handle testdirh;
1414         bool ret = true;
1415         ssize_t len;
1416         AfpInfo *info;
1417         const char *type_creator = "SMB,OLE!";
1418
1419         torture_comment(tctx, "Checking metadata access\n");
1420
1421         smb2_util_unlink(tree, fname);
1422
1423         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1424         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
1425         smb2_util_close(tree, testdirh);
1426
1427         ret = torture_setup_file(mem_ctx, tree, fname, false);
1428         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
1429
1430         info = torture_afpinfo_new(mem_ctx);
1431         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
1432
1433         memcpy(info->afpi_FinderInfo, type_creator, 8);
1434         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
1435         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
1436
1437         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1438                            0, 60, 0, 4, "AFP");
1439         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1440
1441         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1442                            0, 60, 16, 8, type_creator);
1443         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1444
1445         /*
1446          * OS X ignores offset <= 60 and treats the as
1447          * offset=0. Reading from offsets > 60 returns EOF=0.
1448          */
1449
1450         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1451                            16, 8, 0, 8, "AFP\0\0\0\001\0");
1452         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1453
1454         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1455                           AFPINFO_STREAM, 0, 61);
1456         torture_assert_goto(tctx, len == 60, ret, done, "read_stream failed");
1457
1458         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1459                           AFPINFO_STREAM, 59, 2);
1460         torture_assert_goto(tctx, len == 2, ret, done, "read_stream failed");
1461
1462         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1463                            59, 2, 0, 2, "AF");
1464         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1465
1466         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1467                           AFPINFO_STREAM, 60, 1);
1468         torture_assert_goto(tctx, len == 1, ret, done, "read_stream failed");
1469
1470         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1471                            60, 1, 0, 1, "A");
1472         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1473
1474         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1475                           AFPINFO_STREAM, 61, 1);
1476         torture_assert_goto(tctx, len == 0, ret, done, "read_stream failed");
1477
1478 done:
1479         smb2_util_unlink(tree, fname);
1480         smb2_deltree(tree, BASEDIR);
1481         talloc_free(mem_ctx);
1482         return ret;
1483 }
1484
1485 static bool test_write_atalk_metadata(struct torture_context *tctx,
1486                                       struct smb2_tree *tree)
1487 {
1488         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1489         const char *fname = BASEDIR "\\torture_write_metadata";
1490         const char *type_creator = "SMB,OLE!";
1491         NTSTATUS status;
1492         struct smb2_handle testdirh;
1493         bool ret = true;
1494         AfpInfo *info;
1495
1496         smb2_deltree(tree, BASEDIR);
1497         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1498         CHECK_STATUS(status, NT_STATUS_OK);
1499         smb2_util_close(tree, testdirh);
1500
1501         ret = torture_setup_file(mem_ctx, tree, fname, false);
1502         if (ret == false) {
1503                 goto done;
1504         }
1505
1506         info = torture_afpinfo_new(mem_ctx);
1507         if (info == NULL) {
1508                 goto done;
1509         }
1510
1511         memcpy(info->afpi_FinderInfo, type_creator, 8);
1512         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
1513         ret &= check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1514                             0, 60, 16, 8, type_creator);
1515
1516 done:
1517         smb2_util_unlink(tree, fname);
1518         smb2_deltree(tree, BASEDIR);
1519         talloc_free(mem_ctx);
1520         return ret;
1521 }
1522
1523 static bool test_write_atalk_rfork_io(struct torture_context *tctx,
1524                                       struct smb2_tree *tree)
1525 {
1526         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1527         const char *fname = BASEDIR "\\torture_write_rfork_io";
1528         const char *rfork = BASEDIR "\\torture_write_rfork_io" AFPRESOURCE_STREAM_NAME;
1529         const char *rfork_content = "1234567890";
1530         NTSTATUS status;
1531         struct smb2_handle testdirh;
1532         bool ret = true;
1533
1534         union smb_open io;
1535         struct smb2_handle filehandle;
1536         union smb_fileinfo finfo;
1537         union smb_setfileinfo sinfo;
1538
1539         smb2_util_unlink(tree, fname);
1540
1541         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1542         CHECK_STATUS(status, NT_STATUS_OK);
1543         smb2_util_close(tree, testdirh);
1544
1545         ret = torture_setup_file(mem_ctx, tree, fname, false);
1546         if (ret == false) {
1547                 goto done;
1548         }
1549
1550         torture_comment(tctx, "(%s) writing to resource fork\n",
1551             __location__);
1552
1553         ret &= write_stream(tree, __location__, tctx, mem_ctx,
1554                             fname, AFPRESOURCE_STREAM_NAME,
1555                             10, 10, rfork_content);
1556
1557         ret &= check_stream(tree, __location__, tctx, mem_ctx,
1558                             fname, AFPRESOURCE_STREAM_NAME,
1559                             0, 20, 10, 10, rfork_content);
1560
1561         /* Check size after write */
1562
1563         ZERO_STRUCT(io);
1564         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1565         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1566                 SEC_FILE_WRITE_ATTRIBUTE;
1567         io.smb2.in.fname = rfork;
1568         status = smb2_create(tree, mem_ctx, &(io.smb2));
1569         CHECK_STATUS(status, NT_STATUS_OK);
1570         filehandle = io.smb2.out.file.handle;
1571
1572         torture_comment(tctx, "(%s) check resource fork size after write\n",
1573             __location__);
1574
1575         ZERO_STRUCT(finfo);
1576         finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1577         finfo.generic.in.file.handle = filehandle;
1578         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1579         CHECK_STATUS(status, NT_STATUS_OK);
1580         if (finfo.all_info.out.size != 20) {
1581                 torture_result(tctx, TORTURE_FAIL,
1582                                "(%s) Incorrect resource fork size\n",
1583                                __location__);
1584                 ret = false;
1585                 smb2_util_close(tree, filehandle);
1586                 goto done;
1587         }
1588         smb2_util_close(tree, filehandle);
1589
1590         /* Write at large offset */
1591
1592         torture_comment(tctx, "(%s) writing to resource fork at large offset\n",
1593                         __location__);
1594
1595         ret &= write_stream(tree, __location__, tctx, mem_ctx,
1596                             fname, AFPRESOURCE_STREAM_NAME,
1597                             (off_t)64*1024*1024, 10, rfork_content);
1598
1599         ret &= check_stream(tree, __location__, tctx, mem_ctx,
1600                             fname, AFPRESOURCE_STREAM_NAME,
1601                             (off_t)64*1024*1024, 10, 0, 10, rfork_content);
1602
1603         /* Truncate back to size of 1 byte */
1604
1605         torture_comment(tctx, "(%s) truncate resource fork and check size\n",
1606                         __location__);
1607
1608         ZERO_STRUCT(io);
1609         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1610         io.smb2.in.desired_access = SEC_FILE_ALL;
1611         io.smb2.in.fname = rfork;
1612         status = smb2_create(tree, mem_ctx, &(io.smb2));
1613         CHECK_STATUS(status, NT_STATUS_OK);
1614         filehandle = io.smb2.out.file.handle;
1615
1616         ZERO_STRUCT(sinfo);
1617         sinfo.end_of_file_info.level =
1618                 RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1619         sinfo.end_of_file_info.in.file.handle = filehandle;
1620         sinfo.end_of_file_info.in.size = 1;
1621         status = smb2_setinfo_file(tree, &sinfo);
1622         CHECK_STATUS(status, NT_STATUS_OK);
1623
1624         smb2_util_close(tree, filehandle);
1625
1626         /* Now check size */
1627         ZERO_STRUCT(io);
1628         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1629         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1630                 SEC_FILE_WRITE_ATTRIBUTE;
1631         io.smb2.in.fname = rfork;
1632         status = smb2_create(tree, mem_ctx, &(io.smb2));
1633         CHECK_STATUS(status, NT_STATUS_OK);
1634         filehandle = io.smb2.out.file.handle;
1635
1636         ZERO_STRUCT(finfo);
1637         finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1638         finfo.generic.in.file.handle = filehandle;
1639         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1640         CHECK_STATUS(status, NT_STATUS_OK);
1641         if (finfo.all_info.out.size != 1) {
1642                 torture_result(tctx, TORTURE_FAIL,
1643                                "(%s) Incorrect resource fork size\n",
1644                                __location__);
1645                 ret = false;
1646                 smb2_util_close(tree, filehandle);
1647                 goto done;
1648         }
1649         smb2_util_close(tree, filehandle);
1650
1651 done:
1652         smb2_util_unlink(tree, fname);
1653         smb2_deltree(tree, BASEDIR);
1654         talloc_free(mem_ctx);
1655         return ret;
1656 }
1657
1658 static bool test_rfork_truncate(struct torture_context *tctx,
1659                                 struct smb2_tree *tree)
1660 {
1661         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1662         const char *fname = BASEDIR "\\torture_rfork_truncate";
1663         const char *rfork = BASEDIR "\\torture_rfork_truncate" AFPRESOURCE_STREAM;
1664         const char *rfork_content = "1234567890";
1665         NTSTATUS status;
1666         struct smb2_handle testdirh;
1667         bool ret = true;
1668         struct smb2_create create;
1669         struct smb2_handle fh1, fh2, fh3;
1670         union smb_setfileinfo sinfo;
1671
1672         smb2_util_unlink(tree, fname);
1673
1674         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1675         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1676         smb2_util_close(tree, testdirh);
1677
1678         ret = torture_setup_file(mem_ctx, tree, fname, false);
1679         if (ret == false) {
1680                 goto done;
1681         }
1682
1683         ret &= write_stream(tree, __location__, tctx, mem_ctx,
1684                             fname, AFPRESOURCE_STREAM,
1685                             10, 10, rfork_content);
1686
1687         /* Truncate back to size 0, further access MUST return ENOENT */
1688
1689         torture_comment(tctx, "(%s) truncate resource fork to size 0\n",
1690                         __location__);
1691
1692         ZERO_STRUCT(create);
1693         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1694         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1695         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1696         create.in.fname               = fname;
1697         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1698                 NTCREATEX_SHARE_ACCESS_READ |
1699                 NTCREATEX_SHARE_ACCESS_WRITE;
1700         status = smb2_create(tree, mem_ctx, &create);
1701         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1702         fh1 = create.out.file.handle;
1703
1704         ZERO_STRUCT(create);
1705         create.in.create_disposition  = NTCREATEX_DISP_OPEN_IF;
1706         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1707         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1708         create.in.fname               = rfork;
1709         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1710                 NTCREATEX_SHARE_ACCESS_READ |
1711                 NTCREATEX_SHARE_ACCESS_WRITE;
1712         status = smb2_create(tree, mem_ctx, &create);
1713         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1714         fh2 = create.out.file.handle;
1715
1716         ZERO_STRUCT(sinfo);
1717         sinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1718         sinfo.end_of_file_info.in.file.handle = fh2;
1719         sinfo.end_of_file_info.in.size = 0;
1720         status = smb2_setinfo_file(tree, &sinfo);
1721         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file");
1722
1723         /*
1724          * Now check size, we should get OBJECT_NAME_NOT_FOUND (!)
1725          */
1726         ZERO_STRUCT(create);
1727         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1728         create.in.desired_access      = SEC_FILE_ALL;
1729         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1730         create.in.fname               = rfork;
1731         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1732                 NTCREATEX_SHARE_ACCESS_READ |
1733                 NTCREATEX_SHARE_ACCESS_WRITE;
1734         status = smb2_create(tree, mem_ctx, &create);
1735         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1736
1737         /*
1738          * Do another open on the rfork and write to the new handle. A
1739          * naive server might unlink the AppleDouble resource fork
1740          * file when its truncated to 0 bytes above, so in case both
1741          * open handles share the same underlying fd, the unlink would
1742          * cause the below write to be lost.
1743          */
1744         ZERO_STRUCT(create);
1745         create.in.create_disposition  = NTCREATEX_DISP_OPEN_IF;
1746         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1747         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1748         create.in.fname               = rfork;
1749         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1750                 NTCREATEX_SHARE_ACCESS_READ |
1751                 NTCREATEX_SHARE_ACCESS_WRITE;
1752         status = smb2_create(tree, mem_ctx, &create);
1753         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1754         fh3 = create.out.file.handle;
1755
1756         status = smb2_util_write(tree, fh3, "foo", 0, 3);
1757         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write");
1758
1759         smb2_util_close(tree, fh3);
1760         smb2_util_close(tree, fh2);
1761         smb2_util_close(tree, fh1);
1762
1763         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM,
1764                            0, 3, 0, 3, "foo");
1765         torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
1766
1767 done:
1768         smb2_util_unlink(tree, fname);
1769         smb2_deltree(tree, BASEDIR);
1770         talloc_free(mem_ctx);
1771         return ret;
1772 }
1773
1774 static bool test_rfork_create(struct torture_context *tctx,
1775                               struct smb2_tree *tree)
1776 {
1777         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1778         const char *fname = BASEDIR "\\torture_rfork_create";
1779         const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
1780         NTSTATUS status;
1781         struct smb2_handle testdirh;
1782         bool ret = true;
1783         struct smb2_create create;
1784         struct smb2_handle fh1;
1785         const char *streams[] = {
1786                 "::$DATA"
1787         };
1788         union smb_fileinfo finfo;
1789
1790         smb2_util_unlink(tree, fname);
1791
1792         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1793         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1794         smb2_util_close(tree, testdirh);
1795
1796         ret = torture_setup_file(mem_ctx, tree, fname, false);
1797         if (ret == false) {
1798                 goto done;
1799         }
1800
1801         torture_comment(tctx, "(%s) open rfork, should return ENOENT\n",
1802                         __location__);
1803
1804         ZERO_STRUCT(create);
1805         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1806         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1807         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1808         create.in.fname               = rfork;
1809         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1810                 NTCREATEX_SHARE_ACCESS_READ |
1811                 NTCREATEX_SHARE_ACCESS_WRITE;
1812         status = smb2_create(tree, mem_ctx, &create);
1813         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1814
1815         torture_comment(tctx, "(%s) create resource fork\n", __location__);
1816
1817         ZERO_STRUCT(create);
1818         create.in.create_disposition  = NTCREATEX_DISP_OPEN_IF;
1819         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1820         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1821         create.in.fname               = rfork;
1822         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1823                 NTCREATEX_SHARE_ACCESS_READ |
1824                 NTCREATEX_SHARE_ACCESS_WRITE;
1825         status = smb2_create(tree, mem_ctx, &create);
1826         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1827         fh1 = create.out.file.handle;
1828
1829         torture_comment(tctx, "(%s) getinfo on create handle\n",
1830                         __location__);
1831
1832         ZERO_STRUCT(finfo);
1833         finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1834         finfo.generic.in.file.handle = fh1;
1835         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1836         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file");
1837         if (finfo.all_info.out.size != 0) {
1838                 torture_result(tctx, TORTURE_FAIL,
1839                                "(%s) Incorrect resource fork size\n",
1840                                __location__);
1841                 ret = false;
1842                 smb2_util_close(tree, fh1);
1843                 goto done;
1844         }
1845
1846         torture_comment(tctx, "(%s) open rfork, should still return ENOENT\n",
1847                         __location__);
1848
1849         ZERO_STRUCT(create);
1850         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1851         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1852         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1853         create.in.fname               = rfork;
1854         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1855                 NTCREATEX_SHARE_ACCESS_READ |
1856                 NTCREATEX_SHARE_ACCESS_WRITE;
1857         status = smb2_create(tree, mem_ctx, &create);
1858         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1859
1860         ret = check_stream_list(tree, tctx, fname, 1, streams, false);
1861         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
1862
1863         torture_comment(tctx, "(%s) close empty created rfork, open should return ENOENT\n",
1864                         __location__);
1865
1866         ZERO_STRUCT(create);
1867         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1868         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1869         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1870         create.in.fname               = rfork;
1871         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1872                 NTCREATEX_SHARE_ACCESS_READ |
1873                 NTCREATEX_SHARE_ACCESS_WRITE;
1874         status = smb2_create(tree, mem_ctx, &create);
1875         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1876
1877 done:
1878         smb2_util_unlink(tree, fname);
1879         smb2_deltree(tree, BASEDIR);
1880         talloc_free(mem_ctx);
1881         return ret;
1882 }
1883
1884 static bool test_rfork_create_ro(struct torture_context *tctx,
1885                                  struct smb2_tree *tree)
1886 {
1887         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1888         const char *fname = BASEDIR "\\torture_rfork_create";
1889         const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
1890         NTSTATUS status;
1891         struct smb2_handle testdirh;
1892         bool ret = true;
1893         struct smb2_create create;
1894
1895         smb2_util_unlink(tree, fname);
1896         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1897         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1898                 "torture_smb2_testdir\n");
1899         smb2_util_close(tree, testdirh);
1900
1901         ret = torture_setup_file(mem_ctx, tree, fname, false);
1902         if (ret == false) {
1903                 goto done;
1904         }
1905
1906         torture_comment(tctx, "(%s) Try opening read-only with "
1907                         "open_if create disposition, should return ENOENT\n",
1908                         __location__);
1909
1910         ZERO_STRUCT(create);
1911         create.in.fname = rfork;
1912         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1913         create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
1914         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1915         create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
1916         status = smb2_create(tree, mem_ctx, &(create));
1917         torture_assert_ntstatus_equal_goto(tctx, status,
1918                                         NT_STATUS_OBJECT_NAME_NOT_FOUND,
1919                                         ret, done, "smb2_create failed\n");
1920
1921         torture_comment(tctx, "(%s) Now write something to the "
1922                         "rsrc stream, then the same open should succeed\n",
1923                         __location__);
1924
1925         ret = write_stream(tree, __location__, tctx, mem_ctx,
1926                            fname, AFPRESOURCE_STREAM_NAME,
1927                            0, 3, "foo");
1928         torture_assert_goto(tctx, ret == true, ret, done,
1929                         "write_stream failed\n");
1930
1931         ret = check_stream(tree, __location__, tctx, mem_ctx,
1932                            fname, AFPRESOURCE_STREAM,
1933                            0, 3, 0, 3, "foo");
1934         torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
1935
1936         ZERO_STRUCT(create);
1937         create.in.fname = rfork;
1938         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1939         create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
1940         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1941         create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
1942         status = smb2_create(tree, mem_ctx, &(create));
1943         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1944                 "smb2_create failed\n");
1945
1946         smb2_util_close(tree, create.out.file.handle);
1947
1948 done:
1949         smb2_util_unlink(tree, fname);
1950         smb2_deltree(tree, BASEDIR);
1951         talloc_free(mem_ctx);
1952         return ret;
1953 }
1954
1955 static bool test_adouble_conversion(struct torture_context *tctx,
1956                                     struct smb2_tree *tree)
1957 {
1958         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1959         const char *fname = BASEDIR "\\test_adouble_conversion";
1960         const char *adname = BASEDIR "/._test_adouble_conversion";
1961         NTSTATUS status;
1962         struct smb2_handle testdirh;
1963         bool ret = true;
1964         const char *data = "This resource fork intentionally left blank";
1965         size_t datalen = strlen(data);
1966         const char *streams[] = {
1967                 "::$DATA",
1968                 AFPINFO_STREAM,
1969                 AFPRESOURCE_STREAM,
1970                 ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
1971                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
1972         };
1973
1974         smb2_deltree(tree, BASEDIR);
1975
1976         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1977         CHECK_STATUS(status, NT_STATUS_OK);
1978         smb2_util_close(tree, testdirh);
1979
1980         ret = torture_setup_file(tctx, tree, fname, false);
1981         torture_assert_goto(tctx, ret == true, ret, done,
1982                             "torture_setup_file failed\n");
1983
1984         ret = torture_setup_file(tctx, tree, adname, false);
1985         torture_assert_goto(tctx, ret == true, ret, done,
1986                             "torture_setup_file failed\n");
1987
1988         ret = write_stream(tree, __location__, tctx, mem_ctx,
1989                            adname, NULL,
1990                            0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr);
1991         torture_assert_goto(tctx, ret == true, ret, done,
1992                             "write_stream failed\n");
1993
1994         torture_comment(tctx, "(%s) test OS X AppleDouble conversion\n",
1995             __location__);
1996
1997         ret = check_stream(tree, __location__, tctx, mem_ctx,
1998                            fname, AFPRESOURCE_STREAM,
1999                            16, datalen, 0, datalen, data);
2000         torture_assert_goto(tctx, ret == true, ret, done,
2001                             "check AFPRESOURCE_STREAM failed\n");
2002
2003         ret = check_stream(tree, __location__, tctx, mem_ctx,
2004                            fname, AFPINFO_STREAM,
2005                            0, 60, 16, 8, "TESTSLOW");
2006         torture_assert_goto(tctx, ret == true, ret, done,
2007                             "check AFPINFO_STREAM failed\n");
2008
2009         ret = check_stream(tree, __location__, tctx, mem_ctx, fname,
2010                            ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2011                            0, 3, 0, 3, "baz");
2012         torture_assert_goto(tctx, ret == true, ret, done,
2013                             "check foo:bar stream failed\n");
2014
2015         ret = check_stream_list(tree, tctx, fname, 5, streams, false);
2016         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2017
2018 done:
2019         smb2_deltree(tree, BASEDIR);
2020         talloc_free(mem_ctx);
2021         return ret;
2022 }
2023
2024 static bool test_aapl(struct torture_context *tctx,
2025                       struct smb2_tree *tree)
2026 {
2027         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2028         const char *fname = BASEDIR "\\test_aapl";
2029         NTSTATUS status;
2030         struct smb2_handle testdirh;
2031         bool ret = true;
2032         struct smb2_create io;
2033         DATA_BLOB data;
2034         struct smb2_create_blob *aapl = NULL;
2035         AfpInfo *info;
2036         const char *type_creator = "SMB,OLE!";
2037         char type_creator_buf[9];
2038         uint32_t aapl_cmd;
2039         uint32_t aapl_reply_bitmap;
2040         uint32_t aapl_server_caps;
2041         uint32_t aapl_vol_caps;
2042         char *model;
2043         struct smb2_find f;
2044         unsigned int count;
2045         union smb_search_data *d;
2046         uint64_t rfork_len;
2047         bool is_osx_server = torture_setting_bool(tctx, "osx", false);
2048
2049         smb2_deltree(tree, BASEDIR);
2050
2051         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2052         CHECK_STATUS(status, NT_STATUS_OK);
2053         smb2_util_close(tree, testdirh);
2054
2055         ZERO_STRUCT(io);
2056         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
2057         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
2058         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2059         io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2060                               NTCREATEX_SHARE_ACCESS_READ |
2061                               NTCREATEX_SHARE_ACCESS_WRITE);
2062         io.in.fname = fname;
2063
2064         /*
2065          * Issuing an SMB2/CREATE with a suitably formed AAPL context,
2066          * controls behaviour of Apple's SMB2 extensions for the whole
2067          * session!
2068          */
2069
2070         data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2071         SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2072         SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2073                              SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2074                              SMB2_CRTCTX_AAPL_MODEL_INFO));
2075         SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2076                               SMB2_CRTCTX_AAPL_UNIX_BASED |
2077                               SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
2078
2079         torture_comment(tctx, "Testing SMB2 create context AAPL\n");
2080         status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2081         CHECK_STATUS(status, NT_STATUS_OK);
2082
2083         status = smb2_create(tree, tctx, &io);
2084         CHECK_STATUS(status, NT_STATUS_OK);
2085         status = smb2_util_close(tree, io.out.file.handle);
2086         CHECK_STATUS(status, NT_STATUS_OK);
2087
2088         /*
2089          * Now check returned AAPL context
2090          */
2091         torture_comment(tctx, "Comparing returned AAPL capabilities\n");
2092
2093         aapl = smb2_create_blob_find(&io.out.blobs,
2094                                      SMB2_CREATE_TAG_AAPL);
2095
2096         if (aapl == NULL) {
2097                 torture_result(tctx, TORTURE_FAIL,
2098                                "(%s) unexpectedly no AAPL capabilities were returned.",
2099                                __location__);
2100                 ret = false;
2101                 goto done;
2102         }
2103
2104         if (!is_osx_server) {
2105                 size_t expected_aapl_ctx_size;
2106                 bool size_ok;
2107
2108                 /*
2109                  * uint32_t CommandCode = kAAPL_SERVER_QUERY
2110                  * uint32_t Reserved = 0;
2111                  * uint64_t ReplyBitmap = kAAPL_SERVER_CAPS |
2112                  *                        kAAPL_VOLUME_CAPS |
2113                  *                        kAAPL_MODEL_INFO;
2114                  * uint64_t ServerCaps = kAAPL_SUPPORTS_READDIR_ATTR |
2115                  *                       kAAPL_SUPPORTS_OSX_COPYFILE;
2116                  * uint64_t VolumeCaps = kAAPL_SUPPORT_RESOLVE_ID |
2117                  *                       kAAPL_CASE_SENSITIVE;
2118                  * uint32_t Pad2 = 0;
2119                  * uint32_t ModelStringLen = 10;
2120                  * ucs2_t ModelString[5] = "MacSamba";
2121                  */
2122                 expected_aapl_ctx_size = strlen("MacSamba") * 2 + 40;
2123
2124                 size_ok = aapl->data.length == expected_aapl_ctx_size;
2125                 torture_assert_goto(tctx, size_ok, ret, done, "bad AAPL size");
2126         }
2127
2128         aapl_cmd = IVAL(aapl->data.data, 0);
2129         if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2130                 torture_result(tctx, TORTURE_FAIL,
2131                                "(%s) unexpected cmd: %d",
2132                                __location__, (int)aapl_cmd);
2133                 ret = false;
2134                 goto done;
2135         }
2136
2137         aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2138         if (aapl_reply_bitmap != (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2139                                   SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2140                                   SMB2_CRTCTX_AAPL_MODEL_INFO)) {
2141                 torture_result(tctx, TORTURE_FAIL,
2142                                "(%s) unexpected reply_bitmap: %d",
2143                                __location__, (int)aapl_reply_bitmap);
2144                 ret = false;
2145                 goto done;
2146         }
2147
2148         aapl_server_caps = BVAL(aapl->data.data, 16);
2149         if (aapl_server_caps != (SMB2_CRTCTX_AAPL_UNIX_BASED |
2150                                  SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2151                                  SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
2152                                  SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE)) {
2153                 torture_result(tctx, TORTURE_FAIL,
2154                                "(%s) unexpected server_caps: %d",
2155                                __location__, (int)aapl_server_caps);
2156                 ret = false;
2157                 goto done;
2158         }
2159
2160         aapl_vol_caps = BVAL(aapl->data.data, 24);
2161         if (aapl_vol_caps != 0) {
2162                 /* this will fail on a case insensitive fs ... */
2163                 torture_result(tctx, TORTURE_FAIL,
2164                                 "(%s) unexpected vol_caps: %d",
2165                                 __location__, (int)aapl_vol_caps);
2166         }
2167
2168         ret = convert_string_talloc(mem_ctx,
2169                                     CH_UTF16LE, CH_UNIX,
2170                                     aapl->data.data + 40, 10,
2171                                     &model, NULL);
2172         if (ret == false) {
2173                 torture_result(tctx, TORTURE_FAIL,
2174                                "(%s) convert_string_talloc() failed",
2175                                __location__);
2176                 goto done;
2177         }
2178         torture_comment(tctx, "Got server model: \"%s\"\n", model);
2179
2180         /*
2181          * Now that Requested AAPL extensions are enabled, setup some
2182          * Mac files with metadata and resource fork
2183          */
2184         ret = torture_setup_file(mem_ctx, tree, fname, false);
2185         if (ret == false) {
2186                 torture_result(tctx, TORTURE_FAIL,
2187                                "(%s) torture_setup_file() failed",
2188                                __location__);
2189                 goto done;
2190         }
2191
2192         info = torture_afpinfo_new(mem_ctx);
2193         if (info == NULL) {
2194                 torture_result(tctx, TORTURE_FAIL,
2195                                "(%s) torture_afpinfo_new() failed",
2196                                __location__);
2197                 ret = false;
2198                 goto done;
2199         }
2200
2201         memcpy(info->afpi_FinderInfo, type_creator, 8);
2202         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
2203         if (ret == false) {
2204                 torture_result(tctx, TORTURE_FAIL,
2205                                "(%s) torture_write_afpinfo() failed",
2206                                __location__);
2207                 goto done;
2208         }
2209
2210         ret = write_stream(tree, __location__, tctx, mem_ctx,
2211                            fname, AFPRESOURCE_STREAM_NAME,
2212                            0, 3, "foo");
2213         if (ret == false) {
2214                 torture_result(tctx, TORTURE_FAIL,
2215                                "(%s) write_stream() failed",
2216                                __location__);
2217                 goto done;
2218         }
2219
2220         /*
2221          * Ok, file is prepared, now call smb2/find
2222          */
2223
2224         ZERO_STRUCT(io);
2225         io.in.desired_access = SEC_RIGHTS_DIR_READ;
2226         io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2227         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2228         io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
2229                               NTCREATEX_SHARE_ACCESS_WRITE |
2230                               NTCREATEX_SHARE_ACCESS_DELETE);
2231         io.in.create_disposition = NTCREATEX_DISP_OPEN;
2232         io.in.fname = BASEDIR;
2233         status = smb2_create(tree, tctx, &io);
2234         CHECK_STATUS(status, NT_STATUS_OK);
2235
2236         ZERO_STRUCT(f);
2237         f.in.file.handle        = io.out.file.handle;
2238         f.in.pattern            = "test_aapl";
2239         f.in.continue_flags     = SMB2_CONTINUE_FLAG_SINGLE;
2240         f.in.max_response_size  = 0x1000;
2241         f.in.level              = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
2242
2243         status = smb2_find_level(tree, tree, &f, &count, &d);
2244         CHECK_STATUS(status, NT_STATUS_OK);
2245
2246         status = smb2_util_close(tree, io.out.file.handle);
2247         CHECK_STATUS(status, NT_STATUS_OK);
2248
2249         if (strcmp(d[0].id_both_directory_info.name.s, "test_aapl") != 0) {
2250                 torture_result(tctx, TORTURE_FAIL,
2251                                "(%s) write_stream() failed",
2252                                __location__);
2253                 ret = false;
2254                 goto done;
2255         }
2256
2257         if (d[0].id_both_directory_info.short_name.private_length != 24) {
2258                 torture_result(tctx, TORTURE_FAIL,
2259                                "(%s) bad short_name length %" PRIu32 ", expected 24",
2260                                __location__, d[0].id_both_directory_info.short_name.private_length);
2261                 ret = false;
2262                 goto done;
2263         }
2264
2265         torture_comment(tctx, "short_name buffer:\n");
2266         dump_data(0, d[0].id_both_directory_info.short_name_buf, 24);
2267
2268         /*
2269          * Extract data as specified by the AAPL extension:
2270          * - ea_size contains max_access
2271          * - short_name contains resource fork length + FinderInfo
2272          * - reserved2 contains the unix mode
2273          */
2274         torture_comment(tctx, "mac_access: %" PRIx32 "\n",
2275                         d[0].id_both_directory_info.ea_size);
2276
2277         rfork_len = BVAL(d[0].id_both_directory_info.short_name_buf, 0);
2278         if (rfork_len != 3) {
2279                 torture_result(tctx, TORTURE_FAIL,
2280                                "(%s) expected resource fork length 3, got: %" PRIu64,
2281                                __location__, rfork_len);
2282                 ret = false;
2283                 goto done;
2284         }
2285
2286         memcpy(type_creator_buf, d[0].id_both_directory_info.short_name_buf + 8, 8);
2287         type_creator_buf[8] = 0;
2288         if (strcmp(type_creator, type_creator_buf) != 0) {
2289                 torture_result(tctx, TORTURE_FAIL,
2290                                "(%s) expected type/creator \"%s\" , got: %s",
2291                                __location__, type_creator, type_creator_buf);
2292                 ret = false;
2293                 goto done;
2294         }
2295
2296 done:
2297         smb2_util_unlink(tree, fname);
2298         smb2_deltree(tree, BASEDIR);
2299         talloc_free(mem_ctx);
2300         return ret;
2301 }
2302
2303 static uint64_t patt_hash(uint64_t off)
2304 {
2305         return off;
2306 }
2307
2308 static bool write_pattern(struct torture_context *torture,
2309                           struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2310                           struct smb2_handle h, uint64_t off, uint64_t len,
2311                           uint64_t patt_off)
2312 {
2313         NTSTATUS status;
2314         uint64_t i;
2315         uint8_t *buf;
2316         uint64_t io_sz = MIN(1024 * 64, len);
2317
2318         if (len == 0) {
2319                 return true;
2320         }
2321
2322         torture_assert(torture, (len % 8) == 0, "invalid write len");
2323
2324         buf = talloc_zero_size(mem_ctx, io_sz);
2325         torture_assert(torture, (buf != NULL), "no memory for file data buf");
2326
2327         while (len > 0) {
2328                 for (i = 0; i <= io_sz - 8; i += 8) {
2329                         SBVAL(buf, i, patt_hash(patt_off));
2330                         patt_off += 8;
2331                 }
2332
2333                 status = smb2_util_write(tree, h,
2334                                          buf, off, io_sz);
2335                 torture_assert_ntstatus_ok(torture, status, "file write");
2336
2337                 len -= io_sz;
2338                 off += io_sz;
2339         }
2340
2341         talloc_free(buf);
2342
2343         return true;
2344 }
2345
2346 static bool check_pattern(struct torture_context *torture,
2347                           struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2348                           struct smb2_handle h, uint64_t off, uint64_t len,
2349                           uint64_t patt_off)
2350 {
2351         if (len == 0) {
2352                 return true;
2353         }
2354
2355         torture_assert(torture, (len % 8) == 0, "invalid read len");
2356
2357         while (len > 0) {
2358                 uint64_t i;
2359                 struct smb2_read r;
2360                 NTSTATUS status;
2361                 uint64_t io_sz = MIN(1024 * 64, len);
2362
2363                 ZERO_STRUCT(r);
2364                 r.in.file.handle = h;
2365                 r.in.length      = io_sz;
2366                 r.in.offset      = off;
2367                 status = smb2_read(tree, mem_ctx, &r);
2368                 torture_assert_ntstatus_ok(torture, status, "read");
2369
2370                 torture_assert_u64_equal(torture, r.out.data.length, io_sz,
2371                                          "read data len mismatch");
2372
2373                 for (i = 0; i <= io_sz - 8; i += 8, patt_off += 8) {
2374                         uint64_t data = BVAL(r.out.data.data, i);
2375                         torture_assert_u64_equal(torture, data, patt_hash(patt_off),
2376                                                  talloc_asprintf(torture, "read data "
2377                                                                  "pattern bad at %llu\n",
2378                                                                  (unsigned long long)off + i));
2379                 }
2380                 talloc_free(r.out.data.data);
2381                 len -= io_sz;
2382                 off += io_sz;
2383         }
2384
2385         return true;
2386 }
2387
2388 static bool test_setup_open(struct torture_context *torture,
2389                             struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2390                             const char *fname,
2391                             struct smb2_handle *fh,
2392                             uint32_t desired_access,
2393                             uint32_t file_attributes)
2394 {
2395         struct smb2_create io;
2396         NTSTATUS status;
2397
2398         ZERO_STRUCT(io);
2399         io.in.desired_access = desired_access;
2400         io.in.file_attributes = file_attributes;
2401         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2402         io.in.share_access =
2403                 NTCREATEX_SHARE_ACCESS_DELETE|
2404                 NTCREATEX_SHARE_ACCESS_READ|
2405                 NTCREATEX_SHARE_ACCESS_WRITE;
2406         if (file_attributes & FILE_ATTRIBUTE_DIRECTORY) {
2407                 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2408         }
2409         io.in.fname = fname;
2410
2411         status = smb2_create(tree, mem_ctx, &io);
2412         torture_assert_ntstatus_ok(torture, status, "file create");
2413
2414         *fh = io.out.file.handle;
2415
2416         return true;
2417 }
2418
2419 static bool test_setup_create_fill(struct torture_context *torture,
2420                                    struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2421                                    const char *fname,
2422                                    struct smb2_handle *fh,
2423                                    uint64_t size,
2424                                    uint32_t desired_access,
2425                                    uint32_t file_attributes)
2426 {
2427         bool ok;
2428
2429         ok = test_setup_open(torture, tree, mem_ctx,
2430                              fname,
2431                              fh,
2432                              desired_access,
2433                              file_attributes);
2434         torture_assert(torture, ok, "file open");
2435
2436         if (size > 0) {
2437                 ok = write_pattern(torture, tree, mem_ctx, *fh, 0, size, 0);
2438                 torture_assert(torture, ok, "write pattern");
2439         }
2440         return true;
2441 }
2442
2443 static bool test_setup_copy_chunk(struct torture_context *torture,
2444                                   struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2445                                   uint32_t nchunks,
2446                                   const char *src_name,
2447                                   struct smb2_handle *src_h,
2448                                   uint64_t src_size,
2449                                   uint32_t src_desired_access,
2450                                   const char *dst_name,
2451                                   struct smb2_handle *dest_h,
2452                                   uint64_t dest_size,
2453                                   uint32_t dest_desired_access,
2454                                   struct srv_copychunk_copy *cc_copy,
2455                                   union smb_ioctl *io)
2456 {
2457         struct req_resume_key_rsp res_key;
2458         bool ok;
2459         NTSTATUS status;
2460         enum ndr_err_code ndr_ret;
2461
2462         ok = test_setup_create_fill(torture, tree, mem_ctx, src_name,
2463                                     src_h, src_size, src_desired_access,
2464                                     FILE_ATTRIBUTE_NORMAL);
2465         torture_assert(torture, ok, "src file create fill");
2466
2467         ok = test_setup_create_fill(torture, tree, mem_ctx, dst_name,
2468                                     dest_h, dest_size, dest_desired_access,
2469                                     FILE_ATTRIBUTE_NORMAL);
2470         torture_assert(torture, ok, "dest file create fill");
2471
2472         ZERO_STRUCTPN(io);
2473         io->smb2.level = RAW_IOCTL_SMB2;
2474         io->smb2.in.file.handle = *src_h;
2475         io->smb2.in.function = FSCTL_SRV_REQUEST_RESUME_KEY;
2476         /* Allow for Key + ContextLength + Context */
2477         io->smb2.in.max_response_size = 32;
2478         io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2479
2480         status = smb2_ioctl(tree, mem_ctx, &io->smb2);
2481         torture_assert_ntstatus_ok(torture, status,
2482                                    "FSCTL_SRV_REQUEST_RESUME_KEY");
2483
2484         ndr_ret = ndr_pull_struct_blob(&io->smb2.out.out, mem_ctx, &res_key,
2485                         (ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
2486
2487         torture_assert_ndr_success(torture, ndr_ret,
2488                                    "ndr_pull_req_resume_key_rsp");
2489
2490         ZERO_STRUCTPN(io);
2491         io->smb2.level = RAW_IOCTL_SMB2;
2492         io->smb2.in.file.handle = *dest_h;
2493         io->smb2.in.function = FSCTL_SRV_COPYCHUNK;
2494         io->smb2.in.max_response_size = sizeof(struct srv_copychunk_rsp);
2495         io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2496
2497         ZERO_STRUCTPN(cc_copy);
2498         memcpy(cc_copy->source_key, res_key.resume_key, ARRAY_SIZE(cc_copy->source_key));
2499         cc_copy->chunk_count = nchunks;
2500         cc_copy->chunks = talloc_zero_array(mem_ctx, struct srv_copychunk, nchunks);
2501         torture_assert(torture, (cc_copy->chunks != NULL), "no memory for chunks");
2502
2503         return true;
2504 }
2505
2506
2507 static bool check_copy_chunk_rsp(struct torture_context *torture,
2508                                  struct srv_copychunk_rsp *cc_rsp,
2509                                  uint32_t ex_chunks_written,
2510                                  uint32_t ex_chunk_bytes_written,
2511                                  uint32_t ex_total_bytes_written)
2512 {
2513         torture_assert_int_equal(torture, cc_rsp->chunks_written,
2514                                  ex_chunks_written, "num chunks");
2515         torture_assert_int_equal(torture, cc_rsp->chunk_bytes_written,
2516                                  ex_chunk_bytes_written, "chunk bytes written");
2517         torture_assert_int_equal(torture, cc_rsp->total_bytes_written,
2518                                  ex_total_bytes_written, "chunk total bytes");
2519         return true;
2520 }
2521
2522 static bool neg_aapl_copyfile(struct torture_context *tctx,
2523                               struct smb2_tree *tree,
2524                               uint64_t flags)
2525 {
2526         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2527         const char *fname = "aapl";
2528         NTSTATUS status;
2529         struct smb2_create io;
2530         DATA_BLOB data;
2531         struct smb2_create_blob *aapl = NULL;
2532         uint32_t aapl_cmd;
2533         uint32_t aapl_reply_bitmap;
2534         uint32_t aapl_server_caps;
2535         bool ret = true;
2536
2537         ZERO_STRUCT(io);
2538         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
2539         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
2540         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2541         io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2542                               NTCREATEX_SHARE_ACCESS_READ |
2543                               NTCREATEX_SHARE_ACCESS_WRITE);
2544         io.in.fname = fname;
2545
2546         data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2547         SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2548         SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS));
2549         SBVAL(data.data, 16, flags);
2550
2551         status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2552         CHECK_STATUS(status, NT_STATUS_OK);
2553
2554         status = smb2_create(tree, tctx, &io);
2555         CHECK_STATUS(status, NT_STATUS_OK);
2556
2557         aapl = smb2_create_blob_find(&io.out.blobs,
2558                                      SMB2_CREATE_TAG_AAPL);
2559         if (aapl == NULL) {
2560                 ret = false;
2561                 goto done;
2562
2563         }
2564         if (aapl->data.length < 24) {
2565                 ret = false;
2566                 goto done;
2567         }
2568
2569         aapl_cmd = IVAL(aapl->data.data, 0);
2570         if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2571                 torture_result(tctx, TORTURE_FAIL,
2572                                "(%s) unexpected cmd: %d",
2573                                __location__, (int)aapl_cmd);
2574                 ret = false;
2575                 goto done;
2576         }
2577
2578         aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2579         if (!(aapl_reply_bitmap & SMB2_CRTCTX_AAPL_SERVER_CAPS)) {
2580                 torture_result(tctx, TORTURE_FAIL,
2581                                "(%s) unexpected reply_bitmap: %d",
2582                                __location__, (int)aapl_reply_bitmap);
2583                 ret = false;
2584                 goto done;
2585         }
2586
2587         aapl_server_caps = BVAL(aapl->data.data, 16);
2588         if (!(aapl_server_caps & flags)) {
2589                 torture_result(tctx, TORTURE_FAIL,
2590                                "(%s) unexpected server_caps: %d",
2591                                __location__, (int)aapl_server_caps);
2592                 ret = false;
2593                 goto done;
2594         }
2595
2596 done:
2597         status = smb2_util_close(tree, io.out.file.handle);
2598         CHECK_STATUS(status, NT_STATUS_OK);
2599
2600         smb2_util_unlink(tree, "aapl");
2601         talloc_free(mem_ctx);
2602         return ret;
2603 }
2604
2605 static bool test_copyfile(struct torture_context *torture,
2606                           struct smb2_tree *tree)
2607 {
2608         struct smb2_handle src_h;
2609         struct smb2_handle dest_h;
2610         NTSTATUS status;
2611         union smb_ioctl io;
2612         TALLOC_CTX *tmp_ctx = talloc_new(tree);
2613         struct srv_copychunk_copy cc_copy;
2614         struct srv_copychunk_rsp cc_rsp;
2615         enum ndr_err_code ndr_ret;
2616         bool ok;
2617         const char *sname = ":foo" "\xef\x80\xa2" "bar:$DATA";
2618
2619         /*
2620          * First test a copy_chunk with a 0 chunk count without having
2621          * enabled this via AAPL. The request must not fail and the
2622          * copied length in the response must be 0. This is verified
2623          * against Windows 2008r2.
2624          */
2625
2626         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2627                                    0, /* 0 chunks, copyfile semantics */
2628                                    FNAME_CC_SRC,
2629                                    &src_h, 4096, /* fill 4096 byte src file */
2630                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2631                                    FNAME_CC_DST,
2632                                    &dest_h, 0,  /* 0 byte dest file */
2633                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2634                                    &cc_copy,
2635                                    &io);
2636         if (!ok) {
2637                 torture_fail_goto(torture, done, "setup copy chunk error");
2638         }
2639
2640         ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2641                                        &cc_copy,
2642                         (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2643         torture_assert_ndr_success(torture, ndr_ret,
2644                                    "ndr_push_srv_copychunk_copy");
2645
2646         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2647         torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2648
2649         ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2650                                        &cc_rsp,
2651                         (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2652         torture_assert_ndr_success(torture, ndr_ret,
2653                                    "ndr_pull_srv_copychunk_rsp");
2654
2655         ok = check_copy_chunk_rsp(torture, &cc_rsp,
2656                                   0,    /* chunks written */
2657                                   0,    /* chunk bytes unsuccessfully written */
2658                                   0); /* total bytes written */
2659         if (!ok) {
2660                 torture_fail_goto(torture, done, "bad copy chunk response data");
2661         }
2662
2663         /*
2664          * Now enable AAPL copyfile and test again, the file and the
2665          * stream must be copied by the server.
2666          */
2667         ok = neg_aapl_copyfile(torture, tree,
2668                                SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
2669         if (!ok) {
2670                 torture_skip_goto(torture, done, "missing AAPL copyfile");
2671                 goto done;
2672         }
2673
2674         smb2_util_close(tree, src_h);
2675         smb2_util_close(tree, dest_h);
2676         smb2_util_unlink(tree, FNAME_CC_SRC);
2677         smb2_util_unlink(tree, FNAME_CC_DST);
2678
2679         ok = torture_setup_file(tmp_ctx, tree, FNAME_CC_SRC, false);
2680         if (!ok) {
2681                 torture_fail(torture, "setup file error");
2682         }
2683         ok = write_stream(tree, __location__, torture, tmp_ctx,
2684                             FNAME_CC_SRC, AFPRESOURCE_STREAM,
2685                             10, 10, "1234567890");
2686         if (!ok) {
2687                 torture_fail(torture, "setup stream error");
2688         }
2689
2690         ok = write_stream(tree, __location__, torture, tmp_ctx,
2691                             FNAME_CC_SRC, sname,
2692                             10, 10, "abcdefghij");
2693         torture_assert_goto(torture, ok == true, ok, done, "write_stream failed\n");
2694
2695         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2696                                    0, /* 0 chunks, copyfile semantics */
2697                                    FNAME_CC_SRC,
2698                                    &src_h, 4096, /* fill 4096 byte src file */
2699                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2700                                    FNAME_CC_DST,
2701                                    &dest_h, 0,  /* 0 byte dest file */
2702                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2703                                    &cc_copy,
2704                                    &io);
2705         if (!ok) {
2706                 torture_fail_goto(torture, done, "setup copy chunk error");
2707         }
2708
2709         ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2710                                        &cc_copy,
2711                         (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2712         torture_assert_ndr_success(torture, ndr_ret,
2713                                    "ndr_push_srv_copychunk_copy");
2714
2715         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2716         torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2717
2718         ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2719                                        &cc_rsp,
2720                         (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2721         torture_assert_ndr_success(torture, ndr_ret,
2722                                    "ndr_pull_srv_copychunk_rsp");
2723
2724         ok = check_copy_chunk_rsp(torture, &cc_rsp,
2725                                   0,    /* chunks written */
2726                                   0,    /* chunk bytes unsuccessfully written */
2727                                   4096); /* total bytes written */
2728         if (!ok) {
2729                 torture_fail_goto(torture, done, "bad copy chunk response data");
2730         }
2731
2732         ok = test_setup_open(torture, tree, tmp_ctx, FNAME_CC_DST, &dest_h,
2733                              SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL);
2734         if (!ok) {
2735                 torture_fail_goto(torture, done,"open failed");
2736         }
2737         ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 4096, 0);
2738         if (!ok) {
2739                 torture_fail_goto(torture, done, "inconsistent file data");
2740         }
2741
2742         ok = check_stream(tree, __location__, torture, tmp_ctx,
2743                             FNAME_CC_DST, AFPRESOURCE_STREAM,
2744                             0, 20, 10, 10, "1234567890");
2745         if (!ok) {
2746                 torture_fail_goto(torture, done, "inconsistent stream data");
2747         }
2748
2749         ok = check_stream(tree, __location__, torture, tmp_ctx,
2750                             FNAME_CC_DST, sname,
2751                             0, 20, 10, 10, "abcdefghij");
2752         torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
2753
2754 done:
2755         smb2_util_close(tree, src_h);
2756         smb2_util_close(tree, dest_h);
2757         smb2_util_unlink(tree, FNAME_CC_SRC);
2758         smb2_util_unlink(tree, FNAME_CC_DST);
2759         talloc_free(tmp_ctx);
2760         return true;
2761 }
2762
2763 static bool check_stream_list(struct smb2_tree *tree,
2764                               struct torture_context *tctx,
2765                               const char *fname,
2766                               int num_exp,
2767                               const char **exp,
2768                               bool is_dir)
2769 {
2770         bool ret = true;
2771         union smb_fileinfo finfo;
2772         NTSTATUS status;
2773         int i;
2774         TALLOC_CTX *tmp_ctx = talloc_new(tctx);
2775         char **exp_sort;
2776         struct stream_struct *stream_sort;
2777         struct smb2_create create;
2778         struct smb2_handle h;
2779
2780         ZERO_STRUCT(h);
2781         torture_assert_goto(tctx, tmp_ctx != NULL, ret, done, "talloc_new failed");
2782
2783         ZERO_STRUCT(create);
2784         create.in.fname = fname;
2785         create.in.create_disposition = NTCREATEX_DISP_OPEN;
2786         create.in.desired_access = SEC_FILE_ALL;
2787         create.in.create_options = is_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
2788         create.in.file_attributes = is_dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
2789         status = smb2_create(tree, tmp_ctx, &create);
2790         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
2791         h = create.out.file.handle;
2792
2793         finfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
2794         finfo.generic.in.file.handle = h;
2795
2796         status = smb2_getinfo_file(tree, tctx, &finfo);
2797         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "get stream info");
2798
2799         smb2_util_close(tree, h);
2800
2801         torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams, num_exp,
2802                                       ret, done, "stream count");
2803
2804         if (num_exp == 0) {
2805                 TALLOC_FREE(tmp_ctx);
2806                 goto done;
2807         }
2808
2809         exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
2810         torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
2811
2812         TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
2813
2814         stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
2815                                     finfo.stream_info.out.num_streams *
2816                                     sizeof(*stream_sort));
2817         torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
2818
2819         TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
2820
2821         for (i=0; i<num_exp; i++) {
2822                 torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
2823                                 i, exp_sort[i], stream_sort[i].stream_name.s);
2824                 torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s, exp_sort[i],
2825                                               ret, done, "stream name");
2826         }
2827
2828 done:
2829         TALLOC_FREE(tmp_ctx);
2830         return ret;
2831 }
2832
2833 /*
2834   test stream names
2835 */
2836 static bool test_stream_names(struct torture_context *tctx,
2837                               struct smb2_tree *tree)
2838 {
2839         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2840         NTSTATUS status;
2841         struct smb2_create create;
2842         struct smb2_handle h;
2843         const char *fname = BASEDIR "\\stream_names.txt";
2844         const char *sname1;
2845         bool ret;
2846         /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
2847         const char *streams[] = {
2848                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2849                 "::$DATA"
2850         };
2851
2852         sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
2853
2854         /* clean slate ...*/
2855         smb2_util_unlink(tree, fname);
2856         smb2_deltree(tree, fname);
2857         smb2_deltree(tree, BASEDIR);
2858
2859         status = torture_smb2_testdir(tree, BASEDIR, &h);
2860         CHECK_STATUS(status, NT_STATUS_OK);
2861         smb2_util_close(tree, h);
2862
2863         torture_comment(tctx, "(%s) testing stream names\n", __location__);
2864         ZERO_STRUCT(create);
2865         create.in.desired_access = SEC_FILE_WRITE_DATA;
2866         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2867         create.in.share_access =
2868                 NTCREATEX_SHARE_ACCESS_DELETE|
2869                 NTCREATEX_SHARE_ACCESS_READ|
2870                 NTCREATEX_SHARE_ACCESS_WRITE;
2871         create.in.create_disposition = NTCREATEX_DISP_CREATE;
2872         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2873         create.in.fname = sname1;
2874
2875         status = smb2_create(tree, mem_ctx, &create);
2876         CHECK_STATUS(status, NT_STATUS_OK);
2877         smb2_util_close(tree, create.out.file.handle);
2878
2879         ret = check_stream_list(tree, tctx, fname, 2, streams, false);
2880         CHECK_VALUE(ret, true);
2881
2882 done:
2883         status = smb2_util_unlink(tree, fname);
2884         smb2_deltree(tree, BASEDIR);
2885         talloc_free(mem_ctx);
2886
2887         return ret;
2888 }
2889
2890 /* Renaming a directory with open file, should work for OS X AAPL clients */
2891 static bool test_rename_dir_openfile(struct torture_context *torture,
2892                                      struct smb2_tree *tree)
2893 {
2894         bool ret = true;
2895         NTSTATUS status;
2896         union smb_open io;
2897         union smb_close cl;
2898         union smb_setfileinfo sinfo;
2899         struct smb2_handle d1, h1;
2900         const char *renamedir = BASEDIR "-new";
2901         bool server_is_osx = torture_setting_bool(torture, "osx", false);
2902
2903         smb2_deltree(tree, BASEDIR);
2904         smb2_util_rmdir(tree, BASEDIR);
2905         smb2_deltree(tree, renamedir);
2906
2907         ZERO_STRUCT(io.smb2);
2908         io.generic.level = RAW_OPEN_SMB2;
2909         io.smb2.in.create_flags = 0;
2910         io.smb2.in.desired_access = 0x0017019f;
2911         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2912         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2913         io.smb2.in.share_access = 0;
2914         io.smb2.in.alloc_size = 0;
2915         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2916         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2917         io.smb2.in.security_flags = 0;
2918         io.smb2.in.fname = BASEDIR;
2919
2920         status = smb2_create(tree, torture, &(io.smb2));
2921         torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
2922         d1 = io.smb2.out.file.handle;
2923
2924         ZERO_STRUCT(io.smb2);
2925         io.generic.level = RAW_OPEN_SMB2;
2926         io.smb2.in.create_flags = 0;
2927         io.smb2.in.desired_access = 0x0017019f;
2928         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
2929         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2930         io.smb2.in.share_access = 0;
2931         io.smb2.in.alloc_size = 0;
2932         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2933         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2934         io.smb2.in.security_flags = 0;
2935         io.smb2.in.fname = BASEDIR "\\file.txt";
2936
2937         status = smb2_create(tree, torture, &(io.smb2));
2938         torture_assert_ntstatus_ok(torture, status, "smb2_create file");
2939         h1 = io.smb2.out.file.handle;
2940
2941         if (!server_is_osx) {
2942                 torture_comment(torture, "Renaming directory without AAPL, must fail\n");
2943
2944                 ZERO_STRUCT(sinfo);
2945                 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
2946                 sinfo.rename_information.in.file.handle = d1;
2947                 sinfo.rename_information.in.overwrite = 0;
2948                 sinfo.rename_information.in.root_fid = 0;
2949                 sinfo.rename_information.in.new_name = renamedir;
2950                 status = smb2_setinfo_file(tree, &sinfo);
2951
2952                 torture_assert_ntstatus_equal(torture, status,
2953                                               NT_STATUS_ACCESS_DENIED,
2954                                               "smb2_setinfo_file");
2955
2956                 ZERO_STRUCT(cl.smb2);
2957                 cl.smb2.level = RAW_CLOSE_SMB2;
2958                 cl.smb2.in.file.handle = d1;
2959                 status = smb2_close(tree, &(cl.smb2));
2960                 torture_assert_ntstatus_ok(torture, status, "smb2_close");
2961                 ZERO_STRUCT(d1);
2962         }
2963
2964         torture_comment(torture, "Enabling AAPL\n");
2965
2966         ret = enable_aapl(torture, tree);
2967         torture_assert(torture, ret == true, "enable_aapl failed");
2968
2969         torture_comment(torture, "Renaming directory with AAPL\n");
2970
2971         ZERO_STRUCT(io.smb2);
2972         io.generic.level = RAW_OPEN_SMB2;
2973         io.smb2.in.desired_access = 0x0017019f;
2974         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2975         io.smb2.in.share_access = 0;
2976         io.smb2.in.alloc_size = 0;
2977         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
2978         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2979         io.smb2.in.security_flags = 0;
2980         io.smb2.in.fname = BASEDIR;
2981
2982         status = smb2_create(tree, torture, &(io.smb2));
2983         torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
2984         d1 = io.smb2.out.file.handle;
2985
2986         ZERO_STRUCT(sinfo);
2987         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
2988         sinfo.rename_information.in.file.handle = d1;
2989         sinfo.rename_information.in.overwrite = 0;
2990         sinfo.rename_information.in.root_fid = 0;
2991         sinfo.rename_information.in.new_name = renamedir;
2992
2993         status = smb2_setinfo_file(tree, &sinfo);
2994         torture_assert_ntstatus_ok(torture, status, "smb2_setinfo_file");
2995
2996         ZERO_STRUCT(cl.smb2);
2997         cl.smb2.level = RAW_CLOSE_SMB2;
2998         cl.smb2.in.file.handle = d1;
2999         status = smb2_close(tree, &(cl.smb2));
3000         torture_assert_ntstatus_ok(torture, status, "smb2_close");
3001         ZERO_STRUCT(d1);
3002
3003         cl.smb2.in.file.handle = h1;
3004         status = smb2_close(tree, &(cl.smb2));
3005         torture_assert_ntstatus_ok(torture, status, "smb2_close");
3006         ZERO_STRUCT(h1);
3007
3008         torture_comment(torture, "Cleaning up\n");
3009
3010         if (h1.data[0] || h1.data[1]) {
3011                 ZERO_STRUCT(cl.smb2);
3012                 cl.smb2.level = RAW_CLOSE_SMB2;
3013                 cl.smb2.in.file.handle = h1;
3014                 status = smb2_close(tree, &(cl.smb2));
3015         }
3016
3017         smb2_util_unlink(tree, BASEDIR "\\file.txt");
3018         smb2_util_unlink(tree, BASEDIR "-new\\file.txt");
3019         smb2_deltree(tree, renamedir);
3020         smb2_deltree(tree, BASEDIR);
3021         return ret;
3022 }
3023
3024 static bool test_afpinfo_enoent(struct torture_context *tctx,
3025                                 struct smb2_tree *tree)
3026 {
3027         bool ret = true;
3028         NTSTATUS status;
3029         struct smb2_create create;
3030         struct smb2_handle h1;
3031         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3032         const char *fname = BASEDIR "\\file";
3033         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3034
3035         torture_comment(tctx, "Opening file without AFP_AfpInfo\n");
3036
3037         smb2_deltree(tree, BASEDIR);
3038         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3039         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3040         smb2_util_close(tree, h1);
3041         ret = torture_setup_file(mem_ctx, tree, fname, false);
3042         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3043
3044         torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3045
3046         ZERO_STRUCT(create);
3047         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3048         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3049         create.in.fname = sname;
3050
3051         status = smb2_create(tree, mem_ctx, &create);
3052         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3053                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3054
3055 done:
3056         smb2_util_unlink(tree, fname);
3057         smb2_util_rmdir(tree, BASEDIR);
3058         return ret;
3059 }
3060
3061 static bool test_create_delete_on_close(struct torture_context *tctx,
3062                                         struct smb2_tree *tree)
3063 {
3064         bool ret = true;
3065         NTSTATUS status;
3066         struct smb2_create create;
3067         struct smb2_handle h1;
3068         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3069         const char *fname = BASEDIR "\\file";
3070         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3071         const char *type_creator = "SMB,OLE!";
3072         AfpInfo *info = NULL;
3073         const char *streams_basic[] = {
3074                 "::$DATA"
3075         };
3076         const char *streams_afpinfo[] = {
3077                 "::$DATA",
3078                 AFPINFO_STREAM
3079         };
3080
3081         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3082
3083         torture_comment(tctx, "Checking whether create with delete-on-close work with AFP_AfpInfo\n");
3084
3085         smb2_deltree(tree, BASEDIR);
3086         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3087         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3088         smb2_util_close(tree, h1);
3089         ret = torture_setup_file(mem_ctx, tree, fname, false);
3090         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3091
3092         torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3093
3094         ZERO_STRUCT(create);
3095         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3096         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3097         create.in.fname = sname;
3098
3099         status = smb2_create(tree, mem_ctx, &create);
3100         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3101                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3102
3103         ZERO_STRUCT(create);
3104         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3105         create.in.desired_access = SEC_FILE_ALL;
3106         create.in.fname = sname;
3107
3108         status = smb2_create(tree, mem_ctx, &create);
3109         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3110                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3111
3112         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3113         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3114
3115         torture_comment(tctx, "Deleting AFP_AfpInfo via create with delete-on-close\n");
3116
3117         info = torture_afpinfo_new(mem_ctx);
3118         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3119
3120         memcpy(info->afpi_FinderInfo, type_creator, 8);
3121         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3122         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3123
3124         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3125                            0, 60, 16, 8, type_creator);
3126         torture_assert_goto(tctx, ret == true, ret, done, "Bad type/creator in AFP_AfpInfo");
3127
3128         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3129         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3130
3131         ZERO_STRUCT(create);
3132         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3133         create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3134         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3135         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3136         create.in.fname = sname;
3137         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3138
3139         status = smb2_create(tree, mem_ctx, &create);
3140         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3141
3142         h1 = create.out.file.handle;
3143         smb2_util_close(tree, h1);
3144
3145         ZERO_STRUCT(create);
3146         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3147         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
3148         create.in.fname = sname;
3149         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3150         status = smb2_create(tree, mem_ctx, &create);
3151         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3152                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3153
3154         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3155         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3156
3157 done:
3158         smb2_util_unlink(tree, fname);
3159         smb2_util_rmdir(tree, BASEDIR);
3160         return ret;
3161 }
3162
3163 static bool test_setinfo_delete_on_close(struct torture_context *tctx,
3164                                          struct smb2_tree *tree)
3165 {
3166         bool ret = true;
3167         NTSTATUS status;
3168         struct smb2_create create;
3169         union smb_setfileinfo sfinfo;
3170         struct smb2_handle h1;
3171         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3172         const char *fname = BASEDIR "\\file";
3173         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3174         const char *type_creator = "SMB,OLE!";
3175         AfpInfo *info = NULL;
3176         const char *streams_basic[] = {
3177                 "::$DATA"
3178         };
3179
3180         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3181
3182         torture_comment(tctx, "Deleting AFP_AfpInfo via setinfo with delete-on-close\n");
3183
3184         smb2_deltree(tree, BASEDIR);
3185         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3186         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3187         smb2_util_close(tree, h1);
3188         ret = torture_setup_file(mem_ctx, tree, fname, false);
3189         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3190
3191         info = torture_afpinfo_new(mem_ctx);
3192         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3193         memcpy(info->afpi_FinderInfo, type_creator, 8);
3194         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3195         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3196
3197         ZERO_STRUCT(create);
3198         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3199         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3200         create.in.fname = sname;
3201         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3202         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3203
3204         status = smb2_create(tree, mem_ctx, &create);
3205         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3206
3207         h1 = create.out.file.handle;
3208
3209         /* Delete stream via setinfo delete-on-close */
3210         ZERO_STRUCT(sfinfo);
3211         sfinfo.disposition_info.in.delete_on_close = 1;
3212         sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3213         sfinfo.generic.in.file.handle = h1;
3214         status = smb2_setinfo_file(tree, &sfinfo);
3215         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3216
3217         smb2_util_close(tree, h1);
3218
3219         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3220         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3221
3222         ZERO_STRUCT(create);
3223         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3224         create.in.desired_access = SEC_FILE_ALL;
3225         create.in.fname = sname;
3226         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3227         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3228         status = smb2_create(tree, mem_ctx, &create);
3229         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3230                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3231
3232 done:
3233         smb2_util_unlink(tree, fname);
3234         smb2_util_rmdir(tree, BASEDIR);
3235         return ret;
3236 }
3237
3238 static bool test_setinfo_eof(struct torture_context *tctx,
3239                              struct smb2_tree *tree)
3240 {
3241         bool ret = true;
3242         NTSTATUS status;
3243         struct smb2_create create;
3244         union smb_setfileinfo sfinfo;
3245         struct smb2_handle h1;
3246         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3247         const char *fname = BASEDIR "\\file";
3248         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3249         const char *type_creator = "SMB,OLE!";
3250         AfpInfo *info = NULL;
3251         const char *streams_afpinfo[] = {
3252                 "::$DATA",
3253                 AFPINFO_STREAM
3254         };
3255
3256         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3257
3258         torture_comment(tctx, "Set AFP_AfpInfo EOF to 61, 1 and 0\n");
3259
3260         smb2_deltree(tree, BASEDIR);
3261         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3262         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3263         smb2_util_close(tree, h1);
3264         ret = torture_setup_file(mem_ctx, tree, fname, false);
3265         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3266
3267         info = torture_afpinfo_new(mem_ctx);
3268         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3269         memcpy(info->afpi_FinderInfo, type_creator, 8);
3270         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3271         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3272
3273         ZERO_STRUCT(create);
3274         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3275         create.in.desired_access = SEC_FILE_ALL;
3276         create.in.fname = sname;
3277         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3278         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3279
3280         status = smb2_create(tree, mem_ctx, &create);
3281         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3282
3283         h1 = create.out.file.handle;
3284
3285         torture_comment(tctx, "Set AFP_AfpInfo EOF to 61\n");
3286
3287         /* Test setinfo end-of-file info */
3288         ZERO_STRUCT(sfinfo);
3289         sfinfo.generic.in.file.handle = h1;
3290         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3291         sfinfo.position_information.in.position = 61;
3292         status = smb2_setinfo_file(tree, &sfinfo);
3293         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ALLOTTED_SPACE_EXCEEDED,
3294                                            ret, done, "set eof 61 failed");
3295
3296         torture_comment(tctx, "Set AFP_AfpInfo EOF to 1\n");
3297
3298         /* Truncation returns success, but has no effect */
3299         ZERO_STRUCT(sfinfo);
3300         sfinfo.generic.in.file.handle = h1;
3301         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3302         sfinfo.position_information.in.position = 1;
3303         status = smb2_setinfo_file(tree, &sfinfo);
3304         torture_assert_ntstatus_ok_goto(tctx, status,
3305                                         ret, done, "set eof 1 failed");
3306         smb2_util_close(tree, h1);
3307
3308         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3309         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3310
3311         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3312                            0, 60, 16, 8, type_creator);
3313         torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3314
3315         ZERO_STRUCT(create);
3316         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3317         create.in.desired_access = SEC_FILE_ALL;
3318         create.in.fname = sname;
3319         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3320         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3321
3322         status = smb2_create(tree, mem_ctx, &create);
3323         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3324
3325         h1 = create.out.file.handle;
3326
3327         /*
3328          * Delete stream via setinfo end-of-file info to 0, should
3329          * return success but stream MUST NOT deleted
3330          */
3331         ZERO_STRUCT(sfinfo);
3332         sfinfo.generic.in.file.handle = h1;
3333         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3334         sfinfo.position_information.in.position = 0;
3335         status = smb2_setinfo_file(tree, &sfinfo);
3336         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
3337
3338         smb2_util_close(tree, h1);
3339
3340         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3341         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3342
3343         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3344                            0, 60, 16, 8, type_creator);
3345         torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3346
3347 done:
3348         smb2_util_unlink(tree, fname);
3349         smb2_util_rmdir(tree, BASEDIR);
3350         return ret;
3351 }
3352
3353 static bool test_afpinfo_all0(struct torture_context *tctx,
3354                               struct smb2_tree *tree)
3355 {
3356         bool ret = true;
3357         NTSTATUS status;
3358         struct smb2_create create;
3359         struct smb2_handle h1 = {{0}};
3360         struct smb2_handle baseh = {{0}};
3361         union smb_setfileinfo setfinfo;
3362         union smb_fileinfo getfinfo;
3363         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3364         const char *fname = BASEDIR "\\file";
3365         const char *sname = BASEDIR "\\file" AFPINFO_STREAM;
3366         const char *type_creator = "SMB,OLE!";
3367         AfpInfo *info = NULL;
3368         char *infobuf = NULL;
3369         const char *streams_basic[] = {
3370                 "::$DATA"
3371         };
3372         const char *streams_afpinfo[] = {
3373                 "::$DATA",
3374                 AFPINFO_STREAM
3375         };
3376
3377         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3378
3379         torture_comment(tctx, "Write all 0 to AFP_AfpInfo and see what happens\n");
3380
3381         smb2_deltree(tree, BASEDIR);
3382         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3383         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3384         smb2_util_close(tree, h1);
3385         ret = torture_setup_file(mem_ctx, tree, fname, false);
3386         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3387
3388         info = torture_afpinfo_new(mem_ctx);
3389         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3390         memcpy(info->afpi_FinderInfo, type_creator, 8);
3391         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3392         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3393
3394         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3395         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3396
3397         /* Write all 0 to AFP_AfpInfo */
3398         memset(info->afpi_FinderInfo, 0, AFP_FinderSize);
3399         infobuf = torture_afpinfo_pack(mem_ctx, info);
3400         torture_assert_not_null_goto(tctx, infobuf, ret, done,
3401                                      "torture_afpinfo_pack failed\n");
3402
3403         ZERO_STRUCT(create);
3404         create.in.desired_access = SEC_FILE_ALL;
3405         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3406         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3407         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3408         create.in.fname = fname;
3409
3410         status = smb2_create(tree, mem_ctx, &create);
3411         torture_assert_goto(tctx, ret == true, ret, done,
3412                             "smb2_create failed\n");
3413         baseh = create.out.file.handle;
3414
3415         ZERO_STRUCT(create);
3416         create.in.desired_access = SEC_FILE_ALL;
3417         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3418         create.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
3419         create.in.fname = sname;
3420
3421         status = smb2_create(tree, mem_ctx, &create);
3422         torture_assert_goto(tctx, ret == true, ret, done,
3423                             "smb2_create failed\n");
3424         h1 = create.out.file.handle;
3425
3426         status = smb2_util_write(tree, h1, infobuf, 0, AFP_INFO_SIZE);
3427         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3428                                         "smb2_util_write failed\n");
3429
3430         /*
3431          * Get stream information on open handle, must return only default
3432          * stream, the AFP_AfpInfo stream must not be returned.
3433          */
3434
3435         ZERO_STRUCT(getfinfo);
3436         getfinfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
3437         getfinfo.generic.in.file.handle = baseh;
3438
3439         status = smb2_getinfo_file(tree, tctx, &getfinfo);
3440         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3441                                         "get stream info\n");
3442
3443         torture_assert_int_equal_goto(tctx, getfinfo.stream_info.out.num_streams,
3444                                       1, ret, done, "stream count");
3445
3446         smb2_util_close(tree, baseh);
3447         ZERO_STRUCT(baseh);
3448
3449         /*
3450          * Try to set some file-basic-info (time) on the stream. This catches
3451          * naive implementation mistakes that simply deleted the backing store
3452          * from the filesystem in the zero-out step.
3453          */
3454
3455         ZERO_STRUCT(setfinfo);
3456         unix_to_nt_time(&setfinfo.basic_info.in.write_time, time(NULL));
3457         setfinfo.basic_info.in.attrib = 0x20;
3458         setfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
3459         setfinfo.generic.in.file.handle = h1;
3460
3461         status = smb2_setinfo_file(tree, &setfinfo);
3462         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3463                                         "smb2_getinfo_file failed\n");
3464
3465         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3466         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
3467
3468         smb2_util_close(tree, h1);
3469         ZERO_STRUCT(h1);
3470
3471         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3472         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3473
3474 done:
3475         if (!smb2_util_handle_empty(h1)) {
3476                 smb2_util_close(tree, h1);
3477         }
3478         if (!smb2_util_handle_empty(baseh)) {
3479                 smb2_util_close(tree, baseh);
3480         }
3481         smb2_util_unlink(tree, fname);
3482         smb2_util_rmdir(tree, BASEDIR);
3483         return ret;
3484 }
3485
3486 static bool test_create_delete_on_close_resource(struct torture_context *tctx,
3487                                                  struct smb2_tree *tree)
3488 {
3489         bool ret = true;
3490         NTSTATUS status;
3491         struct smb2_create create;
3492         struct smb2_handle h1;
3493         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3494         const char *fname = BASEDIR "\\file";
3495         const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3496         const char *streams_basic[] = {
3497                 "::$DATA"
3498         };
3499         const char *streams_afpresource[] = {
3500                 "::$DATA",
3501                 AFPRESOURCE_STREAM
3502         };
3503
3504         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3505
3506         torture_comment(tctx, "Checking whether create with delete-on-close is ignored for AFP_AfpResource\n");
3507
3508         smb2_deltree(tree, BASEDIR);
3509         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3510         torture_assert_ntstatus_ok(tctx, status, "torture_smb2_testdir");
3511         smb2_util_close(tree, h1);
3512         ret = torture_setup_file(mem_ctx, tree, fname, false);
3513         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3514
3515         torture_comment(tctx, "Opening not existing AFP_AfpResource\n");
3516
3517         ZERO_STRUCT(create);
3518         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3519         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3520         create.in.fname = sname;
3521
3522         status = smb2_create(tree, mem_ctx, &create);
3523         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3524                                            ret, done, "Got unexpected AFP_AfpResource stream");
3525
3526         ZERO_STRUCT(create);
3527         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3528         create.in.desired_access = SEC_FILE_ALL;
3529         create.in.fname = sname;
3530
3531         status = smb2_create(tree, mem_ctx, &create);
3532         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3533                                            ret, done, "Got unexpected AFP_AfpResource stream");
3534
3535         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3536         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3537
3538         torture_comment(tctx, "Trying to delete AFP_AfpResource via create with delete-on-close\n");
3539
3540         ret = write_stream(tree, __location__, tctx, mem_ctx,
3541                            fname, AFPRESOURCE_STREAM_NAME,
3542                            0, 10, "1234567890");
3543         torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3544
3545         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3546                            0, 10, 0, 10, "1234567890");
3547         torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3548
3549         ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3550         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3551
3552         ZERO_STRUCT(create);
3553         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3554         create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3555         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3556         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3557         create.in.fname = sname;
3558         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3559
3560         status = smb2_create(tree, mem_ctx, &create);
3561         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3562
3563         h1 = create.out.file.handle;
3564         smb2_util_close(tree, h1);
3565
3566         ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3567         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3568
3569         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3570                            0, 10, 0, 10, "1234567890");
3571         torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3572
3573 done:
3574         smb2_util_unlink(tree, fname);
3575         smb2_util_rmdir(tree, BASEDIR);
3576         return ret;
3577 }
3578
3579 static bool test_setinfo_delete_on_close_resource(struct torture_context *tctx,
3580                                                   struct smb2_tree *tree)
3581 {
3582         bool ret = true;
3583         NTSTATUS status;
3584         struct smb2_create create;
3585         union smb_setfileinfo sfinfo;
3586         struct smb2_handle h1;
3587         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3588         const char *fname = BASEDIR "\\file";
3589         const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3590         const char *streams_afpresource[] = {
3591                 "::$DATA",
3592                 AFPRESOURCE_STREAM
3593         };
3594
3595         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3596
3597         torture_comment(tctx, "Trying to delete AFP_AfpResource via setinfo with delete-on-close\n");
3598
3599         smb2_deltree(tree, BASEDIR);
3600         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3601         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3602         smb2_util_close(tree, h1);
3603         ret = torture_setup_file(mem_ctx, tree, fname, false);
3604         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3605
3606         ret = write_stream(tree, __location__, tctx, mem_ctx,
3607                            fname, AFPRESOURCE_STREAM_NAME,
3608                            10, 10, "1234567890");
3609         torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3610
3611         ZERO_STRUCT(create);
3612         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3613         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3614         create.in.fname = sname;
3615         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3616         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3617
3618         status = smb2_create(tree, mem_ctx, &create);
3619         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3620
3621         h1 = create.out.file.handle;
3622
3623         /* Try to delete stream via setinfo delete-on-close */
3624         ZERO_STRUCT(sfinfo);
3625         sfinfo.disposition_info.in.delete_on_close = 1;
3626         sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3627         sfinfo.generic.in.file.handle = h1;
3628         status = smb2_setinfo_file(tree, &sfinfo);
3629         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3630
3631         smb2_util_close(tree, h1);
3632
3633         ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3634         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3635
3636         ZERO_STRUCT(create);
3637         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3638         create.in.desired_access = SEC_FILE_ALL;
3639         create.in.fname = sname;
3640         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3641         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3642         status = smb2_create(tree, mem_ctx, &create);
3643         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3644                                         "Got unexpected AFP_AfpResource stream");
3645
3646 done:
3647         smb2_util_unlink(tree, fname);
3648         smb2_util_rmdir(tree, BASEDIR);
3649         return ret;
3650 }
3651
3652 static bool test_setinfo_eof_resource(struct torture_context *tctx,
3653                                       struct smb2_tree *tree)
3654 {
3655         bool ret = true;
3656         NTSTATUS status;
3657         struct smb2_create create;
3658         union smb_setfileinfo sfinfo;
3659         union smb_fileinfo finfo;
3660         struct smb2_handle h1;
3661         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3662         const char *fname = BASEDIR "\\file";
3663         const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3664         const char *streams_basic[] = {
3665                 "::$DATA"
3666         };
3667
3668         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3669
3670         torture_comment(tctx, "Set AFP_AfpResource EOF to 1 and 0\n");
3671
3672         smb2_deltree(tree, BASEDIR);
3673         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3674         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3675         smb2_util_close(tree, h1);
3676         ret = torture_setup_file(mem_ctx, tree, fname, false);
3677         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3678
3679         ret = write_stream(tree, __location__, tctx, mem_ctx,
3680                            fname, AFPRESOURCE_STREAM_NAME,
3681                            10, 10, "1234567890");
3682         torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3683
3684         ZERO_STRUCT(create);
3685         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3686         create.in.desired_access = SEC_FILE_ALL;
3687         create.in.fname = sname;
3688         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3689         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3690
3691         status = smb2_create(tree, mem_ctx, &create);
3692         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3693
3694         h1 = create.out.file.handle;
3695
3696         torture_comment(tctx, "Set AFP_AfpResource EOF to 1\n");
3697
3698         /* Test setinfo end-of-file info */
3699         ZERO_STRUCT(sfinfo);
3700         sfinfo.generic.in.file.handle = h1;
3701         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3702         sfinfo.position_information.in.position = 1;
3703         status = smb2_setinfo_file(tree, &sfinfo);
3704         torture_assert_ntstatus_ok_goto(tctx, status,
3705                                         ret, done, "set eof 1 failed");
3706
3707         smb2_util_close(tree, h1);
3708
3709         /* Check size == 1 */
3710         ZERO_STRUCT(create);
3711         create.in.fname = sname;
3712         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3713         create.in.desired_access = SEC_FILE_ALL;
3714         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3715         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3716         status = smb2_create(tree, mem_ctx, &create);
3717         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3718
3719         h1 = create.out.file.handle;
3720
3721         ZERO_STRUCT(finfo);
3722         finfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
3723         finfo.generic.in.file.handle = h1;
3724         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
3725         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file failed");
3726
3727         smb2_util_close(tree, h1);
3728
3729         torture_assert_goto(tctx, finfo.all_info.out.size == 1, ret, done, "size != 1");
3730
3731         ZERO_STRUCT(create);
3732         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3733         create.in.desired_access = SEC_FILE_ALL;
3734         create.in.fname = sname;
3735         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3736         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3737
3738         status = smb2_create(tree, mem_ctx, &create);
3739         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3740
3741         h1 = create.out.file.handle;
3742
3743         /*
3744          * Delete stream via setinfo end-of-file info to 0, this
3745          * should delete the stream.
3746          */
3747         ZERO_STRUCT(sfinfo);
3748         sfinfo.generic.in.file.handle = h1;
3749         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3750         sfinfo.position_information.in.position = 0;
3751         status = smb2_setinfo_file(tree, &sfinfo);
3752         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
3753
3754         smb2_util_close(tree, h1);
3755
3756         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3757         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3758
3759         ZERO_STRUCT(create);
3760         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3761         create.in.desired_access = SEC_FILE_ALL;
3762         create.in.fname = sname;
3763         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3764         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3765
3766         status = smb2_create(tree, mem_ctx, &create);
3767         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3768                                            ret, done, "smb2_create failed");
3769
3770 done:
3771         smb2_util_unlink(tree, fname);
3772         smb2_util_rmdir(tree, BASEDIR);
3773         return ret;
3774 }
3775
3776 /*
3777  * This tests that right after creating the AFP_AfpInfo stream,
3778  * reading from the stream returns an empty, default metadata blob of
3779  * 60 bytes.
3780  *
3781  * NOTE: against OS X SMB server this only works if the read request
3782  * is compounded with the create that created the stream, is fails
3783  * otherwise. We don't care...
3784  */
3785 static bool test_null_afpinfo(struct torture_context *tctx,
3786                               struct smb2_tree *tree)
3787 {
3788         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3789         const char *fname = "test_null_afpinfo";
3790         const char *sname = "test_null_afpinfo" AFPINFO_STREAM_NAME;
3791         NTSTATUS status;
3792         bool ret = true;
3793         struct smb2_request *req[3];
3794         struct smb2_handle handle;
3795         struct smb2_create create;
3796         struct smb2_read read;
3797         AfpInfo *afpinfo = NULL;
3798         char *afpinfo_buf = NULL;
3799         const char *type_creator = "SMB,OLE!";
3800
3801         torture_comment(tctx, "Checking create of AfpInfo stream\n");
3802
3803         smb2_util_unlink(tree, fname);
3804
3805         ret = torture_setup_file(mem_ctx, tree, fname, false);
3806         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
3807
3808         ZERO_STRUCT(create);
3809         create.in.desired_access = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA;
3810         create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
3811         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3812         create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
3813         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3814         create.in.fname = sname;
3815
3816         smb2_transport_compound_start(tree->session->transport, 2);
3817
3818         req[0] = smb2_create_send(tree, &create);
3819
3820         handle.data[0] = UINT64_MAX;
3821         handle.data[1] = UINT64_MAX;
3822
3823         smb2_transport_compound_set_related(tree->session->transport, true);
3824
3825         ZERO_STRUCT(read);
3826         read.in.file.handle = handle;
3827         read.in.length = AFP_INFO_SIZE;
3828         req[1] = smb2_read_send(tree, &read);
3829
3830         status = smb2_create_recv(req[0], tree, &create);
3831         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_recv failed");
3832
3833         handle = create.out.file.handle;
3834
3835         status = smb2_read_recv(req[1], tree, &read);
3836         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read_recv failed");
3837
3838         afpinfo = torture_afpinfo_new(mem_ctx);
3839         torture_assert_goto(tctx, afpinfo != NULL, ret, done, "torture_afpinfo_new failed");
3840
3841         memcpy(afpinfo->afpi_FinderInfo, type_creator, 8);
3842
3843         afpinfo_buf = torture_afpinfo_pack(tctx, afpinfo);
3844         torture_assert_goto(tctx, afpinfo_buf != NULL, ret, done, "torture_afpinfo_new failed");
3845
3846         status = smb2_util_write(tree, handle, afpinfo_buf, 0, AFP_INFO_SIZE);
3847         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write failed");
3848
3849         smb2_util_close(tree, handle);
3850
3851         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3852                            0, 60, 16, 8, type_creator);
3853         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
3854
3855 done:
3856         smb2_util_unlink(tree, fname);
3857         talloc_free(mem_ctx);
3858         return ret;
3859 }
3860
3861 static bool test_delete_file_with_rfork(struct torture_context *tctx,
3862                                         struct smb2_tree *tree)
3863 {
3864         const char *fname = "torture_write_rfork_io";
3865         const char *rfork_content = "1234567890";
3866         NTSTATUS status;
3867         bool ret = true;
3868
3869         smb2_util_unlink(tree, fname);
3870
3871         torture_comment(tctx, "Test deleting file with resource fork\n");
3872
3873         ret = torture_setup_file(tctx, tree, fname, false);
3874         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed\n");
3875
3876         ret = write_stream(tree, __location__, tctx, tctx,
3877                            fname, AFPRESOURCE_STREAM_NAME,
3878                            10, 10, rfork_content);
3879         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed\n");
3880
3881         ret = check_stream(tree, __location__, tctx, tctx,
3882                            fname, AFPRESOURCE_STREAM_NAME,
3883                            0, 20, 10, 10, rfork_content);
3884         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed\n");
3885
3886         status = smb2_util_unlink(tree, fname);
3887         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "check_stream failed\n");
3888
3889 done:
3890         return ret;
3891 }
3892
3893 static bool test_rename_and_read_rsrc(struct torture_context *tctx,
3894                                       struct smb2_tree *tree)
3895 {
3896         bool ret = true;
3897         NTSTATUS status;
3898         struct smb2_create create, create2;
3899         struct smb2_handle h1, h2;
3900         const char *fname = "test_rename_openfile";
3901         const char *sname = "test_rename_openfile" AFPRESOURCE_STREAM_NAME;
3902         const char *fname_renamed = "test_rename_openfile_renamed";
3903         const char *data = "1234567890";
3904         union smb_setfileinfo sinfo;
3905         struct smb2_read r;
3906
3907         ret = enable_aapl(tctx, tree);
3908         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
3909
3910         torture_comment(tctx, "Create file with resource fork\n");
3911
3912         ret = torture_setup_file(tctx, tree, fname, false);
3913         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3914
3915         ret = write_stream(tree, __location__, tctx, tctx,
3916                            fname, AFPRESOURCE_STREAM_NAME, 0, 10, data);
3917         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
3918
3919         torture_comment(tctx, "Open resource fork\n");
3920
3921         ZERO_STRUCT(create);
3922         create.in.desired_access = SEC_FILE_ALL;
3923         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3924         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3925         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3926         create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
3927         create.in.fname = sname;
3928
3929         status = smb2_create(tree, tctx, &create);
3930         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3931
3932         h1 = create.out.file.handle;
3933
3934         torture_comment(tctx, "Rename base file\n");
3935
3936         ZERO_STRUCT(create2);
3937         create2.in.desired_access = SEC_FILE_ALL;
3938         create2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3939         create2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3940         create2.in.create_disposition = NTCREATEX_DISP_OPEN;
3941         create2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
3942         create2.in.fname = fname;
3943
3944         status = smb2_create(tree, tctx, &create2);
3945         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3946
3947         h2 = create2.out.file.handle;
3948
3949         ZERO_STRUCT(sinfo);
3950         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
3951         sinfo.rename_information.in.file.handle = h2;
3952         sinfo.rename_information.in.overwrite = 0;
3953         sinfo.rename_information.in.root_fid = 0;
3954         sinfo.rename_information.in.new_name = fname_renamed;
3955
3956         status = smb2_setinfo_file(tree, &sinfo);
3957         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file failed");
3958
3959         smb2_util_close(tree, h2);
3960
3961         ZERO_STRUCT(r);
3962         r.in.file.handle = h1;
3963         r.in.length      = 10;
3964         r.in.offset      = 0;
3965
3966         torture_comment(tctx, "Read resource fork of renamed file\n");
3967
3968         status = smb2_read(tree, tree, &r);
3969         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read failed");
3970
3971         smb2_util_close(tree, h1);
3972
3973         torture_assert_goto(tctx, r.out.data.length == 10, ret, done,
3974                             talloc_asprintf(tctx, "smb2_read returned %jd bytes, expected 10\n",
3975                                             (intmax_t)r.out.data.length));
3976
3977         torture_assert_goto(tctx, memcmp(r.out.data.data, data, 10) == 0, ret, done,
3978                             talloc_asprintf(tctx, "Bad data in stream\n"));
3979
3980 done:
3981         smb2_util_unlink(tree, fname);
3982         smb2_util_unlink(tree, fname_renamed);
3983
3984         return ret;
3985 }
3986
3987 static bool test_readdir_attr_illegal_ntfs(struct torture_context *tctx,
3988                                            struct smb2_tree *tree)
3989 {
3990         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3991         const char *name = "test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
3992         const char *fname = BASEDIR "\\test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
3993         NTSTATUS status;
3994         struct smb2_handle testdirh;
3995         bool ret = true;
3996         struct smb2_create io;
3997         AfpInfo *info;
3998         const char *type_creator = "SMB,OLE!";
3999         struct smb2_find f;
4000         unsigned int count;
4001         union smb_search_data *d;
4002         uint64_t rfork_len;
4003         int i;
4004
4005         smb2_deltree(tree, BASEDIR);
4006
4007         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
4008         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
4009         smb2_util_close(tree, testdirh);
4010
4011         torture_comment(tctx, "Enabling AAPL\n");
4012
4013         ret = enable_aapl(tctx, tree);
4014         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
4015
4016         /*
4017          * Now that Requested AAPL extensions are enabled, setup some
4018          * Mac files with metadata and resource fork
4019          */
4020
4021         torture_comment(tctx, "Preparing file\n");
4022
4023         ret = torture_setup_file(mem_ctx, tree, fname, false);
4024         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
4025
4026         info = torture_afpinfo_new(mem_ctx);
4027         torture_assert_not_null_goto(tctx, info, ret, done, "torture_afpinfo_new failed");
4028
4029         memcpy(info->afpi_FinderInfo, type_creator, 8);
4030         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
4031         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
4032
4033         ret = write_stream(tree, __location__, tctx, mem_ctx,
4034                            fname, AFPRESOURCE_STREAM_NAME,
4035                            0, 3, "foo");
4036         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4037
4038         /*
4039          * Ok, file is prepared, now call smb2/find
4040          */
4041
4042         torture_comment(tctx, "Issue find\n");
4043
4044         ZERO_STRUCT(io);
4045         io.in.desired_access = SEC_RIGHTS_DIR_READ;
4046         io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
4047         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
4048         io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
4049                               NTCREATEX_SHARE_ACCESS_WRITE |
4050                               NTCREATEX_SHARE_ACCESS_DELETE);
4051         io.in.create_disposition = NTCREATEX_DISP_OPEN;
4052         io.in.fname = BASEDIR;
4053         status = smb2_create(tree, tctx, &io);
4054         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4055
4056         ZERO_STRUCT(f);
4057         f.in.file.handle        = io.out.file.handle;
4058         f.in.pattern            = "*";
4059         f.in.max_response_size  = 0x1000;
4060         f.in.level              = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
4061
4062         status = smb2_find_level(tree, tree, &f, &count, &d);
4063         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_level failed");
4064
4065         status = smb2_util_close(tree, io.out.file.handle);
4066         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close failed");
4067
4068         torture_comment(tctx, "Checking find response with enriched macOS metadata\n");
4069
4070         for (i = 0; i < count; i++) {
4071                 const char *found = d[i].id_both_directory_info.name.s;
4072
4073                 if (!strcmp(found, ".") || !strcmp(found, ".."))
4074                         continue;
4075                 if (strncmp(found, "._", 2) == 0) {
4076                         continue;
4077                 }
4078                 break;
4079         }
4080
4081         torture_assert_str_equal_goto(tctx,
4082                                       d[i].id_both_directory_info.name.s, name,
4083                                       ret, done, "bad name");
4084
4085         rfork_len = BVAL(d[i].id_both_directory_info.short_name_buf, 0);
4086         torture_assert_int_equal_goto(tctx, rfork_len, 3, ret, done, "bad resource fork length");
4087
4088         torture_assert_mem_equal_goto(tctx, type_creator,
4089                                       d[i].id_both_directory_info.short_name_buf + 8,
4090                                       8, ret, done, "Bad FinderInfo");
4091 done:
4092         smb2_util_unlink(tree, fname);
4093         smb2_deltree(tree, BASEDIR);
4094         talloc_free(mem_ctx);
4095         return ret;
4096 }
4097
4098 static bool test_invalid_afpinfo(struct torture_context *tctx,
4099                                  struct smb2_tree *tree1,
4100                                  struct smb2_tree *tree2)
4101 {
4102         const char *fname = "filtest_invalid_afpinfo";
4103         const char *sname = "filtest_invalid_afpinfo" AFPINFO_STREAM_NAME;
4104         struct smb2_create create;
4105         const char *streams_basic[] = {
4106                 "::$DATA"
4107         };
4108         const char *streams_afpinfo[] = {
4109                 "::$DATA",
4110                 AFPINFO_STREAM
4111         };
4112         NTSTATUS status;
4113         bool ret = true;
4114
4115         if (tree2 == NULL) {
4116                 torture_skip_goto(tctx, done, "need second share without fruit\n");
4117         }
4118
4119         torture_comment(tctx, "Testing invalid AFP_AfpInfo stream\n");
4120
4121         ret = torture_setup_file(tctx, tree2, fname, false);
4122         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4123
4124         ret = write_stream(tree2, __location__, tctx, tctx,
4125                            fname, AFPINFO_STREAM_NAME,
4126                            0, 3, "foo");
4127         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4128
4129         ret = check_stream_list(tree2, tctx, fname, 2, streams_afpinfo, false);
4130         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4131
4132         torture_comment(tctx, "Listing streams, bad AFPINFO stream must not be present\n");
4133
4134         ret = check_stream_list(tree1, tctx, fname, 1, streams_basic, false);
4135         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4136
4137         torture_comment(tctx, "Try to open AFPINFO stream, must fail\n");
4138
4139         ZERO_STRUCT(create);
4140         create.in.desired_access = SEC_FILE_ALL;
4141         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4142         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4143         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4144         create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4145         create.in.fname = sname;
4146
4147         status = smb2_create(tree1, tctx, &create);
4148         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4149                                            ret, done, "Stream still around?");
4150
4151 done:
4152         smb2_util_unlink(tree1, fname);
4153         return ret;
4154 }
4155
4156 static bool test_zero_file_id(struct torture_context *tctx,
4157                               struct smb2_tree *tree)
4158 {
4159         const char *fname = "filtest_file_id";
4160         struct smb2_create create = {0};
4161         NTSTATUS status;
4162         bool ret = true;
4163         uint8_t zero_file_id[8] = {0};
4164
4165         torture_comment(tctx, "Testing zero file id\n");
4166
4167         ret = torture_setup_file(tctx, tree, fname, false);
4168         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4169
4170         ZERO_STRUCT(create);
4171         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4172         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4173         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4174         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4175         create.in.fname = fname;
4176         create.in.query_on_disk_id = true;
4177
4178         status = smb2_create(tree, tctx, &create);
4179         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
4180                                            done,
4181                                            "test file could not be opened");
4182         torture_assert_mem_not_equal_goto(tctx, create.out.on_disk_id,
4183                                           zero_file_id, 8, ret, done,
4184                                           "unexpected zero file id");
4185
4186         smb2_util_close(tree, create.out.file.handle);
4187
4188         ret = enable_aapl(tctx, tree);
4189         torture_assert(tctx, ret == true, "enable_aapl failed");
4190
4191         ZERO_STRUCT(create);
4192         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4193         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4194         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4195         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4196         create.in.fname = fname;
4197         create.in.query_on_disk_id = true;
4198
4199         status = smb2_create(tree, tctx, &create);
4200         torture_assert_ntstatus_equal_goto(
4201             tctx, status, NT_STATUS_OK, ret, done,
4202             "test file could not be opened with AAPL");
4203         torture_assert_mem_equal_goto(tctx, create.out.on_disk_id, zero_file_id,
4204                                       8, ret, done, "non-zero file id");
4205
4206         smb2_util_close(tree, create.out.file.handle);
4207
4208 done:
4209         smb2_util_unlink(tree, fname);
4210         return ret;
4211 }
4212
4213 static bool copy_one_stream(struct torture_context *torture,
4214                             struct smb2_tree *tree,
4215                             TALLOC_CTX *tmp_ctx,
4216                             const char *src_sname,
4217                             const char *dst_sname)
4218 {
4219         struct smb2_handle src_h = {{0}};
4220         struct smb2_handle dest_h = {{0}};
4221         NTSTATUS status;
4222         union smb_ioctl io;
4223         struct srv_copychunk_copy cc_copy;
4224         struct srv_copychunk_rsp cc_rsp;
4225         enum ndr_err_code ndr_ret;
4226         bool ok = false;
4227
4228         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4229                                    1, /* 1 chunk */
4230                                    src_sname,
4231                                    &src_h, 256, /* fill 256 byte src file */
4232                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4233                                    dst_sname,
4234                                    &dest_h, 0,  /* 0 byte dest file */
4235                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4236                                    &cc_copy,
4237                                    &io);
4238         torture_assert_goto(torture, ok == true, ok, done,
4239                             "setup copy chunk error\n");
4240
4241         /* copy all src file data (via a single chunk desc) */
4242         cc_copy.chunks[0].source_off = 0;
4243         cc_copy.chunks[0].target_off = 0;
4244         cc_copy.chunks[0].length = 256;
4245
4246         ndr_ret = ndr_push_struct_blob(
4247                 &io.smb2.in.out, tmp_ctx, &cc_copy,
4248                 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4249
4250         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4251                                    "ndr_push_srv_copychunk_copy\n");
4252
4253         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4254         torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4255                                         "FSCTL_SRV_COPYCHUNK\n");
4256
4257         ndr_ret = ndr_pull_struct_blob(
4258                 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4259                 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4260
4261         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4262                                    "ndr_pull_srv_copychunk_rsp\n");
4263
4264         ok = check_copy_chunk_rsp(torture, &cc_rsp,
4265                                   1,    /* chunks written */
4266                                   0,    /* chunk bytes unsuccessfully written */
4267                                   256); /* total bytes written */
4268         torture_assert_goto(torture, ok == true, ok, done,
4269                             "bad copy chunk response data\n");
4270
4271         ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 256, 0);
4272         if (!ok) {
4273                 torture_fail(torture, "inconsistent file data\n");
4274         }
4275
4276 done:
4277         if (!smb2_util_handle_empty(src_h)) {
4278                 smb2_util_close(tree, src_h);
4279         }
4280         if (!smb2_util_handle_empty(dest_h)) {
4281                 smb2_util_close(tree, dest_h);
4282         }
4283
4284         return ok;
4285 }
4286
4287 static bool copy_finderinfo_stream(struct torture_context *torture,
4288                                    struct smb2_tree *tree,
4289                                    TALLOC_CTX *tmp_ctx,
4290                                    const char *src_name,
4291                                    const char *dst_name)
4292 {
4293         struct smb2_handle src_h = {{0}};
4294         struct smb2_handle dest_h = {{0}};
4295         NTSTATUS status;
4296         union smb_ioctl io;
4297         struct srv_copychunk_copy cc_copy;
4298         struct srv_copychunk_rsp cc_rsp;
4299         enum ndr_err_code ndr_ret;
4300         const char *type_creator = "SMB,OLE!";
4301         AfpInfo *info = NULL;
4302         const char *src_name_afpinfo = NULL;
4303         const char *dst_name_afpinfo = NULL;
4304         bool ok = false;
4305
4306         src_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", src_name,
4307                                            AFPINFO_STREAM);
4308         torture_assert_not_null_goto(torture, src_name_afpinfo, ok, done,
4309                                      "talloc_asprintf failed\n");
4310
4311         dst_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", dst_name,
4312                                            AFPINFO_STREAM);
4313         torture_assert_not_null_goto(torture, dst_name_afpinfo, ok, done,
4314                                      "talloc_asprintf failed\n");
4315
4316         info = torture_afpinfo_new(tmp_ctx);
4317         torture_assert_not_null_goto(torture, info, ok, done,
4318                                      "torture_afpinfo_new failed\n");
4319
4320         memcpy(info->afpi_FinderInfo, type_creator, 8);
4321         ok = torture_write_afpinfo(tree, torture, tmp_ctx, src_name, info);
4322         torture_assert_goto(torture, ok == true, ok, done,
4323                             "torture_write_afpinfo failed\n");
4324
4325         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4326                                    1, /* 1 chunk */
4327                                    src_name_afpinfo,
4328                                    &src_h, 0,
4329                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4330                                    dst_name_afpinfo,
4331                                    &dest_h, 0,
4332                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4333                                    &cc_copy,
4334                                    &io);
4335         torture_assert_goto(torture, ok == true, ok, done,
4336                             "setup copy chunk error\n");
4337
4338         /* copy all src file data (via a single chunk desc) */
4339         cc_copy.chunks[0].source_off = 0;
4340         cc_copy.chunks[0].target_off = 0;
4341         cc_copy.chunks[0].length = 60;
4342
4343         ndr_ret = ndr_push_struct_blob(
4344                 &io.smb2.in.out, tmp_ctx, &cc_copy,
4345                 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4346
4347         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4348                                    "ndr_push_srv_copychunk_copy\n");
4349
4350         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4351         torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4352                                         "FSCTL_SRV_COPYCHUNK\n");
4353
4354         ndr_ret = ndr_pull_struct_blob(
4355                 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4356                 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4357
4358         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4359                                    "ndr_pull_srv_copychunk_rsp\n");
4360
4361         smb2_util_close(tree, src_h);
4362         ZERO_STRUCT(src_h);
4363         smb2_util_close(tree, dest_h);
4364         ZERO_STRUCT(dest_h);
4365
4366         ok = check_copy_chunk_rsp(torture, &cc_rsp,
4367                                   1,    /* chunks written */
4368                                   0,    /* chunk bytes unsuccessfully written */
4369                                   60); /* total bytes written */
4370         torture_assert_goto(torture, ok == true, ok, done,
4371                             "bad copy chunk response data\n");
4372
4373         ok = check_stream(tree, __location__, torture, tmp_ctx,
4374                           dst_name, AFPINFO_STREAM,
4375                           0, 60, 16, 8, type_creator);
4376         torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
4377
4378 done:
4379         if (!smb2_util_handle_empty(src_h)) {
4380                 smb2_util_close(tree, src_h);
4381         }
4382         if (!smb2_util_handle_empty(dest_h)) {
4383                 smb2_util_close(tree, dest_h);
4384         }
4385
4386         return ok;
4387 }
4388
4389 static bool test_copy_chunk_streams(struct torture_context *torture,
4390                                     struct smb2_tree *tree)
4391 {
4392         const char *src_name = "src";
4393         const char *dst_name = "dst";
4394         struct names {
4395                 const char *src_sname;
4396                 const char *dst_sname;
4397         } names[] = {
4398                 { "src:foo", "dst:foo" },
4399                 { "src" AFPRESOURCE_STREAM, "dst" AFPRESOURCE_STREAM }
4400         };
4401         int i;
4402         TALLOC_CTX *tmp_ctx = NULL;
4403         bool ok = false;
4404
4405         tmp_ctx = talloc_new(tree);
4406         torture_assert_not_null_goto(torture, tmp_ctx, ok, done,
4407                                      "torture_setup_file\n");
4408
4409         smb2_util_unlink(tree, src_name);
4410         smb2_util_unlink(tree, dst_name);
4411
4412         ok = torture_setup_file(torture, tree, src_name, false);
4413         torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
4414         ok = torture_setup_file(torture, tree, dst_name, false);
4415         torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
4416
4417         for (i = 0; i < ARRAY_SIZE(names); i++) {
4418                 ok = copy_one_stream(torture, tree, tmp_ctx,
4419                                      names[i].src_sname,
4420                                      names[i].dst_sname);
4421                 torture_assert_goto(torture, ok == true, ok, done,
4422                                     "copy_one_stream failed\n");
4423         }
4424
4425         ok = copy_finderinfo_stream(torture, tree, tmp_ctx,
4426                                     src_name, dst_name);
4427         torture_assert_goto(torture, ok == true, ok, done,
4428                             "copy_finderinfo_stream failed\n");
4429
4430 done:
4431         smb2_util_unlink(tree, src_name);
4432         smb2_util_unlink(tree, dst_name);
4433         talloc_free(tmp_ctx);
4434         return ok;
4435 }
4436
4437 /*
4438  * Ensure this security descriptor has exactly one mode, uid
4439  * and gid.
4440  */
4441
4442 static NTSTATUS check_nfs_sd(const struct security_descriptor *psd)
4443 {
4444         uint32_t i;
4445         bool got_one_mode = false;
4446         bool got_one_uid = false;
4447         bool got_one_gid = false;
4448
4449         if (psd->dacl == NULL) {
4450                 return NT_STATUS_INVALID_SECURITY_DESCR;
4451         }
4452
4453         for (i = 0; i < psd->dacl->num_aces; i++) {
4454                 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Mode,
4455                                            &psd->dacl->aces[i].trustee) == 0) {
4456                         if (got_one_mode == true) {
4457                                 /* Can't have more than one. */
4458                                 return NT_STATUS_INVALID_SECURITY_DESCR;
4459                         }
4460                         got_one_mode = true;
4461                 }
4462         }
4463         for (i = 0; i < psd->dacl->num_aces; i++) {
4464                 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Users,
4465                                            &psd->dacl->aces[i].trustee) == 0) {
4466                         if (got_one_uid == true) {
4467                                 /* Can't have more than one. */
4468                                 return NT_STATUS_INVALID_SECURITY_DESCR;
4469                         }
4470                         got_one_uid = true;
4471                 }
4472         }
4473         for (i = 0; i < psd->dacl->num_aces; i++) {
4474                 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Groups,
4475                                            &psd->dacl->aces[i].trustee) == 0) {
4476                         if (got_one_gid == true) {
4477                                 /* Can't have more than one. */
4478                                 return NT_STATUS_INVALID_SECURITY_DESCR;
4479                         }
4480                         got_one_gid = true;
4481                 }
4482         }
4483         /* Must have at least one of each. */
4484         if (got_one_mode == false ||
4485                         got_one_uid == false ||
4486                         got_one_gid == false) {
4487                 return NT_STATUS_INVALID_SECURITY_DESCR;
4488         }
4489         return NT_STATUS_OK;
4490 }
4491
4492 static bool test_nfs_aces(struct torture_context *tctx,
4493                           struct smb2_tree *tree)
4494 {
4495         TALLOC_CTX *mem_ctx = talloc_new(tctx);
4496         struct security_ace ace;
4497         struct dom_sid sid;
4498         const char *fname = BASEDIR "\\nfs_aces.txt";
4499         struct smb2_handle h = {{0}};
4500         union smb_fileinfo finfo2;
4501         union smb_setfileinfo set;
4502         struct security_descriptor *psd = NULL;
4503         NTSTATUS status;
4504         bool ret = true;
4505
4506         ret = enable_aapl(tctx, tree);
4507         torture_assert(tctx, ret == true, "enable_aapl failed");
4508
4509         /* clean slate ...*/
4510         smb2_util_unlink(tree, fname);
4511         smb2_deltree(tree, fname);
4512         smb2_deltree(tree, BASEDIR);
4513
4514         status = torture_smb2_testdir(tree, BASEDIR, &h);
4515         CHECK_STATUS(status, NT_STATUS_OK);
4516         smb2_util_close(tree, h);
4517
4518         /* Create a test file. */
4519         status = torture_smb2_testfile_access(tree,
4520                                 fname,
4521                                 &h,
4522                                 SEC_STD_READ_CONTROL |
4523                                 SEC_STD_WRITE_DAC |
4524                                 SEC_RIGHTS_FILE_ALL);
4525         CHECK_STATUS(status, NT_STATUS_OK);
4526
4527         /* Get the ACL. */
4528         finfo2.query_secdesc.in.secinfo_flags =
4529                 SECINFO_OWNER |
4530                 SECINFO_GROUP |
4531                 SECINFO_DACL;
4532         finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
4533         finfo2.generic.in.file.handle = h;
4534         status = smb2_getinfo_file(tree, tctx, &finfo2);
4535         CHECK_STATUS(status, NT_STATUS_OK);
4536
4537         psd = finfo2.query_secdesc.out.sd;
4538
4539         /* Ensure we have only single mode/uid/gid NFS entries. */
4540         status = check_nfs_sd(psd);
4541         if (!NT_STATUS_IS_OK(status)) {
4542                 NDR_PRINT_DEBUG(
4543                         security_descriptor,
4544                         discard_const_p(struct security_descriptor, psd));
4545         }
4546         CHECK_STATUS(status, NT_STATUS_OK);
4547
4548         /* Add a couple of extra NFS uids and gids. */
4549         sid_compose(&sid, &global_sid_Unix_NFS_Users, 27);
4550         init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
4551         status = security_descriptor_dacl_add(psd, &ace);
4552         CHECK_STATUS(status, NT_STATUS_OK);
4553         status = security_descriptor_dacl_add(psd, &ace);
4554         CHECK_STATUS(status, NT_STATUS_OK);
4555
4556         sid_compose(&sid, &global_sid_Unix_NFS_Groups, 300);
4557         init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
4558         status = security_descriptor_dacl_add(psd, &ace);
4559         CHECK_STATUS(status, NT_STATUS_OK);
4560         status = security_descriptor_dacl_add(psd, &ace);
4561         CHECK_STATUS(status, NT_STATUS_OK);
4562
4563         /* Now set on the file handle. */
4564         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
4565         set.set_secdesc.in.file.handle = h;
4566         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
4567         set.set_secdesc.in.sd = psd;
4568         status = smb2_setinfo_file(tree, &set);
4569         CHECK_STATUS(status, NT_STATUS_OK);
4570
4571         /* Get the ACL again. */
4572         finfo2.query_secdesc.in.secinfo_flags =
4573                 SECINFO_OWNER |
4574                 SECINFO_GROUP |
4575                 SECINFO_DACL;
4576         finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
4577         finfo2.generic.in.file.handle = h;
4578         status = smb2_getinfo_file(tree, tctx, &finfo2);
4579         CHECK_STATUS(status, NT_STATUS_OK);
4580
4581         psd = finfo2.query_secdesc.out.sd;
4582
4583         /* Ensure we have only single mode/uid/gid NFS entries. */
4584         status = check_nfs_sd(psd);
4585         if (!NT_STATUS_IS_OK(status)) {
4586                 NDR_PRINT_DEBUG(
4587                         security_descriptor,
4588                         discard_const_p(struct security_descriptor, psd));
4589         }
4590         CHECK_STATUS(status, NT_STATUS_OK);
4591
4592 done:
4593         if (!smb2_util_handle_empty(h)) {
4594                 smb2_util_close(tree, h);
4595         }
4596         smb2_util_unlink(tree, fname);
4597         smb2_deltree(tree, fname);
4598         smb2_deltree(tree, BASEDIR);
4599         talloc_free(mem_ctx);
4600         return ret;
4601 }
4602
4603 /*
4604  * Note: This test depends on "vfs objects = catia fruit streams_xattr".  For
4605  * some tests torture must be run on the host it tests and takes an additional
4606  * argument with the local path to the share:
4607  * "--option=torture:localdir=<SHAREPATH>".
4608  *
4609  * When running against an OS X SMB server add "--option=torture:osx=true"
4610  */
4611 struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx)
4612 {
4613         struct torture_suite *suite = torture_suite_create(
4614                 ctx, "fruit");
4615
4616         suite->description = talloc_strdup(suite, "vfs_fruit tests");
4617
4618         torture_suite_add_1smb2_test(suite, "copyfile", test_copyfile);
4619         torture_suite_add_1smb2_test(suite, "read metadata", test_read_afpinfo);
4620         torture_suite_add_1smb2_test(suite, "write metadata", test_write_atalk_metadata);
4621         torture_suite_add_1smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io);
4622         torture_suite_add_1smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl);
4623         torture_suite_add_1smb2_test(suite, "stream names", test_stream_names);
4624         torture_suite_add_1smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate);
4625         torture_suite_add_1smb2_test(suite, "opening and creating resource fork", test_rfork_create);
4626         torture_suite_add_1smb2_test(suite, "rename_dir_openfile", test_rename_dir_openfile);
4627         torture_suite_add_1smb2_test(suite, "File without AFP_AfpInfo", test_afpinfo_enoent);
4628         torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpInfo", test_create_delete_on_close);
4629         torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpInfo", test_setinfo_delete_on_close);
4630         torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpInfo", test_setinfo_eof);
4631         torture_suite_add_1smb2_test(suite, "delete AFP_AfpInfo by writing all 0", test_afpinfo_all0);
4632         torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpResource", test_create_delete_on_close_resource);
4633         torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpResource", test_setinfo_delete_on_close_resource);
4634         torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpResource", test_setinfo_eof_resource);
4635         torture_suite_add_1smb2_test(suite, "null afpinfo", test_null_afpinfo);
4636         torture_suite_add_1smb2_test(suite, "delete", test_delete_file_with_rfork);
4637         torture_suite_add_1smb2_test(suite, "read open rsrc after rename", test_rename_and_read_rsrc);
4638         torture_suite_add_1smb2_test(suite, "readdir_attr with names with illegal ntfs characters", test_readdir_attr_illegal_ntfs);
4639         torture_suite_add_2ns_smb2_test(suite, "invalid AFP_AfpInfo", test_invalid_afpinfo);
4640         torture_suite_add_1smb2_test(suite, "creating rsrc with read-only access", test_rfork_create_ro);
4641         torture_suite_add_1smb2_test(suite, "copy-chunk streams", test_copy_chunk_streams);
4642         torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
4643         torture_suite_add_1smb2_test(suite, "NFS ACE entries", test_nfs_aces);
4644
4645         return suite;
4646 }
4647
4648 static bool test_stream_names_local(struct torture_context *tctx,
4649                                     struct smb2_tree *tree)
4650 {
4651         TALLOC_CTX *mem_ctx = talloc_new(tctx);
4652         NTSTATUS status;
4653         struct smb2_create create;
4654         struct smb2_handle h;
4655         const char *fname = BASEDIR "\\stream_names.txt";
4656         const char *sname1;
4657         bool ret;
4658         /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
4659         const char *streams[] = {
4660                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
4661                 ":bar" "\xef\x80\xa2" "baz:$DATA", /* "bar:baz:$DATA" */
4662                 "::$DATA"
4663         };
4664         const char *localdir = NULL;
4665
4666         localdir = torture_setting_string(tctx, "localdir", NULL);
4667         if (localdir == NULL) {
4668                 torture_skip(tctx, "Need localdir for test");
4669         }
4670
4671         sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
4672
4673         /* clean slate ...*/
4674         smb2_util_unlink(tree, fname);
4675         smb2_deltree(tree, fname);
4676         smb2_deltree(tree, BASEDIR);
4677
4678         status = torture_smb2_testdir(tree, BASEDIR, &h);
4679         CHECK_STATUS(status, NT_STATUS_OK);
4680         smb2_util_close(tree, h);
4681
4682         torture_comment(tctx, "(%s) testing stream names\n", __location__);
4683         ZERO_STRUCT(create);
4684         create.in.desired_access = SEC_FILE_WRITE_DATA;
4685         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4686         create.in.share_access =
4687                 NTCREATEX_SHARE_ACCESS_DELETE|
4688                 NTCREATEX_SHARE_ACCESS_READ|
4689                 NTCREATEX_SHARE_ACCESS_WRITE;
4690         create.in.create_disposition = NTCREATEX_DISP_CREATE;
4691         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4692         create.in.fname = sname1;
4693
4694         status = smb2_create(tree, mem_ctx, &create);
4695         CHECK_STATUS(status, NT_STATUS_OK);
4696         smb2_util_close(tree, create.out.file.handle);
4697
4698         ret = torture_setup_local_xattr(tctx, "localdir", BASEDIR "/stream_names.txt",
4699                                         "user.DosStream.bar:baz:$DATA",
4700                                         "data", strlen("data"));
4701         CHECK_VALUE(ret, true);
4702
4703         ret = check_stream_list(tree, tctx, fname, 3, streams, false);
4704         CHECK_VALUE(ret, true);
4705
4706 done:
4707         status = smb2_util_unlink(tree, fname);
4708         smb2_deltree(tree, BASEDIR);
4709         talloc_free(mem_ctx);
4710
4711         return ret;
4712 }
4713
4714 struct torture_suite *torture_vfs_fruit_netatalk(TALLOC_CTX *ctx)
4715 {
4716         struct torture_suite *suite = torture_suite_create(
4717                 ctx, "fruit_netatalk");
4718
4719         suite->description = talloc_strdup(suite, "vfs_fruit tests for Netatalk interop that require fruit:metadata=netatalk");
4720
4721         torture_suite_add_1smb2_test(suite, "read netatalk metadata", test_read_netatalk_metadata);
4722         torture_suite_add_1smb2_test(suite, "stream names with locally created xattr", test_stream_names_local);
4723
4724         return suite;
4725 }
4726
4727 struct torture_suite *torture_vfs_fruit_file_id(TALLOC_CTX *ctx)
4728 {
4729         struct torture_suite *suite =
4730             torture_suite_create(ctx, "fruit_file_id");
4731
4732         suite->description =
4733             talloc_strdup(suite, "vfs_fruit tests for on-disk file ID that "
4734                                  "require fruit:zero_file_id=yes");
4735
4736         torture_suite_add_1smb2_test(suite, "zero file id if AAPL negotiated",
4737                                      test_zero_file_id);
4738
4739         return suite;
4740 }
4741
4742 static bool test_timemachine_volsize(struct torture_context *tctx,
4743                                      struct smb2_tree *tree)
4744 {
4745         TALLOC_CTX *mem_ctx = talloc_new(tctx);
4746         struct smb2_handle h = {{0}};
4747         union smb_fsinfo fsinfo;
4748         NTSTATUS status;
4749         bool ok = true;
4750         const char *info_plist =
4751                 "<dict>\n"
4752                 "        <key>band-size</key>\n"
4753                 "        <integer>8192</integer>\n"
4754                 "</dict>\n";
4755
4756         smb2_deltree(tree, "test.sparsebundle");
4757
4758         ok = enable_aapl(tctx, tree);
4759         torture_assert_goto(tctx, ok, ok, done, "enable_aapl failed");
4760
4761         status = smb2_util_mkdir(tree, "test.sparsebundle");
4762         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
4763                                         "smb2_util_mkdir\n");
4764
4765         ok = write_stream(tree, __location__, tctx, mem_ctx,
4766                           "test.sparsebundle/Info.plist", NULL,
4767                            0, strlen(info_plist), info_plist);
4768         torture_assert_goto(tctx, ok, ok, done, "write_stream failed\n");
4769
4770         status = smb2_util_mkdir(tree, "test.sparsebundle/bands");
4771         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
4772                                         "smb2_util_mkdir\n");
4773
4774         ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/1", false);
4775         torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
4776
4777         ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/2", false);
4778         torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
4779
4780         status = smb2_util_roothandle(tree, &h);
4781         torture_assert_ntstatus_ok(tctx, status, "Unable to create root handle");
4782
4783         ZERO_STRUCT(fsinfo);
4784         fsinfo.generic.level = RAW_QFS_SIZE_INFORMATION;
4785         fsinfo.generic.handle = h;
4786
4787         status = smb2_getinfo_fs(tree, tree, &fsinfo);
4788         torture_assert_ntstatus_ok(tctx, status, "smb2_getinfo_fs failed");
4789
4790         torture_comment(tctx, "sectors_per_unit: %" PRIu32"\n"
4791                         "bytes_per_sector: %" PRIu32"\n"
4792                         "total_alloc_units: %" PRIu64"\n"
4793                         "avail_alloc_units: %" PRIu64"\n",
4794                         fsinfo.size_info.out.sectors_per_unit,
4795                         fsinfo.size_info.out.bytes_per_sector,
4796                         fsinfo.size_info.out.total_alloc_units,
4797                         fsinfo.size_info.out.avail_alloc_units);
4798
4799         /*
4800          * Let me explain the numbers:
4801          *
4802          * - the share is set to "fruit:time machine max size = 32K"
4803          * - we've faked a bandsize of 8 K in the Info.plist file
4804          * - we've created two bands files
4805          * - one allocation unit is made of two sectors with 512 B each
4806          * => we've consumed 16 allocation units, there should be 16 free
4807          */
4808
4809         torture_assert_goto(tctx, fsinfo.size_info.out.sectors_per_unit == 2,
4810                             ok, done, "Bad sectors_per_unit");
4811
4812         torture_assert_goto(tctx, fsinfo.size_info.out.bytes_per_sector == 512,
4813                             ok, done, "Bad bytes_per_sector");
4814
4815         torture_assert_goto(tctx, fsinfo.size_info.out.total_alloc_units == 32,
4816                             ok, done, "Bad total_alloc_units");
4817
4818         torture_assert_goto(tctx, fsinfo.size_info.out.avail_alloc_units == 16,
4819                             ok, done, "Bad avail_alloc_units");
4820
4821 done:
4822         if (!smb2_util_handle_empty(h)) {
4823                 smb2_util_close(tree, h);
4824         }
4825         smb2_deltree(tree, "test.sparsebundle");
4826         talloc_free(mem_ctx);
4827         return ok;
4828 }
4829
4830 struct torture_suite *torture_vfs_fruit_timemachine(TALLOC_CTX *ctx)
4831 {
4832         struct torture_suite *suite = torture_suite_create(
4833                 ctx, "fruit_timemachine");
4834
4835         suite->description = talloc_strdup(
4836                 suite, "vfs_fruit tests for TimeMachine");
4837
4838         torture_suite_add_1smb2_test(suite, "Timemachine-volsize",
4839                                      test_timemachine_volsize);
4840
4841         return suite;
4842 }