s4/torture: fruit: in test_adouble_conversion() also check stream list and AFPINFO_STREAM
[amitay/samba.git] / source4 / torture / vfs / fruit.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    vfs_fruit tests
5
6    Copyright (C) Ralph Boehme 2014
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "system/filesys.h"
24 #include "libcli/libcli.h"
25 #include "libcli/smb2/smb2.h"
26 #include "libcli/smb2/smb2_calls.h"
27 #include "libcli/smb/smb2_create_ctx.h"
28 #include "lib/cmdline/popt_common.h"
29 #include "param/param.h"
30 #include "libcli/resolve/resolve.h"
31 #include "MacExtensions.h"
32 #include "lib/util/tsort.h"
33
34 #include "torture/torture.h"
35 #include "torture/util.h"
36 #include "torture/smb2/proto.h"
37 #include "torture/vfs/proto.h"
38 #include "librpc/gen_ndr/ndr_ioctl.h"
39
40 #define BASEDIR "vfs_fruit_dir"
41 #define FNAME_CC_SRC "testfsctl.dat"
42 #define FNAME_CC_DST "testfsctl2.dat"
43
44 #define CHECK_STATUS(status, correct) do { \
45         if (!NT_STATUS_EQUAL(status, correct)) { \
46                 torture_result(tctx, TORTURE_FAIL, \
47                     "(%s) Incorrect status %s - should be %s\n", \
48                     __location__, nt_errstr(status), nt_errstr(correct)); \
49                 ret = false; \
50                 goto done; \
51         }} while (0)
52
53 #define CHECK_VALUE(v, correct) do { \
54         if ((v) != (correct)) { \
55                 torture_result(tctx, TORTURE_FAIL, \
56                                "(%s) Incorrect value %s=%u - should be %u\n", \
57                                __location__, #v, (unsigned)v, (unsigned)correct); \
58                 ret = false; \
59                 goto done; \
60         }} while (0)
61
62 static bool check_stream_list(struct smb2_tree *tree,
63                               struct torture_context *tctx,
64                               const char *fname,
65                               int num_exp,
66                               const char **exp,
67                               bool is_dir);
68
69 static int qsort_string(char * const *s1, char * const *s2)
70 {
71         return strcmp(*s1, *s2);
72 }
73
74 static int qsort_stream(const struct stream_struct * s1, const struct stream_struct *s2)
75 {
76         return strcmp(s1->stream_name.s, s2->stream_name.s);
77 }
78
79 /*
80  * REVIEW:
81  * This is hokey, but what else can we do?
82  */
83 #if defined(HAVE_ATTROPEN) || defined(FREEBSD)
84 #define AFPINFO_EA_NETATALK "org.netatalk.Metadata"
85 #define AFPRESOURCE_EA_NETATALK "org.netatalk.ResourceFork"
86 #else
87 #define AFPINFO_EA_NETATALK "user.org.netatalk.Metadata"
88 #define AFPRESOURCE_EA_NETATALK "user.org.netatalk.ResourceFork"
89 #endif
90
91 /*
92 The metadata xattr char buf below contains the following attributes:
93
94 -------------------------------------------------------------------------------
95 Entry ID   : 00000008 : File Dates Info
96 Offset     : 00000162 : 354
97 Length     : 00000010 : 16
98
99 -DATE------:          : (GMT)                    : (Local)
100 create     : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
101 modify     : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
102 backup     : 80000000 : Unknown or Initial
103 access     : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
104
105 -RAW DUMP--:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
106 00000000   : 1B 44 21 69 1B 44 21 69 80 00 00 00 1B 44 21 69 : .D!i.D!i.....D!i
107
108 -------------------------------------------------------------------------------
109 Entry ID   : 00000009 : Finder Info
110 Offset     : 0000007A : 122
111 Length     : 00000020 : 32
112
113 -FInfo-----:
114 Type       : 42415252 : BARR
115 Creator    : 464F4F4F : FOOO
116 isAlias    : 0
117 Invisible  : 1
118 hasBundle  : 0
119 nameLocked : 0
120 Stationery : 0
121 CustomIcon : 0
122 Reserved   : 0
123 Inited     : 0
124 NoINITS    : 0
125 Shared     : 0
126 SwitchLaunc: 0
127 Hidden Ext : 0
128 color      : 000      : none
129 isOnDesk   : 0
130 Location v : 0000     : 0
131 Location h : 0000     : 0
132 Fldr       : 0000     : ..
133
134 -FXInfo----:
135 Rsvd|IconID: 0000     : 0
136 Rsvd       : 0000     : ..
137 Rsvd       : 0000     : ..
138 Rsvd       : 0000     : ..
139 AreInvalid : 0
140 unknown bit: 0
141 unknown bit: 0
142 unknown bit: 0
143 unknown bit: 0
144 unknown bit: 0
145 unknown bit: 0
146 CustomBadge: 0
147 ObjctIsBusy: 0
148 unknown bit: 0
149 unknown bit: 0
150 unknown bit: 0
151 unknown bit: 0
152 RoutingInfo: 0
153 unknown bit: 0
154 unknown bit: 0
155 Rsvd|commnt: 0000     : 0
156 PutAway    : 00000000 : 0
157
158 -RAW DUMP--:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
159 00000000   : 42 41 52 52 46 4F 4F 4F 40 00 00 00 00 00 00 00 : BARRFOOO@.......
160 00000010   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
161
162 -------------------------------------------------------------------------------
163 Entry ID   : 0000000E : AFP File Info
164 Offset     : 00000172 : 370
165 Length     : 00000004 : 4
166
167 -RAW DUMP--:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
168 00000000   : 00 00 01 A1                                     : ....
169  */
170
171 char metadata_xattr[] = {
172         0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
173         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175         0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
176         0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177         0x00, 0x08, 0x00, 0x00, 0x01, 0x62, 0x00, 0x00,
178         0x00, 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
179         0x00, 0x7a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
180         0x00, 0x0e, 0x00, 0x00, 0x01, 0x72, 0x00, 0x00,
181         0x00, 0x04, 0x80, 0x44, 0x45, 0x56, 0x00, 0x00,
182         0x01, 0x76, 0x00, 0x00, 0x00, 0x08, 0x80, 0x49,
183         0x4e, 0x4f, 0x00, 0x00, 0x01, 0x7e, 0x00, 0x00,
184         0x00, 0x08, 0x80, 0x53, 0x59, 0x4e, 0x00, 0x00,
185         0x01, 0x86, 0x00, 0x00, 0x00, 0x08, 0x80, 0x53,
186         0x56, 0x7e, 0x00, 0x00, 0x01, 0x8e, 0x00, 0x00,
187         0x00, 0x04, 0x42, 0x41, 0x52, 0x52, 0x46, 0x4f,
188         0x4f, 0x4f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
189         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192         0x00, 0x00, 0x00, 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, 0x1b, 0x44, 0x21, 0x69, 0x1b, 0x44,
217         0x21, 0x69, 0x80, 0x00, 0x00, 0x00, 0x1b, 0x44,
218         0x21, 0x69, 0x00, 0x00, 0x01, 0xa1, 0x00, 0xfd,
219         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x20,
220         0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xe3,
221         0x86, 0x53, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x01,
222         0x00, 0x00
223 };
224
225 /*
226 The buf below contains the following AppleDouble encoded data:
227
228 -------------------------------------------------------------------------------
229 MagicNumber: 00051607                                        : AppleDouble
230 Version    : 00020000                                        : Version 2
231 Filler     : 4D 61 63 20 4F 53 20 58 20 20 20 20 20 20 20 20 : Mac OS X
232 Num. of ent: 0002                                            : 2
233
234 -------------------------------------------------------------------------------
235 Entry ID   : 00000009 : Finder Info
236 Offset     : 00000032 : 50
237 Length     : 00000EB0 : 3760
238
239 -FInfo-----:
240 Type       : 54455354 : TEST
241 Creator    : 534C4F57 : SLOW
242 isAlias    : 0
243 Invisible  : 0
244 hasBundle  : 0
245 nameLocked : 0
246 Stationery : 0
247 CustomIcon : 0
248 Reserved   : 0
249 Inited     : 0
250 NoINITS    : 0
251 Shared     : 0
252 SwitchLaunc: 0
253 Hidden Ext : 0
254 color      : 100      : blue
255 isOnDesk   : 0
256 Location v : 0000     : 0
257 Location h : 0000     : 0
258 Fldr       : 0000     : ..
259
260 -FXInfo----:
261 Rsvd|IconID: 0000     : 0
262 Rsvd       : 0000     : ..
263 Rsvd       : 0000     : ..
264 Rsvd       : 0000     : ..
265 AreInvalid : 0
266 unknown bit: 0
267 unknown bit: 0
268 unknown bit: 0
269 unknown bit: 0
270 unknown bit: 0
271 unknown bit: 0
272 CustomBadge: 0
273 ObjctIsBusy: 0
274 unknown bit: 0
275 unknown bit: 0
276 unknown bit: 0
277 unknown bit: 0
278 RoutingInfo: 0
279 unknown bit: 0
280 unknown bit: 0
281 Rsvd|commnt: 0000     : 0
282 PutAway    : 00000000 : 0
283
284 -EA--------:
285 pad        : 0000     : ..
286 magic      : 41545452 : ATTR
287 debug_tag  : 53D4580C : 1406425100
288 total_size : 00000EE2 : 3810
289 data_start : 000000BC : 188
290 data_length: 0000005E : 94
291 reserved[0]: 00000000 : ....
292 reserved[1]: 00000000 : ....
293 reserved[2]: 00000000 : ....
294 flags      : 0000     : ..
295 num_attrs  : 0002     : 2
296 -EA ENTRY--:
297 offset     : 000000BC : 188
298 length     : 0000005B : 91
299 flags      : 0000     : ..
300 namelen    : 24       : 36
301 -EA NAME---:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
302 00000000   : 63 6F 6D 2E 61 70 70 6C 65 2E 6D 65 74 61 64 61 : com.apple.metada
303 00000010   : 74 61 3A 5F 6B 4D 44 49 74 65 6D 55 73 65 72 54 : ta:_kMDItemUserT
304 00000020   : 61 67 73 00                                     : ags.
305 -EA VALUE--:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
306 00000000   : 62 70 6C 69 73 74 30 30 A5 01 02 03 04 05 54 74 : bplist00......Tt
307 00000010   : 65 73 74 66 00 47 00 72 00 FC 00 6E 00 0A 00 32 : estf.G.r...n...2
308 00000020   : 56 4C 69 6C 61 0A 33 56 47 65 6C 62 0A 35 56 42 : VLila.3VGelb.5VB
309 00000030   : 6C 61 75 0A 34 08 0E 13 20 27 2E 00 00 00 00 00 : lau.4... '......
310 00000040   : 00 01 01 00 00 00 00 00 00 00 06 00 00 00 00 00 : ................
311 00000050   : 00 00 00 00 00 00 00 00 00 00 35                : ..........5
312 -EA ENTRY--:
313 offset     : 00000117 : 279
314 length     : 00000003 : 3
315 flags      : 0000     : ..
316 namelen    : 08       : 8
317 -EA NAME---:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
318 00000000   : 66 6F 6F 3A 62 61 72 00                         : foo:bar.
319 -EA VALUE--:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
320 00000000   : 62 61 7A                                        : baz
321
322 -RAW DUMP--:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
323 00000000   : 54 45 53 54 53 4C 4F 57 00 08 00 00 00 00 00 00 : TESTSLOW........
324 00000010   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
325 00000020   : 00 00 41 54 54 52 53 D4 58 0C 00 00 0E E2 00 00 : ..ATTRS.X.......
326 00000030   : 00 BC 00 00 00 5E 00 00 00 00 00 00 00 00 00 00 : .....^..........
327 00000040   : 00 00 00 00 00 02 00 00 00 BC 00 00 00 5B 00 00 : .............[..
328 00000050   : 24 63 6F 6D 2E 61 70 70 6C 65 2E 6D 65 74 61 64 : $com.apple.metad
329 00000060   : 61 74 61 3A 5F 6B 4D 44 49 74 65 6D 55 73 65 72 : ata:_kMDItemUser
330 00000070   : 54 61 67 73 00 00 00 00 01 17 00 00 00 03 00 00 : Tags............
331 00000080   : 08 66 6F 6F 3A 62 61 72 00 66 62 70 6C 69 73 74 : .foo:bar.fbplist
332 00000090   : 30 30 A5 01 02 03 04 05 54 74 65 73 74 66 00 47 : 00......Ttestf.G
333 000000A0   : 00 72 00 FC 00 6E 00 0A 00 32 56 4C 69 6C 61 0A : .r...n...2VLila.
334 000000B0   : 33 56 47 65 6C 62 0A 35 56 42 6C 61 75 0A 34 08 : 3VGelb.5VBlau.4.
335 000000C0   : 0E 13 20 27 2E 00 00 00 00 00 00 01 01 00 00 00 : .. '............
336 000000D0   : 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 : ................
337 000000E0   : 00 00 00 00 35 62 61 7A 00 00 00 00 00 00 00 00 : ....5baz........
338 000000F0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
339 ... all zeroes ...
340 00000EA0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
341
342 -------------------------------------------------------------------------------
343 Entry ID   : 00000002 : Resource Fork
344 Offset     : 00000EE2 : 3810
345 Length     : 0000011E : 286
346
347 -RAW DUMP--:  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F : (ASCII)
348 00000000   : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
349 00000010   : 54 68 69 73 20 72 65 73 6F 75 72 63 65 20 66 6F : This resource fo
350 00000020   : 72 6B 20 69 6E 74 65 6E 74 69 6F 6E 61 6C 6C 79 : rk intentionally
351 00000030   : 20 6C 65 66 74 20 62 6C 61 6E 6B 20 20 20 00 00 :  left blank   ..
352 00000040   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
353 00000050   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
354 00000060   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
355 00000070   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
356 00000080   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
357 00000090   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
358 000000A0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
359 000000B0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
360 000000C0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
361 000000D0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
362 000000E0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
363 000000F0   : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
364 00000100   : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
365 00000110   : 00 00 00 00 00 00 00 00 00 1C 00 1E FF FF       : ..............
366
367 It was created with:
368 $ hexdump -ve '"\t" 7/1 "0x%02x, " 1/1 " 0x%02x," "\n"'
369 */
370 static char osx_adouble_w_xattr[] = {
371         0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
372         0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58,
373         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
374         0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
375         0x00, 0x32, 0x00, 0x00, 0x0e, 0xb0, 0x00, 0x00,
376         0x00, 0x02, 0x00, 0x00, 0x0e, 0xe2, 0x00, 0x00,
377         0x01, 0x1e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x4c,
378         0x4f, 0x57, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
379         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
381         0x00, 0x00, 0x00, 0x00, 0x41, 0x54, 0x54, 0x52,
382         0x53, 0xd4, 0x58, 0x0c, 0x00, 0x00, 0x0e, 0xe2,
383         0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x5e,
384         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
386         0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x5b,
387         0x00, 0x00, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x61,
388         0x70, 0x70, 0x6c, 0x65, 0x2e, 0x6d, 0x65, 0x74,
389         0x61, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x5f, 0x6b,
390         0x4d, 0x44, 0x49, 0x74, 0x65, 0x6d, 0x55, 0x73,
391         0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x00, 0x00,
392         0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x00, 0x03,
393         0x00, 0x00, 0x08, 0x66, 0x6f, 0x6f, 0x3a, 0x62,
394         0x61, 0x72, 0x00, 0x66, 0x62, 0x70, 0x6c, 0x69,
395         0x73, 0x74, 0x30, 0x30, 0xa5, 0x01, 0x02, 0x03,
396         0x04, 0x05, 0x54, 0x74, 0x65, 0x73, 0x74, 0x66,
397         0x00, 0x47, 0x00, 0x72, 0x00, 0xfc, 0x00, 0x6e,
398         0x00, 0x0a, 0x00, 0x32, 0x56, 0x4c, 0x69, 0x6c,
399         0x61, 0x0a, 0x33, 0x56, 0x47, 0x65, 0x6c, 0x62,
400         0x0a, 0x35, 0x56, 0x42, 0x6c, 0x61, 0x75, 0x0a,
401         0x34, 0x08, 0x0e, 0x13, 0x20, 0x27, 0x2e, 0x00,
402         0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
403         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
404         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
405         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x62,
406         0x61, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
407         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
408         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
410         0x00, 0x00, 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, 0x01, 0x00, 0x00, 0x00,
848         0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
849         0x00, 0x1e, 0x54, 0x68, 0x69, 0x73, 0x20, 0x72,
850         0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20,
851         0x66, 0x6f, 0x72, 0x6b, 0x20, 0x69, 0x6e, 0x74,
852         0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
853         0x6c, 0x79, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20,
854         0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x20, 0x20, 0x20,
855         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
856         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
857         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
858         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0x01, 0x00, 0x00, 0x00,
880         0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
881         0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
882         0x00, 0x00, 0x00, 0x1c, 0x00, 0x1e, 0xff, 0xff
883 };
884
885 /**
886  * talloc and intialize an AfpInfo
887  **/
888 static AfpInfo *torture_afpinfo_new(TALLOC_CTX *mem_ctx)
889 {
890         AfpInfo *info;
891
892         info = talloc_zero(mem_ctx, AfpInfo);
893         if (info == NULL) {
894                 return NULL;
895         }
896
897         info->afpi_Signature = AFP_Signature;
898         info->afpi_Version = AFP_Version;
899         info->afpi_BackupTime = AFP_BackupTime;
900
901         return info;
902 }
903
904 /**
905  * Pack AfpInfo into a talloced buffer
906  **/
907 static char *torture_afpinfo_pack(TALLOC_CTX *mem_ctx,
908                                   AfpInfo *info)
909 {
910         char *buf;
911
912         buf = talloc_array(mem_ctx, char, AFP_INFO_SIZE);
913         if (buf == NULL) {
914                 return NULL;
915         }
916
917         RSIVAL(buf, 0, info->afpi_Signature);
918         RSIVAL(buf, 4, info->afpi_Version);
919         RSIVAL(buf, 12, info->afpi_BackupTime);
920         memcpy(buf + 16, info->afpi_FinderInfo, sizeof(info->afpi_FinderInfo));
921
922         return buf;
923 }
924
925 /**
926  * Unpack AfpInfo
927  **/
928 #if 0
929 static void torture_afpinfo_unpack(AfpInfo *info, char *data)
930 {
931         info->afpi_Signature = RIVAL(data, 0);
932         info->afpi_Version = RIVAL(data, 4);
933         info->afpi_BackupTime = RIVAL(data, 12);
934         memcpy(info->afpi_FinderInfo, (const char *)data + 16,
935                sizeof(info->afpi_FinderInfo));
936 }
937 #endif
938
939 static bool torture_write_afpinfo(struct smb2_tree *tree,
940                                   struct torture_context *tctx,
941                                   TALLOC_CTX *mem_ctx,
942                                   const char *fname,
943                                   AfpInfo *info)
944 {
945         struct smb2_handle handle;
946         struct smb2_create io;
947         NTSTATUS status;
948         const char *full_name;
949         char *infobuf;
950         bool ret = true;
951
952         full_name = talloc_asprintf(mem_ctx, "%s%s", fname, AFPINFO_STREAM_NAME);
953         if (full_name == NULL) {
954             torture_comment(tctx, "talloc_asprintf error\n");
955             return false;
956         }
957         ZERO_STRUCT(io);
958         io.in.desired_access = SEC_FILE_WRITE_DATA;
959         io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
960         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
961         io.in.create_options = 0;
962         io.in.fname = full_name;
963
964         status = smb2_create(tree, mem_ctx, &io);
965         CHECK_STATUS(status, NT_STATUS_OK);
966
967         handle = io.out.file.handle;
968
969         infobuf = torture_afpinfo_pack(mem_ctx, info);
970         if (infobuf == NULL) {
971                 return false;
972         }
973
974         status = smb2_util_write(tree, handle, infobuf, 0, AFP_INFO_SIZE);
975         CHECK_STATUS(status, NT_STATUS_OK);
976
977         smb2_util_close(tree, handle);
978
979 done:
980         return ret;
981 }
982
983 /**
984  * Read 'count' bytes at 'offset' from stream 'fname:sname' and
985  * compare against buffer 'value'
986  **/
987 static bool check_stream(struct smb2_tree *tree,
988                          const char *location,
989                          struct torture_context *tctx,
990                          TALLOC_CTX *mem_ctx,
991                          const char *fname,
992                          const char *sname,
993                          off_t read_offset,
994                          size_t read_count,
995                          off_t comp_offset,
996                          size_t comp_count,
997                          const char *value)
998 {
999         struct smb2_handle handle;
1000         struct smb2_create create;
1001         struct smb2_read r;
1002         NTSTATUS status;
1003         char *full_name;
1004         bool ret = true;
1005
1006         full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
1007         if (full_name == NULL) {
1008             torture_comment(tctx, "talloc_asprintf error\n");
1009             return false;
1010         }
1011         ZERO_STRUCT(create);
1012         create.in.desired_access = SEC_FILE_READ_DATA;
1013         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1014         create.in.create_disposition = NTCREATEX_DISP_OPEN;
1015         create.in.fname = full_name;
1016
1017         torture_comment(tctx, "Open stream %s\n", full_name);
1018
1019         status = smb2_create(tree, mem_ctx, &create);
1020         if (!NT_STATUS_IS_OK(status)) {
1021                 TALLOC_FREE(full_name);
1022                 if (value == NULL) {
1023                         return true;
1024                 }
1025                 torture_comment(tctx, "Unable to open stream %s\n", full_name);
1026                 return false;
1027         }
1028
1029         handle = create.out.file.handle;
1030         if (value == NULL) {
1031                 TALLOC_FREE(full_name);
1032                 smb2_util_close(tree, handle);
1033                 return true;
1034         }
1035
1036         ZERO_STRUCT(r);
1037         r.in.file.handle = handle;
1038         r.in.length      = read_count;
1039         r.in.offset      = read_offset;
1040
1041         status = smb2_read(tree, tree, &r);
1042
1043         torture_assert_ntstatus_ok_goto(
1044                 tctx, status, ret, done,
1045                 talloc_asprintf(tctx, "(%s) Failed to read %lu bytes from stream '%s'\n",
1046                                 location, (long)strlen(value), full_name));
1047
1048         torture_assert_goto(tctx, r.out.data.length == read_count, ret, done,
1049                             talloc_asprintf(tctx, "smb2_read returned %jd bytes, expected %jd\n",
1050                                             (intmax_t)r.out.data.length, (intmax_t)read_count));
1051
1052         torture_assert_goto(
1053                 tctx, memcmp(r.out.data.data + comp_offset, value, comp_count) == 0,
1054                 ret, done,
1055                 talloc_asprintf(tctx, "(%s) Bad data in stream\n", location));
1056
1057 done:
1058         TALLOC_FREE(full_name);
1059         smb2_util_close(tree, handle);
1060         return ret;
1061 }
1062
1063 /**
1064  * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1065  * compare against buffer 'value'
1066  **/
1067 static ssize_t read_stream(struct smb2_tree *tree,
1068                            const char *location,
1069                            struct torture_context *tctx,
1070                            TALLOC_CTX *mem_ctx,
1071                            const char *fname,
1072                            const char *sname,
1073                            off_t read_offset,
1074                            size_t read_count)
1075 {
1076         struct smb2_handle handle;
1077         struct smb2_create create;
1078         struct smb2_read r;
1079         NTSTATUS status;
1080         const char *full_name;
1081         bool ret = true;
1082
1083         full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
1084         if (full_name == NULL) {
1085             torture_comment(tctx, "talloc_asprintf error\n");
1086             return -1;
1087         }
1088         ZERO_STRUCT(create);
1089         create.in.desired_access = SEC_FILE_READ_DATA;
1090         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1091         create.in.create_disposition = NTCREATEX_DISP_OPEN;
1092         create.in.fname = full_name;
1093
1094         torture_comment(tctx, "Open stream %s\n", full_name);
1095
1096         status = smb2_create(tree, mem_ctx, &create);
1097         if (!NT_STATUS_IS_OK(status)) {
1098                 torture_comment(tctx, "Unable to open stream %s\n",
1099                                 full_name);
1100                 return -1;
1101         }
1102
1103         handle = create.out.file.handle;
1104
1105         ZERO_STRUCT(r);
1106         r.in.file.handle = handle;
1107         r.in.length      = read_count;
1108         r.in.offset      = read_offset;
1109
1110         status = smb2_read(tree, tree, &r);
1111         if (!NT_STATUS_IS_OK(status)) {
1112                 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
1113         }
1114
1115         smb2_util_close(tree, handle);
1116
1117 done:
1118         if (ret == false) {
1119                 return -1;
1120         }
1121         return r.out.data.length;
1122 }
1123
1124 /**
1125  * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1126  * compare against buffer 'value'
1127  **/
1128 static bool write_stream(struct smb2_tree *tree,
1129                          const char *location,
1130                          struct torture_context *tctx,
1131                          TALLOC_CTX *mem_ctx,
1132                          const char *fname,
1133                          const char *sname,
1134                          off_t offset,
1135                          size_t size,
1136                          const char *value)
1137 {
1138         struct smb2_handle handle;
1139         struct smb2_create create;
1140         NTSTATUS status;
1141         const char *full_name;
1142
1143         full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname ? sname : "");
1144         if (full_name == NULL) {
1145             torture_comment(tctx, "talloc_asprintf error\n");
1146             return false;
1147         }
1148         ZERO_STRUCT(create);
1149         create.in.desired_access = SEC_FILE_WRITE_DATA;
1150         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1151         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1152         create.in.fname = full_name;
1153
1154         status = smb2_create(tree, mem_ctx, &create);
1155         if (!NT_STATUS_IS_OK(status)) {
1156                 if (value == NULL) {
1157                         return true;
1158                 } else {
1159                         torture_comment(tctx, "Unable to open stream %s\n",
1160                             full_name);
1161                         sleep(10000000);
1162                         return false;
1163                 }
1164         }
1165
1166         handle = create.out.file.handle;
1167         if (value == NULL) {
1168                 return true;
1169         }
1170
1171         status = smb2_util_write(tree, handle, value, offset, size);
1172
1173         if (!NT_STATUS_IS_OK(status)) {
1174                 torture_comment(tctx, "(%s) Failed to write %lu bytes to "
1175                     "stream '%s'\n", location, (long)size, full_name);
1176                 return false;
1177         }
1178
1179         smb2_util_close(tree, handle);
1180         return true;
1181 }
1182
1183 static bool torture_setup_local_xattr(struct torture_context *tctx,
1184                                       const char *path_option,
1185                                       const char *name,
1186                                       const char *xattr,
1187                                       const char *metadata,
1188                                       size_t size)
1189 {
1190         int ret = true;
1191         int result;
1192         const char *spath;
1193         char *path;
1194
1195         spath = torture_setting_string(tctx, path_option, NULL);
1196         if (spath == NULL) {
1197                 printf("No sharepath for option %s\n", path_option);
1198                 return false;
1199         }
1200
1201         path = talloc_asprintf(tctx, "%s/%s", spath, name);
1202
1203         result = setxattr(path, xattr, metadata, size, 0);
1204         if (result != 0) {
1205                 ret = false;
1206         }
1207
1208         TALLOC_FREE(path);
1209
1210         return ret;
1211 }
1212
1213 /**
1214  * Create a file or directory
1215  **/
1216 static bool torture_setup_file(TALLOC_CTX *mem_ctx, struct smb2_tree *tree,
1217                                const char *name, bool dir)
1218 {
1219         struct smb2_create io;
1220         NTSTATUS status;
1221
1222         smb2_util_unlink(tree, name);
1223         ZERO_STRUCT(io);
1224         io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1225         io.in.file_attributes   = FILE_ATTRIBUTE_NORMAL;
1226         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1227         io.in.share_access =
1228                 NTCREATEX_SHARE_ACCESS_DELETE|
1229                 NTCREATEX_SHARE_ACCESS_READ|
1230                 NTCREATEX_SHARE_ACCESS_WRITE;
1231         io.in.create_options = 0;
1232         io.in.fname = name;
1233         if (dir) {
1234                 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1235                 io.in.share_access &= ~NTCREATEX_SHARE_ACCESS_DELETE;
1236                 io.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
1237                 io.in.create_disposition = NTCREATEX_DISP_CREATE;
1238         }
1239
1240         status = smb2_create(tree, mem_ctx, &io);
1241         if (!NT_STATUS_IS_OK(status)) {
1242                 return false;
1243         }
1244
1245         status = smb2_util_close(tree, io.out.file.handle);
1246         if (!NT_STATUS_IS_OK(status)) {
1247                 return false;
1248         }
1249
1250         return true;
1251 }
1252
1253 static bool enable_aapl(struct torture_context *tctx,
1254                         struct smb2_tree *tree)
1255 {
1256         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1257         NTSTATUS status;
1258         bool ret = true;
1259         struct smb2_create io;
1260         DATA_BLOB data;
1261         struct smb2_create_blob *aapl = NULL;
1262         uint32_t aapl_server_caps;
1263         uint32_t expexted_scaps = (SMB2_CRTCTX_AAPL_UNIX_BASED |
1264                                    SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
1265                                    SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
1266                                    SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
1267         bool is_osx_server = torture_setting_bool(tctx, "osx", false);
1268
1269         ZERO_STRUCT(io);
1270         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
1271         io.in.file_attributes    = FILE_ATTRIBUTE_DIRECTORY;
1272         io.in.create_disposition = NTCREATEX_DISP_OPEN;
1273         io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
1274                               NTCREATEX_SHARE_ACCESS_READ |
1275                               NTCREATEX_SHARE_ACCESS_WRITE);
1276         io.in.fname = "";
1277
1278         /*
1279          * Issuing an SMB2/CREATE with a suitably formed AAPL context,
1280          * controls behaviour of Apple's SMB2 extensions for the whole
1281          * session!
1282          */
1283
1284         data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
1285         SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
1286         SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
1287                              SMB2_CRTCTX_AAPL_VOLUME_CAPS |
1288                              SMB2_CRTCTX_AAPL_MODEL_INFO));
1289         SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
1290                               SMB2_CRTCTX_AAPL_UNIX_BASED |
1291                               SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
1292
1293         status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
1294         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_blob_add");
1295
1296         status = smb2_create(tree, tctx, &io);
1297         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1298
1299         status = smb2_util_close(tree, io.out.file.handle);
1300         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close");
1301
1302         /*
1303          * Now check returned AAPL context
1304          */
1305         torture_comment(tctx, "Comparing returned AAPL capabilities\n");
1306
1307         aapl = smb2_create_blob_find(&io.out.blobs,
1308                                      SMB2_CREATE_TAG_AAPL);
1309         torture_assert_goto(tctx, aapl != NULL, ret, done, "missing AAPL context");
1310
1311         if (!is_osx_server) {
1312                 size_t exptected_aapl_ctx_size;
1313
1314                 exptected_aapl_ctx_size = strlen("MacSamba") * 2 + 40;
1315
1316                 torture_assert_goto(
1317                         tctx, aapl->data.length == exptected_aapl_ctx_size,
1318                         ret, done, "bad AAPL size");
1319         }
1320
1321         aapl_server_caps = BVAL(aapl->data.data, 16);
1322         torture_assert_goto(tctx, aapl_server_caps == expexted_scaps,
1323                             ret, done, "bad AAPL caps");
1324
1325 done:
1326         talloc_free(mem_ctx);
1327         return ret;
1328 }
1329
1330 static bool test_read_netatalk_metadata(struct torture_context *tctx,
1331                                         struct smb2_tree *tree)
1332 {
1333         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1334         const char *fname = BASEDIR "\\torture_read_metadata";
1335         NTSTATUS status;
1336         struct smb2_handle testdirh;
1337         bool ret = true;
1338         ssize_t len;
1339         const char *localdir = NULL;
1340
1341         torture_comment(tctx, "Checking metadata access\n");
1342
1343         localdir = torture_setting_string(tctx, "localdir", NULL);
1344         if (localdir == NULL) {
1345                 torture_skip(tctx, "Need localdir for test");
1346         }
1347
1348         smb2_util_unlink(tree, fname);
1349
1350         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1351         CHECK_STATUS(status, NT_STATUS_OK);
1352         smb2_util_close(tree, testdirh);
1353
1354         ret = torture_setup_file(mem_ctx, tree, fname, false);
1355         if (ret == false) {
1356                 goto done;
1357         }
1358
1359         ret = torture_setup_local_xattr(tctx, "localdir",
1360                                         BASEDIR "/torture_read_metadata",
1361                                         AFPINFO_EA_NETATALK,
1362                                         metadata_xattr, sizeof(metadata_xattr));
1363         if (ret == false) {
1364                 goto done;
1365         }
1366
1367         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1368                            0, 60, 0, 4, "AFP");
1369         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1370
1371         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1372                            0, 60, 16, 8, "BARRFOOO");
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                            16, 8, 0, 3, "AFP");
1377         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1378
1379         /* Check reading offset and read size > sizeof(AFPINFO_STREAM) */
1380
1381         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1382                           AFPINFO_STREAM, 0, 61);
1383         CHECK_VALUE(len, 60);
1384
1385         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1386                           AFPINFO_STREAM, 59, 2);
1387         CHECK_VALUE(len, 2);
1388
1389         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1390                           AFPINFO_STREAM, 60, 1);
1391         CHECK_VALUE(len, 1);
1392
1393         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1394                           AFPINFO_STREAM, 61, 1);
1395         CHECK_VALUE(len, 0);
1396
1397 done:
1398         smb2_deltree(tree, BASEDIR);
1399         talloc_free(mem_ctx);
1400         return ret;
1401 }
1402
1403 static bool test_read_afpinfo(struct torture_context *tctx,
1404                               struct smb2_tree *tree)
1405 {
1406         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1407         const char *fname = BASEDIR "\\torture_read_metadata";
1408         NTSTATUS status;
1409         struct smb2_handle testdirh;
1410         bool ret = true;
1411         ssize_t len;
1412         AfpInfo *info;
1413         const char *type_creator = "SMB,OLE!";
1414
1415         torture_comment(tctx, "Checking metadata access\n");
1416
1417         smb2_util_unlink(tree, fname);
1418
1419         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1420         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
1421         smb2_util_close(tree, testdirh);
1422
1423         ret = torture_setup_file(mem_ctx, tree, fname, false);
1424         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
1425
1426         info = torture_afpinfo_new(mem_ctx);
1427         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
1428
1429         memcpy(info->afpi_FinderInfo, type_creator, 8);
1430         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
1431         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
1432
1433         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1434                            0, 60, 0, 4, "AFP");
1435         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1436
1437         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1438                            0, 60, 16, 8, type_creator);
1439         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1440
1441         /*
1442          * OS X ignores offset <= 60 and treats the as
1443          * offset=0. Reading from offsets > 60 returns EOF=0.
1444          */
1445
1446         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1447                            16, 8, 0, 8, "AFP\0\0\0\001\0");
1448         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1449
1450         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1451                           AFPINFO_STREAM, 0, 61);
1452         torture_assert_goto(tctx, len == 60, ret, done, "read_stream failed");
1453
1454         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1455                           AFPINFO_STREAM, 59, 2);
1456         torture_assert_goto(tctx, len == 2, ret, done, "read_stream failed");
1457
1458         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1459                            59, 2, 0, 2, "AF");
1460         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1461
1462         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1463                           AFPINFO_STREAM, 60, 1);
1464         torture_assert_goto(tctx, len == 1, ret, done, "read_stream failed");
1465
1466         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1467                            60, 1, 0, 1, "A");
1468         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1469
1470         len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1471                           AFPINFO_STREAM, 61, 1);
1472         torture_assert_goto(tctx, len == 0, ret, done, "read_stream failed");
1473
1474 done:
1475         smb2_util_unlink(tree, fname);
1476         smb2_deltree(tree, BASEDIR);
1477         talloc_free(mem_ctx);
1478         return ret;
1479 }
1480
1481 static bool test_write_atalk_metadata(struct torture_context *tctx,
1482                                       struct smb2_tree *tree)
1483 {
1484         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1485         const char *fname = BASEDIR "\\torture_write_metadata";
1486         const char *type_creator = "SMB,OLE!";
1487         NTSTATUS status;
1488         struct smb2_handle testdirh;
1489         bool ret = true;
1490         AfpInfo *info;
1491
1492         smb2_deltree(tree, BASEDIR);
1493         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1494         CHECK_STATUS(status, NT_STATUS_OK);
1495         smb2_util_close(tree, testdirh);
1496
1497         ret = torture_setup_file(mem_ctx, tree, fname, false);
1498         if (ret == false) {
1499                 goto done;
1500         }
1501
1502         info = torture_afpinfo_new(mem_ctx);
1503         if (info == NULL) {
1504                 goto done;
1505         }
1506
1507         memcpy(info->afpi_FinderInfo, type_creator, 8);
1508         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
1509         ret &= check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1510                             0, 60, 16, 8, type_creator);
1511
1512 done:
1513         smb2_util_unlink(tree, fname);
1514         smb2_deltree(tree, BASEDIR);
1515         talloc_free(mem_ctx);
1516         return ret;
1517 }
1518
1519 static bool test_write_atalk_rfork_io(struct torture_context *tctx,
1520                                       struct smb2_tree *tree)
1521 {
1522         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1523         const char *fname = BASEDIR "\\torture_write_rfork_io";
1524         const char *rfork = BASEDIR "\\torture_write_rfork_io" AFPRESOURCE_STREAM_NAME;
1525         const char *rfork_content = "1234567890";
1526         NTSTATUS status;
1527         struct smb2_handle testdirh;
1528         bool ret = true;
1529
1530         union smb_open io;
1531         struct smb2_handle filehandle;
1532         union smb_fileinfo finfo;
1533         union smb_setfileinfo sinfo;
1534
1535         smb2_util_unlink(tree, fname);
1536
1537         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1538         CHECK_STATUS(status, NT_STATUS_OK);
1539         smb2_util_close(tree, testdirh);
1540
1541         ret = torture_setup_file(mem_ctx, tree, fname, false);
1542         if (ret == false) {
1543                 goto done;
1544         }
1545
1546         torture_comment(tctx, "(%s) writing to resource fork\n",
1547             __location__);
1548
1549         ret &= write_stream(tree, __location__, tctx, mem_ctx,
1550                             fname, AFPRESOURCE_STREAM_NAME,
1551                             10, 10, rfork_content);
1552
1553         ret &= check_stream(tree, __location__, tctx, mem_ctx,
1554                             fname, AFPRESOURCE_STREAM_NAME,
1555                             0, 20, 10, 10, rfork_content);
1556
1557         /* Check size after write */
1558
1559         ZERO_STRUCT(io);
1560         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1561         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1562                 SEC_FILE_WRITE_ATTRIBUTE;
1563         io.smb2.in.fname = rfork;
1564         status = smb2_create(tree, mem_ctx, &(io.smb2));
1565         CHECK_STATUS(status, NT_STATUS_OK);
1566         filehandle = io.smb2.out.file.handle;
1567
1568         torture_comment(tctx, "(%s) check resource fork size after write\n",
1569             __location__);
1570
1571         ZERO_STRUCT(finfo);
1572         finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1573         finfo.generic.in.file.handle = filehandle;
1574         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1575         CHECK_STATUS(status, NT_STATUS_OK);
1576         if (finfo.all_info.out.size != 20) {
1577                 torture_result(tctx, TORTURE_FAIL,
1578                                "(%s) Incorrect resource fork size\n",
1579                                __location__);
1580                 ret = false;
1581                 smb2_util_close(tree, filehandle);
1582                 goto done;
1583         }
1584         smb2_util_close(tree, filehandle);
1585
1586         /* Write at large offset */
1587
1588         torture_comment(tctx, "(%s) writing to resource fork at large offset\n",
1589                         __location__);
1590
1591         ret &= write_stream(tree, __location__, tctx, mem_ctx,
1592                             fname, AFPRESOURCE_STREAM_NAME,
1593                             (off_t)1<<32, 10, rfork_content);
1594
1595         ret &= check_stream(tree, __location__, tctx, mem_ctx,
1596                             fname, AFPRESOURCE_STREAM_NAME,
1597                             (off_t)1<<32, 10, 0, 10, rfork_content);
1598
1599         /* Truncate back to size of 1 byte */
1600
1601         torture_comment(tctx, "(%s) truncate resource fork and check size\n",
1602                         __location__);
1603
1604         ZERO_STRUCT(io);
1605         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1606         io.smb2.in.desired_access = SEC_FILE_ALL;
1607         io.smb2.in.fname = rfork;
1608         status = smb2_create(tree, mem_ctx, &(io.smb2));
1609         CHECK_STATUS(status, NT_STATUS_OK);
1610         filehandle = io.smb2.out.file.handle;
1611
1612         ZERO_STRUCT(sinfo);
1613         sinfo.end_of_file_info.level =
1614                 RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1615         sinfo.end_of_file_info.in.file.handle = filehandle;
1616         sinfo.end_of_file_info.in.size = 1;
1617         status = smb2_setinfo_file(tree, &sinfo);
1618         CHECK_STATUS(status, NT_STATUS_OK);
1619
1620         smb2_util_close(tree, filehandle);
1621
1622         /* Now check size */
1623         ZERO_STRUCT(io);
1624         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1625         io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1626                 SEC_FILE_WRITE_ATTRIBUTE;
1627         io.smb2.in.fname = rfork;
1628         status = smb2_create(tree, mem_ctx, &(io.smb2));
1629         CHECK_STATUS(status, NT_STATUS_OK);
1630         filehandle = io.smb2.out.file.handle;
1631
1632         ZERO_STRUCT(finfo);
1633         finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1634         finfo.generic.in.file.handle = filehandle;
1635         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1636         CHECK_STATUS(status, NT_STATUS_OK);
1637         if (finfo.all_info.out.size != 1) {
1638                 torture_result(tctx, TORTURE_FAIL,
1639                                "(%s) Incorrect resource fork size\n",
1640                                __location__);
1641                 ret = false;
1642                 smb2_util_close(tree, filehandle);
1643                 goto done;
1644         }
1645         smb2_util_close(tree, filehandle);
1646
1647 done:
1648         smb2_util_unlink(tree, fname);
1649         smb2_deltree(tree, BASEDIR);
1650         talloc_free(mem_ctx);
1651         return ret;
1652 }
1653
1654 static bool test_rfork_truncate(struct torture_context *tctx,
1655                                 struct smb2_tree *tree)
1656 {
1657         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1658         const char *fname = BASEDIR "\\torture_rfork_truncate";
1659         const char *rfork = BASEDIR "\\torture_rfork_truncate" AFPRESOURCE_STREAM;
1660         const char *rfork_content = "1234567890";
1661         NTSTATUS status;
1662         struct smb2_handle testdirh;
1663         bool ret = true;
1664         struct smb2_create create;
1665         struct smb2_handle fh1, fh2, fh3;
1666         union smb_setfileinfo sinfo;
1667
1668         smb2_util_unlink(tree, fname);
1669
1670         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1671         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1672         smb2_util_close(tree, testdirh);
1673
1674         ret = torture_setup_file(mem_ctx, tree, fname, false);
1675         if (ret == false) {
1676                 goto done;
1677         }
1678
1679         ret &= write_stream(tree, __location__, tctx, mem_ctx,
1680                             fname, AFPRESOURCE_STREAM,
1681                             10, 10, rfork_content);
1682
1683         /* Truncate back to size 0, further access MUST return ENOENT */
1684
1685         torture_comment(tctx, "(%s) truncate resource fork to size 0\n",
1686                         __location__);
1687
1688         ZERO_STRUCT(create);
1689         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1690         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1691         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1692         create.in.fname               = fname;
1693         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1694                 NTCREATEX_SHARE_ACCESS_READ |
1695                 NTCREATEX_SHARE_ACCESS_WRITE;
1696         status = smb2_create(tree, mem_ctx, &create);
1697         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1698         fh1 = create.out.file.handle;
1699
1700         ZERO_STRUCT(create);
1701         create.in.create_disposition  = NTCREATEX_DISP_OPEN_IF;
1702         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1703         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1704         create.in.fname               = rfork;
1705         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1706                 NTCREATEX_SHARE_ACCESS_READ |
1707                 NTCREATEX_SHARE_ACCESS_WRITE;
1708         status = smb2_create(tree, mem_ctx, &create);
1709         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1710         fh2 = create.out.file.handle;
1711
1712         ZERO_STRUCT(sinfo);
1713         sinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1714         sinfo.end_of_file_info.in.file.handle = fh2;
1715         sinfo.end_of_file_info.in.size = 0;
1716         status = smb2_setinfo_file(tree, &sinfo);
1717         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file");
1718
1719         /*
1720          * Now check size, we should get OBJECT_NAME_NOT_FOUND (!)
1721          */
1722         ZERO_STRUCT(create);
1723         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1724         create.in.desired_access      = SEC_FILE_ALL;
1725         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1726         create.in.fname               = rfork;
1727         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1728                 NTCREATEX_SHARE_ACCESS_READ |
1729                 NTCREATEX_SHARE_ACCESS_WRITE;
1730         status = smb2_create(tree, mem_ctx, &create);
1731         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1732
1733         /*
1734          * Do another open on the rfork and write to the new handle. A
1735          * naive server might unlink the AppleDouble resource fork
1736          * file when its truncated to 0 bytes above, so in case both
1737          * open handles share the same underlying fd, the unlink would
1738          * cause the below write to be lost.
1739          */
1740         ZERO_STRUCT(create);
1741         create.in.create_disposition  = NTCREATEX_DISP_OPEN_IF;
1742         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1743         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1744         create.in.fname               = rfork;
1745         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1746                 NTCREATEX_SHARE_ACCESS_READ |
1747                 NTCREATEX_SHARE_ACCESS_WRITE;
1748         status = smb2_create(tree, mem_ctx, &create);
1749         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1750         fh3 = create.out.file.handle;
1751
1752         status = smb2_util_write(tree, fh3, "foo", 0, 3);
1753         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write");
1754
1755         smb2_util_close(tree, fh3);
1756         smb2_util_close(tree, fh2);
1757         smb2_util_close(tree, fh1);
1758
1759         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM,
1760                            0, 3, 0, 3, "foo");
1761         torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
1762
1763 done:
1764         smb2_util_unlink(tree, fname);
1765         smb2_deltree(tree, BASEDIR);
1766         talloc_free(mem_ctx);
1767         return ret;
1768 }
1769
1770 static bool test_rfork_create(struct torture_context *tctx,
1771                               struct smb2_tree *tree)
1772 {
1773         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1774         const char *fname = BASEDIR "\\torture_rfork_create";
1775         const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
1776         NTSTATUS status;
1777         struct smb2_handle testdirh;
1778         bool ret = true;
1779         struct smb2_create create;
1780         struct smb2_handle fh1;
1781         const char *streams[] = {
1782                 "::$DATA"
1783         };
1784         union smb_fileinfo finfo;
1785
1786         smb2_util_unlink(tree, fname);
1787
1788         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1789         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1790         smb2_util_close(tree, testdirh);
1791
1792         ret = torture_setup_file(mem_ctx, tree, fname, false);
1793         if (ret == false) {
1794                 goto done;
1795         }
1796
1797         torture_comment(tctx, "(%s) open rfork, should return ENOENT\n",
1798                         __location__);
1799
1800         ZERO_STRUCT(create);
1801         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1802         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1803         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1804         create.in.fname               = rfork;
1805         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1806                 NTCREATEX_SHARE_ACCESS_READ |
1807                 NTCREATEX_SHARE_ACCESS_WRITE;
1808         status = smb2_create(tree, mem_ctx, &create);
1809         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1810
1811         torture_comment(tctx, "(%s) create resource fork\n", __location__);
1812
1813         ZERO_STRUCT(create);
1814         create.in.create_disposition  = NTCREATEX_DISP_OPEN_IF;
1815         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1816         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1817         create.in.fname               = rfork;
1818         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1819                 NTCREATEX_SHARE_ACCESS_READ |
1820                 NTCREATEX_SHARE_ACCESS_WRITE;
1821         status = smb2_create(tree, mem_ctx, &create);
1822         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1823         fh1 = create.out.file.handle;
1824
1825         torture_comment(tctx, "(%s) getinfo on create handle\n",
1826                         __location__);
1827
1828         ZERO_STRUCT(finfo);
1829         finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1830         finfo.generic.in.file.handle = fh1;
1831         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1832         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file");
1833         if (finfo.all_info.out.size != 0) {
1834                 torture_result(tctx, TORTURE_FAIL,
1835                                "(%s) Incorrect resource fork size\n",
1836                                __location__);
1837                 ret = false;
1838                 smb2_util_close(tree, fh1);
1839                 goto done;
1840         }
1841
1842         torture_comment(tctx, "(%s) open rfork, should still return ENOENT\n",
1843                         __location__);
1844
1845         ZERO_STRUCT(create);
1846         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1847         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1848         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1849         create.in.fname               = rfork;
1850         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1851                 NTCREATEX_SHARE_ACCESS_READ |
1852                 NTCREATEX_SHARE_ACCESS_WRITE;
1853         status = smb2_create(tree, mem_ctx, &create);
1854         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1855
1856         ret = check_stream_list(tree, tctx, fname, 1, streams, false);
1857         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
1858
1859         torture_comment(tctx, "(%s) close empty created rfork, open should return ENOENT\n",
1860                         __location__);
1861
1862         ZERO_STRUCT(create);
1863         create.in.create_disposition  = NTCREATEX_DISP_OPEN;
1864         create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1865         create.in.file_attributes     = FILE_ATTRIBUTE_NORMAL;
1866         create.in.fname               = rfork;
1867         create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
1868                 NTCREATEX_SHARE_ACCESS_READ |
1869                 NTCREATEX_SHARE_ACCESS_WRITE;
1870         status = smb2_create(tree, mem_ctx, &create);
1871         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1872
1873 done:
1874         smb2_util_unlink(tree, fname);
1875         smb2_deltree(tree, BASEDIR);
1876         talloc_free(mem_ctx);
1877         return ret;
1878 }
1879
1880 static bool test_rfork_create_ro(struct torture_context *tctx,
1881                                  struct smb2_tree *tree)
1882 {
1883         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1884         const char *fname = BASEDIR "\\torture_rfork_create";
1885         const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
1886         NTSTATUS status;
1887         struct smb2_handle testdirh;
1888         bool ret = true;
1889         struct smb2_create create;
1890
1891         smb2_util_unlink(tree, fname);
1892         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1893         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1894                 "torture_smb2_testdir\n");
1895         smb2_util_close(tree, testdirh);
1896
1897         ret = torture_setup_file(mem_ctx, tree, fname, false);
1898         if (ret == false) {
1899                 goto done;
1900         }
1901
1902         torture_comment(tctx, "(%s) Try opening read-only with "
1903                         "open_if create disposition, should return ENOENT\n",
1904                         __location__);
1905
1906         ZERO_STRUCT(create);
1907         create.in.fname = rfork;
1908         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1909         create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
1910         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1911         create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
1912         status = smb2_create(tree, mem_ctx, &(create));
1913         torture_assert_ntstatus_equal_goto(tctx, status,
1914                                         NT_STATUS_OBJECT_NAME_NOT_FOUND,
1915                                         ret, done, "smb2_create failed\n");
1916
1917         torture_comment(tctx, "(%s) Now write something to the "
1918                         "rsrc stream, then the same open should succeed\n",
1919                         __location__);
1920
1921         ret = write_stream(tree, __location__, tctx, mem_ctx,
1922                            fname, AFPRESOURCE_STREAM_NAME,
1923                            0, 3, "foo");
1924         torture_assert_goto(tctx, ret == true, ret, done,
1925                         "write_stream failed\n");
1926
1927         ret = check_stream(tree, __location__, tctx, mem_ctx,
1928                            fname, AFPRESOURCE_STREAM,
1929                            0, 3, 0, 3, "foo");
1930         torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
1931
1932         ZERO_STRUCT(create);
1933         create.in.fname = rfork;
1934         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1935         create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
1936         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1937         create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
1938         status = smb2_create(tree, mem_ctx, &(create));
1939         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1940                 "smb2_create failed\n");
1941
1942         smb2_util_close(tree, create.out.file.handle);
1943
1944 done:
1945         smb2_util_unlink(tree, fname);
1946         smb2_deltree(tree, BASEDIR);
1947         talloc_free(mem_ctx);
1948         return ret;
1949 }
1950
1951 static bool test_adouble_conversion(struct torture_context *tctx,
1952                                     struct smb2_tree *tree)
1953 {
1954         TALLOC_CTX *mem_ctx = talloc_new(tctx);
1955         const char *fname = BASEDIR "\\test_adouble_conversion";
1956         const char *adname = BASEDIR "/._test_adouble_conversion";
1957         NTSTATUS status;
1958         struct smb2_handle testdirh;
1959         bool ret = true;
1960         const char *data = "This resource fork intentionally left blank";
1961         size_t datalen = strlen(data);
1962         const char *streams[] = {
1963                 "::$DATA",
1964                 AFPINFO_STREAM,
1965                 AFPRESOURCE_STREAM,
1966                 ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
1967                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
1968         };
1969
1970         smb2_deltree(tree, BASEDIR);
1971
1972         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1973         CHECK_STATUS(status, NT_STATUS_OK);
1974         smb2_util_close(tree, testdirh);
1975
1976         ret = torture_setup_file(tctx, tree, fname, false);
1977         torture_assert_goto(tctx, ret == true, ret, done,
1978                             "torture_setup_file failed\n");
1979
1980         ret = torture_setup_file(tctx, tree, adname, false);
1981         torture_assert_goto(tctx, ret == true, ret, done,
1982                             "torture_setup_file failed\n");
1983
1984         ret = write_stream(tree, __location__, tctx, mem_ctx,
1985                            adname, NULL,
1986                            0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr);
1987         torture_assert_goto(tctx, ret == true, ret, done,
1988                             "write_stream failed\n");
1989
1990         torture_comment(tctx, "(%s) test OS X AppleDouble conversion\n",
1991             __location__);
1992
1993         ret = check_stream(tree, __location__, tctx, mem_ctx,
1994                            fname, AFPRESOURCE_STREAM,
1995                            16, datalen, 0, datalen, data);
1996         torture_assert_goto(tctx, ret == true, ret, done,
1997                             "check AFPRESOURCE_STREAM failed\n");
1998
1999         ret = check_stream(tree, __location__, tctx, mem_ctx,
2000                            fname, AFPINFO_STREAM,
2001                            0, 60, 16, 8, "TESTSLOW");
2002         torture_assert_goto(tctx, ret == true, ret, done,
2003                             "check AFPINFO_STREAM failed\n");
2004
2005         ret = check_stream(tree, __location__, tctx, mem_ctx, fname,
2006                            ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2007                            0, 3, 0, 3, "baz");
2008         torture_assert_goto(tctx, ret == true, ret, done,
2009                             "check foo:bar stream failed\n");
2010
2011         ret = check_stream_list(tree, tctx, fname, 5, streams, false);
2012         torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2013
2014 done:
2015         smb2_deltree(tree, BASEDIR);
2016         talloc_free(mem_ctx);
2017         return ret;
2018 }
2019
2020 static bool test_aapl(struct torture_context *tctx,
2021                       struct smb2_tree *tree)
2022 {
2023         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2024         const char *fname = BASEDIR "\\test_aapl";
2025         NTSTATUS status;
2026         struct smb2_handle testdirh;
2027         bool ret = true;
2028         struct smb2_create io;
2029         DATA_BLOB data;
2030         struct smb2_create_blob *aapl = NULL;
2031         AfpInfo *info;
2032         const char *type_creator = "SMB,OLE!";
2033         char type_creator_buf[9];
2034         uint32_t aapl_cmd;
2035         uint32_t aapl_reply_bitmap;
2036         uint32_t aapl_server_caps;
2037         uint32_t aapl_vol_caps;
2038         char *model;
2039         struct smb2_find f;
2040         unsigned int count;
2041         union smb_search_data *d;
2042         uint64_t rfork_len;
2043
2044         smb2_deltree(tree, BASEDIR);
2045
2046         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2047         CHECK_STATUS(status, NT_STATUS_OK);
2048         smb2_util_close(tree, testdirh);
2049
2050         ZERO_STRUCT(io);
2051         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
2052         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
2053         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2054         io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2055                               NTCREATEX_SHARE_ACCESS_READ |
2056                               NTCREATEX_SHARE_ACCESS_WRITE);
2057         io.in.fname = fname;
2058
2059         /*
2060          * Issuing an SMB2/CREATE with a suitably formed AAPL context,
2061          * controls behaviour of Apple's SMB2 extensions for the whole
2062          * session!
2063          */
2064
2065         data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2066         SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2067         SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2068                              SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2069                              SMB2_CRTCTX_AAPL_MODEL_INFO));
2070         SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2071                               SMB2_CRTCTX_AAPL_UNIX_BASED |
2072                               SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
2073
2074         torture_comment(tctx, "Testing SMB2 create context AAPL\n");
2075         status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2076         CHECK_STATUS(status, NT_STATUS_OK);
2077
2078         status = smb2_create(tree, tctx, &io);
2079         CHECK_STATUS(status, NT_STATUS_OK);
2080         status = smb2_util_close(tree, io.out.file.handle);
2081         CHECK_STATUS(status, NT_STATUS_OK);
2082
2083         /*
2084          * Now check returned AAPL context
2085          */
2086         torture_comment(tctx, "Comparing returned AAPL capabilities\n");
2087
2088         aapl = smb2_create_blob_find(&io.out.blobs,
2089                                      SMB2_CREATE_TAG_AAPL);
2090
2091         if (aapl == NULL) {
2092                 torture_result(tctx, TORTURE_FAIL,
2093                                "(%s) unexpectedly no AAPL capabilities were returned.",
2094                                __location__);
2095                 ret = false;
2096                 goto done;
2097         }
2098
2099         if (aapl->data.length != 50) {
2100                 /*
2101                  * uint32_t CommandCode = kAAPL_SERVER_QUERY
2102                  * uint32_t Reserved = 0;
2103                  * uint64_t ReplyBitmap = kAAPL_SERVER_CAPS |
2104                  *                        kAAPL_VOLUME_CAPS |
2105                  *                        kAAPL_MODEL_INFO;
2106                  * uint64_t ServerCaps = kAAPL_SUPPORTS_READDIR_ATTR |
2107                  *                       kAAPL_SUPPORTS_OSX_COPYFILE;
2108                  * uint64_t VolumeCaps = kAAPL_SUPPORT_RESOLVE_ID |
2109                  *                       kAAPL_CASE_SENSITIVE;
2110                  * uint32_t Pad2 = 0;
2111                  * uint32_t ModelStringLen = 10;
2112                  * ucs2_t ModelString[5] = "Samba";
2113                  */
2114                 torture_warning(tctx,
2115                                 "(%s) unexpected AAPL context length: %zd, expected 50",
2116                                 __location__, aapl->data.length);
2117         }
2118
2119         aapl_cmd = IVAL(aapl->data.data, 0);
2120         if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2121                 torture_result(tctx, TORTURE_FAIL,
2122                                "(%s) unexpected cmd: %d",
2123                                __location__, (int)aapl_cmd);
2124                 ret = false;
2125                 goto done;
2126         }
2127
2128         aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2129         if (aapl_reply_bitmap != (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2130                                   SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2131                                   SMB2_CRTCTX_AAPL_MODEL_INFO)) {
2132                 torture_result(tctx, TORTURE_FAIL,
2133                                "(%s) unexpected reply_bitmap: %d",
2134                                __location__, (int)aapl_reply_bitmap);
2135                 ret = false;
2136                 goto done;
2137         }
2138
2139         aapl_server_caps = BVAL(aapl->data.data, 16);
2140         if (aapl_server_caps != (SMB2_CRTCTX_AAPL_UNIX_BASED |
2141                                  SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2142                                  SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
2143                                  SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE)) {
2144                 torture_result(tctx, TORTURE_FAIL,
2145                                "(%s) unexpected server_caps: %d",
2146                                __location__, (int)aapl_server_caps);
2147                 ret = false;
2148                 goto done;
2149         }
2150
2151         aapl_vol_caps = BVAL(aapl->data.data, 24);
2152         if (aapl_vol_caps != 0) {
2153                 /* this will fail on a case insensitive fs ... */
2154                 torture_result(tctx, TORTURE_FAIL,
2155                                 "(%s) unexpected vol_caps: %d",
2156                                 __location__, (int)aapl_vol_caps);
2157         }
2158
2159         ret = convert_string_talloc(mem_ctx,
2160                                     CH_UTF16LE, CH_UNIX,
2161                                     aapl->data.data + 40, 10,
2162                                     &model, NULL);
2163         if (ret == false) {
2164                 torture_result(tctx, TORTURE_FAIL,
2165                                "(%s) convert_string_talloc() failed",
2166                                __location__);
2167                 goto done;
2168         }
2169         torture_comment(tctx, "Got server model: \"%s\"\n", model);
2170
2171         /*
2172          * Now that Requested AAPL extensions are enabled, setup some
2173          * Mac files with metadata and resource fork
2174          */
2175         ret = torture_setup_file(mem_ctx, tree, fname, false);
2176         if (ret == false) {
2177                 torture_result(tctx, TORTURE_FAIL,
2178                                "(%s) torture_setup_file() failed",
2179                                __location__);
2180                 goto done;
2181         }
2182
2183         info = torture_afpinfo_new(mem_ctx);
2184         if (info == NULL) {
2185                 torture_result(tctx, TORTURE_FAIL,
2186                                "(%s) torture_afpinfo_new() failed",
2187                                __location__);
2188                 ret = false;
2189                 goto done;
2190         }
2191
2192         memcpy(info->afpi_FinderInfo, type_creator, 8);
2193         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
2194         if (ret == false) {
2195                 torture_result(tctx, TORTURE_FAIL,
2196                                "(%s) torture_write_afpinfo() failed",
2197                                __location__);
2198                 goto done;
2199         }
2200
2201         ret = write_stream(tree, __location__, tctx, mem_ctx,
2202                            fname, AFPRESOURCE_STREAM_NAME,
2203                            0, 3, "foo");
2204         if (ret == false) {
2205                 torture_result(tctx, TORTURE_FAIL,
2206                                "(%s) write_stream() failed",
2207                                __location__);
2208                 goto done;
2209         }
2210
2211         /*
2212          * Ok, file is prepared, now call smb2/find
2213          */
2214
2215         ZERO_STRUCT(io);
2216         io.in.desired_access = SEC_RIGHTS_DIR_READ;
2217         io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2218         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2219         io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
2220                               NTCREATEX_SHARE_ACCESS_WRITE |
2221                               NTCREATEX_SHARE_ACCESS_DELETE);
2222         io.in.create_disposition = NTCREATEX_DISP_OPEN;
2223         io.in.fname = BASEDIR;
2224         status = smb2_create(tree, tctx, &io);
2225         CHECK_STATUS(status, NT_STATUS_OK);
2226
2227         ZERO_STRUCT(f);
2228         f.in.file.handle        = io.out.file.handle;
2229         f.in.pattern            = "test_aapl";
2230         f.in.continue_flags     = SMB2_CONTINUE_FLAG_SINGLE;
2231         f.in.max_response_size  = 0x1000;
2232         f.in.level              = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
2233
2234         status = smb2_find_level(tree, tree, &f, &count, &d);
2235         CHECK_STATUS(status, NT_STATUS_OK);
2236
2237         status = smb2_util_close(tree, io.out.file.handle);
2238         CHECK_STATUS(status, NT_STATUS_OK);
2239
2240         if (strcmp(d[0].id_both_directory_info.name.s, "test_aapl") != 0) {
2241                 torture_result(tctx, TORTURE_FAIL,
2242                                "(%s) write_stream() failed",
2243                                __location__);
2244                 ret = false;
2245                 goto done;
2246         }
2247
2248         if (d[0].id_both_directory_info.short_name.private_length != 24) {
2249                 torture_result(tctx, TORTURE_FAIL,
2250                                "(%s) bad short_name length %" PRIu32 ", expected 24",
2251                                __location__, d[0].id_both_directory_info.short_name.private_length);
2252                 ret = false;
2253                 goto done;
2254         }
2255
2256         torture_comment(tctx, "short_name buffer:\n");
2257         dump_data(0, d[0].id_both_directory_info.short_name_buf, 24);
2258
2259         /*
2260          * Extract data as specified by the AAPL extension:
2261          * - ea_size contains max_access
2262          * - short_name contains resource fork length + FinderInfo
2263          * - reserved2 contains the unix mode
2264          */
2265         torture_comment(tctx, "mac_access: %" PRIx32 "\n",
2266                         d[0].id_both_directory_info.ea_size);
2267
2268         rfork_len = BVAL(d[0].id_both_directory_info.short_name_buf, 0);
2269         if (rfork_len != 3) {
2270                 torture_result(tctx, TORTURE_FAIL,
2271                                "(%s) expected resource fork length 3, got: %" PRIu64,
2272                                __location__, rfork_len);
2273                 ret = false;
2274                 goto done;
2275         }
2276
2277         memcpy(type_creator_buf, d[0].id_both_directory_info.short_name_buf + 8, 8);
2278         type_creator_buf[8] = 0;
2279         if (strcmp(type_creator, type_creator_buf) != 0) {
2280                 torture_result(tctx, TORTURE_FAIL,
2281                                "(%s) expected type/creator \"%s\" , got: %s",
2282                                __location__, type_creator, type_creator_buf);
2283                 ret = false;
2284                 goto done;
2285         }
2286
2287 done:
2288         smb2_util_unlink(tree, fname);
2289         smb2_deltree(tree, BASEDIR);
2290         talloc_free(mem_ctx);
2291         return ret;
2292 }
2293
2294 static uint64_t patt_hash(uint64_t off)
2295 {
2296         return off;
2297 }
2298
2299 static bool write_pattern(struct torture_context *torture,
2300                           struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2301                           struct smb2_handle h, uint64_t off, uint64_t len,
2302                           uint64_t patt_off)
2303 {
2304         NTSTATUS status;
2305         uint64_t i;
2306         uint8_t *buf;
2307         uint64_t io_sz = MIN(1024 * 64, len);
2308
2309         if (len == 0) {
2310                 return true;
2311         }
2312
2313         torture_assert(torture, (len % 8) == 0, "invalid write len");
2314
2315         buf = talloc_zero_size(mem_ctx, io_sz);
2316         torture_assert(torture, (buf != NULL), "no memory for file data buf");
2317
2318         while (len > 0) {
2319                 for (i = 0; i <= io_sz - 8; i += 8) {
2320                         SBVAL(buf, i, patt_hash(patt_off));
2321                         patt_off += 8;
2322                 }
2323
2324                 status = smb2_util_write(tree, h,
2325                                          buf, off, io_sz);
2326                 torture_assert_ntstatus_ok(torture, status, "file write");
2327
2328                 len -= io_sz;
2329                 off += io_sz;
2330         }
2331
2332         talloc_free(buf);
2333
2334         return true;
2335 }
2336
2337 static bool check_pattern(struct torture_context *torture,
2338                           struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2339                           struct smb2_handle h, uint64_t off, uint64_t len,
2340                           uint64_t patt_off)
2341 {
2342         if (len == 0) {
2343                 return true;
2344         }
2345
2346         torture_assert(torture, (len % 8) == 0, "invalid read len");
2347
2348         while (len > 0) {
2349                 uint64_t i;
2350                 struct smb2_read r;
2351                 NTSTATUS status;
2352                 uint64_t io_sz = MIN(1024 * 64, len);
2353
2354                 ZERO_STRUCT(r);
2355                 r.in.file.handle = h;
2356                 r.in.length      = io_sz;
2357                 r.in.offset      = off;
2358                 status = smb2_read(tree, mem_ctx, &r);
2359                 torture_assert_ntstatus_ok(torture, status, "read");
2360
2361                 torture_assert_u64_equal(torture, r.out.data.length, io_sz,
2362                                          "read data len mismatch");
2363
2364                 for (i = 0; i <= io_sz - 8; i += 8, patt_off += 8) {
2365                         uint64_t data = BVAL(r.out.data.data, i);
2366                         torture_assert_u64_equal(torture, data, patt_hash(patt_off),
2367                                                  talloc_asprintf(torture, "read data "
2368                                                                  "pattern bad at %llu\n",
2369                                                                  (unsigned long long)off + i));
2370                 }
2371                 talloc_free(r.out.data.data);
2372                 len -= io_sz;
2373                 off += io_sz;
2374         }
2375
2376         return true;
2377 }
2378
2379 static bool test_setup_open(struct torture_context *torture,
2380                             struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2381                             const char *fname,
2382                             struct smb2_handle *fh,
2383                             uint32_t desired_access,
2384                             uint32_t file_attributes)
2385 {
2386         struct smb2_create io;
2387         NTSTATUS status;
2388
2389         ZERO_STRUCT(io);
2390         io.in.desired_access = desired_access;
2391         io.in.file_attributes = file_attributes;
2392         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2393         io.in.share_access =
2394                 NTCREATEX_SHARE_ACCESS_DELETE|
2395                 NTCREATEX_SHARE_ACCESS_READ|
2396                 NTCREATEX_SHARE_ACCESS_WRITE;
2397         if (file_attributes & FILE_ATTRIBUTE_DIRECTORY) {
2398                 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2399         }
2400         io.in.fname = fname;
2401
2402         status = smb2_create(tree, mem_ctx, &io);
2403         torture_assert_ntstatus_ok(torture, status, "file create");
2404
2405         *fh = io.out.file.handle;
2406
2407         return true;
2408 }
2409
2410 static bool test_setup_create_fill(struct torture_context *torture,
2411                                    struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2412                                    const char *fname,
2413                                    struct smb2_handle *fh,
2414                                    uint64_t size,
2415                                    uint32_t desired_access,
2416                                    uint32_t file_attributes)
2417 {
2418         bool ok;
2419
2420         ok = test_setup_open(torture, tree, mem_ctx,
2421                              fname,
2422                              fh,
2423                              desired_access,
2424                              file_attributes);
2425         torture_assert(torture, ok, "file open");
2426
2427         if (size > 0) {
2428                 ok = write_pattern(torture, tree, mem_ctx, *fh, 0, size, 0);
2429                 torture_assert(torture, ok, "write pattern");
2430         }
2431         return true;
2432 }
2433
2434 static bool test_setup_copy_chunk(struct torture_context *torture,
2435                                   struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2436                                   uint32_t nchunks,
2437                                   const char *src_name,
2438                                   struct smb2_handle *src_h,
2439                                   uint64_t src_size,
2440                                   uint32_t src_desired_access,
2441                                   const char *dst_name,
2442                                   struct smb2_handle *dest_h,
2443                                   uint64_t dest_size,
2444                                   uint32_t dest_desired_access,
2445                                   struct srv_copychunk_copy *cc_copy,
2446                                   union smb_ioctl *io)
2447 {
2448         struct req_resume_key_rsp res_key;
2449         bool ok;
2450         NTSTATUS status;
2451         enum ndr_err_code ndr_ret;
2452
2453         ok = test_setup_create_fill(torture, tree, mem_ctx, src_name,
2454                                     src_h, src_size, src_desired_access,
2455                                     FILE_ATTRIBUTE_NORMAL);
2456         torture_assert(torture, ok, "src file create fill");
2457
2458         ok = test_setup_create_fill(torture, tree, mem_ctx, dst_name,
2459                                     dest_h, dest_size, dest_desired_access,
2460                                     FILE_ATTRIBUTE_NORMAL);
2461         torture_assert(torture, ok, "dest file create fill");
2462
2463         ZERO_STRUCTPN(io);
2464         io->smb2.level = RAW_IOCTL_SMB2;
2465         io->smb2.in.file.handle = *src_h;
2466         io->smb2.in.function = FSCTL_SRV_REQUEST_RESUME_KEY;
2467         /* Allow for Key + ContextLength + Context */
2468         io->smb2.in.max_response_size = 32;
2469         io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2470
2471         status = smb2_ioctl(tree, mem_ctx, &io->smb2);
2472         torture_assert_ntstatus_ok(torture, status,
2473                                    "FSCTL_SRV_REQUEST_RESUME_KEY");
2474
2475         ndr_ret = ndr_pull_struct_blob(&io->smb2.out.out, mem_ctx, &res_key,
2476                         (ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
2477
2478         torture_assert_ndr_success(torture, ndr_ret,
2479                                    "ndr_pull_req_resume_key_rsp");
2480
2481         ZERO_STRUCTPN(io);
2482         io->smb2.level = RAW_IOCTL_SMB2;
2483         io->smb2.in.file.handle = *dest_h;
2484         io->smb2.in.function = FSCTL_SRV_COPYCHUNK;
2485         io->smb2.in.max_response_size = sizeof(struct srv_copychunk_rsp);
2486         io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2487
2488         ZERO_STRUCTPN(cc_copy);
2489         memcpy(cc_copy->source_key, res_key.resume_key, ARRAY_SIZE(cc_copy->source_key));
2490         cc_copy->chunk_count = nchunks;
2491         cc_copy->chunks = talloc_zero_array(mem_ctx, struct srv_copychunk, nchunks);
2492         torture_assert(torture, (cc_copy->chunks != NULL), "no memory for chunks");
2493
2494         return true;
2495 }
2496
2497
2498 static bool check_copy_chunk_rsp(struct torture_context *torture,
2499                                  struct srv_copychunk_rsp *cc_rsp,
2500                                  uint32_t ex_chunks_written,
2501                                  uint32_t ex_chunk_bytes_written,
2502                                  uint32_t ex_total_bytes_written)
2503 {
2504         torture_assert_int_equal(torture, cc_rsp->chunks_written,
2505                                  ex_chunks_written, "num chunks");
2506         torture_assert_int_equal(torture, cc_rsp->chunk_bytes_written,
2507                                  ex_chunk_bytes_written, "chunk bytes written");
2508         torture_assert_int_equal(torture, cc_rsp->total_bytes_written,
2509                                  ex_total_bytes_written, "chunk total bytes");
2510         return true;
2511 }
2512
2513 static bool neg_aapl_copyfile(struct torture_context *tctx,
2514                               struct smb2_tree *tree,
2515                               uint64_t flags)
2516 {
2517         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2518         const char *fname = "aapl";
2519         NTSTATUS status;
2520         struct smb2_create io;
2521         DATA_BLOB data;
2522         struct smb2_create_blob *aapl = NULL;
2523         uint32_t aapl_cmd;
2524         uint32_t aapl_reply_bitmap;
2525         uint32_t aapl_server_caps;
2526         bool ret = true;
2527
2528         ZERO_STRUCT(io);
2529         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
2530         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
2531         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2532         io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2533                               NTCREATEX_SHARE_ACCESS_READ |
2534                               NTCREATEX_SHARE_ACCESS_WRITE);
2535         io.in.fname = fname;
2536
2537         data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2538         SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2539         SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS));
2540         SBVAL(data.data, 16, flags);
2541
2542         status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2543         CHECK_STATUS(status, NT_STATUS_OK);
2544
2545         status = smb2_create(tree, tctx, &io);
2546         CHECK_STATUS(status, NT_STATUS_OK);
2547
2548         aapl = smb2_create_blob_find(&io.out.blobs,
2549                                      SMB2_CREATE_TAG_AAPL);
2550         if (aapl == NULL) {
2551                 ret = false;
2552                 goto done;
2553
2554         }
2555         if (aapl->data.length < 24) {
2556                 ret = false;
2557                 goto done;
2558         }
2559
2560         aapl_cmd = IVAL(aapl->data.data, 0);
2561         if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2562                 torture_result(tctx, TORTURE_FAIL,
2563                                "(%s) unexpected cmd: %d",
2564                                __location__, (int)aapl_cmd);
2565                 ret = false;
2566                 goto done;
2567         }
2568
2569         aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2570         if (!(aapl_reply_bitmap & SMB2_CRTCTX_AAPL_SERVER_CAPS)) {
2571                 torture_result(tctx, TORTURE_FAIL,
2572                                "(%s) unexpected reply_bitmap: %d",
2573                                __location__, (int)aapl_reply_bitmap);
2574                 ret = false;
2575                 goto done;
2576         }
2577
2578         aapl_server_caps = BVAL(aapl->data.data, 16);
2579         if (!(aapl_server_caps & flags)) {
2580                 torture_result(tctx, TORTURE_FAIL,
2581                                "(%s) unexpected server_caps: %d",
2582                                __location__, (int)aapl_server_caps);
2583                 ret = false;
2584                 goto done;
2585         }
2586
2587 done:
2588         status = smb2_util_close(tree, io.out.file.handle);
2589         CHECK_STATUS(status, NT_STATUS_OK);
2590
2591         smb2_util_unlink(tree, "aapl");
2592         talloc_free(mem_ctx);
2593         return ret;
2594 }
2595
2596 static bool test_copyfile(struct torture_context *torture,
2597                           struct smb2_tree *tree)
2598 {
2599         struct smb2_handle src_h;
2600         struct smb2_handle dest_h;
2601         NTSTATUS status;
2602         union smb_ioctl io;
2603         TALLOC_CTX *tmp_ctx = talloc_new(tree);
2604         struct srv_copychunk_copy cc_copy;
2605         struct srv_copychunk_rsp cc_rsp;
2606         enum ndr_err_code ndr_ret;
2607         bool ok;
2608         const char *sname = ":foo" "\xef\x80\xa2" "bar:$DATA";
2609
2610         /*
2611          * First test a copy_chunk with a 0 chunk count without having
2612          * enabled this via AAPL. The request must not fail and the
2613          * copied length in the response must be 0. This is verified
2614          * against Windows 2008r2.
2615          */
2616
2617         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2618                                    0, /* 0 chunks, copyfile semantics */
2619                                    FNAME_CC_SRC,
2620                                    &src_h, 4096, /* fill 4096 byte src file */
2621                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2622                                    FNAME_CC_DST,
2623                                    &dest_h, 0,  /* 0 byte dest file */
2624                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2625                                    &cc_copy,
2626                                    &io);
2627         if (!ok) {
2628                 torture_fail_goto(torture, done, "setup copy chunk error");
2629         }
2630
2631         ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2632                                        &cc_copy,
2633                         (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2634         torture_assert_ndr_success(torture, ndr_ret,
2635                                    "ndr_push_srv_copychunk_copy");
2636
2637         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2638         torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2639
2640         ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2641                                        &cc_rsp,
2642                         (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2643         torture_assert_ndr_success(torture, ndr_ret,
2644                                    "ndr_pull_srv_copychunk_rsp");
2645
2646         ok = check_copy_chunk_rsp(torture, &cc_rsp,
2647                                   0,    /* chunks written */
2648                                   0,    /* chunk bytes unsuccessfully written */
2649                                   0); /* total bytes written */
2650         if (!ok) {
2651                 torture_fail_goto(torture, done, "bad copy chunk response data");
2652         }
2653
2654         /*
2655          * Now enable AAPL copyfile and test again, the file and the
2656          * stream must be copied by the server.
2657          */
2658         ok = neg_aapl_copyfile(torture, tree,
2659                                SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
2660         if (!ok) {
2661                 torture_skip_goto(torture, done, "missing AAPL copyfile");
2662                 goto done;
2663         }
2664
2665         smb2_util_close(tree, src_h);
2666         smb2_util_close(tree, dest_h);
2667         smb2_util_unlink(tree, FNAME_CC_SRC);
2668         smb2_util_unlink(tree, FNAME_CC_DST);
2669
2670         ok = torture_setup_file(tmp_ctx, tree, FNAME_CC_SRC, false);
2671         if (!ok) {
2672                 torture_fail(torture, "setup file error");
2673         }
2674         ok = write_stream(tree, __location__, torture, tmp_ctx,
2675                             FNAME_CC_SRC, AFPRESOURCE_STREAM,
2676                             10, 10, "1234567890");
2677         if (!ok) {
2678                 torture_fail(torture, "setup stream error");
2679         }
2680
2681         ok = write_stream(tree, __location__, torture, tmp_ctx,
2682                             FNAME_CC_SRC, sname,
2683                             10, 10, "abcdefghij");
2684         torture_assert_goto(torture, ok == true, ok, done, "write_stream failed\n");
2685
2686         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2687                                    0, /* 0 chunks, copyfile semantics */
2688                                    FNAME_CC_SRC,
2689                                    &src_h, 4096, /* fill 4096 byte src file */
2690                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2691                                    FNAME_CC_DST,
2692                                    &dest_h, 0,  /* 0 byte dest file */
2693                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2694                                    &cc_copy,
2695                                    &io);
2696         if (!ok) {
2697                 torture_fail_goto(torture, done, "setup copy chunk error");
2698         }
2699
2700         ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2701                                        &cc_copy,
2702                         (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2703         torture_assert_ndr_success(torture, ndr_ret,
2704                                    "ndr_push_srv_copychunk_copy");
2705
2706         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2707         torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2708
2709         ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2710                                        &cc_rsp,
2711                         (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2712         torture_assert_ndr_success(torture, ndr_ret,
2713                                    "ndr_pull_srv_copychunk_rsp");
2714
2715         ok = check_copy_chunk_rsp(torture, &cc_rsp,
2716                                   0,    /* chunks written */
2717                                   0,    /* chunk bytes unsuccessfully written */
2718                                   4096); /* total bytes written */
2719         if (!ok) {
2720                 torture_fail_goto(torture, done, "bad copy chunk response data");
2721         }
2722
2723         ok = test_setup_open(torture, tree, tmp_ctx, FNAME_CC_DST, &dest_h,
2724                              SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL);
2725         if (!ok) {
2726                 torture_fail_goto(torture, done,"open failed");
2727         }
2728         ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 4096, 0);
2729         if (!ok) {
2730                 torture_fail_goto(torture, done, "inconsistent file data");
2731         }
2732
2733         ok = check_stream(tree, __location__, torture, tmp_ctx,
2734                             FNAME_CC_DST, AFPRESOURCE_STREAM,
2735                             0, 20, 10, 10, "1234567890");
2736         if (!ok) {
2737                 torture_fail_goto(torture, done, "inconsistent stream data");
2738         }
2739
2740         ok = check_stream(tree, __location__, torture, tmp_ctx,
2741                             FNAME_CC_DST, sname,
2742                             0, 20, 10, 10, "abcdefghij");
2743         torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
2744
2745 done:
2746         smb2_util_close(tree, src_h);
2747         smb2_util_close(tree, dest_h);
2748         smb2_util_unlink(tree, FNAME_CC_SRC);
2749         smb2_util_unlink(tree, FNAME_CC_DST);
2750         talloc_free(tmp_ctx);
2751         return true;
2752 }
2753
2754 static bool check_stream_list(struct smb2_tree *tree,
2755                               struct torture_context *tctx,
2756                               const char *fname,
2757                               int num_exp,
2758                               const char **exp,
2759                               bool is_dir)
2760 {
2761         bool ret = true;
2762         union smb_fileinfo finfo;
2763         NTSTATUS status;
2764         int i;
2765         TALLOC_CTX *tmp_ctx = talloc_new(tctx);
2766         char **exp_sort;
2767         struct stream_struct *stream_sort;
2768         struct smb2_create create;
2769         struct smb2_handle h;
2770
2771         ZERO_STRUCT(h);
2772         torture_assert_goto(tctx, tmp_ctx != NULL, ret, done, "talloc_new failed");
2773
2774         ZERO_STRUCT(create);
2775         create.in.fname = fname;
2776         create.in.create_disposition = NTCREATEX_DISP_OPEN;
2777         create.in.desired_access = SEC_FILE_ALL;
2778         create.in.create_options = is_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
2779         create.in.file_attributes = is_dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
2780         status = smb2_create(tree, tmp_ctx, &create);
2781         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
2782         h = create.out.file.handle;
2783
2784         finfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
2785         finfo.generic.in.file.handle = h;
2786
2787         status = smb2_getinfo_file(tree, tctx, &finfo);
2788         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "get stream info");
2789
2790         smb2_util_close(tree, h);
2791
2792         torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams, num_exp,
2793                                       ret, done, "stream count");
2794
2795         if (num_exp == 0) {
2796                 TALLOC_FREE(tmp_ctx);
2797                 goto done;
2798         }
2799
2800         exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
2801         torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
2802
2803         TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
2804
2805         stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
2806                                     finfo.stream_info.out.num_streams *
2807                                     sizeof(*stream_sort));
2808         torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
2809
2810         TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
2811
2812         for (i=0; i<num_exp; i++) {
2813                 torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
2814                                 i, exp_sort[i], stream_sort[i].stream_name.s);
2815                 torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s, exp_sort[i],
2816                                               ret, done, "stream name");
2817         }
2818
2819 done:
2820         TALLOC_FREE(tmp_ctx);
2821         return ret;
2822 }
2823
2824 /*
2825   test stream names
2826 */
2827 static bool test_stream_names(struct torture_context *tctx,
2828                               struct smb2_tree *tree)
2829 {
2830         TALLOC_CTX *mem_ctx = talloc_new(tctx);
2831         NTSTATUS status;
2832         struct smb2_create create;
2833         struct smb2_handle h;
2834         const char *fname = BASEDIR "\\stream_names.txt";
2835         const char *sname1;
2836         bool ret;
2837         /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
2838         const char *streams[] = {
2839                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2840                 "::$DATA"
2841         };
2842
2843         sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
2844
2845         /* clean slate ...*/
2846         smb2_util_unlink(tree, fname);
2847         smb2_deltree(tree, fname);
2848         smb2_deltree(tree, BASEDIR);
2849
2850         status = torture_smb2_testdir(tree, BASEDIR, &h);
2851         CHECK_STATUS(status, NT_STATUS_OK);
2852         smb2_util_close(tree, h);
2853
2854         torture_comment(tctx, "(%s) testing stream names\n", __location__);
2855         ZERO_STRUCT(create);
2856         create.in.desired_access = SEC_FILE_WRITE_DATA;
2857         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2858         create.in.share_access =
2859                 NTCREATEX_SHARE_ACCESS_DELETE|
2860                 NTCREATEX_SHARE_ACCESS_READ|
2861                 NTCREATEX_SHARE_ACCESS_WRITE;
2862         create.in.create_disposition = NTCREATEX_DISP_CREATE;
2863         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2864         create.in.fname = sname1;
2865
2866         status = smb2_create(tree, mem_ctx, &create);
2867         CHECK_STATUS(status, NT_STATUS_OK);
2868         smb2_util_close(tree, create.out.file.handle);
2869
2870         ret = check_stream_list(tree, tctx, fname, 2, streams, false);
2871         CHECK_VALUE(ret, true);
2872
2873 done:
2874         status = smb2_util_unlink(tree, fname);
2875         smb2_deltree(tree, BASEDIR);
2876         talloc_free(mem_ctx);
2877
2878         return ret;
2879 }
2880
2881 /* Renaming a directory with open file, should work for OS X AAPL clients */
2882 static bool test_rename_dir_openfile(struct torture_context *torture,
2883                                      struct smb2_tree *tree)
2884 {
2885         bool ret = true;
2886         NTSTATUS status;
2887         union smb_open io;
2888         union smb_close cl;
2889         union smb_setfileinfo sinfo;
2890         struct smb2_handle d1, h1;
2891         const char *renamedir = BASEDIR "-new";
2892         bool server_is_osx = torture_setting_bool(torture, "osx", false);
2893
2894         smb2_deltree(tree, BASEDIR);
2895         smb2_util_rmdir(tree, BASEDIR);
2896         smb2_deltree(tree, renamedir);
2897
2898         ZERO_STRUCT(io.smb2);
2899         io.generic.level = RAW_OPEN_SMB2;
2900         io.smb2.in.create_flags = 0;
2901         io.smb2.in.desired_access = 0x0017019f;
2902         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2903         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2904         io.smb2.in.share_access = 0;
2905         io.smb2.in.alloc_size = 0;
2906         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2907         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2908         io.smb2.in.security_flags = 0;
2909         io.smb2.in.fname = BASEDIR;
2910
2911         status = smb2_create(tree, torture, &(io.smb2));
2912         torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
2913         d1 = io.smb2.out.file.handle;
2914
2915         ZERO_STRUCT(io.smb2);
2916         io.generic.level = RAW_OPEN_SMB2;
2917         io.smb2.in.create_flags = 0;
2918         io.smb2.in.desired_access = 0x0017019f;
2919         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
2920         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2921         io.smb2.in.share_access = 0;
2922         io.smb2.in.alloc_size = 0;
2923         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2924         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2925         io.smb2.in.security_flags = 0;
2926         io.smb2.in.fname = BASEDIR "\\file.txt";
2927
2928         status = smb2_create(tree, torture, &(io.smb2));
2929         torture_assert_ntstatus_ok(torture, status, "smb2_create file");
2930         h1 = io.smb2.out.file.handle;
2931
2932         if (!server_is_osx) {
2933                 torture_comment(torture, "Renaming directory without AAPL, must fail\n");
2934
2935                 ZERO_STRUCT(sinfo);
2936                 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
2937                 sinfo.rename_information.in.file.handle = d1;
2938                 sinfo.rename_information.in.overwrite = 0;
2939                 sinfo.rename_information.in.root_fid = 0;
2940                 sinfo.rename_information.in.new_name = renamedir;
2941                 status = smb2_setinfo_file(tree, &sinfo);
2942
2943                 torture_assert_ntstatus_equal(torture, status,
2944                                               NT_STATUS_ACCESS_DENIED,
2945                                               "smb2_setinfo_file");
2946
2947                 ZERO_STRUCT(cl.smb2);
2948                 cl.smb2.level = RAW_CLOSE_SMB2;
2949                 cl.smb2.in.file.handle = d1;
2950                 status = smb2_close(tree, &(cl.smb2));
2951                 torture_assert_ntstatus_ok(torture, status, "smb2_close");
2952                 ZERO_STRUCT(d1);
2953         }
2954
2955         torture_comment(torture, "Enabling AAPL\n");
2956
2957         ret = enable_aapl(torture, tree);
2958         torture_assert(torture, ret == true, "enable_aapl failed");
2959
2960         torture_comment(torture, "Renaming directory with AAPL\n");
2961
2962         ZERO_STRUCT(io.smb2);
2963         io.generic.level = RAW_OPEN_SMB2;
2964         io.smb2.in.desired_access = 0x0017019f;
2965         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2966         io.smb2.in.share_access = 0;
2967         io.smb2.in.alloc_size = 0;
2968         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
2969         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2970         io.smb2.in.security_flags = 0;
2971         io.smb2.in.fname = BASEDIR;
2972
2973         status = smb2_create(tree, torture, &(io.smb2));
2974         torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
2975         d1 = io.smb2.out.file.handle;
2976
2977         ZERO_STRUCT(sinfo);
2978         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
2979         sinfo.rename_information.in.file.handle = d1;
2980         sinfo.rename_information.in.overwrite = 0;
2981         sinfo.rename_information.in.root_fid = 0;
2982         sinfo.rename_information.in.new_name = renamedir;
2983
2984         status = smb2_setinfo_file(tree, &sinfo);
2985         torture_assert_ntstatus_ok(torture, status, "smb2_setinfo_file");
2986
2987         ZERO_STRUCT(cl.smb2);
2988         cl.smb2.level = RAW_CLOSE_SMB2;
2989         cl.smb2.in.file.handle = d1;
2990         status = smb2_close(tree, &(cl.smb2));
2991         torture_assert_ntstatus_ok(torture, status, "smb2_close");
2992         ZERO_STRUCT(d1);
2993
2994         cl.smb2.in.file.handle = h1;
2995         status = smb2_close(tree, &(cl.smb2));
2996         torture_assert_ntstatus_ok(torture, status, "smb2_close");
2997         ZERO_STRUCT(h1);
2998
2999         torture_comment(torture, "Cleaning up\n");
3000
3001         if (h1.data[0] || h1.data[1]) {
3002                 ZERO_STRUCT(cl.smb2);
3003                 cl.smb2.level = RAW_CLOSE_SMB2;
3004                 cl.smb2.in.file.handle = h1;
3005                 status = smb2_close(tree, &(cl.smb2));
3006         }
3007
3008         smb2_util_unlink(tree, BASEDIR "\\file.txt");
3009         smb2_util_unlink(tree, BASEDIR "-new\\file.txt");
3010         smb2_deltree(tree, renamedir);
3011         smb2_deltree(tree, BASEDIR);
3012         return ret;
3013 }
3014
3015 static bool test_afpinfo_enoent(struct torture_context *tctx,
3016                                 struct smb2_tree *tree)
3017 {
3018         bool ret = true;
3019         NTSTATUS status;
3020         struct smb2_create create;
3021         struct smb2_handle h1;
3022         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3023         const char *fname = BASEDIR "\\file";
3024         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3025
3026         torture_comment(tctx, "Opening file without AFP_AfpInfo\n");
3027
3028         smb2_deltree(tree, BASEDIR);
3029         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3030         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3031         smb2_util_close(tree, h1);
3032         ret = torture_setup_file(mem_ctx, tree, fname, false);
3033         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3034
3035         torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3036
3037         ZERO_STRUCT(create);
3038         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3039         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3040         create.in.fname = sname;
3041
3042         status = smb2_create(tree, mem_ctx, &create);
3043         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3044                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3045
3046 done:
3047         smb2_util_unlink(tree, fname);
3048         smb2_util_rmdir(tree, BASEDIR);
3049         return ret;
3050 }
3051
3052 static bool test_create_delete_on_close(struct torture_context *tctx,
3053                                         struct smb2_tree *tree)
3054 {
3055         bool ret = true;
3056         NTSTATUS status;
3057         struct smb2_create create;
3058         struct smb2_handle h1;
3059         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3060         const char *fname = BASEDIR "\\file";
3061         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3062         const char *type_creator = "SMB,OLE!";
3063         AfpInfo *info = NULL;
3064         const char *streams_basic[] = {
3065                 "::$DATA"
3066         };
3067         const char *streams_afpinfo[] = {
3068                 "::$DATA",
3069                 AFPINFO_STREAM
3070         };
3071
3072         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3073
3074         torture_comment(tctx, "Checking whether create with delete-on-close work with AFP_AfpInfo\n");
3075
3076         smb2_deltree(tree, BASEDIR);
3077         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3078         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3079         smb2_util_close(tree, h1);
3080         ret = torture_setup_file(mem_ctx, tree, fname, false);
3081         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3082
3083         torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3084
3085         ZERO_STRUCT(create);
3086         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3087         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3088         create.in.fname = sname;
3089
3090         status = smb2_create(tree, mem_ctx, &create);
3091         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3092                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3093
3094         ZERO_STRUCT(create);
3095         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3096         create.in.desired_access = SEC_FILE_ALL;
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         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3104         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3105
3106         torture_comment(tctx, "Deleting AFP_AfpInfo via create with delete-on-close\n");
3107
3108         info = torture_afpinfo_new(mem_ctx);
3109         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3110
3111         memcpy(info->afpi_FinderInfo, type_creator, 8);
3112         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3113         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3114
3115         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3116                            0, 60, 16, 8, type_creator);
3117         torture_assert_goto(tctx, ret == true, ret, done, "Bad type/creator in AFP_AfpInfo");
3118
3119         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3120         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3121
3122         ZERO_STRUCT(create);
3123         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3124         create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3125         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3126         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3127         create.in.fname = sname;
3128         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3129
3130         status = smb2_create(tree, mem_ctx, &create);
3131         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3132
3133         h1 = create.out.file.handle;
3134         smb2_util_close(tree, h1);
3135
3136         ZERO_STRUCT(create);
3137         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3138         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
3139         create.in.fname = sname;
3140         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3141         status = smb2_create(tree, mem_ctx, &create);
3142         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3143                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3144
3145         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3146         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3147
3148 done:
3149         smb2_util_unlink(tree, fname);
3150         smb2_util_rmdir(tree, BASEDIR);
3151         return ret;
3152 }
3153
3154 static bool test_setinfo_delete_on_close(struct torture_context *tctx,
3155                                          struct smb2_tree *tree)
3156 {
3157         bool ret = true;
3158         NTSTATUS status;
3159         struct smb2_create create;
3160         union smb_setfileinfo sfinfo;
3161         struct smb2_handle h1;
3162         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3163         const char *fname = BASEDIR "\\file";
3164         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3165         const char *type_creator = "SMB,OLE!";
3166         AfpInfo *info = NULL;
3167         const char *streams_basic[] = {
3168                 "::$DATA"
3169         };
3170
3171         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3172
3173         torture_comment(tctx, "Deleting AFP_AfpInfo via setinfo with delete-on-close\n");
3174
3175         smb2_deltree(tree, BASEDIR);
3176         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3177         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3178         smb2_util_close(tree, h1);
3179         ret = torture_setup_file(mem_ctx, tree, fname, false);
3180         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3181
3182         info = torture_afpinfo_new(mem_ctx);
3183         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3184         memcpy(info->afpi_FinderInfo, type_creator, 8);
3185         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3186         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3187
3188         ZERO_STRUCT(create);
3189         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3190         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3191         create.in.fname = sname;
3192         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3193         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3194
3195         status = smb2_create(tree, mem_ctx, &create);
3196         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3197
3198         h1 = create.out.file.handle;
3199
3200         /* Delete stream via setinfo delete-on-close */
3201         ZERO_STRUCT(sfinfo);
3202         sfinfo.disposition_info.in.delete_on_close = 1;
3203         sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3204         sfinfo.generic.in.file.handle = h1;
3205         status = smb2_setinfo_file(tree, &sfinfo);
3206         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3207
3208         smb2_util_close(tree, h1);
3209
3210         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3211         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3212
3213         ZERO_STRUCT(create);
3214         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3215         create.in.desired_access = SEC_FILE_ALL;
3216         create.in.fname = sname;
3217         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3218         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3219         status = smb2_create(tree, mem_ctx, &create);
3220         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3221                                            ret, done, "Got unexpected AFP_AfpInfo stream");
3222
3223 done:
3224         smb2_util_unlink(tree, fname);
3225         smb2_util_rmdir(tree, BASEDIR);
3226         return ret;
3227 }
3228
3229 static bool test_setinfo_eof(struct torture_context *tctx,
3230                              struct smb2_tree *tree)
3231 {
3232         bool ret = true;
3233         NTSTATUS status;
3234         struct smb2_create create;
3235         union smb_setfileinfo sfinfo;
3236         struct smb2_handle h1;
3237         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3238         const char *fname = BASEDIR "\\file";
3239         const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3240         const char *type_creator = "SMB,OLE!";
3241         AfpInfo *info = NULL;
3242         const char *streams_afpinfo[] = {
3243                 "::$DATA",
3244                 AFPINFO_STREAM
3245         };
3246
3247         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3248
3249         torture_comment(tctx, "Set AFP_AfpInfo EOF to 61, 1 and 0\n");
3250
3251         smb2_deltree(tree, BASEDIR);
3252         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3253         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3254         smb2_util_close(tree, h1);
3255         ret = torture_setup_file(mem_ctx, tree, fname, false);
3256         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3257
3258         info = torture_afpinfo_new(mem_ctx);
3259         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3260         memcpy(info->afpi_FinderInfo, type_creator, 8);
3261         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3262         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3263
3264         ZERO_STRUCT(create);
3265         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3266         create.in.desired_access = SEC_FILE_ALL;
3267         create.in.fname = sname;
3268         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3269         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3270
3271         status = smb2_create(tree, mem_ctx, &create);
3272         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3273
3274         h1 = create.out.file.handle;
3275
3276         torture_comment(tctx, "Set AFP_AfpInfo EOF to 61\n");
3277
3278         /* Test setinfo end-of-file info */
3279         ZERO_STRUCT(sfinfo);
3280         sfinfo.generic.in.file.handle = h1;
3281         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3282         sfinfo.position_information.in.position = 61;
3283         status = smb2_setinfo_file(tree, &sfinfo);
3284         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ALLOTTED_SPACE_EXCEEDED,
3285                                            ret, done, "set eof 61 failed");
3286
3287         torture_comment(tctx, "Set AFP_AfpInfo EOF to 1\n");
3288
3289         /* Truncation returns success, but has no effect */
3290         ZERO_STRUCT(sfinfo);
3291         sfinfo.generic.in.file.handle = h1;
3292         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3293         sfinfo.position_information.in.position = 1;
3294         status = smb2_setinfo_file(tree, &sfinfo);
3295         torture_assert_ntstatus_ok_goto(tctx, status,
3296                                         ret, done, "set eof 1 failed");
3297         smb2_util_close(tree, h1);
3298
3299         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3300         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3301
3302         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3303                            0, 60, 16, 8, type_creator);
3304         torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3305
3306         ZERO_STRUCT(create);
3307         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3308         create.in.desired_access = SEC_FILE_ALL;
3309         create.in.fname = sname;
3310         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3311         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3312
3313         status = smb2_create(tree, mem_ctx, &create);
3314         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3315
3316         h1 = create.out.file.handle;
3317
3318         /*
3319          * Delete stream via setinfo end-of-file info to 0, should
3320          * return success but stream MUST NOT deleted
3321          */
3322         ZERO_STRUCT(sfinfo);
3323         sfinfo.generic.in.file.handle = h1;
3324         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3325         sfinfo.position_information.in.position = 0;
3326         status = smb2_setinfo_file(tree, &sfinfo);
3327         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
3328
3329         smb2_util_close(tree, h1);
3330
3331         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3332         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3333
3334         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3335                            0, 60, 16, 8, type_creator);
3336         torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3337
3338 done:
3339         smb2_util_unlink(tree, fname);
3340         smb2_util_rmdir(tree, BASEDIR);
3341         return ret;
3342 }
3343
3344 static bool test_afpinfo_all0(struct torture_context *tctx,
3345                               struct smb2_tree *tree)
3346 {
3347         bool ret = true;
3348         NTSTATUS status;
3349         struct smb2_handle h1;
3350         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3351         const char *fname = BASEDIR "\\file";
3352         const char *type_creator = "SMB,OLE!";
3353         AfpInfo *info = NULL;
3354         const char *streams_basic[] = {
3355                 "::$DATA"
3356         };
3357         const char *streams_afpinfo[] = {
3358                 "::$DATA",
3359                 AFPINFO_STREAM
3360         };
3361
3362         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3363
3364         torture_comment(tctx, "Write all 0 to AFP_AfpInfo and see what happens\n");
3365
3366         smb2_deltree(tree, BASEDIR);
3367         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3368         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3369         smb2_util_close(tree, h1);
3370         ret = torture_setup_file(mem_ctx, tree, fname, false);
3371         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3372
3373         info = torture_afpinfo_new(mem_ctx);
3374         torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3375         memcpy(info->afpi_FinderInfo, type_creator, 8);
3376         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3377         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3378
3379         ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3380         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3381
3382         /* Write all 0 to AFP_AfpInfo */
3383         memset(info->afpi_FinderInfo, 0, AFP_FinderSize);
3384         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3385         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3386
3387         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3388         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3389
3390 done:
3391         smb2_util_unlink(tree, fname);
3392         smb2_util_rmdir(tree, BASEDIR);
3393         return ret;
3394 }
3395
3396 static bool test_create_delete_on_close_resource(struct torture_context *tctx,
3397                                                  struct smb2_tree *tree)
3398 {
3399         bool ret = true;
3400         NTSTATUS status;
3401         struct smb2_create create;
3402         struct smb2_handle h1;
3403         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3404         const char *fname = BASEDIR "\\file";
3405         const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3406         const char *streams_basic[] = {
3407                 "::$DATA"
3408         };
3409         const char *streams_afpresource[] = {
3410                 "::$DATA",
3411                 AFPRESOURCE_STREAM
3412         };
3413
3414         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3415
3416         torture_comment(tctx, "Checking whether create with delete-on-close is ignored for AFP_AfpResource\n");
3417
3418         smb2_deltree(tree, BASEDIR);
3419         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3420         torture_assert_ntstatus_ok(tctx, status, "torture_smb2_testdir");
3421         smb2_util_close(tree, h1);
3422         ret = torture_setup_file(mem_ctx, tree, fname, false);
3423         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3424
3425         torture_comment(tctx, "Opening not existing AFP_AfpResource\n");
3426
3427         ZERO_STRUCT(create);
3428         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3429         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3430         create.in.fname = sname;
3431
3432         status = smb2_create(tree, mem_ctx, &create);
3433         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3434                                            ret, done, "Got unexpected AFP_AfpResource stream");
3435
3436         ZERO_STRUCT(create);
3437         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3438         create.in.desired_access = SEC_FILE_ALL;
3439         create.in.fname = sname;
3440
3441         status = smb2_create(tree, mem_ctx, &create);
3442         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3443                                            ret, done, "Got unexpected AFP_AfpResource stream");
3444
3445         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3446         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3447
3448         torture_comment(tctx, "Trying to delete AFP_AfpResource via create with delete-on-close\n");
3449
3450         ret = write_stream(tree, __location__, tctx, mem_ctx,
3451                            fname, AFPRESOURCE_STREAM_NAME,
3452                            0, 10, "1234567890");
3453         torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3454
3455         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3456                            0, 10, 0, 10, "1234567890");
3457         torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3458
3459         ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3460         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3461
3462         ZERO_STRUCT(create);
3463         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3464         create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3465         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3466         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3467         create.in.fname = sname;
3468         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3469
3470         status = smb2_create(tree, mem_ctx, &create);
3471         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3472
3473         h1 = create.out.file.handle;
3474         smb2_util_close(tree, h1);
3475
3476         ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3477         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3478
3479         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3480                            0, 10, 0, 10, "1234567890");
3481         torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3482
3483 done:
3484         smb2_util_unlink(tree, fname);
3485         smb2_util_rmdir(tree, BASEDIR);
3486         return ret;
3487 }
3488
3489 static bool test_setinfo_delete_on_close_resource(struct torture_context *tctx,
3490                                                   struct smb2_tree *tree)
3491 {
3492         bool ret = true;
3493         NTSTATUS status;
3494         struct smb2_create create;
3495         union smb_setfileinfo sfinfo;
3496         struct smb2_handle h1;
3497         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3498         const char *fname = BASEDIR "\\file";
3499         const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3500         const char *streams_afpresource[] = {
3501                 "::$DATA",
3502                 AFPRESOURCE_STREAM
3503         };
3504
3505         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3506
3507         torture_comment(tctx, "Trying to delete AFP_AfpResource via setinfo with delete-on-close\n");
3508
3509         smb2_deltree(tree, BASEDIR);
3510         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3511         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3512         smb2_util_close(tree, h1);
3513         ret = torture_setup_file(mem_ctx, tree, fname, false);
3514         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3515
3516         ret = write_stream(tree, __location__, tctx, mem_ctx,
3517                            fname, AFPRESOURCE_STREAM_NAME,
3518                            10, 10, "1234567890");
3519         torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3520
3521         ZERO_STRUCT(create);
3522         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3523         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3524         create.in.fname = sname;
3525         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3526         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3527
3528         status = smb2_create(tree, mem_ctx, &create);
3529         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3530
3531         h1 = create.out.file.handle;
3532
3533         /* Try to delete stream via setinfo delete-on-close */
3534         ZERO_STRUCT(sfinfo);
3535         sfinfo.disposition_info.in.delete_on_close = 1;
3536         sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3537         sfinfo.generic.in.file.handle = h1;
3538         status = smb2_setinfo_file(tree, &sfinfo);
3539         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3540
3541         smb2_util_close(tree, h1);
3542
3543         ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3544         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3545
3546         ZERO_STRUCT(create);
3547         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3548         create.in.desired_access = SEC_FILE_ALL;
3549         create.in.fname = sname;
3550         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3551         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3552         status = smb2_create(tree, mem_ctx, &create);
3553         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3554                                         "Got unexpected AFP_AfpResource stream");
3555
3556 done:
3557         smb2_util_unlink(tree, fname);
3558         smb2_util_rmdir(tree, BASEDIR);
3559         return ret;
3560 }
3561
3562 static bool test_setinfo_eof_resource(struct torture_context *tctx,
3563                                       struct smb2_tree *tree)
3564 {
3565         bool ret = true;
3566         NTSTATUS status;
3567         struct smb2_create create;
3568         union smb_setfileinfo sfinfo;
3569         union smb_fileinfo finfo;
3570         struct smb2_handle h1;
3571         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3572         const char *fname = BASEDIR "\\file";
3573         const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3574         const char *streams_basic[] = {
3575                 "::$DATA"
3576         };
3577
3578         torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3579
3580         torture_comment(tctx, "Set AFP_AfpResource EOF to 1 and 0\n");
3581
3582         smb2_deltree(tree, BASEDIR);
3583         status = torture_smb2_testdir(tree, BASEDIR, &h1);
3584         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3585         smb2_util_close(tree, h1);
3586         ret = torture_setup_file(mem_ctx, tree, fname, false);
3587         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3588
3589         ret = write_stream(tree, __location__, tctx, mem_ctx,
3590                            fname, AFPRESOURCE_STREAM_NAME,
3591                            10, 10, "1234567890");
3592         torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3593
3594         ZERO_STRUCT(create);
3595         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3596         create.in.desired_access = SEC_FILE_ALL;
3597         create.in.fname = sname;
3598         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3599         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3600
3601         status = smb2_create(tree, mem_ctx, &create);
3602         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3603
3604         h1 = create.out.file.handle;
3605
3606         torture_comment(tctx, "Set AFP_AfpResource EOF to 1\n");
3607
3608         /* Test setinfo end-of-file info */
3609         ZERO_STRUCT(sfinfo);
3610         sfinfo.generic.in.file.handle = h1;
3611         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3612         sfinfo.position_information.in.position = 1;
3613         status = smb2_setinfo_file(tree, &sfinfo);
3614         torture_assert_ntstatus_ok_goto(tctx, status,
3615                                         ret, done, "set eof 1 failed");
3616
3617         smb2_util_close(tree, h1);
3618
3619         /* Check size == 1 */
3620         ZERO_STRUCT(create);
3621         create.in.fname = sname;
3622         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3623         create.in.desired_access = SEC_FILE_ALL;
3624         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3625         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3626         status = smb2_create(tree, mem_ctx, &create);
3627         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3628
3629         h1 = create.out.file.handle;
3630
3631         ZERO_STRUCT(finfo);
3632         finfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
3633         finfo.generic.in.file.handle = h1;
3634         status = smb2_getinfo_file(tree, mem_ctx, &finfo);
3635         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file failed");
3636
3637         smb2_util_close(tree, h1);
3638
3639         torture_assert_goto(tctx, finfo.all_info.out.size == 1, ret, done, "size != 1");
3640
3641         ZERO_STRUCT(create);
3642         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3643         create.in.desired_access = SEC_FILE_ALL;
3644         create.in.fname = sname;
3645         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3646         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3647
3648         status = smb2_create(tree, mem_ctx, &create);
3649         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3650
3651         h1 = create.out.file.handle;
3652
3653         /*
3654          * Delete stream via setinfo end-of-file info to 0, this
3655          * should delete the stream.
3656          */
3657         ZERO_STRUCT(sfinfo);
3658         sfinfo.generic.in.file.handle = h1;
3659         sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3660         sfinfo.position_information.in.position = 0;
3661         status = smb2_setinfo_file(tree, &sfinfo);
3662         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
3663
3664         smb2_util_close(tree, h1);
3665
3666         ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3667         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3668
3669         ZERO_STRUCT(create);
3670         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3671         create.in.desired_access = SEC_FILE_ALL;
3672         create.in.fname = sname;
3673         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3674         create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3675
3676         status = smb2_create(tree, mem_ctx, &create);
3677         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3678                                            ret, done, "smb2_create failed");
3679
3680 done:
3681         smb2_util_unlink(tree, fname);
3682         smb2_util_rmdir(tree, BASEDIR);
3683         return ret;
3684 }
3685
3686 /*
3687  * This tests that right after creating the AFP_AfpInfo stream,
3688  * reading from the stream returns an empty, default metadata blob of
3689  * 60 bytes.
3690  *
3691  * NOTE: against OS X SMB server this only works if the read request
3692  * is compounded with the create that created the stream, is fails
3693  * otherwise. We don't care...
3694  */
3695 static bool test_null_afpinfo(struct torture_context *tctx,
3696                               struct smb2_tree *tree)
3697 {
3698         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3699         const char *fname = "test_null_afpinfo";
3700         const char *sname = "test_null_afpinfo" AFPINFO_STREAM_NAME;
3701         NTSTATUS status;
3702         bool ret = true;
3703         struct smb2_request *req[3];
3704         struct smb2_handle handle;
3705         struct smb2_create create;
3706         struct smb2_read read;
3707         AfpInfo *afpinfo = NULL;
3708         char *afpinfo_buf = NULL;
3709         const char *type_creator = "SMB,OLE!";
3710
3711         torture_comment(tctx, "Checking create of AfpInfo stream\n");
3712
3713         smb2_util_unlink(tree, fname);
3714
3715         ret = torture_setup_file(mem_ctx, tree, fname, false);
3716         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
3717
3718         ZERO_STRUCT(create);
3719         create.in.desired_access = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA;
3720         create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
3721         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3722         create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
3723         create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3724         create.in.fname = sname;
3725
3726         smb2_transport_compound_start(tree->session->transport, 2);
3727
3728         req[0] = smb2_create_send(tree, &create);
3729
3730         handle.data[0] = UINT64_MAX;
3731         handle.data[1] = UINT64_MAX;
3732
3733         smb2_transport_compound_set_related(tree->session->transport, true);
3734
3735         ZERO_STRUCT(read);
3736         read.in.file.handle = handle;
3737         read.in.length = AFP_INFO_SIZE;
3738         req[1] = smb2_read_send(tree, &read);
3739
3740         status = smb2_create_recv(req[0], tree, &create);
3741         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_recv failed");
3742
3743         handle = create.out.file.handle;
3744
3745         status = smb2_read_recv(req[1], tree, &read);
3746         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read_recv failed");
3747
3748         afpinfo = torture_afpinfo_new(mem_ctx);
3749         torture_assert_goto(tctx, afpinfo != NULL, ret, done, "torture_afpinfo_new failed");
3750
3751         memcpy(afpinfo->afpi_FinderInfo, type_creator, 8);
3752
3753         afpinfo_buf = torture_afpinfo_pack(tctx, afpinfo);
3754         torture_assert_goto(tctx, afpinfo_buf != NULL, ret, done, "torture_afpinfo_new failed");
3755
3756         status = smb2_util_write(tree, handle, afpinfo_buf, 0, AFP_INFO_SIZE);
3757         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write failed");
3758
3759         smb2_util_close(tree, handle);
3760
3761         ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3762                            0, 60, 16, 8, type_creator);
3763         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
3764
3765 done:
3766         smb2_util_unlink(tree, fname);
3767         talloc_free(mem_ctx);
3768         return ret;
3769 }
3770
3771 static bool test_delete_file_with_rfork(struct torture_context *tctx,
3772                                         struct smb2_tree *tree)
3773 {
3774         const char *fname = "torture_write_rfork_io";
3775         const char *rfork_content = "1234567890";
3776         NTSTATUS status;
3777         bool ret = true;
3778
3779         smb2_util_unlink(tree, fname);
3780
3781         torture_comment(tctx, "Test deleting file with resource fork\n");
3782
3783         ret = torture_setup_file(tctx, tree, fname, false);
3784         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed\n");
3785
3786         ret = write_stream(tree, __location__, tctx, tctx,
3787                            fname, AFPRESOURCE_STREAM_NAME,
3788                            10, 10, rfork_content);
3789         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed\n");
3790
3791         ret = check_stream(tree, __location__, tctx, tctx,
3792                            fname, AFPRESOURCE_STREAM_NAME,
3793                            0, 20, 10, 10, rfork_content);
3794         torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed\n");
3795
3796         status = smb2_util_unlink(tree, fname);
3797         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "check_stream failed\n");
3798
3799 done:
3800         return ret;
3801 }
3802
3803 static bool test_rename_and_read_rsrc(struct torture_context *tctx,
3804                                       struct smb2_tree *tree)
3805 {
3806         bool ret = true;
3807         NTSTATUS status;
3808         struct smb2_create create, create2;
3809         struct smb2_handle h1, h2;
3810         const char *fname = "test_rename_openfile";
3811         const char *sname = "test_rename_openfile" AFPRESOURCE_STREAM_NAME;
3812         const char *fname_renamed = "test_rename_openfile_renamed";
3813         const char *data = "1234567890";
3814         union smb_setfileinfo sinfo;
3815         struct smb2_read r;
3816
3817         ret = enable_aapl(tctx, tree);
3818         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
3819
3820         torture_comment(tctx, "Create file with resource fork\n");
3821
3822         ret = torture_setup_file(tctx, tree, fname, false);
3823         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3824
3825         ret = write_stream(tree, __location__, tctx, tctx,
3826                            fname, AFPRESOURCE_STREAM_NAME, 0, 10, data);
3827         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
3828
3829         torture_comment(tctx, "Open resource fork\n");
3830
3831         ZERO_STRUCT(create);
3832         create.in.desired_access = SEC_FILE_ALL;
3833         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3834         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3835         create.in.create_disposition = NTCREATEX_DISP_OPEN;
3836         create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
3837         create.in.fname = sname;
3838
3839         status = smb2_create(tree, tctx, &create);
3840         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3841
3842         h1 = create.out.file.handle;
3843
3844         torture_comment(tctx, "Rename base file\n");
3845
3846         ZERO_STRUCT(create2);
3847         create2.in.desired_access = SEC_FILE_ALL;
3848         create2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3849         create2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3850         create2.in.create_disposition = NTCREATEX_DISP_OPEN;
3851         create2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
3852         create2.in.fname = fname;
3853
3854         status = smb2_create(tree, tctx, &create2);
3855         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3856
3857         h2 = create2.out.file.handle;
3858
3859         ZERO_STRUCT(sinfo);
3860         sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
3861         sinfo.rename_information.in.file.handle = h2;
3862         sinfo.rename_information.in.overwrite = 0;
3863         sinfo.rename_information.in.root_fid = 0;
3864         sinfo.rename_information.in.new_name = fname_renamed;
3865
3866         status = smb2_setinfo_file(tree, &sinfo);
3867         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file failed");
3868
3869         smb2_util_close(tree, h2);
3870
3871         ZERO_STRUCT(r);
3872         r.in.file.handle = h1;
3873         r.in.length      = 10;
3874         r.in.offset      = 0;
3875
3876         torture_comment(tctx, "Read resource fork of renamed file\n");
3877
3878         status = smb2_read(tree, tree, &r);
3879         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read failed");
3880
3881         smb2_util_close(tree, h1);
3882
3883         torture_assert_goto(tctx, r.out.data.length == 10, ret, done,
3884                             talloc_asprintf(tctx, "smb2_read returned %jd bytes, expected 10\n",
3885                                             (intmax_t)r.out.data.length));
3886
3887         torture_assert_goto(tctx, memcmp(r.out.data.data, data, 10) == 0, ret, done,
3888                             talloc_asprintf(tctx, "Bad data in stream\n"));
3889
3890 done:
3891         smb2_util_unlink(tree, fname);
3892         smb2_util_unlink(tree, fname_renamed);
3893
3894         return ret;
3895 }
3896
3897 static bool test_readdir_attr_illegal_ntfs(struct torture_context *tctx,
3898                                            struct smb2_tree *tree)
3899 {
3900         TALLOC_CTX *mem_ctx = talloc_new(tctx);
3901         const char *name = "test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
3902         const char *fname = BASEDIR "\\test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
3903         NTSTATUS status;
3904         struct smb2_handle testdirh;
3905         bool ret = true;
3906         struct smb2_create io;
3907         AfpInfo *info;
3908         const char *type_creator = "SMB,OLE!";
3909         struct smb2_find f;
3910         unsigned int count;
3911         union smb_search_data *d;
3912         uint64_t rfork_len;
3913         int i;
3914
3915         smb2_deltree(tree, BASEDIR);
3916
3917         status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
3918         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
3919         smb2_util_close(tree, testdirh);
3920
3921         torture_comment(tctx, "Enabling AAPL\n");
3922
3923         ret = enable_aapl(tctx, tree);
3924         torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
3925
3926         /*
3927          * Now that Requested AAPL extensions are enabled, setup some
3928          * Mac files with metadata and resource fork
3929          */
3930
3931         torture_comment(tctx, "Preparing file\n");
3932
3933         ret = torture_setup_file(mem_ctx, tree, fname, false);
3934         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
3935
3936         info = torture_afpinfo_new(mem_ctx);
3937         torture_assert_not_null_goto(tctx, info, ret, done, "torture_afpinfo_new failed");
3938
3939         memcpy(info->afpi_FinderInfo, type_creator, 8);
3940         ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3941         torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3942
3943         ret = write_stream(tree, __location__, tctx, mem_ctx,
3944                            fname, AFPRESOURCE_STREAM_NAME,
3945                            0, 3, "foo");
3946         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
3947
3948         /*
3949          * Ok, file is prepared, now call smb2/find
3950          */
3951
3952         torture_comment(tctx, "Issue find\n");
3953
3954         ZERO_STRUCT(io);
3955         io.in.desired_access = SEC_RIGHTS_DIR_READ;
3956         io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
3957         io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
3958         io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
3959                               NTCREATEX_SHARE_ACCESS_WRITE |
3960                               NTCREATEX_SHARE_ACCESS_DELETE);
3961         io.in.create_disposition = NTCREATEX_DISP_OPEN;
3962         io.in.fname = BASEDIR;
3963         status = smb2_create(tree, tctx, &io);
3964         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3965
3966         ZERO_STRUCT(f);
3967         f.in.file.handle        = io.out.file.handle;
3968         f.in.pattern            = "*";
3969         f.in.max_response_size  = 0x1000;
3970         f.in.level              = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
3971
3972         status = smb2_find_level(tree, tree, &f, &count, &d);
3973         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_level failed");
3974
3975         status = smb2_util_close(tree, io.out.file.handle);
3976         torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close failed");
3977
3978         torture_comment(tctx, "Checking find response with enriched macOS metadata\n");
3979
3980         for (i = 0; i < count; i++) {
3981                 const char *found = d[i].id_both_directory_info.name.s;
3982
3983                 if (!strcmp(found, ".") || !strcmp(found, ".."))
3984                         continue;
3985                 if (strncmp(found, "._", 2) == 0) {
3986                         continue;
3987                 }
3988                 break;
3989         }
3990
3991         torture_assert_str_equal_goto(tctx,
3992                                       d[i].id_both_directory_info.name.s, name,
3993                                       ret, done, "bad name");
3994
3995         rfork_len = BVAL(d[i].id_both_directory_info.short_name_buf, 0);
3996         torture_assert_int_equal_goto(tctx, rfork_len, 3, ret, done, "bad resource fork length");
3997
3998         torture_assert_mem_equal_goto(tctx, type_creator,
3999                                       d[i].id_both_directory_info.short_name_buf + 8,
4000                                       8, ret, done, "Bad FinderInfo");
4001 done:
4002         smb2_util_unlink(tree, fname);
4003         smb2_deltree(tree, BASEDIR);
4004         talloc_free(mem_ctx);
4005         return ret;
4006 }
4007
4008 static bool test_invalid_afpinfo(struct torture_context *tctx,
4009                                  struct smb2_tree *tree1,
4010                                  struct smb2_tree *tree2)
4011 {
4012         const char *fname = "filtest_invalid_afpinfo";
4013         const char *sname = "filtest_invalid_afpinfo" AFPINFO_STREAM_NAME;
4014         struct smb2_create create;
4015         const char *streams_basic[] = {
4016                 "::$DATA"
4017         };
4018         const char *streams_afpinfo[] = {
4019                 "::$DATA",
4020                 AFPINFO_STREAM
4021         };
4022         NTSTATUS status;
4023         bool ret = true;
4024
4025         if (tree2 == NULL) {
4026                 torture_skip_goto(tctx, done, "need second share without fruit\n");
4027         }
4028
4029         torture_comment(tctx, "Testing invalid AFP_AfpInfo stream\n");
4030
4031         ret = torture_setup_file(tctx, tree2, fname, false);
4032         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4033
4034         ret = write_stream(tree2, __location__, tctx, tctx,
4035                            fname, AFPINFO_STREAM_NAME,
4036                            0, 3, "foo");
4037         torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4038
4039         ret = check_stream_list(tree2, tctx, fname, 2, streams_afpinfo, false);
4040         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4041
4042         torture_comment(tctx, "Listing streams, bad AFPINFO stream must not be present\n");
4043
4044         ret = check_stream_list(tree1, tctx, fname, 1, streams_basic, false);
4045         torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4046
4047         torture_comment(tctx, "Try to open AFPINFO stream, must fail\n");
4048
4049         ZERO_STRUCT(create);
4050         create.in.desired_access = SEC_FILE_ALL;
4051         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4052         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4053         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4054         create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4055         create.in.fname = sname;
4056
4057         status = smb2_create(tree1, tctx, &create);
4058         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4059                                            ret, done, "Stream still around?");
4060
4061 done:
4062         smb2_util_unlink(tree1, fname);
4063         return ret;
4064 }
4065
4066 static bool test_zero_file_id(struct torture_context *tctx,
4067                               struct smb2_tree *tree)
4068 {
4069         const char *fname = "filtest_file_id";
4070         struct smb2_create create = {0};
4071         NTSTATUS status;
4072         bool ret = true;
4073         uint8_t zero_file_id[8] = {0};
4074
4075         torture_comment(tctx, "Testing zero file id\n");
4076
4077         ret = torture_setup_file(tctx, tree, fname, false);
4078         torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4079
4080         ZERO_STRUCT(create);
4081         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4082         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4083         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4084         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4085         create.in.fname = fname;
4086         create.in.query_on_disk_id = true;
4087
4088         status = smb2_create(tree, tctx, &create);
4089         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
4090                                            done,
4091                                            "test file could not be opened");
4092         torture_assert_mem_not_equal_goto(tctx, create.out.on_disk_id,
4093                                           zero_file_id, 8, ret, done,
4094                                           "unexpected zero file id");
4095
4096         smb2_util_close(tree, create.out.file.handle);
4097
4098         ret = enable_aapl(tctx, tree);
4099         torture_assert(tctx, ret == true, "enable_aapl failed");
4100
4101         ZERO_STRUCT(create);
4102         create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4103         create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4104         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4105         create.in.create_disposition = NTCREATEX_DISP_OPEN;
4106         create.in.fname = fname;
4107         create.in.query_on_disk_id = true;
4108
4109         status = smb2_create(tree, tctx, &create);
4110         torture_assert_ntstatus_equal_goto(
4111             tctx, status, NT_STATUS_OK, ret, done,
4112             "test file could not be opened with AAPL");
4113         torture_assert_mem_equal_goto(tctx, create.out.on_disk_id, zero_file_id,
4114                                       8, ret, done, "non-zero file id");
4115
4116         smb2_util_close(tree, create.out.file.handle);
4117
4118 done:
4119         smb2_util_unlink(tree, fname);
4120         return ret;
4121 }
4122
4123 static bool copy_one_stream(struct torture_context *torture,
4124                             struct smb2_tree *tree,
4125                             TALLOC_CTX *tmp_ctx,
4126                             const char *src_sname,
4127                             const char *dst_sname)
4128 {
4129         struct smb2_handle src_h = {{0}};
4130         struct smb2_handle dest_h = {{0}};
4131         NTSTATUS status;
4132         union smb_ioctl io;
4133         struct srv_copychunk_copy cc_copy;
4134         struct srv_copychunk_rsp cc_rsp;
4135         enum ndr_err_code ndr_ret;
4136         bool ok = false;
4137
4138         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4139                                    1, /* 1 chunk */
4140                                    src_sname,
4141                                    &src_h, 256, /* fill 256 byte src file */
4142                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4143                                    dst_sname,
4144                                    &dest_h, 0,  /* 0 byte dest file */
4145                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4146                                    &cc_copy,
4147                                    &io);
4148         torture_assert_goto(torture, ok == true, ok, done,
4149                             "setup copy chunk error\n");
4150
4151         /* copy all src file data (via a single chunk desc) */
4152         cc_copy.chunks[0].source_off = 0;
4153         cc_copy.chunks[0].target_off = 0;
4154         cc_copy.chunks[0].length = 256;
4155
4156         ndr_ret = ndr_push_struct_blob(
4157                 &io.smb2.in.out, tmp_ctx, &cc_copy,
4158                 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4159
4160         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4161                                    "ndr_push_srv_copychunk_copy\n");
4162
4163         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4164         torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4165                                         "FSCTL_SRV_COPYCHUNK\n");
4166
4167         ndr_ret = ndr_pull_struct_blob(
4168                 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4169                 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4170
4171         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4172                                    "ndr_pull_srv_copychunk_rsp\n");
4173
4174         ok = check_copy_chunk_rsp(torture, &cc_rsp,
4175                                   1,    /* chunks written */
4176                                   0,    /* chunk bytes unsuccessfully written */
4177                                   256); /* total bytes written */
4178         torture_assert_goto(torture, ok == true, ok, done,
4179                             "bad copy chunk response data\n");
4180
4181         ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 256, 0);
4182         if (!ok) {
4183                 torture_fail(torture, "inconsistent file data\n");
4184         }
4185
4186 done:
4187         if (!smb2_util_handle_empty(src_h)) {
4188                 smb2_util_close(tree, src_h);
4189         }
4190         if (!smb2_util_handle_empty(dest_h)) {
4191                 smb2_util_close(tree, dest_h);
4192         }
4193
4194         return ok;
4195 }
4196
4197 static bool copy_finderinfo_stream(struct torture_context *torture,
4198                                    struct smb2_tree *tree,
4199                                    TALLOC_CTX *tmp_ctx,
4200                                    const char *src_name,
4201                                    const char *dst_name)
4202 {
4203         struct smb2_handle src_h = {{0}};
4204         struct smb2_handle dest_h = {{0}};
4205         NTSTATUS status;
4206         union smb_ioctl io;
4207         struct srv_copychunk_copy cc_copy;
4208         struct srv_copychunk_rsp cc_rsp;
4209         enum ndr_err_code ndr_ret;
4210         const char *type_creator = "SMB,OLE!";
4211         AfpInfo *info = NULL;
4212         const char *src_name_afpinfo = NULL;
4213         const char *dst_name_afpinfo = NULL;
4214         bool ok = false;
4215
4216         src_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", src_name,
4217                                            AFPINFO_STREAM);
4218         torture_assert_not_null_goto(torture, src_name_afpinfo, ok, done,
4219                                      "talloc_asprintf failed\n");
4220
4221         dst_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", dst_name,
4222                                            AFPINFO_STREAM);
4223         torture_assert_not_null_goto(torture, dst_name_afpinfo, ok, done,
4224                                      "talloc_asprintf failed\n");
4225
4226         info = torture_afpinfo_new(tmp_ctx);
4227         torture_assert_not_null_goto(torture, info, ok, done,
4228                                      "torture_afpinfo_new failed\n");
4229
4230         memcpy(info->afpi_FinderInfo, type_creator, 8);
4231         ok = torture_write_afpinfo(tree, torture, tmp_ctx, src_name, info);
4232         torture_assert_goto(torture, ok == true, ok, done,
4233                             "torture_write_afpinfo failed\n");
4234
4235         ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4236                                    1, /* 1 chunk */
4237                                    src_name_afpinfo,
4238                                    &src_h, 0,
4239                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4240                                    dst_name_afpinfo,
4241                                    &dest_h, 0,
4242                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4243                                    &cc_copy,
4244                                    &io);
4245         torture_assert_goto(torture, ok == true, ok, done,
4246                             "setup copy chunk error\n");
4247
4248         /* copy all src file data (via a single chunk desc) */
4249         cc_copy.chunks[0].source_off = 0;
4250         cc_copy.chunks[0].target_off = 0;
4251         cc_copy.chunks[0].length = 60;
4252
4253         ndr_ret = ndr_push_struct_blob(
4254                 &io.smb2.in.out, tmp_ctx, &cc_copy,
4255                 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4256
4257         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4258                                    "ndr_push_srv_copychunk_copy\n");
4259
4260         status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4261         torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4262                                         "FSCTL_SRV_COPYCHUNK\n");
4263
4264         ndr_ret = ndr_pull_struct_blob(
4265                 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4266                 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4267
4268         torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4269                                    "ndr_pull_srv_copychunk_rsp\n");
4270
4271         smb2_util_close(tree, src_h);
4272         ZERO_STRUCT(src_h);
4273         smb2_util_close(tree, dest_h);
4274         ZERO_STRUCT(dest_h);
4275
4276         ok = check_copy_chunk_rsp(torture, &cc_rsp,
4277                                   1,    /* chunks written */
4278                                   0,    /* chunk bytes unsuccessfully written */
4279                                   60); /* total bytes written */
4280         torture_assert_goto(torture, ok == true, ok, done,
4281                             "bad copy chunk response data\n");
4282
4283         ok = check_stream(tree, __location__, torture, tmp_ctx,
4284                           dst_name, AFPINFO_STREAM,
4285                           0, 60, 16, 8, type_creator);
4286         torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
4287
4288 done:
4289         if (!smb2_util_handle_empty(src_h)) {
4290                 smb2_util_close(tree, src_h);
4291         }
4292         if (!smb2_util_handle_empty(dest_h)) {
4293                 smb2_util_close(tree, dest_h);
4294         }
4295
4296         return ok;
4297 }
4298
4299 static bool test_copy_chunk_streams(struct torture_context *torture,
4300                                     struct smb2_tree *tree)
4301 {
4302         const char *src_name = "src";
4303         const char *dst_name = "dst";
4304         struct names {
4305                 const char *src_sname;
4306                 const char *dst_sname;
4307         } names[] = {
4308                 { "src:foo", "dst:foo" },
4309                 { "src" AFPRESOURCE_STREAM, "dst" AFPRESOURCE_STREAM }
4310         };
4311         int i;
4312         TALLOC_CTX *tmp_ctx = NULL;
4313         bool ok = false;
4314
4315         tmp_ctx = talloc_new(tree);
4316         torture_assert_not_null_goto(torture, tmp_ctx, ok, done,
4317                                      "torture_setup_file\n");
4318
4319         smb2_util_unlink(tree, src_name);
4320         smb2_util_unlink(tree, dst_name);
4321
4322         ok = torture_setup_file(torture, tree, src_name, false);
4323         torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
4324         ok = torture_setup_file(torture, tree, dst_name, false);
4325         torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
4326
4327         for (i = 0; i < ARRAY_SIZE(names); i++) {
4328                 ok = copy_one_stream(torture, tree, tmp_ctx,
4329                                      names[i].src_sname,
4330                                      names[i].dst_sname);
4331                 torture_assert_goto(torture, ok == true, ok, done,
4332                                     "copy_one_stream failed\n");
4333         }
4334
4335         ok = copy_finderinfo_stream(torture, tree, tmp_ctx,
4336                                     src_name, dst_name);
4337         torture_assert_goto(torture, ok == true, ok, done,
4338                             "copy_finderinfo_stream failed\n");
4339
4340 done:
4341         smb2_util_unlink(tree, src_name);
4342         smb2_util_unlink(tree, dst_name);
4343         talloc_free(tmp_ctx);
4344         return ok;
4345 }
4346
4347 /*
4348  * Note: This test depends on "vfs objects = catia fruit streams_xattr".  For
4349  * some tests torture must be run on the host it tests and takes an additional
4350  * argument with the local path to the share:
4351  * "--option=torture:localdir=<SHAREPATH>".
4352  *
4353  * When running against an OS X SMB server add "--option=torture:osx=true"
4354  */
4355 struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx)
4356 {
4357         struct torture_suite *suite = torture_suite_create(
4358                 ctx, "fruit");
4359
4360         suite->description = talloc_strdup(suite, "vfs_fruit tests");
4361
4362         torture_suite_add_1smb2_test(suite, "copyfile", test_copyfile);
4363         torture_suite_add_1smb2_test(suite, "read metadata", test_read_afpinfo);
4364         torture_suite_add_1smb2_test(suite, "write metadata", test_write_atalk_metadata);
4365         torture_suite_add_1smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io);
4366         torture_suite_add_1smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl);
4367         torture_suite_add_1smb2_test(suite, "stream names", test_stream_names);
4368         torture_suite_add_1smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate);
4369         torture_suite_add_1smb2_test(suite, "opening and creating resource fork", test_rfork_create);
4370         torture_suite_add_1smb2_test(suite, "rename_dir_openfile", test_rename_dir_openfile);
4371         torture_suite_add_1smb2_test(suite, "File without AFP_AfpInfo", test_afpinfo_enoent);
4372         torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpInfo", test_create_delete_on_close);
4373         torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpInfo", test_setinfo_delete_on_close);
4374         torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpInfo", test_setinfo_eof);
4375         torture_suite_add_1smb2_test(suite, "delete AFP_AfpInfo by writing all 0", test_afpinfo_all0);
4376         torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpResource", test_create_delete_on_close_resource);
4377         torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpResource", test_setinfo_delete_on_close_resource);
4378         torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpResource", test_setinfo_eof_resource);
4379         torture_suite_add_1smb2_test(suite, "null afpinfo", test_null_afpinfo);
4380         torture_suite_add_1smb2_test(suite, "delete", test_delete_file_with_rfork);
4381         torture_suite_add_1smb2_test(suite, "read open rsrc after rename", test_rename_and_read_rsrc);
4382         torture_suite_add_1smb2_test(suite, "readdir_attr with names with illegal ntfs characters", test_readdir_attr_illegal_ntfs);
4383         torture_suite_add_2ns_smb2_test(suite, "invalid AFP_AfpInfo", test_invalid_afpinfo);
4384         torture_suite_add_1smb2_test(suite, "creating rsrc with read-only access", test_rfork_create_ro);
4385         torture_suite_add_1smb2_test(suite, "copy-chunk streams", test_copy_chunk_streams);
4386         torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
4387
4388         return suite;
4389 }
4390
4391 static bool test_stream_names_local(struct torture_context *tctx,
4392                                     struct smb2_tree *tree)
4393 {
4394         TALLOC_CTX *mem_ctx = talloc_new(tctx);
4395         NTSTATUS status;
4396         struct smb2_create create;
4397         struct smb2_handle h;
4398         const char *fname = BASEDIR "\\stream_names.txt";
4399         const char *sname1;
4400         bool ret;
4401         /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
4402         const char *streams[] = {
4403                 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
4404                 ":bar" "\xef\x80\xa2" "baz:$DATA", /* "bar:baz:$DATA" */
4405                 "::$DATA"
4406         };
4407         const char *localdir = NULL;
4408
4409         localdir = torture_setting_string(tctx, "localdir", NULL);
4410         if (localdir == NULL) {
4411                 torture_skip(tctx, "Need localdir for test");
4412         }
4413
4414         sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
4415
4416         /* clean slate ...*/
4417         smb2_util_unlink(tree, fname);
4418         smb2_deltree(tree, fname);
4419         smb2_deltree(tree, BASEDIR);
4420
4421         status = torture_smb2_testdir(tree, BASEDIR, &h);
4422         CHECK_STATUS(status, NT_STATUS_OK);
4423         smb2_util_close(tree, h);
4424
4425         torture_comment(tctx, "(%s) testing stream names\n", __location__);
4426         ZERO_STRUCT(create);
4427         create.in.desired_access = SEC_FILE_WRITE_DATA;
4428         create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4429         create.in.share_access =
4430                 NTCREATEX_SHARE_ACCESS_DELETE|
4431                 NTCREATEX_SHARE_ACCESS_READ|
4432                 NTCREATEX_SHARE_ACCESS_WRITE;
4433         create.in.create_disposition = NTCREATEX_DISP_CREATE;
4434         create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4435         create.in.fname = sname1;
4436
4437         status = smb2_create(tree, mem_ctx, &create);
4438         CHECK_STATUS(status, NT_STATUS_OK);
4439         smb2_util_close(tree, create.out.file.handle);
4440
4441         ret = torture_setup_local_xattr(tctx, "localdir", BASEDIR "/stream_names.txt",
4442                                         "user.DosStream.bar:baz:$DATA",
4443                                         "data", strlen("data"));
4444         CHECK_VALUE(ret, true);
4445
4446         ret = check_stream_list(tree, tctx, fname, 3, streams, false);
4447         CHECK_VALUE(ret, true);
4448
4449 done:
4450         status = smb2_util_unlink(tree, fname);
4451         smb2_deltree(tree, BASEDIR);
4452         talloc_free(mem_ctx);
4453
4454         return ret;
4455 }
4456
4457 struct torture_suite *torture_vfs_fruit_netatalk(TALLOC_CTX *ctx)
4458 {
4459         struct torture_suite *suite = torture_suite_create(
4460                 ctx, "fruit_netatalk");
4461
4462         suite->description = talloc_strdup(suite, "vfs_fruit tests for Netatalk interop that require fruit:metadata=netatalk");
4463
4464         torture_suite_add_1smb2_test(suite, "read netatalk metadata", test_read_netatalk_metadata);
4465         torture_suite_add_1smb2_test(suite, "stream names with locally created xattr", test_stream_names_local);
4466
4467         return suite;
4468 }
4469
4470 struct torture_suite *torture_vfs_fruit_file_id(TALLOC_CTX *ctx)
4471 {
4472         struct torture_suite *suite =
4473             torture_suite_create(ctx, "fruit_file_id");
4474
4475         suite->description =
4476             talloc_strdup(suite, "vfs_fruit tests for on-disk file ID that "
4477                                  "require fruit:zero_file_id=yes");
4478
4479         torture_suite_add_1smb2_test(suite, "zero file id if AAPL negotiated",
4480                                      test_zero_file_id);
4481
4482         return suite;
4483 }