s4: vfs: fruit tests: Add regression test for dealing with NFS ACE entries.
[Samba.git] / source4 / torture / vfs / fruit.c
blob65109cc193445115cfc5ab8343747f270e4f6c99
1 /*
2 Unix SMB/CIFS implementation.
4 vfs_fruit tests
6 Copyright (C) Ralph Boehme 2014
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.
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.
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/>.
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"
34 #include "torture/torture.h"
35 #include "torture/util.h"
36 #include "torture/smb2/proto.h"
37 #include "torture/vfs/proto.h"
38 #include "librpc/gen_ndr/ndr_ioctl.h"
39 #include "libcli/security/dom_sid.h"
40 #include "../librpc/gen_ndr/ndr_security.h"
41 #include "libcli/security/secace.h"
42 #include "libcli/security/security_descriptor.h"
44 #define BASEDIR "vfs_fruit_dir"
45 #define FNAME_CC_SRC "testfsctl.dat"
46 #define FNAME_CC_DST "testfsctl2.dat"
48 #define CHECK_STATUS(status, correct) do { \
49 if (!NT_STATUS_EQUAL(status, correct)) { \
50 torture_result(tctx, TORTURE_FAIL, \
51 "(%s) Incorrect status %s - should be %s\n", \
52 __location__, nt_errstr(status), nt_errstr(correct)); \
53 ret = false; \
54 goto done; \
55 }} while (0)
57 #define CHECK_VALUE(v, correct) do { \
58 if ((v) != (correct)) { \
59 torture_result(tctx, TORTURE_FAIL, \
60 "(%s) Incorrect value %s=%u - should be %u\n", \
61 __location__, #v, (unsigned)v, (unsigned)correct); \
62 ret = false; \
63 goto done; \
64 }} while (0)
66 static bool check_stream_list(struct smb2_tree *tree,
67 struct torture_context *tctx,
68 const char *fname,
69 int num_exp,
70 const char **exp,
71 bool is_dir);
73 static int qsort_string(char * const *s1, char * const *s2)
75 return strcmp(*s1, *s2);
78 static int qsort_stream(const struct stream_struct * s1, const struct stream_struct *s2)
80 return strcmp(s1->stream_name.s, s2->stream_name.s);
84 * REVIEW:
85 * This is hokey, but what else can we do?
87 #if defined(HAVE_ATTROPEN) || defined(FREEBSD)
88 #define AFPINFO_EA_NETATALK "org.netatalk.Metadata"
89 #define AFPRESOURCE_EA_NETATALK "org.netatalk.ResourceFork"
90 #else
91 #define AFPINFO_EA_NETATALK "user.org.netatalk.Metadata"
92 #define AFPRESOURCE_EA_NETATALK "user.org.netatalk.ResourceFork"
93 #endif
96 The metadata xattr char buf below contains the following attributes:
98 -------------------------------------------------------------------------------
99 Entry ID : 00000008 : File Dates Info
100 Offset : 00000162 : 354
101 Length : 00000010 : 16
103 -DATE------: : (GMT) : (Local)
104 create : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
105 modify : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
106 backup : 80000000 : Unknown or Initial
107 access : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
109 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
110 00000000 : 1B 44 21 69 1B 44 21 69 80 00 00 00 1B 44 21 69 : .D!i.D!i.....D!i
112 -------------------------------------------------------------------------------
113 Entry ID : 00000009 : Finder Info
114 Offset : 0000007A : 122
115 Length : 00000020 : 32
117 -FInfo-----:
118 Type : 42415252 : BARR
119 Creator : 464F4F4F : FOOO
120 isAlias : 0
121 Invisible : 1
122 hasBundle : 0
123 nameLocked : 0
124 Stationery : 0
125 CustomIcon : 0
126 Reserved : 0
127 Inited : 0
128 NoINITS : 0
129 Shared : 0
130 SwitchLaunc: 0
131 Hidden Ext : 0
132 color : 000 : none
133 isOnDesk : 0
134 Location v : 0000 : 0
135 Location h : 0000 : 0
136 Fldr : 0000 : ..
138 -FXInfo----:
139 Rsvd|IconID: 0000 : 0
140 Rsvd : 0000 : ..
141 Rsvd : 0000 : ..
142 Rsvd : 0000 : ..
143 AreInvalid : 0
144 unknown bit: 0
145 unknown bit: 0
146 unknown bit: 0
147 unknown bit: 0
148 unknown bit: 0
149 unknown bit: 0
150 CustomBadge: 0
151 ObjctIsBusy: 0
152 unknown bit: 0
153 unknown bit: 0
154 unknown bit: 0
155 unknown bit: 0
156 RoutingInfo: 0
157 unknown bit: 0
158 unknown bit: 0
159 Rsvd|commnt: 0000 : 0
160 PutAway : 00000000 : 0
162 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
163 00000000 : 42 41 52 52 46 4F 4F 4F 40 00 00 00 00 00 00 00 : BARRFOOO@.......
164 00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
166 -------------------------------------------------------------------------------
167 Entry ID : 0000000E : AFP File Info
168 Offset : 00000172 : 370
169 Length : 00000004 : 4
171 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
172 00000000 : 00 00 01 A1 : ....
175 char metadata_xattr[] = {
176 0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
180 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 0x00, 0x08, 0x00, 0x00, 0x01, 0x62, 0x00, 0x00,
182 0x00, 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
183 0x00, 0x7a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
184 0x00, 0x0e, 0x00, 0x00, 0x01, 0x72, 0x00, 0x00,
185 0x00, 0x04, 0x80, 0x44, 0x45, 0x56, 0x00, 0x00,
186 0x01, 0x76, 0x00, 0x00, 0x00, 0x08, 0x80, 0x49,
187 0x4e, 0x4f, 0x00, 0x00, 0x01, 0x7e, 0x00, 0x00,
188 0x00, 0x08, 0x80, 0x53, 0x59, 0x4e, 0x00, 0x00,
189 0x01, 0x86, 0x00, 0x00, 0x00, 0x08, 0x80, 0x53,
190 0x56, 0x7e, 0x00, 0x00, 0x01, 0x8e, 0x00, 0x00,
191 0x00, 0x04, 0x42, 0x41, 0x52, 0x52, 0x46, 0x4f,
192 0x4f, 0x4f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x1b, 0x44, 0x21, 0x69, 0x1b, 0x44,
221 0x21, 0x69, 0x80, 0x00, 0x00, 0x00, 0x1b, 0x44,
222 0x21, 0x69, 0x00, 0x00, 0x01, 0xa1, 0x00, 0xfd,
223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x20,
224 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xe3,
225 0x86, 0x53, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x01,
226 0x00, 0x00
230 The buf below contains the following AppleDouble encoded data:
232 -------------------------------------------------------------------------------
233 MagicNumber: 00051607 : AppleDouble
234 Version : 00020000 : Version 2
235 Filler : 4D 61 63 20 4F 53 20 58 20 20 20 20 20 20 20 20 : Mac OS X
236 Num. of ent: 0002 : 2
238 -------------------------------------------------------------------------------
239 Entry ID : 00000009 : Finder Info
240 Offset : 00000032 : 50
241 Length : 00000EB0 : 3760
243 -FInfo-----:
244 Type : 54455354 : TEST
245 Creator : 534C4F57 : SLOW
246 isAlias : 0
247 Invisible : 0
248 hasBundle : 0
249 nameLocked : 0
250 Stationery : 0
251 CustomIcon : 0
252 Reserved : 0
253 Inited : 0
254 NoINITS : 0
255 Shared : 0
256 SwitchLaunc: 0
257 Hidden Ext : 0
258 color : 100 : blue
259 isOnDesk : 0
260 Location v : 0000 : 0
261 Location h : 0000 : 0
262 Fldr : 0000 : ..
264 -FXInfo----:
265 Rsvd|IconID: 0000 : 0
266 Rsvd : 0000 : ..
267 Rsvd : 0000 : ..
268 Rsvd : 0000 : ..
269 AreInvalid : 0
270 unknown bit: 0
271 unknown bit: 0
272 unknown bit: 0
273 unknown bit: 0
274 unknown bit: 0
275 unknown bit: 0
276 CustomBadge: 0
277 ObjctIsBusy: 0
278 unknown bit: 0
279 unknown bit: 0
280 unknown bit: 0
281 unknown bit: 0
282 RoutingInfo: 0
283 unknown bit: 0
284 unknown bit: 0
285 Rsvd|commnt: 0000 : 0
286 PutAway : 00000000 : 0
288 -EA--------:
289 pad : 0000 : ..
290 magic : 41545452 : ATTR
291 debug_tag : 53D4580C : 1406425100
292 total_size : 00000EE2 : 3810
293 data_start : 000000BC : 188
294 data_length: 0000005E : 94
295 reserved[0]: 00000000 : ....
296 reserved[1]: 00000000 : ....
297 reserved[2]: 00000000 : ....
298 flags : 0000 : ..
299 num_attrs : 0002 : 2
300 -EA ENTRY--:
301 offset : 000000BC : 188
302 length : 0000005B : 91
303 flags : 0000 : ..
304 namelen : 24 : 36
305 -EA NAME---: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
306 00000000 : 63 6F 6D 2E 61 70 70 6C 65 2E 6D 65 74 61 64 61 : com.apple.metada
307 00000010 : 74 61 3A 5F 6B 4D 44 49 74 65 6D 55 73 65 72 54 : ta:_kMDItemUserT
308 00000020 : 61 67 73 00 : ags.
309 -EA VALUE--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
310 00000000 : 62 70 6C 69 73 74 30 30 A5 01 02 03 04 05 54 74 : bplist00......Tt
311 00000010 : 65 73 74 66 00 47 00 72 00 FC 00 6E 00 0A 00 32 : estf.G.r...n...2
312 00000020 : 56 4C 69 6C 61 0A 33 56 47 65 6C 62 0A 35 56 42 : VLila.3VGelb.5VB
313 00000030 : 6C 61 75 0A 34 08 0E 13 20 27 2E 00 00 00 00 00 : lau.4... '......
314 00000040 : 00 01 01 00 00 00 00 00 00 00 06 00 00 00 00 00 : ................
315 00000050 : 00 00 00 00 00 00 00 00 00 00 35 : ..........5
316 -EA ENTRY--:
317 offset : 00000117 : 279
318 length : 00000003 : 3
319 flags : 0000 : ..
320 namelen : 08 : 8
321 -EA NAME---: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
322 00000000 : 66 6F 6F 3A 62 61 72 00 : foo:bar.
323 -EA VALUE--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
324 00000000 : 62 61 7A : baz
326 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
327 00000000 : 54 45 53 54 53 4C 4F 57 00 08 00 00 00 00 00 00 : TESTSLOW........
328 00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
329 00000020 : 00 00 41 54 54 52 53 D4 58 0C 00 00 0E E2 00 00 : ..ATTRS.X.......
330 00000030 : 00 BC 00 00 00 5E 00 00 00 00 00 00 00 00 00 00 : .....^..........
331 00000040 : 00 00 00 00 00 02 00 00 00 BC 00 00 00 5B 00 00 : .............[..
332 00000050 : 24 63 6F 6D 2E 61 70 70 6C 65 2E 6D 65 74 61 64 : $com.apple.metad
333 00000060 : 61 74 61 3A 5F 6B 4D 44 49 74 65 6D 55 73 65 72 : ata:_kMDItemUser
334 00000070 : 54 61 67 73 00 00 00 00 01 17 00 00 00 03 00 00 : Tags............
335 00000080 : 08 66 6F 6F 3A 62 61 72 00 66 62 70 6C 69 73 74 : .foo:bar.fbplist
336 00000090 : 30 30 A5 01 02 03 04 05 54 74 65 73 74 66 00 47 : 00......Ttestf.G
337 000000A0 : 00 72 00 FC 00 6E 00 0A 00 32 56 4C 69 6C 61 0A : .r...n...2VLila.
338 000000B0 : 33 56 47 65 6C 62 0A 35 56 42 6C 61 75 0A 34 08 : 3VGelb.5VBlau.4.
339 000000C0 : 0E 13 20 27 2E 00 00 00 00 00 00 01 01 00 00 00 : .. '............
340 000000D0 : 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 : ................
341 000000E0 : 00 00 00 00 35 62 61 7A 00 00 00 00 00 00 00 00 : ....5baz........
342 000000F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
343 ... all zeroes ...
344 00000EA0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
346 -------------------------------------------------------------------------------
347 Entry ID : 00000002 : Resource Fork
348 Offset : 00000EE2 : 3810
349 Length : 0000011E : 286
351 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
352 00000000 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
353 00000010 : 54 68 69 73 20 72 65 73 6F 75 72 63 65 20 66 6F : This resource fo
354 00000020 : 72 6B 20 69 6E 74 65 6E 74 69 6F 6E 61 6C 6C 79 : rk intentionally
355 00000030 : 20 6C 65 66 74 20 62 6C 61 6E 6B 20 20 20 00 00 : left blank ..
356 00000040 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
357 00000050 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
358 00000060 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
359 00000070 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
360 00000080 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
361 00000090 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
362 000000A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
363 000000B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
364 000000C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
365 000000D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
366 000000E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
367 000000F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
368 00000100 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
369 00000110 : 00 00 00 00 00 00 00 00 00 1C 00 1E FF FF : ..............
371 It was created with:
372 $ hexdump -ve '"\t" 7/1 "0x%02x, " 1/1 " 0x%02x," "\n"'
374 static char osx_adouble_w_xattr[] = {
375 0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
376 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58,
377 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
378 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
379 0x00, 0x32, 0x00, 0x00, 0x0e, 0xb0, 0x00, 0x00,
380 0x00, 0x02, 0x00, 0x00, 0x0e, 0xe2, 0x00, 0x00,
381 0x01, 0x1e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x4c,
382 0x4f, 0x57, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x41, 0x54, 0x54, 0x52,
386 0x53, 0xd4, 0x58, 0x0c, 0x00, 0x00, 0x0e, 0xe2,
387 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x5e,
388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
390 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x5b,
391 0x00, 0x00, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x61,
392 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x6d, 0x65, 0x74,
393 0x61, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x5f, 0x6b,
394 0x4d, 0x44, 0x49, 0x74, 0x65, 0x6d, 0x55, 0x73,
395 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x00, 0x00,
396 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x00, 0x03,
397 0x00, 0x00, 0x08, 0x66, 0x6f, 0x6f, 0x3a, 0x62,
398 0x61, 0x72, 0x00, 0x66, 0x62, 0x70, 0x6c, 0x69,
399 0x73, 0x74, 0x30, 0x30, 0xa5, 0x01, 0x02, 0x03,
400 0x04, 0x05, 0x54, 0x74, 0x65, 0x73, 0x74, 0x66,
401 0x00, 0x47, 0x00, 0x72, 0x00, 0xfc, 0x00, 0x6e,
402 0x00, 0x0a, 0x00, 0x32, 0x56, 0x4c, 0x69, 0x6c,
403 0x61, 0x0a, 0x33, 0x56, 0x47, 0x65, 0x6c, 0x62,
404 0x0a, 0x35, 0x56, 0x42, 0x6c, 0x61, 0x75, 0x0a,
405 0x34, 0x08, 0x0e, 0x13, 0x20, 0x27, 0x2e, 0x00,
406 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
407 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x62,
410 0x61, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
418 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
500 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
501 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
695 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
708 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
709 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
713 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
721 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
723 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
733 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
734 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
736 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
737 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
738 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
739 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
746 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
747 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
749 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
750 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
752 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
754 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
755 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
757 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
758 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
759 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
760 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
761 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
762 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
764 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
765 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
772 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
778 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
779 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
780 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
781 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
782 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
783 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
784 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
785 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
786 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
787 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
788 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
789 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
790 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
791 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
792 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
793 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
794 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
795 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
796 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
797 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
798 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
799 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
800 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
801 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
802 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
803 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
804 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
805 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
806 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
808 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
809 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
810 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
811 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
812 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
813 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
814 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
815 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
817 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
818 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
819 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
820 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
821 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
822 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
823 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
824 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
825 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
826 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
827 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
828 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
834 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
835 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
836 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
837 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
838 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
839 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
840 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
841 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
842 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
843 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
844 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
845 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
846 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
847 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
848 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
849 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
850 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
851 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
852 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
853 0x00, 0x1e, 0x54, 0x68, 0x69, 0x73, 0x20, 0x72,
854 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20,
855 0x66, 0x6f, 0x72, 0x6b, 0x20, 0x69, 0x6e, 0x74,
856 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
857 0x6c, 0x79, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20,
858 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x20, 0x20, 0x20,
859 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
860 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
861 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
862 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
863 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
864 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
865 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
866 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
867 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
868 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
869 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
870 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
871 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
872 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
873 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
874 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
875 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
876 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
878 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
883 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
884 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
885 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
886 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1e, 0xff, 0xff
890 * talloc and intialize an AfpInfo
892 static AfpInfo *torture_afpinfo_new(TALLOC_CTX *mem_ctx)
894 AfpInfo *info;
896 info = talloc_zero(mem_ctx, AfpInfo);
897 if (info == NULL) {
898 return NULL;
901 info->afpi_Signature = AFP_Signature;
902 info->afpi_Version = AFP_Version;
903 info->afpi_BackupTime = AFP_BackupTime;
905 return info;
909 * Pack AfpInfo into a talloced buffer
911 static char *torture_afpinfo_pack(TALLOC_CTX *mem_ctx,
912 AfpInfo *info)
914 char *buf;
916 buf = talloc_zero_array(mem_ctx, char, AFP_INFO_SIZE);
917 if (buf == NULL) {
918 return NULL;
921 RSIVAL(buf, 0, info->afpi_Signature);
922 RSIVAL(buf, 4, info->afpi_Version);
923 RSIVAL(buf, 12, info->afpi_BackupTime);
924 memcpy(buf + 16, info->afpi_FinderInfo, sizeof(info->afpi_FinderInfo));
926 return buf;
930 * Unpack AfpInfo
932 #if 0
933 static void torture_afpinfo_unpack(AfpInfo *info, char *data)
935 info->afpi_Signature = RIVAL(data, 0);
936 info->afpi_Version = RIVAL(data, 4);
937 info->afpi_BackupTime = RIVAL(data, 12);
938 memcpy(info->afpi_FinderInfo, (const char *)data + 16,
939 sizeof(info->afpi_FinderInfo));
941 #endif
943 static bool torture_write_afpinfo(struct smb2_tree *tree,
944 struct torture_context *tctx,
945 TALLOC_CTX *mem_ctx,
946 const char *fname,
947 AfpInfo *info)
949 struct smb2_handle handle;
950 struct smb2_create io;
951 NTSTATUS status;
952 const char *full_name;
953 char *infobuf;
954 bool ret = true;
956 full_name = talloc_asprintf(mem_ctx, "%s%s", fname, AFPINFO_STREAM_NAME);
957 if (full_name == NULL) {
958 torture_comment(tctx, "talloc_asprintf error\n");
959 return false;
961 ZERO_STRUCT(io);
962 io.in.desired_access = SEC_FILE_WRITE_DATA;
963 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
964 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
965 io.in.create_options = 0;
966 io.in.fname = full_name;
968 status = smb2_create(tree, mem_ctx, &io);
969 CHECK_STATUS(status, NT_STATUS_OK);
971 handle = io.out.file.handle;
973 infobuf = torture_afpinfo_pack(mem_ctx, info);
974 if (infobuf == NULL) {
975 return false;
978 status = smb2_util_write(tree, handle, infobuf, 0, AFP_INFO_SIZE);
979 CHECK_STATUS(status, NT_STATUS_OK);
981 smb2_util_close(tree, handle);
983 done:
984 return ret;
988 * Read 'count' bytes at 'offset' from stream 'fname:sname' and
989 * compare against buffer 'value'
991 static bool check_stream(struct smb2_tree *tree,
992 const char *location,
993 struct torture_context *tctx,
994 TALLOC_CTX *mem_ctx,
995 const char *fname,
996 const char *sname,
997 off_t read_offset,
998 size_t read_count,
999 off_t comp_offset,
1000 size_t comp_count,
1001 const char *value)
1003 struct smb2_handle handle;
1004 struct smb2_create create;
1005 struct smb2_read r;
1006 NTSTATUS status;
1007 char *full_name;
1008 bool ret = true;
1010 full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
1011 if (full_name == NULL) {
1012 torture_comment(tctx, "talloc_asprintf error\n");
1013 return false;
1015 ZERO_STRUCT(create);
1016 create.in.desired_access = SEC_FILE_READ_DATA;
1017 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1018 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1019 create.in.fname = full_name;
1021 torture_comment(tctx, "Open stream %s\n", full_name);
1023 status = smb2_create(tree, mem_ctx, &create);
1024 if (!NT_STATUS_IS_OK(status)) {
1025 TALLOC_FREE(full_name);
1026 if (value == NULL) {
1027 return true;
1029 torture_comment(tctx, "Unable to open stream %s\n", full_name);
1030 return false;
1033 handle = create.out.file.handle;
1034 if (value == NULL) {
1035 TALLOC_FREE(full_name);
1036 smb2_util_close(tree, handle);
1037 return true;
1040 ZERO_STRUCT(r);
1041 r.in.file.handle = handle;
1042 r.in.length = read_count;
1043 r.in.offset = read_offset;
1045 status = smb2_read(tree, tree, &r);
1047 torture_assert_ntstatus_ok_goto(
1048 tctx, status, ret, done,
1049 talloc_asprintf(tctx, "(%s) Failed to read %lu bytes from stream '%s'\n",
1050 location, (long)strlen(value), full_name));
1052 torture_assert_goto(tctx, r.out.data.length == read_count, ret, done,
1053 talloc_asprintf(tctx, "smb2_read returned %jd bytes, expected %jd\n",
1054 (intmax_t)r.out.data.length, (intmax_t)read_count));
1056 torture_assert_goto(
1057 tctx, memcmp(r.out.data.data + comp_offset, value, comp_count) == 0,
1058 ret, done,
1059 talloc_asprintf(tctx, "(%s) Bad data in stream\n", location));
1061 done:
1062 TALLOC_FREE(full_name);
1063 smb2_util_close(tree, handle);
1064 return ret;
1068 * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1069 * compare against buffer 'value'
1071 static ssize_t read_stream(struct smb2_tree *tree,
1072 const char *location,
1073 struct torture_context *tctx,
1074 TALLOC_CTX *mem_ctx,
1075 const char *fname,
1076 const char *sname,
1077 off_t read_offset,
1078 size_t read_count)
1080 struct smb2_handle handle;
1081 struct smb2_create create;
1082 struct smb2_read r;
1083 NTSTATUS status;
1084 const char *full_name;
1085 bool ret = true;
1087 full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
1088 if (full_name == NULL) {
1089 torture_comment(tctx, "talloc_asprintf error\n");
1090 return -1;
1092 ZERO_STRUCT(create);
1093 create.in.desired_access = SEC_FILE_READ_DATA;
1094 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1095 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1096 create.in.fname = full_name;
1098 torture_comment(tctx, "Open stream %s\n", full_name);
1100 status = smb2_create(tree, mem_ctx, &create);
1101 if (!NT_STATUS_IS_OK(status)) {
1102 torture_comment(tctx, "Unable to open stream %s\n",
1103 full_name);
1104 return -1;
1107 handle = create.out.file.handle;
1109 ZERO_STRUCT(r);
1110 r.in.file.handle = handle;
1111 r.in.length = read_count;
1112 r.in.offset = read_offset;
1114 status = smb2_read(tree, tree, &r);
1115 if (!NT_STATUS_IS_OK(status)) {
1116 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
1119 smb2_util_close(tree, handle);
1121 done:
1122 if (ret == false) {
1123 return -1;
1125 return r.out.data.length;
1129 * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1130 * compare against buffer 'value'
1132 static bool write_stream(struct smb2_tree *tree,
1133 const char *location,
1134 struct torture_context *tctx,
1135 TALLOC_CTX *mem_ctx,
1136 const char *fname,
1137 const char *sname,
1138 off_t offset,
1139 size_t size,
1140 const char *value)
1142 struct smb2_handle handle;
1143 struct smb2_create create;
1144 NTSTATUS status;
1145 const char *full_name;
1147 full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname ? sname : "");
1148 if (full_name == NULL) {
1149 torture_comment(tctx, "talloc_asprintf error\n");
1150 return false;
1152 ZERO_STRUCT(create);
1153 create.in.desired_access = SEC_FILE_WRITE_DATA;
1154 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1155 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1156 create.in.fname = full_name;
1158 status = smb2_create(tree, mem_ctx, &create);
1159 if (!NT_STATUS_IS_OK(status)) {
1160 if (value == NULL) {
1161 return true;
1162 } else {
1163 torture_comment(tctx, "Unable to open stream %s\n",
1164 full_name);
1165 sleep(10000000);
1166 return false;
1170 handle = create.out.file.handle;
1171 if (value == NULL) {
1172 return true;
1175 status = smb2_util_write(tree, handle, value, offset, size);
1177 if (!NT_STATUS_IS_OK(status)) {
1178 torture_comment(tctx, "(%s) Failed to write %lu bytes to "
1179 "stream '%s'\n", location, (long)size, full_name);
1180 return false;
1183 smb2_util_close(tree, handle);
1184 return true;
1187 static bool torture_setup_local_xattr(struct torture_context *tctx,
1188 const char *path_option,
1189 const char *name,
1190 const char *xattr,
1191 const char *metadata,
1192 size_t size)
1194 int ret = true;
1195 int result;
1196 const char *spath;
1197 char *path;
1199 spath = torture_setting_string(tctx, path_option, NULL);
1200 if (spath == NULL) {
1201 printf("No sharepath for option %s\n", path_option);
1202 return false;
1205 path = talloc_asprintf(tctx, "%s/%s", spath, name);
1207 result = setxattr(path, xattr, metadata, size, 0);
1208 if (result != 0) {
1209 ret = false;
1212 TALLOC_FREE(path);
1214 return ret;
1218 * Create a file or directory
1220 static bool torture_setup_file(TALLOC_CTX *mem_ctx, struct smb2_tree *tree,
1221 const char *name, bool dir)
1223 struct smb2_create io;
1224 NTSTATUS status;
1226 smb2_util_unlink(tree, name);
1227 ZERO_STRUCT(io);
1228 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1229 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1230 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1231 io.in.share_access =
1232 NTCREATEX_SHARE_ACCESS_DELETE|
1233 NTCREATEX_SHARE_ACCESS_READ|
1234 NTCREATEX_SHARE_ACCESS_WRITE;
1235 io.in.create_options = 0;
1236 io.in.fname = name;
1237 if (dir) {
1238 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1239 io.in.share_access &= ~NTCREATEX_SHARE_ACCESS_DELETE;
1240 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1241 io.in.create_disposition = NTCREATEX_DISP_CREATE;
1244 status = smb2_create(tree, mem_ctx, &io);
1245 if (!NT_STATUS_IS_OK(status)) {
1246 return false;
1249 status = smb2_util_close(tree, io.out.file.handle);
1250 if (!NT_STATUS_IS_OK(status)) {
1251 return false;
1254 return true;
1257 static bool enable_aapl(struct torture_context *tctx,
1258 struct smb2_tree *tree)
1260 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1261 NTSTATUS status;
1262 bool ret = true;
1263 struct smb2_create io;
1264 DATA_BLOB data;
1265 struct smb2_create_blob *aapl = NULL;
1266 uint32_t aapl_server_caps;
1267 uint32_t expexted_scaps = (SMB2_CRTCTX_AAPL_UNIX_BASED |
1268 SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
1269 SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
1270 SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
1271 bool is_osx_server = torture_setting_bool(tctx, "osx", false);
1273 ZERO_STRUCT(io);
1274 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1275 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1276 io.in.create_disposition = NTCREATEX_DISP_OPEN;
1277 io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
1278 NTCREATEX_SHARE_ACCESS_READ |
1279 NTCREATEX_SHARE_ACCESS_WRITE);
1280 io.in.fname = "";
1283 * Issuing an SMB2/CREATE with a suitably formed AAPL context,
1284 * controls behaviour of Apple's SMB2 extensions for the whole
1285 * session!
1288 data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
1289 SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
1290 SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
1291 SMB2_CRTCTX_AAPL_VOLUME_CAPS |
1292 SMB2_CRTCTX_AAPL_MODEL_INFO));
1293 SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
1294 SMB2_CRTCTX_AAPL_UNIX_BASED |
1295 SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
1297 status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
1298 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_blob_add");
1300 status = smb2_create(tree, tctx, &io);
1301 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1303 status = smb2_util_close(tree, io.out.file.handle);
1304 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close");
1307 * Now check returned AAPL context
1309 torture_comment(tctx, "Comparing returned AAPL capabilities\n");
1311 aapl = smb2_create_blob_find(&io.out.blobs,
1312 SMB2_CREATE_TAG_AAPL);
1313 torture_assert_goto(tctx, aapl != NULL, ret, done, "missing AAPL context");
1315 if (!is_osx_server) {
1316 size_t exptected_aapl_ctx_size;
1318 exptected_aapl_ctx_size = strlen("MacSamba") * 2 + 40;
1320 torture_assert_goto(
1321 tctx, aapl->data.length == exptected_aapl_ctx_size,
1322 ret, done, "bad AAPL size");
1325 aapl_server_caps = BVAL(aapl->data.data, 16);
1326 torture_assert_goto(tctx, aapl_server_caps == expexted_scaps,
1327 ret, done, "bad AAPL caps");
1329 done:
1330 talloc_free(mem_ctx);
1331 return ret;
1334 static bool test_read_netatalk_metadata(struct torture_context *tctx,
1335 struct smb2_tree *tree)
1337 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1338 const char *fname = BASEDIR "\\torture_read_metadata";
1339 NTSTATUS status;
1340 struct smb2_handle testdirh;
1341 bool ret = true;
1342 ssize_t len;
1343 const char *localdir = NULL;
1345 torture_comment(tctx, "Checking metadata access\n");
1347 localdir = torture_setting_string(tctx, "localdir", NULL);
1348 if (localdir == NULL) {
1349 torture_skip(tctx, "Need localdir for test");
1352 smb2_util_unlink(tree, fname);
1354 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1355 CHECK_STATUS(status, NT_STATUS_OK);
1356 smb2_util_close(tree, testdirh);
1358 ret = torture_setup_file(mem_ctx, tree, fname, false);
1359 if (ret == false) {
1360 goto done;
1363 ret = torture_setup_local_xattr(tctx, "localdir",
1364 BASEDIR "/torture_read_metadata",
1365 AFPINFO_EA_NETATALK,
1366 metadata_xattr, sizeof(metadata_xattr));
1367 if (ret == false) {
1368 goto done;
1371 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1372 0, 60, 0, 4, "AFP");
1373 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1375 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1376 0, 60, 16, 8, "BARRFOOO");
1377 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1379 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1380 16, 8, 0, 3, "AFP");
1381 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1383 /* Check reading offset and read size > sizeof(AFPINFO_STREAM) */
1385 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1386 AFPINFO_STREAM, 0, 61);
1387 CHECK_VALUE(len, 60);
1389 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1390 AFPINFO_STREAM, 59, 2);
1391 CHECK_VALUE(len, 2);
1393 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1394 AFPINFO_STREAM, 60, 1);
1395 CHECK_VALUE(len, 1);
1397 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1398 AFPINFO_STREAM, 61, 1);
1399 CHECK_VALUE(len, 0);
1401 done:
1402 smb2_deltree(tree, BASEDIR);
1403 talloc_free(mem_ctx);
1404 return ret;
1407 static bool test_read_afpinfo(struct torture_context *tctx,
1408 struct smb2_tree *tree)
1410 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1411 const char *fname = BASEDIR "\\torture_read_metadata";
1412 NTSTATUS status;
1413 struct smb2_handle testdirh;
1414 bool ret = true;
1415 ssize_t len;
1416 AfpInfo *info;
1417 const char *type_creator = "SMB,OLE!";
1419 torture_comment(tctx, "Checking metadata access\n");
1421 smb2_util_unlink(tree, fname);
1423 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1424 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
1425 smb2_util_close(tree, testdirh);
1427 ret = torture_setup_file(mem_ctx, tree, fname, false);
1428 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
1430 info = torture_afpinfo_new(mem_ctx);
1431 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
1433 memcpy(info->afpi_FinderInfo, type_creator, 8);
1434 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
1435 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
1437 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1438 0, 60, 0, 4, "AFP");
1439 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1441 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1442 0, 60, 16, 8, type_creator);
1443 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1446 * OS X ignores offset <= 60 and treats the as
1447 * offset=0. Reading from offsets > 60 returns EOF=0.
1450 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1451 16, 8, 0, 8, "AFP\0\0\0\001\0");
1452 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1454 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1455 AFPINFO_STREAM, 0, 61);
1456 torture_assert_goto(tctx, len == 60, ret, done, "read_stream failed");
1458 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1459 AFPINFO_STREAM, 59, 2);
1460 torture_assert_goto(tctx, len == 2, ret, done, "read_stream failed");
1462 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1463 59, 2, 0, 2, "AF");
1464 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1466 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1467 AFPINFO_STREAM, 60, 1);
1468 torture_assert_goto(tctx, len == 1, ret, done, "read_stream failed");
1470 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1471 60, 1, 0, 1, "A");
1472 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1474 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1475 AFPINFO_STREAM, 61, 1);
1476 torture_assert_goto(tctx, len == 0, ret, done, "read_stream failed");
1478 done:
1479 smb2_util_unlink(tree, fname);
1480 smb2_deltree(tree, BASEDIR);
1481 talloc_free(mem_ctx);
1482 return ret;
1485 static bool test_write_atalk_metadata(struct torture_context *tctx,
1486 struct smb2_tree *tree)
1488 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1489 const char *fname = BASEDIR "\\torture_write_metadata";
1490 const char *type_creator = "SMB,OLE!";
1491 NTSTATUS status;
1492 struct smb2_handle testdirh;
1493 bool ret = true;
1494 AfpInfo *info;
1496 smb2_deltree(tree, BASEDIR);
1497 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1498 CHECK_STATUS(status, NT_STATUS_OK);
1499 smb2_util_close(tree, testdirh);
1501 ret = torture_setup_file(mem_ctx, tree, fname, false);
1502 if (ret == false) {
1503 goto done;
1506 info = torture_afpinfo_new(mem_ctx);
1507 if (info == NULL) {
1508 goto done;
1511 memcpy(info->afpi_FinderInfo, type_creator, 8);
1512 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
1513 ret &= check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1514 0, 60, 16, 8, type_creator);
1516 done:
1517 smb2_util_unlink(tree, fname);
1518 smb2_deltree(tree, BASEDIR);
1519 talloc_free(mem_ctx);
1520 return ret;
1523 static bool test_write_atalk_rfork_io(struct torture_context *tctx,
1524 struct smb2_tree *tree)
1526 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1527 const char *fname = BASEDIR "\\torture_write_rfork_io";
1528 const char *rfork = BASEDIR "\\torture_write_rfork_io" AFPRESOURCE_STREAM_NAME;
1529 const char *rfork_content = "1234567890";
1530 NTSTATUS status;
1531 struct smb2_handle testdirh;
1532 bool ret = true;
1534 union smb_open io;
1535 struct smb2_handle filehandle;
1536 union smb_fileinfo finfo;
1537 union smb_setfileinfo sinfo;
1539 smb2_util_unlink(tree, fname);
1541 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1542 CHECK_STATUS(status, NT_STATUS_OK);
1543 smb2_util_close(tree, testdirh);
1545 ret = torture_setup_file(mem_ctx, tree, fname, false);
1546 if (ret == false) {
1547 goto done;
1550 torture_comment(tctx, "(%s) writing to resource fork\n",
1551 __location__);
1553 ret &= write_stream(tree, __location__, tctx, mem_ctx,
1554 fname, AFPRESOURCE_STREAM_NAME,
1555 10, 10, rfork_content);
1557 ret &= check_stream(tree, __location__, tctx, mem_ctx,
1558 fname, AFPRESOURCE_STREAM_NAME,
1559 0, 20, 10, 10, rfork_content);
1561 /* Check size after write */
1563 ZERO_STRUCT(io);
1564 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1565 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1566 SEC_FILE_WRITE_ATTRIBUTE;
1567 io.smb2.in.fname = rfork;
1568 status = smb2_create(tree, mem_ctx, &(io.smb2));
1569 CHECK_STATUS(status, NT_STATUS_OK);
1570 filehandle = io.smb2.out.file.handle;
1572 torture_comment(tctx, "(%s) check resource fork size after write\n",
1573 __location__);
1575 ZERO_STRUCT(finfo);
1576 finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1577 finfo.generic.in.file.handle = filehandle;
1578 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1579 CHECK_STATUS(status, NT_STATUS_OK);
1580 if (finfo.all_info.out.size != 20) {
1581 torture_result(tctx, TORTURE_FAIL,
1582 "(%s) Incorrect resource fork size\n",
1583 __location__);
1584 ret = false;
1585 smb2_util_close(tree, filehandle);
1586 goto done;
1588 smb2_util_close(tree, filehandle);
1590 /* Write at large offset */
1592 torture_comment(tctx, "(%s) writing to resource fork at large offset\n",
1593 __location__);
1595 ret &= write_stream(tree, __location__, tctx, mem_ctx,
1596 fname, AFPRESOURCE_STREAM_NAME,
1597 (off_t)1<<32, 10, rfork_content);
1599 ret &= check_stream(tree, __location__, tctx, mem_ctx,
1600 fname, AFPRESOURCE_STREAM_NAME,
1601 (off_t)1<<32, 10, 0, 10, rfork_content);
1603 /* Truncate back to size of 1 byte */
1605 torture_comment(tctx, "(%s) truncate resource fork and check size\n",
1606 __location__);
1608 ZERO_STRUCT(io);
1609 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1610 io.smb2.in.desired_access = SEC_FILE_ALL;
1611 io.smb2.in.fname = rfork;
1612 status = smb2_create(tree, mem_ctx, &(io.smb2));
1613 CHECK_STATUS(status, NT_STATUS_OK);
1614 filehandle = io.smb2.out.file.handle;
1616 ZERO_STRUCT(sinfo);
1617 sinfo.end_of_file_info.level =
1618 RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1619 sinfo.end_of_file_info.in.file.handle = filehandle;
1620 sinfo.end_of_file_info.in.size = 1;
1621 status = smb2_setinfo_file(tree, &sinfo);
1622 CHECK_STATUS(status, NT_STATUS_OK);
1624 smb2_util_close(tree, filehandle);
1626 /* Now check size */
1627 ZERO_STRUCT(io);
1628 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1629 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1630 SEC_FILE_WRITE_ATTRIBUTE;
1631 io.smb2.in.fname = rfork;
1632 status = smb2_create(tree, mem_ctx, &(io.smb2));
1633 CHECK_STATUS(status, NT_STATUS_OK);
1634 filehandle = io.smb2.out.file.handle;
1636 ZERO_STRUCT(finfo);
1637 finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1638 finfo.generic.in.file.handle = filehandle;
1639 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1640 CHECK_STATUS(status, NT_STATUS_OK);
1641 if (finfo.all_info.out.size != 1) {
1642 torture_result(tctx, TORTURE_FAIL,
1643 "(%s) Incorrect resource fork size\n",
1644 __location__);
1645 ret = false;
1646 smb2_util_close(tree, filehandle);
1647 goto done;
1649 smb2_util_close(tree, filehandle);
1651 done:
1652 smb2_util_unlink(tree, fname);
1653 smb2_deltree(tree, BASEDIR);
1654 talloc_free(mem_ctx);
1655 return ret;
1658 static bool test_rfork_truncate(struct torture_context *tctx,
1659 struct smb2_tree *tree)
1661 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1662 const char *fname = BASEDIR "\\torture_rfork_truncate";
1663 const char *rfork = BASEDIR "\\torture_rfork_truncate" AFPRESOURCE_STREAM;
1664 const char *rfork_content = "1234567890";
1665 NTSTATUS status;
1666 struct smb2_handle testdirh;
1667 bool ret = true;
1668 struct smb2_create create;
1669 struct smb2_handle fh1, fh2, fh3;
1670 union smb_setfileinfo sinfo;
1672 smb2_util_unlink(tree, fname);
1674 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1675 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1676 smb2_util_close(tree, testdirh);
1678 ret = torture_setup_file(mem_ctx, tree, fname, false);
1679 if (ret == false) {
1680 goto done;
1683 ret &= write_stream(tree, __location__, tctx, mem_ctx,
1684 fname, AFPRESOURCE_STREAM,
1685 10, 10, rfork_content);
1687 /* Truncate back to size 0, further access MUST return ENOENT */
1689 torture_comment(tctx, "(%s) truncate resource fork to size 0\n",
1690 __location__);
1692 ZERO_STRUCT(create);
1693 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1694 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1695 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1696 create.in.fname = fname;
1697 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1698 NTCREATEX_SHARE_ACCESS_READ |
1699 NTCREATEX_SHARE_ACCESS_WRITE;
1700 status = smb2_create(tree, mem_ctx, &create);
1701 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1702 fh1 = create.out.file.handle;
1704 ZERO_STRUCT(create);
1705 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1706 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1707 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1708 create.in.fname = rfork;
1709 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1710 NTCREATEX_SHARE_ACCESS_READ |
1711 NTCREATEX_SHARE_ACCESS_WRITE;
1712 status = smb2_create(tree, mem_ctx, &create);
1713 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1714 fh2 = create.out.file.handle;
1716 ZERO_STRUCT(sinfo);
1717 sinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1718 sinfo.end_of_file_info.in.file.handle = fh2;
1719 sinfo.end_of_file_info.in.size = 0;
1720 status = smb2_setinfo_file(tree, &sinfo);
1721 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file");
1724 * Now check size, we should get OBJECT_NAME_NOT_FOUND (!)
1726 ZERO_STRUCT(create);
1727 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1728 create.in.desired_access = SEC_FILE_ALL;
1729 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1730 create.in.fname = rfork;
1731 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1732 NTCREATEX_SHARE_ACCESS_READ |
1733 NTCREATEX_SHARE_ACCESS_WRITE;
1734 status = smb2_create(tree, mem_ctx, &create);
1735 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1738 * Do another open on the rfork and write to the new handle. A
1739 * naive server might unlink the AppleDouble resource fork
1740 * file when its truncated to 0 bytes above, so in case both
1741 * open handles share the same underlying fd, the unlink would
1742 * cause the below write to be lost.
1744 ZERO_STRUCT(create);
1745 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1746 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1747 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1748 create.in.fname = rfork;
1749 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1750 NTCREATEX_SHARE_ACCESS_READ |
1751 NTCREATEX_SHARE_ACCESS_WRITE;
1752 status = smb2_create(tree, mem_ctx, &create);
1753 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1754 fh3 = create.out.file.handle;
1756 status = smb2_util_write(tree, fh3, "foo", 0, 3);
1757 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write");
1759 smb2_util_close(tree, fh3);
1760 smb2_util_close(tree, fh2);
1761 smb2_util_close(tree, fh1);
1763 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM,
1764 0, 3, 0, 3, "foo");
1765 torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
1767 done:
1768 smb2_util_unlink(tree, fname);
1769 smb2_deltree(tree, BASEDIR);
1770 talloc_free(mem_ctx);
1771 return ret;
1774 static bool test_rfork_create(struct torture_context *tctx,
1775 struct smb2_tree *tree)
1777 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1778 const char *fname = BASEDIR "\\torture_rfork_create";
1779 const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
1780 NTSTATUS status;
1781 struct smb2_handle testdirh;
1782 bool ret = true;
1783 struct smb2_create create;
1784 struct smb2_handle fh1;
1785 const char *streams[] = {
1786 "::$DATA"
1788 union smb_fileinfo finfo;
1790 smb2_util_unlink(tree, fname);
1792 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1793 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1794 smb2_util_close(tree, testdirh);
1796 ret = torture_setup_file(mem_ctx, tree, fname, false);
1797 if (ret == false) {
1798 goto done;
1801 torture_comment(tctx, "(%s) open rfork, should return ENOENT\n",
1802 __location__);
1804 ZERO_STRUCT(create);
1805 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1806 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1807 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1808 create.in.fname = rfork;
1809 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1810 NTCREATEX_SHARE_ACCESS_READ |
1811 NTCREATEX_SHARE_ACCESS_WRITE;
1812 status = smb2_create(tree, mem_ctx, &create);
1813 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1815 torture_comment(tctx, "(%s) create resource fork\n", __location__);
1817 ZERO_STRUCT(create);
1818 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1819 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1820 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1821 create.in.fname = rfork;
1822 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1823 NTCREATEX_SHARE_ACCESS_READ |
1824 NTCREATEX_SHARE_ACCESS_WRITE;
1825 status = smb2_create(tree, mem_ctx, &create);
1826 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1827 fh1 = create.out.file.handle;
1829 torture_comment(tctx, "(%s) getinfo on create handle\n",
1830 __location__);
1832 ZERO_STRUCT(finfo);
1833 finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1834 finfo.generic.in.file.handle = fh1;
1835 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1836 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file");
1837 if (finfo.all_info.out.size != 0) {
1838 torture_result(tctx, TORTURE_FAIL,
1839 "(%s) Incorrect resource fork size\n",
1840 __location__);
1841 ret = false;
1842 smb2_util_close(tree, fh1);
1843 goto done;
1846 torture_comment(tctx, "(%s) open rfork, should still return ENOENT\n",
1847 __location__);
1849 ZERO_STRUCT(create);
1850 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1851 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1852 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1853 create.in.fname = rfork;
1854 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1855 NTCREATEX_SHARE_ACCESS_READ |
1856 NTCREATEX_SHARE_ACCESS_WRITE;
1857 status = smb2_create(tree, mem_ctx, &create);
1858 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1860 ret = check_stream_list(tree, tctx, fname, 1, streams, false);
1861 torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
1863 torture_comment(tctx, "(%s) close empty created rfork, open should return ENOENT\n",
1864 __location__);
1866 ZERO_STRUCT(create);
1867 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1868 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1869 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1870 create.in.fname = rfork;
1871 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1872 NTCREATEX_SHARE_ACCESS_READ |
1873 NTCREATEX_SHARE_ACCESS_WRITE;
1874 status = smb2_create(tree, mem_ctx, &create);
1875 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1877 done:
1878 smb2_util_unlink(tree, fname);
1879 smb2_deltree(tree, BASEDIR);
1880 talloc_free(mem_ctx);
1881 return ret;
1884 static bool test_rfork_create_ro(struct torture_context *tctx,
1885 struct smb2_tree *tree)
1887 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1888 const char *fname = BASEDIR "\\torture_rfork_create";
1889 const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
1890 NTSTATUS status;
1891 struct smb2_handle testdirh;
1892 bool ret = true;
1893 struct smb2_create create;
1895 smb2_util_unlink(tree, fname);
1896 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1897 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1898 "torture_smb2_testdir\n");
1899 smb2_util_close(tree, testdirh);
1901 ret = torture_setup_file(mem_ctx, tree, fname, false);
1902 if (ret == false) {
1903 goto done;
1906 torture_comment(tctx, "(%s) Try opening read-only with "
1907 "open_if create disposition, should return ENOENT\n",
1908 __location__);
1910 ZERO_STRUCT(create);
1911 create.in.fname = rfork;
1912 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1913 create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
1914 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1915 create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
1916 status = smb2_create(tree, mem_ctx, &(create));
1917 torture_assert_ntstatus_equal_goto(tctx, status,
1918 NT_STATUS_OBJECT_NAME_NOT_FOUND,
1919 ret, done, "smb2_create failed\n");
1921 torture_comment(tctx, "(%s) Now write something to the "
1922 "rsrc stream, then the same open should succeed\n",
1923 __location__);
1925 ret = write_stream(tree, __location__, tctx, mem_ctx,
1926 fname, AFPRESOURCE_STREAM_NAME,
1927 0, 3, "foo");
1928 torture_assert_goto(tctx, ret == true, ret, done,
1929 "write_stream failed\n");
1931 ret = check_stream(tree, __location__, tctx, mem_ctx,
1932 fname, AFPRESOURCE_STREAM,
1933 0, 3, 0, 3, "foo");
1934 torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
1936 ZERO_STRUCT(create);
1937 create.in.fname = rfork;
1938 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1939 create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
1940 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1941 create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
1942 status = smb2_create(tree, mem_ctx, &(create));
1943 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
1944 "smb2_create failed\n");
1946 smb2_util_close(tree, create.out.file.handle);
1948 done:
1949 smb2_util_unlink(tree, fname);
1950 smb2_deltree(tree, BASEDIR);
1951 talloc_free(mem_ctx);
1952 return ret;
1955 static bool test_adouble_conversion(struct torture_context *tctx,
1956 struct smb2_tree *tree)
1958 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1959 const char *fname = BASEDIR "\\test_adouble_conversion";
1960 const char *adname = BASEDIR "/._test_adouble_conversion";
1961 NTSTATUS status;
1962 struct smb2_handle testdirh;
1963 bool ret = true;
1964 const char *data = "This resource fork intentionally left blank";
1965 size_t datalen = strlen(data);
1966 const char *streams[] = {
1967 "::$DATA",
1968 AFPINFO_STREAM,
1969 AFPRESOURCE_STREAM,
1970 ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
1971 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
1974 smb2_deltree(tree, BASEDIR);
1976 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1977 CHECK_STATUS(status, NT_STATUS_OK);
1978 smb2_util_close(tree, testdirh);
1980 ret = torture_setup_file(tctx, tree, fname, false);
1981 torture_assert_goto(tctx, ret == true, ret, done,
1982 "torture_setup_file failed\n");
1984 ret = torture_setup_file(tctx, tree, adname, false);
1985 torture_assert_goto(tctx, ret == true, ret, done,
1986 "torture_setup_file failed\n");
1988 ret = write_stream(tree, __location__, tctx, mem_ctx,
1989 adname, NULL,
1990 0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr);
1991 torture_assert_goto(tctx, ret == true, ret, done,
1992 "write_stream failed\n");
1994 torture_comment(tctx, "(%s) test OS X AppleDouble conversion\n",
1995 __location__);
1997 ret = check_stream(tree, __location__, tctx, mem_ctx,
1998 fname, AFPRESOURCE_STREAM,
1999 16, datalen, 0, datalen, data);
2000 torture_assert_goto(tctx, ret == true, ret, done,
2001 "check AFPRESOURCE_STREAM failed\n");
2003 ret = check_stream(tree, __location__, tctx, mem_ctx,
2004 fname, AFPINFO_STREAM,
2005 0, 60, 16, 8, "TESTSLOW");
2006 torture_assert_goto(tctx, ret == true, ret, done,
2007 "check AFPINFO_STREAM failed\n");
2009 ret = check_stream(tree, __location__, tctx, mem_ctx, fname,
2010 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2011 0, 3, 0, 3, "baz");
2012 torture_assert_goto(tctx, ret == true, ret, done,
2013 "check foo:bar stream failed\n");
2015 ret = check_stream_list(tree, tctx, fname, 5, streams, false);
2016 torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2018 done:
2019 smb2_deltree(tree, BASEDIR);
2020 talloc_free(mem_ctx);
2021 return ret;
2024 static bool test_aapl(struct torture_context *tctx,
2025 struct smb2_tree *tree)
2027 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2028 const char *fname = BASEDIR "\\test_aapl";
2029 NTSTATUS status;
2030 struct smb2_handle testdirh;
2031 bool ret = true;
2032 struct smb2_create io;
2033 DATA_BLOB data;
2034 struct smb2_create_blob *aapl = NULL;
2035 AfpInfo *info;
2036 const char *type_creator = "SMB,OLE!";
2037 char type_creator_buf[9];
2038 uint32_t aapl_cmd;
2039 uint32_t aapl_reply_bitmap;
2040 uint32_t aapl_server_caps;
2041 uint32_t aapl_vol_caps;
2042 char *model;
2043 struct smb2_find f;
2044 unsigned int count;
2045 union smb_search_data *d;
2046 uint64_t rfork_len;
2048 smb2_deltree(tree, BASEDIR);
2050 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2051 CHECK_STATUS(status, NT_STATUS_OK);
2052 smb2_util_close(tree, testdirh);
2054 ZERO_STRUCT(io);
2055 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
2056 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2057 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2058 io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2059 NTCREATEX_SHARE_ACCESS_READ |
2060 NTCREATEX_SHARE_ACCESS_WRITE);
2061 io.in.fname = fname;
2064 * Issuing an SMB2/CREATE with a suitably formed AAPL context,
2065 * controls behaviour of Apple's SMB2 extensions for the whole
2066 * session!
2069 data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2070 SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2071 SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2072 SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2073 SMB2_CRTCTX_AAPL_MODEL_INFO));
2074 SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2075 SMB2_CRTCTX_AAPL_UNIX_BASED |
2076 SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
2078 torture_comment(tctx, "Testing SMB2 create context AAPL\n");
2079 status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2080 CHECK_STATUS(status, NT_STATUS_OK);
2082 status = smb2_create(tree, tctx, &io);
2083 CHECK_STATUS(status, NT_STATUS_OK);
2084 status = smb2_util_close(tree, io.out.file.handle);
2085 CHECK_STATUS(status, NT_STATUS_OK);
2088 * Now check returned AAPL context
2090 torture_comment(tctx, "Comparing returned AAPL capabilities\n");
2092 aapl = smb2_create_blob_find(&io.out.blobs,
2093 SMB2_CREATE_TAG_AAPL);
2095 if (aapl == NULL) {
2096 torture_result(tctx, TORTURE_FAIL,
2097 "(%s) unexpectedly no AAPL capabilities were returned.",
2098 __location__);
2099 ret = false;
2100 goto done;
2103 if (aapl->data.length != 50) {
2105 * uint32_t CommandCode = kAAPL_SERVER_QUERY
2106 * uint32_t Reserved = 0;
2107 * uint64_t ReplyBitmap = kAAPL_SERVER_CAPS |
2108 * kAAPL_VOLUME_CAPS |
2109 * kAAPL_MODEL_INFO;
2110 * uint64_t ServerCaps = kAAPL_SUPPORTS_READDIR_ATTR |
2111 * kAAPL_SUPPORTS_OSX_COPYFILE;
2112 * uint64_t VolumeCaps = kAAPL_SUPPORT_RESOLVE_ID |
2113 * kAAPL_CASE_SENSITIVE;
2114 * uint32_t Pad2 = 0;
2115 * uint32_t ModelStringLen = 10;
2116 * ucs2_t ModelString[5] = "Samba";
2118 torture_warning(tctx,
2119 "(%s) unexpected AAPL context length: %zd, expected 50",
2120 __location__, aapl->data.length);
2123 aapl_cmd = IVAL(aapl->data.data, 0);
2124 if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2125 torture_result(tctx, TORTURE_FAIL,
2126 "(%s) unexpected cmd: %d",
2127 __location__, (int)aapl_cmd);
2128 ret = false;
2129 goto done;
2132 aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2133 if (aapl_reply_bitmap != (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2134 SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2135 SMB2_CRTCTX_AAPL_MODEL_INFO)) {
2136 torture_result(tctx, TORTURE_FAIL,
2137 "(%s) unexpected reply_bitmap: %d",
2138 __location__, (int)aapl_reply_bitmap);
2139 ret = false;
2140 goto done;
2143 aapl_server_caps = BVAL(aapl->data.data, 16);
2144 if (aapl_server_caps != (SMB2_CRTCTX_AAPL_UNIX_BASED |
2145 SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2146 SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
2147 SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE)) {
2148 torture_result(tctx, TORTURE_FAIL,
2149 "(%s) unexpected server_caps: %d",
2150 __location__, (int)aapl_server_caps);
2151 ret = false;
2152 goto done;
2155 aapl_vol_caps = BVAL(aapl->data.data, 24);
2156 if (aapl_vol_caps != 0) {
2157 /* this will fail on a case insensitive fs ... */
2158 torture_result(tctx, TORTURE_FAIL,
2159 "(%s) unexpected vol_caps: %d",
2160 __location__, (int)aapl_vol_caps);
2163 ret = convert_string_talloc(mem_ctx,
2164 CH_UTF16LE, CH_UNIX,
2165 aapl->data.data + 40, 10,
2166 &model, NULL);
2167 if (ret == false) {
2168 torture_result(tctx, TORTURE_FAIL,
2169 "(%s) convert_string_talloc() failed",
2170 __location__);
2171 goto done;
2173 torture_comment(tctx, "Got server model: \"%s\"\n", model);
2176 * Now that Requested AAPL extensions are enabled, setup some
2177 * Mac files with metadata and resource fork
2179 ret = torture_setup_file(mem_ctx, tree, fname, false);
2180 if (ret == false) {
2181 torture_result(tctx, TORTURE_FAIL,
2182 "(%s) torture_setup_file() failed",
2183 __location__);
2184 goto done;
2187 info = torture_afpinfo_new(mem_ctx);
2188 if (info == NULL) {
2189 torture_result(tctx, TORTURE_FAIL,
2190 "(%s) torture_afpinfo_new() failed",
2191 __location__);
2192 ret = false;
2193 goto done;
2196 memcpy(info->afpi_FinderInfo, type_creator, 8);
2197 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
2198 if (ret == false) {
2199 torture_result(tctx, TORTURE_FAIL,
2200 "(%s) torture_write_afpinfo() failed",
2201 __location__);
2202 goto done;
2205 ret = write_stream(tree, __location__, tctx, mem_ctx,
2206 fname, AFPRESOURCE_STREAM_NAME,
2207 0, 3, "foo");
2208 if (ret == false) {
2209 torture_result(tctx, TORTURE_FAIL,
2210 "(%s) write_stream() failed",
2211 __location__);
2212 goto done;
2216 * Ok, file is prepared, now call smb2/find
2219 ZERO_STRUCT(io);
2220 io.in.desired_access = SEC_RIGHTS_DIR_READ;
2221 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2222 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2223 io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
2224 NTCREATEX_SHARE_ACCESS_WRITE |
2225 NTCREATEX_SHARE_ACCESS_DELETE);
2226 io.in.create_disposition = NTCREATEX_DISP_OPEN;
2227 io.in.fname = BASEDIR;
2228 status = smb2_create(tree, tctx, &io);
2229 CHECK_STATUS(status, NT_STATUS_OK);
2231 ZERO_STRUCT(f);
2232 f.in.file.handle = io.out.file.handle;
2233 f.in.pattern = "test_aapl";
2234 f.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE;
2235 f.in.max_response_size = 0x1000;
2236 f.in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
2238 status = smb2_find_level(tree, tree, &f, &count, &d);
2239 CHECK_STATUS(status, NT_STATUS_OK);
2241 status = smb2_util_close(tree, io.out.file.handle);
2242 CHECK_STATUS(status, NT_STATUS_OK);
2244 if (strcmp(d[0].id_both_directory_info.name.s, "test_aapl") != 0) {
2245 torture_result(tctx, TORTURE_FAIL,
2246 "(%s) write_stream() failed",
2247 __location__);
2248 ret = false;
2249 goto done;
2252 if (d[0].id_both_directory_info.short_name.private_length != 24) {
2253 torture_result(tctx, TORTURE_FAIL,
2254 "(%s) bad short_name length %" PRIu32 ", expected 24",
2255 __location__, d[0].id_both_directory_info.short_name.private_length);
2256 ret = false;
2257 goto done;
2260 torture_comment(tctx, "short_name buffer:\n");
2261 dump_data(0, d[0].id_both_directory_info.short_name_buf, 24);
2264 * Extract data as specified by the AAPL extension:
2265 * - ea_size contains max_access
2266 * - short_name contains resource fork length + FinderInfo
2267 * - reserved2 contains the unix mode
2269 torture_comment(tctx, "mac_access: %" PRIx32 "\n",
2270 d[0].id_both_directory_info.ea_size);
2272 rfork_len = BVAL(d[0].id_both_directory_info.short_name_buf, 0);
2273 if (rfork_len != 3) {
2274 torture_result(tctx, TORTURE_FAIL,
2275 "(%s) expected resource fork length 3, got: %" PRIu64,
2276 __location__, rfork_len);
2277 ret = false;
2278 goto done;
2281 memcpy(type_creator_buf, d[0].id_both_directory_info.short_name_buf + 8, 8);
2282 type_creator_buf[8] = 0;
2283 if (strcmp(type_creator, type_creator_buf) != 0) {
2284 torture_result(tctx, TORTURE_FAIL,
2285 "(%s) expected type/creator \"%s\" , got: %s",
2286 __location__, type_creator, type_creator_buf);
2287 ret = false;
2288 goto done;
2291 done:
2292 smb2_util_unlink(tree, fname);
2293 smb2_deltree(tree, BASEDIR);
2294 talloc_free(mem_ctx);
2295 return ret;
2298 static uint64_t patt_hash(uint64_t off)
2300 return off;
2303 static bool write_pattern(struct torture_context *torture,
2304 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2305 struct smb2_handle h, uint64_t off, uint64_t len,
2306 uint64_t patt_off)
2308 NTSTATUS status;
2309 uint64_t i;
2310 uint8_t *buf;
2311 uint64_t io_sz = MIN(1024 * 64, len);
2313 if (len == 0) {
2314 return true;
2317 torture_assert(torture, (len % 8) == 0, "invalid write len");
2319 buf = talloc_zero_size(mem_ctx, io_sz);
2320 torture_assert(torture, (buf != NULL), "no memory for file data buf");
2322 while (len > 0) {
2323 for (i = 0; i <= io_sz - 8; i += 8) {
2324 SBVAL(buf, i, patt_hash(patt_off));
2325 patt_off += 8;
2328 status = smb2_util_write(tree, h,
2329 buf, off, io_sz);
2330 torture_assert_ntstatus_ok(torture, status, "file write");
2332 len -= io_sz;
2333 off += io_sz;
2336 talloc_free(buf);
2338 return true;
2341 static bool check_pattern(struct torture_context *torture,
2342 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2343 struct smb2_handle h, uint64_t off, uint64_t len,
2344 uint64_t patt_off)
2346 if (len == 0) {
2347 return true;
2350 torture_assert(torture, (len % 8) == 0, "invalid read len");
2352 while (len > 0) {
2353 uint64_t i;
2354 struct smb2_read r;
2355 NTSTATUS status;
2356 uint64_t io_sz = MIN(1024 * 64, len);
2358 ZERO_STRUCT(r);
2359 r.in.file.handle = h;
2360 r.in.length = io_sz;
2361 r.in.offset = off;
2362 status = smb2_read(tree, mem_ctx, &r);
2363 torture_assert_ntstatus_ok(torture, status, "read");
2365 torture_assert_u64_equal(torture, r.out.data.length, io_sz,
2366 "read data len mismatch");
2368 for (i = 0; i <= io_sz - 8; i += 8, patt_off += 8) {
2369 uint64_t data = BVAL(r.out.data.data, i);
2370 torture_assert_u64_equal(torture, data, patt_hash(patt_off),
2371 talloc_asprintf(torture, "read data "
2372 "pattern bad at %llu\n",
2373 (unsigned long long)off + i));
2375 talloc_free(r.out.data.data);
2376 len -= io_sz;
2377 off += io_sz;
2380 return true;
2383 static bool test_setup_open(struct torture_context *torture,
2384 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2385 const char *fname,
2386 struct smb2_handle *fh,
2387 uint32_t desired_access,
2388 uint32_t file_attributes)
2390 struct smb2_create io;
2391 NTSTATUS status;
2393 ZERO_STRUCT(io);
2394 io.in.desired_access = desired_access;
2395 io.in.file_attributes = file_attributes;
2396 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2397 io.in.share_access =
2398 NTCREATEX_SHARE_ACCESS_DELETE|
2399 NTCREATEX_SHARE_ACCESS_READ|
2400 NTCREATEX_SHARE_ACCESS_WRITE;
2401 if (file_attributes & FILE_ATTRIBUTE_DIRECTORY) {
2402 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2404 io.in.fname = fname;
2406 status = smb2_create(tree, mem_ctx, &io);
2407 torture_assert_ntstatus_ok(torture, status, "file create");
2409 *fh = io.out.file.handle;
2411 return true;
2414 static bool test_setup_create_fill(struct torture_context *torture,
2415 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2416 const char *fname,
2417 struct smb2_handle *fh,
2418 uint64_t size,
2419 uint32_t desired_access,
2420 uint32_t file_attributes)
2422 bool ok;
2424 ok = test_setup_open(torture, tree, mem_ctx,
2425 fname,
2427 desired_access,
2428 file_attributes);
2429 torture_assert(torture, ok, "file open");
2431 if (size > 0) {
2432 ok = write_pattern(torture, tree, mem_ctx, *fh, 0, size, 0);
2433 torture_assert(torture, ok, "write pattern");
2435 return true;
2438 static bool test_setup_copy_chunk(struct torture_context *torture,
2439 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2440 uint32_t nchunks,
2441 const char *src_name,
2442 struct smb2_handle *src_h,
2443 uint64_t src_size,
2444 uint32_t src_desired_access,
2445 const char *dst_name,
2446 struct smb2_handle *dest_h,
2447 uint64_t dest_size,
2448 uint32_t dest_desired_access,
2449 struct srv_copychunk_copy *cc_copy,
2450 union smb_ioctl *io)
2452 struct req_resume_key_rsp res_key;
2453 bool ok;
2454 NTSTATUS status;
2455 enum ndr_err_code ndr_ret;
2457 ok = test_setup_create_fill(torture, tree, mem_ctx, src_name,
2458 src_h, src_size, src_desired_access,
2459 FILE_ATTRIBUTE_NORMAL);
2460 torture_assert(torture, ok, "src file create fill");
2462 ok = test_setup_create_fill(torture, tree, mem_ctx, dst_name,
2463 dest_h, dest_size, dest_desired_access,
2464 FILE_ATTRIBUTE_NORMAL);
2465 torture_assert(torture, ok, "dest file create fill");
2467 ZERO_STRUCTPN(io);
2468 io->smb2.level = RAW_IOCTL_SMB2;
2469 io->smb2.in.file.handle = *src_h;
2470 io->smb2.in.function = FSCTL_SRV_REQUEST_RESUME_KEY;
2471 /* Allow for Key + ContextLength + Context */
2472 io->smb2.in.max_response_size = 32;
2473 io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2475 status = smb2_ioctl(tree, mem_ctx, &io->smb2);
2476 torture_assert_ntstatus_ok(torture, status,
2477 "FSCTL_SRV_REQUEST_RESUME_KEY");
2479 ndr_ret = ndr_pull_struct_blob(&io->smb2.out.out, mem_ctx, &res_key,
2480 (ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
2482 torture_assert_ndr_success(torture, ndr_ret,
2483 "ndr_pull_req_resume_key_rsp");
2485 ZERO_STRUCTPN(io);
2486 io->smb2.level = RAW_IOCTL_SMB2;
2487 io->smb2.in.file.handle = *dest_h;
2488 io->smb2.in.function = FSCTL_SRV_COPYCHUNK;
2489 io->smb2.in.max_response_size = sizeof(struct srv_copychunk_rsp);
2490 io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2492 ZERO_STRUCTPN(cc_copy);
2493 memcpy(cc_copy->source_key, res_key.resume_key, ARRAY_SIZE(cc_copy->source_key));
2494 cc_copy->chunk_count = nchunks;
2495 cc_copy->chunks = talloc_zero_array(mem_ctx, struct srv_copychunk, nchunks);
2496 torture_assert(torture, (cc_copy->chunks != NULL), "no memory for chunks");
2498 return true;
2502 static bool check_copy_chunk_rsp(struct torture_context *torture,
2503 struct srv_copychunk_rsp *cc_rsp,
2504 uint32_t ex_chunks_written,
2505 uint32_t ex_chunk_bytes_written,
2506 uint32_t ex_total_bytes_written)
2508 torture_assert_int_equal(torture, cc_rsp->chunks_written,
2509 ex_chunks_written, "num chunks");
2510 torture_assert_int_equal(torture, cc_rsp->chunk_bytes_written,
2511 ex_chunk_bytes_written, "chunk bytes written");
2512 torture_assert_int_equal(torture, cc_rsp->total_bytes_written,
2513 ex_total_bytes_written, "chunk total bytes");
2514 return true;
2517 static bool neg_aapl_copyfile(struct torture_context *tctx,
2518 struct smb2_tree *tree,
2519 uint64_t flags)
2521 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2522 const char *fname = "aapl";
2523 NTSTATUS status;
2524 struct smb2_create io;
2525 DATA_BLOB data;
2526 struct smb2_create_blob *aapl = NULL;
2527 uint32_t aapl_cmd;
2528 uint32_t aapl_reply_bitmap;
2529 uint32_t aapl_server_caps;
2530 bool ret = true;
2532 ZERO_STRUCT(io);
2533 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
2534 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2535 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2536 io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2537 NTCREATEX_SHARE_ACCESS_READ |
2538 NTCREATEX_SHARE_ACCESS_WRITE);
2539 io.in.fname = fname;
2541 data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2542 SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2543 SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS));
2544 SBVAL(data.data, 16, flags);
2546 status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2547 CHECK_STATUS(status, NT_STATUS_OK);
2549 status = smb2_create(tree, tctx, &io);
2550 CHECK_STATUS(status, NT_STATUS_OK);
2552 aapl = smb2_create_blob_find(&io.out.blobs,
2553 SMB2_CREATE_TAG_AAPL);
2554 if (aapl == NULL) {
2555 ret = false;
2556 goto done;
2559 if (aapl->data.length < 24) {
2560 ret = false;
2561 goto done;
2564 aapl_cmd = IVAL(aapl->data.data, 0);
2565 if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2566 torture_result(tctx, TORTURE_FAIL,
2567 "(%s) unexpected cmd: %d",
2568 __location__, (int)aapl_cmd);
2569 ret = false;
2570 goto done;
2573 aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2574 if (!(aapl_reply_bitmap & SMB2_CRTCTX_AAPL_SERVER_CAPS)) {
2575 torture_result(tctx, TORTURE_FAIL,
2576 "(%s) unexpected reply_bitmap: %d",
2577 __location__, (int)aapl_reply_bitmap);
2578 ret = false;
2579 goto done;
2582 aapl_server_caps = BVAL(aapl->data.data, 16);
2583 if (!(aapl_server_caps & flags)) {
2584 torture_result(tctx, TORTURE_FAIL,
2585 "(%s) unexpected server_caps: %d",
2586 __location__, (int)aapl_server_caps);
2587 ret = false;
2588 goto done;
2591 done:
2592 status = smb2_util_close(tree, io.out.file.handle);
2593 CHECK_STATUS(status, NT_STATUS_OK);
2595 smb2_util_unlink(tree, "aapl");
2596 talloc_free(mem_ctx);
2597 return ret;
2600 static bool test_copyfile(struct torture_context *torture,
2601 struct smb2_tree *tree)
2603 struct smb2_handle src_h;
2604 struct smb2_handle dest_h;
2605 NTSTATUS status;
2606 union smb_ioctl io;
2607 TALLOC_CTX *tmp_ctx = talloc_new(tree);
2608 struct srv_copychunk_copy cc_copy;
2609 struct srv_copychunk_rsp cc_rsp;
2610 enum ndr_err_code ndr_ret;
2611 bool ok;
2612 const char *sname = ":foo" "\xef\x80\xa2" "bar:$DATA";
2615 * First test a copy_chunk with a 0 chunk count without having
2616 * enabled this via AAPL. The request must not fail and the
2617 * copied length in the response must be 0. This is verified
2618 * against Windows 2008r2.
2621 ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2622 0, /* 0 chunks, copyfile semantics */
2623 FNAME_CC_SRC,
2624 &src_h, 4096, /* fill 4096 byte src file */
2625 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2626 FNAME_CC_DST,
2627 &dest_h, 0, /* 0 byte dest file */
2628 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2629 &cc_copy,
2630 &io);
2631 if (!ok) {
2632 torture_fail_goto(torture, done, "setup copy chunk error");
2635 ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2636 &cc_copy,
2637 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2638 torture_assert_ndr_success(torture, ndr_ret,
2639 "ndr_push_srv_copychunk_copy");
2641 status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2642 torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2644 ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2645 &cc_rsp,
2646 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2647 torture_assert_ndr_success(torture, ndr_ret,
2648 "ndr_pull_srv_copychunk_rsp");
2650 ok = check_copy_chunk_rsp(torture, &cc_rsp,
2651 0, /* chunks written */
2652 0, /* chunk bytes unsuccessfully written */
2653 0); /* total bytes written */
2654 if (!ok) {
2655 torture_fail_goto(torture, done, "bad copy chunk response data");
2659 * Now enable AAPL copyfile and test again, the file and the
2660 * stream must be copied by the server.
2662 ok = neg_aapl_copyfile(torture, tree,
2663 SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
2664 if (!ok) {
2665 torture_skip_goto(torture, done, "missing AAPL copyfile");
2666 goto done;
2669 smb2_util_close(tree, src_h);
2670 smb2_util_close(tree, dest_h);
2671 smb2_util_unlink(tree, FNAME_CC_SRC);
2672 smb2_util_unlink(tree, FNAME_CC_DST);
2674 ok = torture_setup_file(tmp_ctx, tree, FNAME_CC_SRC, false);
2675 if (!ok) {
2676 torture_fail(torture, "setup file error");
2678 ok = write_stream(tree, __location__, torture, tmp_ctx,
2679 FNAME_CC_SRC, AFPRESOURCE_STREAM,
2680 10, 10, "1234567890");
2681 if (!ok) {
2682 torture_fail(torture, "setup stream error");
2685 ok = write_stream(tree, __location__, torture, tmp_ctx,
2686 FNAME_CC_SRC, sname,
2687 10, 10, "abcdefghij");
2688 torture_assert_goto(torture, ok == true, ok, done, "write_stream failed\n");
2690 ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2691 0, /* 0 chunks, copyfile semantics */
2692 FNAME_CC_SRC,
2693 &src_h, 4096, /* fill 4096 byte src file */
2694 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2695 FNAME_CC_DST,
2696 &dest_h, 0, /* 0 byte dest file */
2697 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2698 &cc_copy,
2699 &io);
2700 if (!ok) {
2701 torture_fail_goto(torture, done, "setup copy chunk error");
2704 ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2705 &cc_copy,
2706 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2707 torture_assert_ndr_success(torture, ndr_ret,
2708 "ndr_push_srv_copychunk_copy");
2710 status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2711 torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2713 ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2714 &cc_rsp,
2715 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2716 torture_assert_ndr_success(torture, ndr_ret,
2717 "ndr_pull_srv_copychunk_rsp");
2719 ok = check_copy_chunk_rsp(torture, &cc_rsp,
2720 0, /* chunks written */
2721 0, /* chunk bytes unsuccessfully written */
2722 4096); /* total bytes written */
2723 if (!ok) {
2724 torture_fail_goto(torture, done, "bad copy chunk response data");
2727 ok = test_setup_open(torture, tree, tmp_ctx, FNAME_CC_DST, &dest_h,
2728 SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL);
2729 if (!ok) {
2730 torture_fail_goto(torture, done,"open failed");
2732 ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 4096, 0);
2733 if (!ok) {
2734 torture_fail_goto(torture, done, "inconsistent file data");
2737 ok = check_stream(tree, __location__, torture, tmp_ctx,
2738 FNAME_CC_DST, AFPRESOURCE_STREAM,
2739 0, 20, 10, 10, "1234567890");
2740 if (!ok) {
2741 torture_fail_goto(torture, done, "inconsistent stream data");
2744 ok = check_stream(tree, __location__, torture, tmp_ctx,
2745 FNAME_CC_DST, sname,
2746 0, 20, 10, 10, "abcdefghij");
2747 torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
2749 done:
2750 smb2_util_close(tree, src_h);
2751 smb2_util_close(tree, dest_h);
2752 smb2_util_unlink(tree, FNAME_CC_SRC);
2753 smb2_util_unlink(tree, FNAME_CC_DST);
2754 talloc_free(tmp_ctx);
2755 return true;
2758 static bool check_stream_list(struct smb2_tree *tree,
2759 struct torture_context *tctx,
2760 const char *fname,
2761 int num_exp,
2762 const char **exp,
2763 bool is_dir)
2765 bool ret = true;
2766 union smb_fileinfo finfo;
2767 NTSTATUS status;
2768 int i;
2769 TALLOC_CTX *tmp_ctx = talloc_new(tctx);
2770 char **exp_sort;
2771 struct stream_struct *stream_sort;
2772 struct smb2_create create;
2773 struct smb2_handle h;
2775 ZERO_STRUCT(h);
2776 torture_assert_goto(tctx, tmp_ctx != NULL, ret, done, "talloc_new failed");
2778 ZERO_STRUCT(create);
2779 create.in.fname = fname;
2780 create.in.create_disposition = NTCREATEX_DISP_OPEN;
2781 create.in.desired_access = SEC_FILE_ALL;
2782 create.in.create_options = is_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
2783 create.in.file_attributes = is_dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
2784 status = smb2_create(tree, tmp_ctx, &create);
2785 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
2786 h = create.out.file.handle;
2788 finfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
2789 finfo.generic.in.file.handle = h;
2791 status = smb2_getinfo_file(tree, tctx, &finfo);
2792 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "get stream info");
2794 smb2_util_close(tree, h);
2796 torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams, num_exp,
2797 ret, done, "stream count");
2799 if (num_exp == 0) {
2800 TALLOC_FREE(tmp_ctx);
2801 goto done;
2804 exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
2805 torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
2807 TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
2809 stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
2810 finfo.stream_info.out.num_streams *
2811 sizeof(*stream_sort));
2812 torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
2814 TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
2816 for (i=0; i<num_exp; i++) {
2817 torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
2818 i, exp_sort[i], stream_sort[i].stream_name.s);
2819 torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s, exp_sort[i],
2820 ret, done, "stream name");
2823 done:
2824 TALLOC_FREE(tmp_ctx);
2825 return ret;
2829 test stream names
2831 static bool test_stream_names(struct torture_context *tctx,
2832 struct smb2_tree *tree)
2834 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2835 NTSTATUS status;
2836 struct smb2_create create;
2837 struct smb2_handle h;
2838 const char *fname = BASEDIR "\\stream_names.txt";
2839 const char *sname1;
2840 bool ret;
2841 /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
2842 const char *streams[] = {
2843 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2844 "::$DATA"
2847 sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
2849 /* clean slate ...*/
2850 smb2_util_unlink(tree, fname);
2851 smb2_deltree(tree, fname);
2852 smb2_deltree(tree, BASEDIR);
2854 status = torture_smb2_testdir(tree, BASEDIR, &h);
2855 CHECK_STATUS(status, NT_STATUS_OK);
2856 smb2_util_close(tree, h);
2858 torture_comment(tctx, "(%s) testing stream names\n", __location__);
2859 ZERO_STRUCT(create);
2860 create.in.desired_access = SEC_FILE_WRITE_DATA;
2861 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2862 create.in.share_access =
2863 NTCREATEX_SHARE_ACCESS_DELETE|
2864 NTCREATEX_SHARE_ACCESS_READ|
2865 NTCREATEX_SHARE_ACCESS_WRITE;
2866 create.in.create_disposition = NTCREATEX_DISP_CREATE;
2867 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2868 create.in.fname = sname1;
2870 status = smb2_create(tree, mem_ctx, &create);
2871 CHECK_STATUS(status, NT_STATUS_OK);
2872 smb2_util_close(tree, create.out.file.handle);
2874 ret = check_stream_list(tree, tctx, fname, 2, streams, false);
2875 CHECK_VALUE(ret, true);
2877 done:
2878 status = smb2_util_unlink(tree, fname);
2879 smb2_deltree(tree, BASEDIR);
2880 talloc_free(mem_ctx);
2882 return ret;
2885 /* Renaming a directory with open file, should work for OS X AAPL clients */
2886 static bool test_rename_dir_openfile(struct torture_context *torture,
2887 struct smb2_tree *tree)
2889 bool ret = true;
2890 NTSTATUS status;
2891 union smb_open io;
2892 union smb_close cl;
2893 union smb_setfileinfo sinfo;
2894 struct smb2_handle d1, h1;
2895 const char *renamedir = BASEDIR "-new";
2896 bool server_is_osx = torture_setting_bool(torture, "osx", false);
2898 smb2_deltree(tree, BASEDIR);
2899 smb2_util_rmdir(tree, BASEDIR);
2900 smb2_deltree(tree, renamedir);
2902 ZERO_STRUCT(io.smb2);
2903 io.generic.level = RAW_OPEN_SMB2;
2904 io.smb2.in.create_flags = 0;
2905 io.smb2.in.desired_access = 0x0017019f;
2906 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2907 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2908 io.smb2.in.share_access = 0;
2909 io.smb2.in.alloc_size = 0;
2910 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2911 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2912 io.smb2.in.security_flags = 0;
2913 io.smb2.in.fname = BASEDIR;
2915 status = smb2_create(tree, torture, &(io.smb2));
2916 torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
2917 d1 = io.smb2.out.file.handle;
2919 ZERO_STRUCT(io.smb2);
2920 io.generic.level = RAW_OPEN_SMB2;
2921 io.smb2.in.create_flags = 0;
2922 io.smb2.in.desired_access = 0x0017019f;
2923 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
2924 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2925 io.smb2.in.share_access = 0;
2926 io.smb2.in.alloc_size = 0;
2927 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
2928 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2929 io.smb2.in.security_flags = 0;
2930 io.smb2.in.fname = BASEDIR "\\file.txt";
2932 status = smb2_create(tree, torture, &(io.smb2));
2933 torture_assert_ntstatus_ok(torture, status, "smb2_create file");
2934 h1 = io.smb2.out.file.handle;
2936 if (!server_is_osx) {
2937 torture_comment(torture, "Renaming directory without AAPL, must fail\n");
2939 ZERO_STRUCT(sinfo);
2940 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
2941 sinfo.rename_information.in.file.handle = d1;
2942 sinfo.rename_information.in.overwrite = 0;
2943 sinfo.rename_information.in.root_fid = 0;
2944 sinfo.rename_information.in.new_name = renamedir;
2945 status = smb2_setinfo_file(tree, &sinfo);
2947 torture_assert_ntstatus_equal(torture, status,
2948 NT_STATUS_ACCESS_DENIED,
2949 "smb2_setinfo_file");
2951 ZERO_STRUCT(cl.smb2);
2952 cl.smb2.level = RAW_CLOSE_SMB2;
2953 cl.smb2.in.file.handle = d1;
2954 status = smb2_close(tree, &(cl.smb2));
2955 torture_assert_ntstatus_ok(torture, status, "smb2_close");
2956 ZERO_STRUCT(d1);
2959 torture_comment(torture, "Enabling AAPL\n");
2961 ret = enable_aapl(torture, tree);
2962 torture_assert(torture, ret == true, "enable_aapl failed");
2964 torture_comment(torture, "Renaming directory with AAPL\n");
2966 ZERO_STRUCT(io.smb2);
2967 io.generic.level = RAW_OPEN_SMB2;
2968 io.smb2.in.desired_access = 0x0017019f;
2969 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2970 io.smb2.in.share_access = 0;
2971 io.smb2.in.alloc_size = 0;
2972 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
2973 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
2974 io.smb2.in.security_flags = 0;
2975 io.smb2.in.fname = BASEDIR;
2977 status = smb2_create(tree, torture, &(io.smb2));
2978 torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
2979 d1 = io.smb2.out.file.handle;
2981 ZERO_STRUCT(sinfo);
2982 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
2983 sinfo.rename_information.in.file.handle = d1;
2984 sinfo.rename_information.in.overwrite = 0;
2985 sinfo.rename_information.in.root_fid = 0;
2986 sinfo.rename_information.in.new_name = renamedir;
2988 status = smb2_setinfo_file(tree, &sinfo);
2989 torture_assert_ntstatus_ok(torture, status, "smb2_setinfo_file");
2991 ZERO_STRUCT(cl.smb2);
2992 cl.smb2.level = RAW_CLOSE_SMB2;
2993 cl.smb2.in.file.handle = d1;
2994 status = smb2_close(tree, &(cl.smb2));
2995 torture_assert_ntstatus_ok(torture, status, "smb2_close");
2996 ZERO_STRUCT(d1);
2998 cl.smb2.in.file.handle = h1;
2999 status = smb2_close(tree, &(cl.smb2));
3000 torture_assert_ntstatus_ok(torture, status, "smb2_close");
3001 ZERO_STRUCT(h1);
3003 torture_comment(torture, "Cleaning up\n");
3005 if (h1.data[0] || h1.data[1]) {
3006 ZERO_STRUCT(cl.smb2);
3007 cl.smb2.level = RAW_CLOSE_SMB2;
3008 cl.smb2.in.file.handle = h1;
3009 status = smb2_close(tree, &(cl.smb2));
3012 smb2_util_unlink(tree, BASEDIR "\\file.txt");
3013 smb2_util_unlink(tree, BASEDIR "-new\\file.txt");
3014 smb2_deltree(tree, renamedir);
3015 smb2_deltree(tree, BASEDIR);
3016 return ret;
3019 static bool test_afpinfo_enoent(struct torture_context *tctx,
3020 struct smb2_tree *tree)
3022 bool ret = true;
3023 NTSTATUS status;
3024 struct smb2_create create;
3025 struct smb2_handle h1;
3026 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3027 const char *fname = BASEDIR "\\file";
3028 const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3030 torture_comment(tctx, "Opening file without AFP_AfpInfo\n");
3032 smb2_deltree(tree, BASEDIR);
3033 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3034 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3035 smb2_util_close(tree, h1);
3036 ret = torture_setup_file(mem_ctx, tree, fname, false);
3037 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3039 torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3041 ZERO_STRUCT(create);
3042 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3043 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3044 create.in.fname = sname;
3046 status = smb2_create(tree, mem_ctx, &create);
3047 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3048 ret, done, "Got unexpected AFP_AfpInfo stream");
3050 done:
3051 smb2_util_unlink(tree, fname);
3052 smb2_util_rmdir(tree, BASEDIR);
3053 return ret;
3056 static bool test_create_delete_on_close(struct torture_context *tctx,
3057 struct smb2_tree *tree)
3059 bool ret = true;
3060 NTSTATUS status;
3061 struct smb2_create create;
3062 struct smb2_handle h1;
3063 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3064 const char *fname = BASEDIR "\\file";
3065 const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3066 const char *type_creator = "SMB,OLE!";
3067 AfpInfo *info = NULL;
3068 const char *streams_basic[] = {
3069 "::$DATA"
3071 const char *streams_afpinfo[] = {
3072 "::$DATA",
3073 AFPINFO_STREAM
3076 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3078 torture_comment(tctx, "Checking whether create with delete-on-close work with AFP_AfpInfo\n");
3080 smb2_deltree(tree, BASEDIR);
3081 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3082 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3083 smb2_util_close(tree, h1);
3084 ret = torture_setup_file(mem_ctx, tree, fname, false);
3085 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3087 torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3089 ZERO_STRUCT(create);
3090 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3091 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3092 create.in.fname = sname;
3094 status = smb2_create(tree, mem_ctx, &create);
3095 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3096 ret, done, "Got unexpected AFP_AfpInfo stream");
3098 ZERO_STRUCT(create);
3099 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3100 create.in.desired_access = SEC_FILE_ALL;
3101 create.in.fname = sname;
3103 status = smb2_create(tree, mem_ctx, &create);
3104 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3105 ret, done, "Got unexpected AFP_AfpInfo stream");
3107 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3108 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3110 torture_comment(tctx, "Deleting AFP_AfpInfo via create with delete-on-close\n");
3112 info = torture_afpinfo_new(mem_ctx);
3113 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3115 memcpy(info->afpi_FinderInfo, type_creator, 8);
3116 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3117 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3119 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3120 0, 60, 16, 8, type_creator);
3121 torture_assert_goto(tctx, ret == true, ret, done, "Bad type/creator in AFP_AfpInfo");
3123 ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3124 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3126 ZERO_STRUCT(create);
3127 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3128 create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3129 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3130 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3131 create.in.fname = sname;
3132 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3134 status = smb2_create(tree, mem_ctx, &create);
3135 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3137 h1 = create.out.file.handle;
3138 smb2_util_close(tree, h1);
3140 ZERO_STRUCT(create);
3141 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3142 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
3143 create.in.fname = sname;
3144 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3145 status = smb2_create(tree, mem_ctx, &create);
3146 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3147 ret, done, "Got unexpected AFP_AfpInfo stream");
3149 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3150 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3152 done:
3153 smb2_util_unlink(tree, fname);
3154 smb2_util_rmdir(tree, BASEDIR);
3155 return ret;
3158 static bool test_setinfo_delete_on_close(struct torture_context *tctx,
3159 struct smb2_tree *tree)
3161 bool ret = true;
3162 NTSTATUS status;
3163 struct smb2_create create;
3164 union smb_setfileinfo sfinfo;
3165 struct smb2_handle h1;
3166 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3167 const char *fname = BASEDIR "\\file";
3168 const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3169 const char *type_creator = "SMB,OLE!";
3170 AfpInfo *info = NULL;
3171 const char *streams_basic[] = {
3172 "::$DATA"
3175 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3177 torture_comment(tctx, "Deleting AFP_AfpInfo via setinfo with delete-on-close\n");
3179 smb2_deltree(tree, BASEDIR);
3180 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3181 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3182 smb2_util_close(tree, h1);
3183 ret = torture_setup_file(mem_ctx, tree, fname, false);
3184 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3186 info = torture_afpinfo_new(mem_ctx);
3187 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3188 memcpy(info->afpi_FinderInfo, type_creator, 8);
3189 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3190 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3192 ZERO_STRUCT(create);
3193 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3194 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3195 create.in.fname = sname;
3196 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3197 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3199 status = smb2_create(tree, mem_ctx, &create);
3200 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3202 h1 = create.out.file.handle;
3204 /* Delete stream via setinfo delete-on-close */
3205 ZERO_STRUCT(sfinfo);
3206 sfinfo.disposition_info.in.delete_on_close = 1;
3207 sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3208 sfinfo.generic.in.file.handle = h1;
3209 status = smb2_setinfo_file(tree, &sfinfo);
3210 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3212 smb2_util_close(tree, h1);
3214 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3215 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3217 ZERO_STRUCT(create);
3218 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3219 create.in.desired_access = SEC_FILE_ALL;
3220 create.in.fname = sname;
3221 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3222 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3223 status = smb2_create(tree, mem_ctx, &create);
3224 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3225 ret, done, "Got unexpected AFP_AfpInfo stream");
3227 done:
3228 smb2_util_unlink(tree, fname);
3229 smb2_util_rmdir(tree, BASEDIR);
3230 return ret;
3233 static bool test_setinfo_eof(struct torture_context *tctx,
3234 struct smb2_tree *tree)
3236 bool ret = true;
3237 NTSTATUS status;
3238 struct smb2_create create;
3239 union smb_setfileinfo sfinfo;
3240 struct smb2_handle h1;
3241 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3242 const char *fname = BASEDIR "\\file";
3243 const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3244 const char *type_creator = "SMB,OLE!";
3245 AfpInfo *info = NULL;
3246 const char *streams_afpinfo[] = {
3247 "::$DATA",
3248 AFPINFO_STREAM
3251 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3253 torture_comment(tctx, "Set AFP_AfpInfo EOF to 61, 1 and 0\n");
3255 smb2_deltree(tree, BASEDIR);
3256 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3257 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3258 smb2_util_close(tree, h1);
3259 ret = torture_setup_file(mem_ctx, tree, fname, false);
3260 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3262 info = torture_afpinfo_new(mem_ctx);
3263 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3264 memcpy(info->afpi_FinderInfo, type_creator, 8);
3265 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3266 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3268 ZERO_STRUCT(create);
3269 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3270 create.in.desired_access = SEC_FILE_ALL;
3271 create.in.fname = sname;
3272 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3273 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3275 status = smb2_create(tree, mem_ctx, &create);
3276 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3278 h1 = create.out.file.handle;
3280 torture_comment(tctx, "Set AFP_AfpInfo EOF to 61\n");
3282 /* Test setinfo end-of-file info */
3283 ZERO_STRUCT(sfinfo);
3284 sfinfo.generic.in.file.handle = h1;
3285 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3286 sfinfo.position_information.in.position = 61;
3287 status = smb2_setinfo_file(tree, &sfinfo);
3288 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ALLOTTED_SPACE_EXCEEDED,
3289 ret, done, "set eof 61 failed");
3291 torture_comment(tctx, "Set AFP_AfpInfo EOF to 1\n");
3293 /* Truncation returns success, but has no effect */
3294 ZERO_STRUCT(sfinfo);
3295 sfinfo.generic.in.file.handle = h1;
3296 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3297 sfinfo.position_information.in.position = 1;
3298 status = smb2_setinfo_file(tree, &sfinfo);
3299 torture_assert_ntstatus_ok_goto(tctx, status,
3300 ret, done, "set eof 1 failed");
3301 smb2_util_close(tree, h1);
3303 ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3304 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3306 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3307 0, 60, 16, 8, type_creator);
3308 torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3310 ZERO_STRUCT(create);
3311 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3312 create.in.desired_access = SEC_FILE_ALL;
3313 create.in.fname = sname;
3314 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3315 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3317 status = smb2_create(tree, mem_ctx, &create);
3318 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3320 h1 = create.out.file.handle;
3323 * Delete stream via setinfo end-of-file info to 0, should
3324 * return success but stream MUST NOT deleted
3326 ZERO_STRUCT(sfinfo);
3327 sfinfo.generic.in.file.handle = h1;
3328 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3329 sfinfo.position_information.in.position = 0;
3330 status = smb2_setinfo_file(tree, &sfinfo);
3331 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
3333 smb2_util_close(tree, h1);
3335 ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3336 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3338 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3339 0, 60, 16, 8, type_creator);
3340 torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3342 done:
3343 smb2_util_unlink(tree, fname);
3344 smb2_util_rmdir(tree, BASEDIR);
3345 return ret;
3348 static bool test_afpinfo_all0(struct torture_context *tctx,
3349 struct smb2_tree *tree)
3351 bool ret = true;
3352 NTSTATUS status;
3353 struct smb2_create create;
3354 struct smb2_handle h1 = {{0}};
3355 struct smb2_handle baseh = {{0}};
3356 union smb_setfileinfo setfinfo;
3357 union smb_fileinfo getfinfo;
3358 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3359 const char *fname = BASEDIR "\\file";
3360 const char *sname = BASEDIR "\\file" AFPINFO_STREAM;
3361 const char *type_creator = "SMB,OLE!";
3362 AfpInfo *info = NULL;
3363 char *infobuf = NULL;
3364 const char *streams_basic[] = {
3365 "::$DATA"
3367 const char *streams_afpinfo[] = {
3368 "::$DATA",
3369 AFPINFO_STREAM
3372 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3374 torture_comment(tctx, "Write all 0 to AFP_AfpInfo and see what happens\n");
3376 smb2_deltree(tree, BASEDIR);
3377 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3378 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3379 smb2_util_close(tree, h1);
3380 ret = torture_setup_file(mem_ctx, tree, fname, false);
3381 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3383 info = torture_afpinfo_new(mem_ctx);
3384 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3385 memcpy(info->afpi_FinderInfo, type_creator, 8);
3386 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3387 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3389 ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3390 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3392 /* Write all 0 to AFP_AfpInfo */
3393 memset(info->afpi_FinderInfo, 0, AFP_FinderSize);
3394 infobuf = torture_afpinfo_pack(mem_ctx, info);
3395 torture_assert_not_null_goto(tctx, infobuf, ret, done,
3396 "torture_afpinfo_pack failed\n");
3398 ZERO_STRUCT(create);
3399 create.in.desired_access = SEC_FILE_ALL;
3400 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3401 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3402 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3403 create.in.fname = fname;
3405 status = smb2_create(tree, mem_ctx, &create);
3406 torture_assert_goto(tctx, ret == true, ret, done,
3407 "smb2_create failed\n");
3408 baseh = create.out.file.handle;
3410 ZERO_STRUCT(create);
3411 create.in.desired_access = SEC_FILE_ALL;
3412 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3413 create.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
3414 create.in.fname = sname;
3416 status = smb2_create(tree, mem_ctx, &create);
3417 torture_assert_goto(tctx, ret == true, ret, done,
3418 "smb2_create failed\n");
3419 h1 = create.out.file.handle;
3421 status = smb2_util_write(tree, h1, infobuf, 0, AFP_INFO_SIZE);
3422 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3423 "smb2_util_write failed\n");
3426 * Get stream information on open handle, must return only default
3427 * stream, the AFP_AfpInfo stream must not be returned.
3430 ZERO_STRUCT(getfinfo);
3431 getfinfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
3432 getfinfo.generic.in.file.handle = baseh;
3434 status = smb2_getinfo_file(tree, tctx, &getfinfo);
3435 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3436 "get stream info\n");
3438 torture_assert_int_equal_goto(tctx, getfinfo.stream_info.out.num_streams,
3439 1, ret, done, "stream count");
3441 smb2_util_close(tree, baseh);
3442 ZERO_STRUCT(baseh);
3445 * Try to set some file-basic-info (time) on the stream. This catches
3446 * naive implementation mistakes that simply deleted the backing store
3447 * from the filesystem in the zero-out step.
3450 ZERO_STRUCT(setfinfo);
3451 unix_to_nt_time(&setfinfo.basic_info.in.write_time, time(NULL));
3452 setfinfo.basic_info.in.attrib = 0x20;
3453 setfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
3454 setfinfo.generic.in.file.handle = h1;
3456 status = smb2_setinfo_file(tree, &setfinfo);
3457 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3458 "smb2_getinfo_file failed\n");
3460 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3461 torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
3463 smb2_util_close(tree, h1);
3464 ZERO_STRUCT(h1);
3466 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3467 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3469 done:
3470 if (!smb2_util_handle_empty(h1)) {
3471 smb2_util_close(tree, h1);
3473 if (!smb2_util_handle_empty(baseh)) {
3474 smb2_util_close(tree, baseh);
3476 smb2_util_unlink(tree, fname);
3477 smb2_util_rmdir(tree, BASEDIR);
3478 return ret;
3481 static bool test_create_delete_on_close_resource(struct torture_context *tctx,
3482 struct smb2_tree *tree)
3484 bool ret = true;
3485 NTSTATUS status;
3486 struct smb2_create create;
3487 struct smb2_handle h1;
3488 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3489 const char *fname = BASEDIR "\\file";
3490 const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3491 const char *streams_basic[] = {
3492 "::$DATA"
3494 const char *streams_afpresource[] = {
3495 "::$DATA",
3496 AFPRESOURCE_STREAM
3499 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3501 torture_comment(tctx, "Checking whether create with delete-on-close is ignored for AFP_AfpResource\n");
3503 smb2_deltree(tree, BASEDIR);
3504 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3505 torture_assert_ntstatus_ok(tctx, status, "torture_smb2_testdir");
3506 smb2_util_close(tree, h1);
3507 ret = torture_setup_file(mem_ctx, tree, fname, false);
3508 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3510 torture_comment(tctx, "Opening not existing AFP_AfpResource\n");
3512 ZERO_STRUCT(create);
3513 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3514 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3515 create.in.fname = sname;
3517 status = smb2_create(tree, mem_ctx, &create);
3518 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3519 ret, done, "Got unexpected AFP_AfpResource stream");
3521 ZERO_STRUCT(create);
3522 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3523 create.in.desired_access = SEC_FILE_ALL;
3524 create.in.fname = sname;
3526 status = smb2_create(tree, mem_ctx, &create);
3527 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3528 ret, done, "Got unexpected AFP_AfpResource stream");
3530 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3531 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3533 torture_comment(tctx, "Trying to delete AFP_AfpResource via create with delete-on-close\n");
3535 ret = write_stream(tree, __location__, tctx, mem_ctx,
3536 fname, AFPRESOURCE_STREAM_NAME,
3537 0, 10, "1234567890");
3538 torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3540 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3541 0, 10, 0, 10, "1234567890");
3542 torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3544 ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3545 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3547 ZERO_STRUCT(create);
3548 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3549 create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3550 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3551 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3552 create.in.fname = sname;
3553 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3555 status = smb2_create(tree, mem_ctx, &create);
3556 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3558 h1 = create.out.file.handle;
3559 smb2_util_close(tree, h1);
3561 ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3562 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3564 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3565 0, 10, 0, 10, "1234567890");
3566 torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3568 done:
3569 smb2_util_unlink(tree, fname);
3570 smb2_util_rmdir(tree, BASEDIR);
3571 return ret;
3574 static bool test_setinfo_delete_on_close_resource(struct torture_context *tctx,
3575 struct smb2_tree *tree)
3577 bool ret = true;
3578 NTSTATUS status;
3579 struct smb2_create create;
3580 union smb_setfileinfo sfinfo;
3581 struct smb2_handle h1;
3582 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3583 const char *fname = BASEDIR "\\file";
3584 const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3585 const char *streams_afpresource[] = {
3586 "::$DATA",
3587 AFPRESOURCE_STREAM
3590 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3592 torture_comment(tctx, "Trying to delete AFP_AfpResource via setinfo with delete-on-close\n");
3594 smb2_deltree(tree, BASEDIR);
3595 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3596 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3597 smb2_util_close(tree, h1);
3598 ret = torture_setup_file(mem_ctx, tree, fname, false);
3599 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3601 ret = write_stream(tree, __location__, tctx, mem_ctx,
3602 fname, AFPRESOURCE_STREAM_NAME,
3603 10, 10, "1234567890");
3604 torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3606 ZERO_STRUCT(create);
3607 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3608 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3609 create.in.fname = sname;
3610 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3611 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3613 status = smb2_create(tree, mem_ctx, &create);
3614 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3616 h1 = create.out.file.handle;
3618 /* Try to delete stream via setinfo delete-on-close */
3619 ZERO_STRUCT(sfinfo);
3620 sfinfo.disposition_info.in.delete_on_close = 1;
3621 sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3622 sfinfo.generic.in.file.handle = h1;
3623 status = smb2_setinfo_file(tree, &sfinfo);
3624 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3626 smb2_util_close(tree, h1);
3628 ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3629 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3631 ZERO_STRUCT(create);
3632 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3633 create.in.desired_access = SEC_FILE_ALL;
3634 create.in.fname = sname;
3635 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3636 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3637 status = smb2_create(tree, mem_ctx, &create);
3638 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3639 "Got unexpected AFP_AfpResource stream");
3641 done:
3642 smb2_util_unlink(tree, fname);
3643 smb2_util_rmdir(tree, BASEDIR);
3644 return ret;
3647 static bool test_setinfo_eof_resource(struct torture_context *tctx,
3648 struct smb2_tree *tree)
3650 bool ret = true;
3651 NTSTATUS status;
3652 struct smb2_create create;
3653 union smb_setfileinfo sfinfo;
3654 union smb_fileinfo finfo;
3655 struct smb2_handle h1;
3656 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3657 const char *fname = BASEDIR "\\file";
3658 const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3659 const char *streams_basic[] = {
3660 "::$DATA"
3663 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3665 torture_comment(tctx, "Set AFP_AfpResource EOF to 1 and 0\n");
3667 smb2_deltree(tree, BASEDIR);
3668 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3669 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3670 smb2_util_close(tree, h1);
3671 ret = torture_setup_file(mem_ctx, tree, fname, false);
3672 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3674 ret = write_stream(tree, __location__, tctx, mem_ctx,
3675 fname, AFPRESOURCE_STREAM_NAME,
3676 10, 10, "1234567890");
3677 torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3679 ZERO_STRUCT(create);
3680 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3681 create.in.desired_access = SEC_FILE_ALL;
3682 create.in.fname = sname;
3683 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3684 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3686 status = smb2_create(tree, mem_ctx, &create);
3687 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3689 h1 = create.out.file.handle;
3691 torture_comment(tctx, "Set AFP_AfpResource EOF to 1\n");
3693 /* Test setinfo end-of-file info */
3694 ZERO_STRUCT(sfinfo);
3695 sfinfo.generic.in.file.handle = h1;
3696 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3697 sfinfo.position_information.in.position = 1;
3698 status = smb2_setinfo_file(tree, &sfinfo);
3699 torture_assert_ntstatus_ok_goto(tctx, status,
3700 ret, done, "set eof 1 failed");
3702 smb2_util_close(tree, h1);
3704 /* Check size == 1 */
3705 ZERO_STRUCT(create);
3706 create.in.fname = sname;
3707 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3708 create.in.desired_access = SEC_FILE_ALL;
3709 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3710 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3711 status = smb2_create(tree, mem_ctx, &create);
3712 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3714 h1 = create.out.file.handle;
3716 ZERO_STRUCT(finfo);
3717 finfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
3718 finfo.generic.in.file.handle = h1;
3719 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
3720 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file failed");
3722 smb2_util_close(tree, h1);
3724 torture_assert_goto(tctx, finfo.all_info.out.size == 1, ret, done, "size != 1");
3726 ZERO_STRUCT(create);
3727 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3728 create.in.desired_access = SEC_FILE_ALL;
3729 create.in.fname = sname;
3730 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3731 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3733 status = smb2_create(tree, mem_ctx, &create);
3734 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3736 h1 = create.out.file.handle;
3739 * Delete stream via setinfo end-of-file info to 0, this
3740 * should delete the stream.
3742 ZERO_STRUCT(sfinfo);
3743 sfinfo.generic.in.file.handle = h1;
3744 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3745 sfinfo.position_information.in.position = 0;
3746 status = smb2_setinfo_file(tree, &sfinfo);
3747 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
3749 smb2_util_close(tree, h1);
3751 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3752 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3754 ZERO_STRUCT(create);
3755 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3756 create.in.desired_access = SEC_FILE_ALL;
3757 create.in.fname = sname;
3758 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3759 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3761 status = smb2_create(tree, mem_ctx, &create);
3762 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3763 ret, done, "smb2_create failed");
3765 done:
3766 smb2_util_unlink(tree, fname);
3767 smb2_util_rmdir(tree, BASEDIR);
3768 return ret;
3772 * This tests that right after creating the AFP_AfpInfo stream,
3773 * reading from the stream returns an empty, default metadata blob of
3774 * 60 bytes.
3776 * NOTE: against OS X SMB server this only works if the read request
3777 * is compounded with the create that created the stream, is fails
3778 * otherwise. We don't care...
3780 static bool test_null_afpinfo(struct torture_context *tctx,
3781 struct smb2_tree *tree)
3783 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3784 const char *fname = "test_null_afpinfo";
3785 const char *sname = "test_null_afpinfo" AFPINFO_STREAM_NAME;
3786 NTSTATUS status;
3787 bool ret = true;
3788 struct smb2_request *req[3];
3789 struct smb2_handle handle;
3790 struct smb2_create create;
3791 struct smb2_read read;
3792 AfpInfo *afpinfo = NULL;
3793 char *afpinfo_buf = NULL;
3794 const char *type_creator = "SMB,OLE!";
3796 torture_comment(tctx, "Checking create of AfpInfo stream\n");
3798 smb2_util_unlink(tree, fname);
3800 ret = torture_setup_file(mem_ctx, tree, fname, false);
3801 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
3803 ZERO_STRUCT(create);
3804 create.in.desired_access = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA;
3805 create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
3806 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3807 create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
3808 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
3809 create.in.fname = sname;
3811 smb2_transport_compound_start(tree->session->transport, 2);
3813 req[0] = smb2_create_send(tree, &create);
3815 handle.data[0] = UINT64_MAX;
3816 handle.data[1] = UINT64_MAX;
3818 smb2_transport_compound_set_related(tree->session->transport, true);
3820 ZERO_STRUCT(read);
3821 read.in.file.handle = handle;
3822 read.in.length = AFP_INFO_SIZE;
3823 req[1] = smb2_read_send(tree, &read);
3825 status = smb2_create_recv(req[0], tree, &create);
3826 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_recv failed");
3828 handle = create.out.file.handle;
3830 status = smb2_read_recv(req[1], tree, &read);
3831 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read_recv failed");
3833 afpinfo = torture_afpinfo_new(mem_ctx);
3834 torture_assert_goto(tctx, afpinfo != NULL, ret, done, "torture_afpinfo_new failed");
3836 memcpy(afpinfo->afpi_FinderInfo, type_creator, 8);
3838 afpinfo_buf = torture_afpinfo_pack(tctx, afpinfo);
3839 torture_assert_goto(tctx, afpinfo_buf != NULL, ret, done, "torture_afpinfo_new failed");
3841 status = smb2_util_write(tree, handle, afpinfo_buf, 0, AFP_INFO_SIZE);
3842 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write failed");
3844 smb2_util_close(tree, handle);
3846 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3847 0, 60, 16, 8, type_creator);
3848 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
3850 done:
3851 smb2_util_unlink(tree, fname);
3852 talloc_free(mem_ctx);
3853 return ret;
3856 static bool test_delete_file_with_rfork(struct torture_context *tctx,
3857 struct smb2_tree *tree)
3859 const char *fname = "torture_write_rfork_io";
3860 const char *rfork_content = "1234567890";
3861 NTSTATUS status;
3862 bool ret = true;
3864 smb2_util_unlink(tree, fname);
3866 torture_comment(tctx, "Test deleting file with resource fork\n");
3868 ret = torture_setup_file(tctx, tree, fname, false);
3869 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed\n");
3871 ret = write_stream(tree, __location__, tctx, tctx,
3872 fname, AFPRESOURCE_STREAM_NAME,
3873 10, 10, rfork_content);
3874 torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed\n");
3876 ret = check_stream(tree, __location__, tctx, tctx,
3877 fname, AFPRESOURCE_STREAM_NAME,
3878 0, 20, 10, 10, rfork_content);
3879 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed\n");
3881 status = smb2_util_unlink(tree, fname);
3882 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "check_stream failed\n");
3884 done:
3885 return ret;
3888 static bool test_rename_and_read_rsrc(struct torture_context *tctx,
3889 struct smb2_tree *tree)
3891 bool ret = true;
3892 NTSTATUS status;
3893 struct smb2_create create, create2;
3894 struct smb2_handle h1, h2;
3895 const char *fname = "test_rename_openfile";
3896 const char *sname = "test_rename_openfile" AFPRESOURCE_STREAM_NAME;
3897 const char *fname_renamed = "test_rename_openfile_renamed";
3898 const char *data = "1234567890";
3899 union smb_setfileinfo sinfo;
3900 struct smb2_read r;
3902 ret = enable_aapl(tctx, tree);
3903 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
3905 torture_comment(tctx, "Create file with resource fork\n");
3907 ret = torture_setup_file(tctx, tree, fname, false);
3908 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3910 ret = write_stream(tree, __location__, tctx, tctx,
3911 fname, AFPRESOURCE_STREAM_NAME, 0, 10, data);
3912 torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
3914 torture_comment(tctx, "Open resource fork\n");
3916 ZERO_STRUCT(create);
3917 create.in.desired_access = SEC_FILE_ALL;
3918 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3919 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3920 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3921 create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
3922 create.in.fname = sname;
3924 status = smb2_create(tree, tctx, &create);
3925 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3927 h1 = create.out.file.handle;
3929 torture_comment(tctx, "Rename base file\n");
3931 ZERO_STRUCT(create2);
3932 create2.in.desired_access = SEC_FILE_ALL;
3933 create2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3934 create2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3935 create2.in.create_disposition = NTCREATEX_DISP_OPEN;
3936 create2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
3937 create2.in.fname = fname;
3939 status = smb2_create(tree, tctx, &create2);
3940 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3942 h2 = create2.out.file.handle;
3944 ZERO_STRUCT(sinfo);
3945 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
3946 sinfo.rename_information.in.file.handle = h2;
3947 sinfo.rename_information.in.overwrite = 0;
3948 sinfo.rename_information.in.root_fid = 0;
3949 sinfo.rename_information.in.new_name = fname_renamed;
3951 status = smb2_setinfo_file(tree, &sinfo);
3952 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file failed");
3954 smb2_util_close(tree, h2);
3956 ZERO_STRUCT(r);
3957 r.in.file.handle = h1;
3958 r.in.length = 10;
3959 r.in.offset = 0;
3961 torture_comment(tctx, "Read resource fork of renamed file\n");
3963 status = smb2_read(tree, tree, &r);
3964 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read failed");
3966 smb2_util_close(tree, h1);
3968 torture_assert_goto(tctx, r.out.data.length == 10, ret, done,
3969 talloc_asprintf(tctx, "smb2_read returned %jd bytes, expected 10\n",
3970 (intmax_t)r.out.data.length));
3972 torture_assert_goto(tctx, memcmp(r.out.data.data, data, 10) == 0, ret, done,
3973 talloc_asprintf(tctx, "Bad data in stream\n"));
3975 done:
3976 smb2_util_unlink(tree, fname);
3977 smb2_util_unlink(tree, fname_renamed);
3979 return ret;
3982 static bool test_readdir_attr_illegal_ntfs(struct torture_context *tctx,
3983 struct smb2_tree *tree)
3985 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3986 const char *name = "test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
3987 const char *fname = BASEDIR "\\test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
3988 NTSTATUS status;
3989 struct smb2_handle testdirh;
3990 bool ret = true;
3991 struct smb2_create io;
3992 AfpInfo *info;
3993 const char *type_creator = "SMB,OLE!";
3994 struct smb2_find f;
3995 unsigned int count;
3996 union smb_search_data *d;
3997 uint64_t rfork_len;
3998 int i;
4000 smb2_deltree(tree, BASEDIR);
4002 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
4003 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
4004 smb2_util_close(tree, testdirh);
4006 torture_comment(tctx, "Enabling AAPL\n");
4008 ret = enable_aapl(tctx, tree);
4009 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
4012 * Now that Requested AAPL extensions are enabled, setup some
4013 * Mac files with metadata and resource fork
4016 torture_comment(tctx, "Preparing file\n");
4018 ret = torture_setup_file(mem_ctx, tree, fname, false);
4019 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
4021 info = torture_afpinfo_new(mem_ctx);
4022 torture_assert_not_null_goto(tctx, info, ret, done, "torture_afpinfo_new failed");
4024 memcpy(info->afpi_FinderInfo, type_creator, 8);
4025 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
4026 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
4028 ret = write_stream(tree, __location__, tctx, mem_ctx,
4029 fname, AFPRESOURCE_STREAM_NAME,
4030 0, 3, "foo");
4031 torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4034 * Ok, file is prepared, now call smb2/find
4037 torture_comment(tctx, "Issue find\n");
4039 ZERO_STRUCT(io);
4040 io.in.desired_access = SEC_RIGHTS_DIR_READ;
4041 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
4042 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
4043 io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
4044 NTCREATEX_SHARE_ACCESS_WRITE |
4045 NTCREATEX_SHARE_ACCESS_DELETE);
4046 io.in.create_disposition = NTCREATEX_DISP_OPEN;
4047 io.in.fname = BASEDIR;
4048 status = smb2_create(tree, tctx, &io);
4049 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4051 ZERO_STRUCT(f);
4052 f.in.file.handle = io.out.file.handle;
4053 f.in.pattern = "*";
4054 f.in.max_response_size = 0x1000;
4055 f.in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
4057 status = smb2_find_level(tree, tree, &f, &count, &d);
4058 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_level failed");
4060 status = smb2_util_close(tree, io.out.file.handle);
4061 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close failed");
4063 torture_comment(tctx, "Checking find response with enriched macOS metadata\n");
4065 for (i = 0; i < count; i++) {
4066 const char *found = d[i].id_both_directory_info.name.s;
4068 if (!strcmp(found, ".") || !strcmp(found, ".."))
4069 continue;
4070 if (strncmp(found, "._", 2) == 0) {
4071 continue;
4073 break;
4076 torture_assert_str_equal_goto(tctx,
4077 d[i].id_both_directory_info.name.s, name,
4078 ret, done, "bad name");
4080 rfork_len = BVAL(d[i].id_both_directory_info.short_name_buf, 0);
4081 torture_assert_int_equal_goto(tctx, rfork_len, 3, ret, done, "bad resource fork length");
4083 torture_assert_mem_equal_goto(tctx, type_creator,
4084 d[i].id_both_directory_info.short_name_buf + 8,
4085 8, ret, done, "Bad FinderInfo");
4086 done:
4087 smb2_util_unlink(tree, fname);
4088 smb2_deltree(tree, BASEDIR);
4089 talloc_free(mem_ctx);
4090 return ret;
4093 static bool test_invalid_afpinfo(struct torture_context *tctx,
4094 struct smb2_tree *tree1,
4095 struct smb2_tree *tree2)
4097 const char *fname = "filtest_invalid_afpinfo";
4098 const char *sname = "filtest_invalid_afpinfo" AFPINFO_STREAM_NAME;
4099 struct smb2_create create;
4100 const char *streams_basic[] = {
4101 "::$DATA"
4103 const char *streams_afpinfo[] = {
4104 "::$DATA",
4105 AFPINFO_STREAM
4107 NTSTATUS status;
4108 bool ret = true;
4110 if (tree2 == NULL) {
4111 torture_skip_goto(tctx, done, "need second share without fruit\n");
4114 torture_comment(tctx, "Testing invalid AFP_AfpInfo stream\n");
4116 ret = torture_setup_file(tctx, tree2, fname, false);
4117 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4119 ret = write_stream(tree2, __location__, tctx, tctx,
4120 fname, AFPINFO_STREAM_NAME,
4121 0, 3, "foo");
4122 torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4124 ret = check_stream_list(tree2, tctx, fname, 2, streams_afpinfo, false);
4125 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4127 torture_comment(tctx, "Listing streams, bad AFPINFO stream must not be present\n");
4129 ret = check_stream_list(tree1, tctx, fname, 1, streams_basic, false);
4130 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4132 torture_comment(tctx, "Try to open AFPINFO stream, must fail\n");
4134 ZERO_STRUCT(create);
4135 create.in.desired_access = SEC_FILE_ALL;
4136 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4137 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4138 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4139 create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4140 create.in.fname = sname;
4142 status = smb2_create(tree1, tctx, &create);
4143 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4144 ret, done, "Stream still around?");
4146 done:
4147 smb2_util_unlink(tree1, fname);
4148 return ret;
4151 static bool test_zero_file_id(struct torture_context *tctx,
4152 struct smb2_tree *tree)
4154 const char *fname = "filtest_file_id";
4155 struct smb2_create create = {0};
4156 NTSTATUS status;
4157 bool ret = true;
4158 uint8_t zero_file_id[8] = {0};
4160 torture_comment(tctx, "Testing zero file id\n");
4162 ret = torture_setup_file(tctx, tree, fname, false);
4163 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4165 ZERO_STRUCT(create);
4166 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4167 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4168 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4169 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4170 create.in.fname = fname;
4171 create.in.query_on_disk_id = true;
4173 status = smb2_create(tree, tctx, &create);
4174 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
4175 done,
4176 "test file could not be opened");
4177 torture_assert_mem_not_equal_goto(tctx, create.out.on_disk_id,
4178 zero_file_id, 8, ret, done,
4179 "unexpected zero file id");
4181 smb2_util_close(tree, create.out.file.handle);
4183 ret = enable_aapl(tctx, tree);
4184 torture_assert(tctx, ret == true, "enable_aapl failed");
4186 ZERO_STRUCT(create);
4187 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4188 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4189 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4190 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4191 create.in.fname = fname;
4192 create.in.query_on_disk_id = true;
4194 status = smb2_create(tree, tctx, &create);
4195 torture_assert_ntstatus_equal_goto(
4196 tctx, status, NT_STATUS_OK, ret, done,
4197 "test file could not be opened with AAPL");
4198 torture_assert_mem_equal_goto(tctx, create.out.on_disk_id, zero_file_id,
4199 8, ret, done, "non-zero file id");
4201 smb2_util_close(tree, create.out.file.handle);
4203 done:
4204 smb2_util_unlink(tree, fname);
4205 return ret;
4208 static bool copy_one_stream(struct torture_context *torture,
4209 struct smb2_tree *tree,
4210 TALLOC_CTX *tmp_ctx,
4211 const char *src_sname,
4212 const char *dst_sname)
4214 struct smb2_handle src_h = {{0}};
4215 struct smb2_handle dest_h = {{0}};
4216 NTSTATUS status;
4217 union smb_ioctl io;
4218 struct srv_copychunk_copy cc_copy;
4219 struct srv_copychunk_rsp cc_rsp;
4220 enum ndr_err_code ndr_ret;
4221 bool ok = false;
4223 ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4224 1, /* 1 chunk */
4225 src_sname,
4226 &src_h, 256, /* fill 256 byte src file */
4227 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4228 dst_sname,
4229 &dest_h, 0, /* 0 byte dest file */
4230 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4231 &cc_copy,
4232 &io);
4233 torture_assert_goto(torture, ok == true, ok, done,
4234 "setup copy chunk error\n");
4236 /* copy all src file data (via a single chunk desc) */
4237 cc_copy.chunks[0].source_off = 0;
4238 cc_copy.chunks[0].target_off = 0;
4239 cc_copy.chunks[0].length = 256;
4241 ndr_ret = ndr_push_struct_blob(
4242 &io.smb2.in.out, tmp_ctx, &cc_copy,
4243 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4245 torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4246 "ndr_push_srv_copychunk_copy\n");
4248 status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4249 torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4250 "FSCTL_SRV_COPYCHUNK\n");
4252 ndr_ret = ndr_pull_struct_blob(
4253 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4254 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4256 torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4257 "ndr_pull_srv_copychunk_rsp\n");
4259 ok = check_copy_chunk_rsp(torture, &cc_rsp,
4260 1, /* chunks written */
4261 0, /* chunk bytes unsuccessfully written */
4262 256); /* total bytes written */
4263 torture_assert_goto(torture, ok == true, ok, done,
4264 "bad copy chunk response data\n");
4266 ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 256, 0);
4267 if (!ok) {
4268 torture_fail(torture, "inconsistent file data\n");
4271 done:
4272 if (!smb2_util_handle_empty(src_h)) {
4273 smb2_util_close(tree, src_h);
4275 if (!smb2_util_handle_empty(dest_h)) {
4276 smb2_util_close(tree, dest_h);
4279 return ok;
4282 static bool copy_finderinfo_stream(struct torture_context *torture,
4283 struct smb2_tree *tree,
4284 TALLOC_CTX *tmp_ctx,
4285 const char *src_name,
4286 const char *dst_name)
4288 struct smb2_handle src_h = {{0}};
4289 struct smb2_handle dest_h = {{0}};
4290 NTSTATUS status;
4291 union smb_ioctl io;
4292 struct srv_copychunk_copy cc_copy;
4293 struct srv_copychunk_rsp cc_rsp;
4294 enum ndr_err_code ndr_ret;
4295 const char *type_creator = "SMB,OLE!";
4296 AfpInfo *info = NULL;
4297 const char *src_name_afpinfo = NULL;
4298 const char *dst_name_afpinfo = NULL;
4299 bool ok = false;
4301 src_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", src_name,
4302 AFPINFO_STREAM);
4303 torture_assert_not_null_goto(torture, src_name_afpinfo, ok, done,
4304 "talloc_asprintf failed\n");
4306 dst_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", dst_name,
4307 AFPINFO_STREAM);
4308 torture_assert_not_null_goto(torture, dst_name_afpinfo, ok, done,
4309 "talloc_asprintf failed\n");
4311 info = torture_afpinfo_new(tmp_ctx);
4312 torture_assert_not_null_goto(torture, info, ok, done,
4313 "torture_afpinfo_new failed\n");
4315 memcpy(info->afpi_FinderInfo, type_creator, 8);
4316 ok = torture_write_afpinfo(tree, torture, tmp_ctx, src_name, info);
4317 torture_assert_goto(torture, ok == true, ok, done,
4318 "torture_write_afpinfo failed\n");
4320 ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4321 1, /* 1 chunk */
4322 src_name_afpinfo,
4323 &src_h, 0,
4324 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4325 dst_name_afpinfo,
4326 &dest_h, 0,
4327 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4328 &cc_copy,
4329 &io);
4330 torture_assert_goto(torture, ok == true, ok, done,
4331 "setup copy chunk error\n");
4333 /* copy all src file data (via a single chunk desc) */
4334 cc_copy.chunks[0].source_off = 0;
4335 cc_copy.chunks[0].target_off = 0;
4336 cc_copy.chunks[0].length = 60;
4338 ndr_ret = ndr_push_struct_blob(
4339 &io.smb2.in.out, tmp_ctx, &cc_copy,
4340 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4342 torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4343 "ndr_push_srv_copychunk_copy\n");
4345 status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4346 torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4347 "FSCTL_SRV_COPYCHUNK\n");
4349 ndr_ret = ndr_pull_struct_blob(
4350 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4351 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4353 torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4354 "ndr_pull_srv_copychunk_rsp\n");
4356 smb2_util_close(tree, src_h);
4357 ZERO_STRUCT(src_h);
4358 smb2_util_close(tree, dest_h);
4359 ZERO_STRUCT(dest_h);
4361 ok = check_copy_chunk_rsp(torture, &cc_rsp,
4362 1, /* chunks written */
4363 0, /* chunk bytes unsuccessfully written */
4364 60); /* total bytes written */
4365 torture_assert_goto(torture, ok == true, ok, done,
4366 "bad copy chunk response data\n");
4368 ok = check_stream(tree, __location__, torture, tmp_ctx,
4369 dst_name, AFPINFO_STREAM,
4370 0, 60, 16, 8, type_creator);
4371 torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
4373 done:
4374 if (!smb2_util_handle_empty(src_h)) {
4375 smb2_util_close(tree, src_h);
4377 if (!smb2_util_handle_empty(dest_h)) {
4378 smb2_util_close(tree, dest_h);
4381 return ok;
4384 static bool test_copy_chunk_streams(struct torture_context *torture,
4385 struct smb2_tree *tree)
4387 const char *src_name = "src";
4388 const char *dst_name = "dst";
4389 struct names {
4390 const char *src_sname;
4391 const char *dst_sname;
4392 } names[] = {
4393 { "src:foo", "dst:foo" },
4394 { "src" AFPRESOURCE_STREAM, "dst" AFPRESOURCE_STREAM }
4396 int i;
4397 TALLOC_CTX *tmp_ctx = NULL;
4398 bool ok = false;
4400 tmp_ctx = talloc_new(tree);
4401 torture_assert_not_null_goto(torture, tmp_ctx, ok, done,
4402 "torture_setup_file\n");
4404 smb2_util_unlink(tree, src_name);
4405 smb2_util_unlink(tree, dst_name);
4407 ok = torture_setup_file(torture, tree, src_name, false);
4408 torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
4409 ok = torture_setup_file(torture, tree, dst_name, false);
4410 torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
4412 for (i = 0; i < ARRAY_SIZE(names); i++) {
4413 ok = copy_one_stream(torture, tree, tmp_ctx,
4414 names[i].src_sname,
4415 names[i].dst_sname);
4416 torture_assert_goto(torture, ok == true, ok, done,
4417 "copy_one_stream failed\n");
4420 ok = copy_finderinfo_stream(torture, tree, tmp_ctx,
4421 src_name, dst_name);
4422 torture_assert_goto(torture, ok == true, ok, done,
4423 "copy_finderinfo_stream failed\n");
4425 done:
4426 smb2_util_unlink(tree, src_name);
4427 smb2_util_unlink(tree, dst_name);
4428 talloc_free(tmp_ctx);
4429 return ok;
4433 * Ensure this security descriptor has exactly one mode, uid
4434 * and gid.
4437 static NTSTATUS check_nfs_sd(const struct security_descriptor *psd)
4439 uint32_t i;
4440 bool got_one_mode = false;
4441 bool got_one_uid = false;
4442 bool got_one_gid = false;
4444 if (psd->dacl == NULL) {
4445 return NT_STATUS_INVALID_SECURITY_DESCR;
4448 for (i = 0; i < psd->dacl->num_aces; i++) {
4449 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Mode,
4450 &psd->dacl->aces[i].trustee) == 0) {
4451 if (got_one_mode == true) {
4452 /* Can't have more than one. */
4453 return NT_STATUS_INVALID_SECURITY_DESCR;
4455 got_one_mode = true;
4458 for (i = 0; i < psd->dacl->num_aces; i++) {
4459 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Users,
4460 &psd->dacl->aces[i].trustee) == 0) {
4461 if (got_one_uid == true) {
4462 /* Can't have more than one. */
4463 return NT_STATUS_INVALID_SECURITY_DESCR;
4465 got_one_uid = true;
4468 for (i = 0; i < psd->dacl->num_aces; i++) {
4469 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Groups,
4470 &psd->dacl->aces[i].trustee) == 0) {
4471 if (got_one_gid == true) {
4472 /* Can't have more than one. */
4473 return NT_STATUS_INVALID_SECURITY_DESCR;
4475 got_one_gid = true;
4478 /* Must have at least one of each. */
4479 if (got_one_mode == false ||
4480 got_one_uid == false ||
4481 got_one_gid == false) {
4482 return NT_STATUS_INVALID_SECURITY_DESCR;
4484 return NT_STATUS_OK;
4487 static bool test_nfs_aces(struct torture_context *tctx,
4488 struct smb2_tree *tree)
4490 TALLOC_CTX *mem_ctx = talloc_new(tctx);
4491 struct security_ace ace;
4492 struct dom_sid sid;
4493 const char *fname = BASEDIR "\\nfs_aces.txt";
4494 struct smb2_handle h = {{0}};
4495 union smb_fileinfo finfo2;
4496 union smb_setfileinfo set;
4497 struct security_descriptor *psd = NULL;
4498 NTSTATUS status;
4499 bool ret = true;
4501 ret = enable_aapl(tctx, tree);
4502 torture_assert(tctx, ret == true, "enable_aapl failed");
4504 /* clean slate ...*/
4505 smb2_util_unlink(tree, fname);
4506 smb2_deltree(tree, fname);
4507 smb2_deltree(tree, BASEDIR);
4509 status = torture_smb2_testdir(tree, BASEDIR, &h);
4510 CHECK_STATUS(status, NT_STATUS_OK);
4511 smb2_util_close(tree, h);
4513 /* Create a test file. */
4514 status = torture_smb2_testfile_access(tree,
4515 fname,
4517 SEC_STD_READ_CONTROL |
4518 SEC_STD_WRITE_DAC |
4519 SEC_RIGHTS_FILE_ALL);
4520 CHECK_STATUS(status, NT_STATUS_OK);
4522 /* Get the ACL. */
4523 finfo2.query_secdesc.in.secinfo_flags =
4524 SECINFO_OWNER |
4525 SECINFO_GROUP |
4526 SECINFO_DACL;
4527 finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
4528 finfo2.generic.in.file.handle = h;
4529 status = smb2_getinfo_file(tree, tctx, &finfo2);
4530 CHECK_STATUS(status, NT_STATUS_OK);
4532 psd = finfo2.query_secdesc.out.sd;
4534 /* Ensure we have only single mode/uid/gid NFS entries. */
4535 status = check_nfs_sd(psd);
4536 if (!NT_STATUS_IS_OK(status)) {
4537 NDR_PRINT_DEBUG(
4538 security_descriptor,
4539 discard_const_p(struct security_descriptor, psd));
4541 CHECK_STATUS(status, NT_STATUS_OK);
4543 /* Add a couple of extra NFS uids and gids. */
4544 sid_compose(&sid, &global_sid_Unix_NFS_Users, 27);
4545 init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
4546 status = security_descriptor_dacl_add(psd, &ace);
4547 CHECK_STATUS(status, NT_STATUS_OK);
4548 status = security_descriptor_dacl_add(psd, &ace);
4549 CHECK_STATUS(status, NT_STATUS_OK);
4551 sid_compose(&sid, &global_sid_Unix_NFS_Groups, 300);
4552 init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
4553 status = security_descriptor_dacl_add(psd, &ace);
4554 CHECK_STATUS(status, NT_STATUS_OK);
4555 status = security_descriptor_dacl_add(psd, &ace);
4556 CHECK_STATUS(status, NT_STATUS_OK);
4558 /* Now set on the file handle. */
4559 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
4560 set.set_secdesc.in.file.handle = h;
4561 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
4562 set.set_secdesc.in.sd = psd;
4563 status = smb2_setinfo_file(tree, &set);
4564 CHECK_STATUS(status, NT_STATUS_OK);
4566 /* Get the ACL again. */
4567 finfo2.query_secdesc.in.secinfo_flags =
4568 SECINFO_OWNER |
4569 SECINFO_GROUP |
4570 SECINFO_DACL;
4571 finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
4572 finfo2.generic.in.file.handle = h;
4573 status = smb2_getinfo_file(tree, tctx, &finfo2);
4574 CHECK_STATUS(status, NT_STATUS_OK);
4576 psd = finfo2.query_secdesc.out.sd;
4578 /* Ensure we have only single mode/uid/gid NFS entries. */
4579 status = check_nfs_sd(psd);
4580 if (!NT_STATUS_IS_OK(status)) {
4581 NDR_PRINT_DEBUG(
4582 security_descriptor,
4583 discard_const_p(struct security_descriptor, psd));
4585 CHECK_STATUS(status, NT_STATUS_OK);
4587 done:
4588 if (!smb2_util_handle_empty(h)) {
4589 smb2_util_close(tree, h);
4591 smb2_util_unlink(tree, fname);
4592 smb2_deltree(tree, fname);
4593 smb2_deltree(tree, BASEDIR);
4594 talloc_free(mem_ctx);
4595 return ret;
4599 * Note: This test depends on "vfs objects = catia fruit streams_xattr". For
4600 * some tests torture must be run on the host it tests and takes an additional
4601 * argument with the local path to the share:
4602 * "--option=torture:localdir=<SHAREPATH>".
4604 * When running against an OS X SMB server add "--option=torture:osx=true"
4606 struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx)
4608 struct torture_suite *suite = torture_suite_create(
4609 ctx, "fruit");
4611 suite->description = talloc_strdup(suite, "vfs_fruit tests");
4613 torture_suite_add_1smb2_test(suite, "copyfile", test_copyfile);
4614 torture_suite_add_1smb2_test(suite, "read metadata", test_read_afpinfo);
4615 torture_suite_add_1smb2_test(suite, "write metadata", test_write_atalk_metadata);
4616 torture_suite_add_1smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io);
4617 torture_suite_add_1smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl);
4618 torture_suite_add_1smb2_test(suite, "stream names", test_stream_names);
4619 torture_suite_add_1smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate);
4620 torture_suite_add_1smb2_test(suite, "opening and creating resource fork", test_rfork_create);
4621 torture_suite_add_1smb2_test(suite, "rename_dir_openfile", test_rename_dir_openfile);
4622 torture_suite_add_1smb2_test(suite, "File without AFP_AfpInfo", test_afpinfo_enoent);
4623 torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpInfo", test_create_delete_on_close);
4624 torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpInfo", test_setinfo_delete_on_close);
4625 torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpInfo", test_setinfo_eof);
4626 torture_suite_add_1smb2_test(suite, "delete AFP_AfpInfo by writing all 0", test_afpinfo_all0);
4627 torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpResource", test_create_delete_on_close_resource);
4628 torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpResource", test_setinfo_delete_on_close_resource);
4629 torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpResource", test_setinfo_eof_resource);
4630 torture_suite_add_1smb2_test(suite, "null afpinfo", test_null_afpinfo);
4631 torture_suite_add_1smb2_test(suite, "delete", test_delete_file_with_rfork);
4632 torture_suite_add_1smb2_test(suite, "read open rsrc after rename", test_rename_and_read_rsrc);
4633 torture_suite_add_1smb2_test(suite, "readdir_attr with names with illegal ntfs characters", test_readdir_attr_illegal_ntfs);
4634 torture_suite_add_2ns_smb2_test(suite, "invalid AFP_AfpInfo", test_invalid_afpinfo);
4635 torture_suite_add_1smb2_test(suite, "creating rsrc with read-only access", test_rfork_create_ro);
4636 torture_suite_add_1smb2_test(suite, "copy-chunk streams", test_copy_chunk_streams);
4637 torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
4638 torture_suite_add_1smb2_test(suite, "NFS ACE entries", test_nfs_aces);
4640 return suite;
4643 static bool test_stream_names_local(struct torture_context *tctx,
4644 struct smb2_tree *tree)
4646 TALLOC_CTX *mem_ctx = talloc_new(tctx);
4647 NTSTATUS status;
4648 struct smb2_create create;
4649 struct smb2_handle h;
4650 const char *fname = BASEDIR "\\stream_names.txt";
4651 const char *sname1;
4652 bool ret;
4653 /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
4654 const char *streams[] = {
4655 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
4656 ":bar" "\xef\x80\xa2" "baz:$DATA", /* "bar:baz:$DATA" */
4657 "::$DATA"
4659 const char *localdir = NULL;
4661 localdir = torture_setting_string(tctx, "localdir", NULL);
4662 if (localdir == NULL) {
4663 torture_skip(tctx, "Need localdir for test");
4666 sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
4668 /* clean slate ...*/
4669 smb2_util_unlink(tree, fname);
4670 smb2_deltree(tree, fname);
4671 smb2_deltree(tree, BASEDIR);
4673 status = torture_smb2_testdir(tree, BASEDIR, &h);
4674 CHECK_STATUS(status, NT_STATUS_OK);
4675 smb2_util_close(tree, h);
4677 torture_comment(tctx, "(%s) testing stream names\n", __location__);
4678 ZERO_STRUCT(create);
4679 create.in.desired_access = SEC_FILE_WRITE_DATA;
4680 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4681 create.in.share_access =
4682 NTCREATEX_SHARE_ACCESS_DELETE|
4683 NTCREATEX_SHARE_ACCESS_READ|
4684 NTCREATEX_SHARE_ACCESS_WRITE;
4685 create.in.create_disposition = NTCREATEX_DISP_CREATE;
4686 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
4687 create.in.fname = sname1;
4689 status = smb2_create(tree, mem_ctx, &create);
4690 CHECK_STATUS(status, NT_STATUS_OK);
4691 smb2_util_close(tree, create.out.file.handle);
4693 ret = torture_setup_local_xattr(tctx, "localdir", BASEDIR "/stream_names.txt",
4694 "user.DosStream.bar:baz:$DATA",
4695 "data", strlen("data"));
4696 CHECK_VALUE(ret, true);
4698 ret = check_stream_list(tree, tctx, fname, 3, streams, false);
4699 CHECK_VALUE(ret, true);
4701 done:
4702 status = smb2_util_unlink(tree, fname);
4703 smb2_deltree(tree, BASEDIR);
4704 talloc_free(mem_ctx);
4706 return ret;
4709 struct torture_suite *torture_vfs_fruit_netatalk(TALLOC_CTX *ctx)
4711 struct torture_suite *suite = torture_suite_create(
4712 ctx, "fruit_netatalk");
4714 suite->description = talloc_strdup(suite, "vfs_fruit tests for Netatalk interop that require fruit:metadata=netatalk");
4716 torture_suite_add_1smb2_test(suite, "read netatalk metadata", test_read_netatalk_metadata);
4717 torture_suite_add_1smb2_test(suite, "stream names with locally created xattr", test_stream_names_local);
4719 return suite;
4722 struct torture_suite *torture_vfs_fruit_file_id(TALLOC_CTX *ctx)
4724 struct torture_suite *suite =
4725 torture_suite_create(ctx, "fruit_file_id");
4727 suite->description =
4728 talloc_strdup(suite, "vfs_fruit tests for on-disk file ID that "
4729 "require fruit:zero_file_id=yes");
4731 torture_suite_add_1smb2_test(suite, "zero file id if AAPL negotiated",
4732 test_zero_file_id);
4734 return suite;
4737 static bool test_timemachine_volsize(struct torture_context *tctx,
4738 struct smb2_tree *tree)
4740 TALLOC_CTX *mem_ctx = talloc_new(tctx);
4741 struct smb2_handle h = {{0}};
4742 union smb_fsinfo fsinfo;
4743 NTSTATUS status;
4744 bool ok = true;
4745 const char *info_plist =
4746 "<dict>\n"
4747 " <key>band-size</key>\n"
4748 " <integer>8192</integer>\n"
4749 "</dict>\n";
4751 smb2_deltree(tree, "test.sparsebundle");
4753 ok = enable_aapl(tctx, tree);
4754 torture_assert_goto(tctx, ok, ok, done, "enable_aapl failed");
4756 status = smb2_util_mkdir(tree, "test.sparsebundle");
4757 torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
4758 "smb2_util_mkdir\n");
4760 ok = write_stream(tree, __location__, tctx, mem_ctx,
4761 "test.sparsebundle/Info.plist", NULL,
4762 0, strlen(info_plist), info_plist);
4763 torture_assert_goto(tctx, ok, ok, done, "write_stream failed\n");
4765 status = smb2_util_mkdir(tree, "test.sparsebundle/bands");
4766 torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
4767 "smb2_util_mkdir\n");
4769 ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/1", false);
4770 torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
4772 ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/2", false);
4773 torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
4775 status = smb2_util_roothandle(tree, &h);
4776 torture_assert_ntstatus_ok(tctx, status, "Unable to create root handle");
4778 ZERO_STRUCT(fsinfo);
4779 fsinfo.generic.level = RAW_QFS_SIZE_INFORMATION;
4780 fsinfo.generic.handle = h;
4782 status = smb2_getinfo_fs(tree, tree, &fsinfo);
4783 torture_assert_ntstatus_ok(tctx, status, "smb2_getinfo_fs failed");
4785 torture_comment(tctx, "sectors_per_unit: %" PRIu32"\n"
4786 "bytes_per_sector: %" PRIu32"\n"
4787 "total_alloc_units: %" PRIu64"\n"
4788 "avail_alloc_units: %" PRIu64"\n",
4789 fsinfo.size_info.out.sectors_per_unit,
4790 fsinfo.size_info.out.bytes_per_sector,
4791 fsinfo.size_info.out.total_alloc_units,
4792 fsinfo.size_info.out.avail_alloc_units);
4795 * Let me explain the numbers:
4797 * - the share is set to "fruit:time machine max size = 32K"
4798 * - we've faked a bandsize of 8 K in the Info.plist file
4799 * - we've created two bands files
4800 * - one allocation unit is made of two sectors with 512 B each
4801 * => we've consumed 16 allocation units, there should be 16 free
4804 torture_assert_goto(tctx, fsinfo.size_info.out.sectors_per_unit == 2,
4805 ok, done, "Bad sectors_per_unit");
4807 torture_assert_goto(tctx, fsinfo.size_info.out.bytes_per_sector == 512,
4808 ok, done, "Bad bytes_per_sector");
4810 torture_assert_goto(tctx, fsinfo.size_info.out.total_alloc_units == 32,
4811 ok, done, "Bad total_alloc_units");
4813 torture_assert_goto(tctx, fsinfo.size_info.out.avail_alloc_units == 16,
4814 ok, done, "Bad avail_alloc_units");
4816 done:
4817 if (!smb2_util_handle_empty(h)) {
4818 smb2_util_close(tree, h);
4820 smb2_deltree(tree, "test.sparsebundle");
4821 talloc_free(mem_ctx);
4822 return ok;
4825 struct torture_suite *torture_vfs_fruit_timemachine(TALLOC_CTX *ctx)
4827 struct torture_suite *suite = torture_suite_create(
4828 ctx, "fruit_timemachine");
4830 suite->description = talloc_strdup(
4831 suite, "vfs_fruit tests for TimeMachine");
4833 torture_suite_add_1smb2_test(suite, "Timemachine-volsize",
4834 test_timemachine_volsize);
4836 return suite;