22918d39ccdc78210d3e83cfae550d4136223d15
[samba.git] / source3 / torture / test_smb2.c
1 /*
2    Unix SMB/CIFS implementation.
3    Initial test for the smb2 client lib
4    Copyright (C) Volker Lendecke 2011
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "torture/proto.h"
22 #include "client.h"
23 #include "trans2.h"
24 #include "../libcli/smb/smbXcli_base.h"
25 #include "libcli/security/security.h"
26 #include "libsmb/proto.h"
27 #include "auth/credentials/credentials.h"
28 #include "auth/gensec/gensec.h"
29 #include "auth_generic.h"
30 #include "../librpc/ndr/libndr.h"
31 #include "libsmb/clirap.h"
32 #include "libsmb/cli_smb2_fnum.h"
33
34 extern fstring host, workgroup, share, password, username, myname;
35 extern struct cli_credentials *torture_creds;
36
37 bool run_smb2_basic(int dummy)
38 {
39         struct cli_state *cli;
40         NTSTATUS status;
41         uint64_t fid_persistent, fid_volatile;
42         const char *hello = "Hello, world\n";
43         uint8_t *result;
44         uint32_t nread;
45         uint8_t *dir_data;
46         uint32_t dir_data_length;
47         uint32_t saved_tid = 0;
48         struct smbXcli_tcon *saved_tcon = NULL;
49         char *saved_share = NULL;
50         uint64_t saved_uid = 0;
51
52         printf("Starting SMB2-BASIC\n");
53
54         if (!torture_init_connection(&cli)) {
55                 return false;
56         }
57
58         status = smbXcli_negprot(cli->conn, cli->timeout,
59                                  PROTOCOL_SMB2_02, PROTOCOL_SMB2_02);
60         if (!NT_STATUS_IS_OK(status)) {
61                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
62                 return false;
63         }
64
65         status = cli_session_setup_creds(cli, torture_creds);
66         if (!NT_STATUS_IS_OK(status)) {
67                 printf("cli_session_setup returned %s\n", nt_errstr(status));
68                 return false;
69         }
70
71         status = cli_tree_connect(cli, share, "?????", NULL);
72         if (!NT_STATUS_IS_OK(status)) {
73                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
74                 return false;
75         }
76
77         status = smb2cli_create(
78                 cli->conn,
79                 cli->timeout,
80                 cli->smb2.session,
81                 cli->smb2.tcon,
82                 "smb2-basic.txt",
83                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
84                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
85                 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
86                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
87                 FILE_SHARE_READ|
88                 FILE_SHARE_WRITE|
89                 FILE_SHARE_DELETE, /* share_access, */
90                 FILE_CREATE, /* create_disposition, */
91                 FILE_DELETE_ON_CLOSE, /* create_options, */
92                 NULL, /* smb2_create_blobs *blobs */
93                 &fid_persistent,
94                 &fid_volatile,
95                 NULL,
96                 NULL,
97                 NULL,
98                 NULL);
99         if (!NT_STATUS_IS_OK(status)) {
100                 printf("smb2cli_create returned %s\n", nt_errstr(status));
101                 return false;
102         }
103
104         status = smb2cli_write(cli->conn, cli->timeout, cli->smb2.session,
105                                cli->smb2.tcon, strlen(hello), 0, fid_persistent,
106                                fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
107         if (!NT_STATUS_IS_OK(status)) {
108                 printf("smb2cli_write returned %s\n", nt_errstr(status));
109                 return false;
110         }
111
112         status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
113                                cli->smb2.tcon, fid_persistent, fid_volatile);
114         if (!NT_STATUS_IS_OK(status)) {
115                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
116                 return false;
117         }
118
119         status = smb2cli_read(cli->conn, cli->timeout, cli->smb2.session,
120                               cli->smb2.tcon, 0x10000, 0, fid_persistent,
121                               fid_volatile, 2, 0,
122                               talloc_tos(), &result, &nread);
123         if (!NT_STATUS_IS_OK(status)) {
124                 printf("smb2cli_read returned %s\n", nt_errstr(status));
125                 return false;
126         }
127
128         if (nread != strlen(hello)) {
129                 printf("smb2cli_read returned %d bytes, expected %d\n",
130                        (int)nread, (int)strlen(hello));
131                 return false;
132         }
133
134         if (memcmp(hello, result, nread) != 0) {
135                 printf("smb2cli_read returned '%s', expected '%s'\n",
136                        result, hello);
137                 return false;
138         }
139
140         status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
141                                cli->smb2.tcon, 0, fid_persistent, fid_volatile);
142         if (!NT_STATUS_IS_OK(status)) {
143                 printf("smb2cli_close returned %s\n", nt_errstr(status));
144                 return false;
145         }
146
147         status = smb2cli_create(
148                 cli->conn,
149                 cli->timeout,
150                 cli->smb2.session,
151                 cli->smb2.tcon,
152                 "",
153                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
154                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
155                 SEC_STD_SYNCHRONIZE|
156                 SEC_DIR_LIST|
157                 SEC_DIR_READ_ATTRIBUTE, /* desired_access, */
158                 0, /* file_attributes, */
159                 FILE_SHARE_READ|
160                 FILE_SHARE_WRITE|
161                 FILE_SHARE_DELETE, /* share_access, */
162                 FILE_OPEN, /* create_disposition, */
163                 FILE_SYNCHRONOUS_IO_NONALERT|
164                 FILE_DIRECTORY_FILE, /* create_options, */
165                 NULL, /* smb2_create_blobs *blobs */
166                 &fid_persistent,
167                 &fid_volatile,
168                 NULL,
169                 NULL,
170                 NULL,
171                 NULL);
172         if (!NT_STATUS_IS_OK(status)) {
173                 printf("smb2cli_create returned %s\n", nt_errstr(status));
174                 return false;
175         }
176
177         status = smb2cli_query_directory(
178                 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
179                 1, 0, 0, fid_persistent, fid_volatile, "*", 0xffff,
180                 talloc_tos(), &dir_data, &dir_data_length);
181
182         if (!NT_STATUS_IS_OK(status)) {
183                 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
184                 return false;
185         }
186
187         status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
188                                cli->smb2.tcon, 0, fid_persistent, fid_volatile);
189         if (!NT_STATUS_IS_OK(status)) {
190                 printf("smb2cli_close returned %s\n", nt_errstr(status));
191                 return false;
192         }
193
194         saved_tid = smb2cli_tcon_current_id(cli->smb2.tcon);
195         cli_state_save_tcon_share(cli, &saved_tcon, &saved_share);
196         cli->smb2.tcon = smbXcli_tcon_create(cli);
197         smb2cli_tcon_set_values(cli->smb2.tcon,
198                                 NULL, /* session */
199                                 saved_tid,
200                                 0, /* type */
201                                 0, /* flags */
202                                 0, /* capabilities */
203                                 0  /* maximal_access */);
204         status = smb2cli_tdis(cli->conn,
205                               cli->timeout,
206                               cli->smb2.session,
207                               cli->smb2.tcon);
208         cli_state_restore_tcon_share(cli, saved_tcon, saved_share);
209         if (!NT_STATUS_IS_OK(status)) {
210                 printf("smb2cli_tdis returned %s\n", nt_errstr(status));
211                 return false;
212         }
213
214         status = smb2cli_tdis(cli->conn,
215                               cli->timeout,
216                               cli->smb2.session,
217                               cli->smb2.tcon);
218         if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) {
219                 printf("2nd smb2cli_tdis returned %s\n", nt_errstr(status));
220                 return false;
221         }
222
223         saved_uid = smb2cli_session_current_id(cli->smb2.session);
224         status = smb2cli_logoff(cli->conn, cli->timeout, cli->smb2.session);
225         if (!NT_STATUS_IS_OK(status)) {
226                 printf("smb2cli_logoff returned %s\n", nt_errstr(status));
227                 return false;
228         }
229
230         cli->smb2.session = smbXcli_session_create(cli, cli->conn);
231         if (cli->smb2.session == NULL) {
232                 printf("smbXcli_session_create() returned NULL\n");
233                 return false;
234         }
235
236         smb2cli_session_set_id_and_flags(cli->smb2.session, saved_uid, 0);
237
238         status = smb2cli_logoff(cli->conn, cli->timeout, cli->smb2.session);
239         if (!NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
240                 printf("2nd smb2cli_logoff returned %s\n", nt_errstr(status));
241                 return false;
242         }
243
244         return true;
245 }
246
247 bool run_smb2_negprot(int dummy)
248 {
249         struct cli_state *cli;
250         NTSTATUS status;
251         enum protocol_types protocol;
252         const char *name = NULL;
253
254         printf("Starting SMB2-NEGPROT\n");
255
256         if (!torture_init_connection(&cli)) {
257                 return false;
258         }
259
260         status = smbXcli_negprot(cli->conn, cli->timeout,
261                                  PROTOCOL_CORE, PROTOCOL_LATEST);
262         if (!NT_STATUS_IS_OK(status)) {
263                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
264                 return false;
265         }
266
267         protocol = smbXcli_conn_protocol(cli->conn);
268         name = smb_protocol_types_string(protocol);
269
270         if (protocol >= PROTOCOL_SMB2_02) {
271                 printf("Server supports %s\n", name);
272         } else {
273                 printf("Server DOES NOT support SMB2, only %s\n", name);
274                 return false;
275         }
276
277         status = smbXcli_negprot(cli->conn, cli->timeout,
278                                  protocol, protocol);
279         if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET) &&
280             !NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_DISCONNECTED) &&
281             !NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_ABORTED)) {
282                 printf("2nd smbXcli_negprot should disconnect - returned %s\n",
283                         nt_errstr(status));
284                 return false;
285         }
286
287         if (smbXcli_conn_is_connected(cli->conn)) {
288                 printf("2nd smbXcli_negprot should disconnect "
289                        "- still connected\n");
290                 return false;
291         }
292
293         return true;
294 }
295
296 bool run_smb2_anonymous(int dummy)
297 {
298         struct cli_state *cli = NULL;
299         NTSTATUS status;
300         struct cli_credentials *anon_creds = NULL;
301         bool guest = false;
302
303         printf("Starting SMB2-ANONYMOUS\n");
304
305         if (!torture_init_connection(&cli)) {
306                 return false;
307         }
308
309         status = smbXcli_negprot(cli->conn, cli->timeout,
310                                  PROTOCOL_SMB2_02, PROTOCOL_LATEST);
311         if (!NT_STATUS_IS_OK(status)) {
312                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
313                 return false;
314         }
315
316         anon_creds = cli_credentials_init_anon(talloc_tos());
317         if (anon_creds == NULL) {
318                 printf("cli_credentials_init_anon failed\n");
319                 return false;
320         }
321
322         status = cli_session_setup_creds(cli, anon_creds);
323         if (!NT_STATUS_IS_OK(status)) {
324                 printf("cli_session_setup returned %s\n", nt_errstr(status));
325                 return false;
326         }
327
328         guest = smbXcli_session_is_guest(cli->smb2.session);
329         if (guest) {
330                 printf("anonymous session should not have guest authentication\n");
331                 return false;
332         }
333
334         return true;
335 }
336
337 bool run_smb2_session_reconnect(int dummy)
338 {
339         struct cli_state *cli1;
340         struct cli_state *cli2;
341         NTSTATUS status;
342         bool ok;
343         uint64_t fid_persistent, fid_volatile;
344         struct tevent_context *ev;
345         struct tevent_req *subreq;
346         DATA_BLOB in_blob = data_blob_null;
347         DATA_BLOB out_blob;
348         DATA_BLOB session_key;
349         struct auth_generic_state *auth_generic_state;
350         struct iovec *recv_iov;
351         const char *hello = "Hello, world\n";
352         uint8_t *result;
353         uint32_t nread;
354
355         printf("Starting SMB2-SESSION-RECONNECT\n");
356
357         if (!torture_init_connection(&cli1)) {
358                 return false;
359         }
360
361         status = smbXcli_negprot(cli1->conn, cli1->timeout,
362                                  PROTOCOL_SMB2_02, PROTOCOL_LATEST);
363         if (!NT_STATUS_IS_OK(status)) {
364                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
365                 return false;
366         }
367
368         status = cli_session_setup_creds(cli1, torture_creds);
369         if (!NT_STATUS_IS_OK(status)) {
370                 printf("cli_session_setup returned %s\n", nt_errstr(status));
371                 return false;
372         }
373
374         status = cli_tree_connect(cli1, share, "?????", NULL);
375         if (!NT_STATUS_IS_OK(status)) {
376                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
377                 return false;
378         }
379
380         status = smb2cli_create(
381                 cli1->conn,
382                 cli1->timeout,
383                 cli1->smb2.session,
384                 cli1->smb2.tcon,
385                 "session-reconnect.txt",
386                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
387                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
388                 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
389                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
390                 FILE_SHARE_READ|
391                 FILE_SHARE_WRITE|
392                 FILE_SHARE_DELETE, /* share_access, */
393                 FILE_CREATE, /* create_disposition, */
394                 FILE_DELETE_ON_CLOSE, /* create_options, */
395                 NULL, /* smb2_create_blobs *blobs */
396                 &fid_persistent,
397                 &fid_volatile,
398                 NULL,
399                 NULL,
400                 NULL,
401                 NULL);
402         if (!NT_STATUS_IS_OK(status)) {
403                 printf("smb2cli_create on cli1 %s\n", nt_errstr(status));
404                 return false;
405         }
406
407         status = smb2cli_write(cli1->conn, cli1->timeout, cli1->smb2.session,
408                                cli1->smb2.tcon, strlen(hello), 0, fid_persistent,
409                                fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
410         if (!NT_STATUS_IS_OK(status)) {
411                 printf("smb2cli_write returned %s\n", nt_errstr(status));
412                 return false;
413         }
414
415         status = smb2cli_flush(cli1->conn, cli1->timeout, cli1->smb2.session,
416                                cli1->smb2.tcon, fid_persistent, fid_volatile);
417         if (!NT_STATUS_IS_OK(status)) {
418                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
419                 return false;
420         }
421
422         status = smb2cli_read(cli1->conn, cli1->timeout, cli1->smb2.session,
423                               cli1->smb2.tcon, 0x10000, 0, fid_persistent,
424                               fid_volatile, 2, 0,
425                               talloc_tos(), &result, &nread);
426         if (!NT_STATUS_IS_OK(status)) {
427                 printf("smb2cli_read returned %s\n", nt_errstr(status));
428                 return false;
429         }
430
431         if (nread != strlen(hello)) {
432                 printf("smb2cli_read returned %d bytes, expected %d\n",
433                        (int)nread, (int)strlen(hello));
434                 return false;
435         }
436
437         if (memcmp(hello, result, nread) != 0) {
438                 printf("smb2cli_read returned '%s', expected '%s'\n",
439                        result, hello);
440                 return false;
441         }
442
443         /* prepare second session */
444
445         if (!torture_init_connection(&cli2)) {
446                 return false;
447         }
448
449         status = smbXcli_negprot(cli2->conn, cli2->timeout,
450                                  PROTOCOL_SMB2_02, PROTOCOL_LATEST);
451         if (!NT_STATUS_IS_OK(status)) {
452                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
453                 return false;
454         }
455
456         status = auth_generic_client_prepare(talloc_tos(), &auth_generic_state);
457         if (!NT_STATUS_IS_OK(status)) {
458                 printf("auth_generic_client_prepare returned %s\n", nt_errstr(status));
459                 return false;
460         }
461
462         gensec_want_feature(auth_generic_state->gensec_security,
463                             GENSEC_FEATURE_SESSION_KEY);
464
465         status = auth_generic_set_creds(auth_generic_state, torture_creds);
466         if (!NT_STATUS_IS_OK(status)) {
467                 printf("auth_generic_set_creds returned %s\n", nt_errstr(status));
468                 return false;
469         }
470
471         status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
472         if (!NT_STATUS_IS_OK(status)) {
473                 printf("auth_generic_client_start returned %s\n", nt_errstr(status));
474                 return false;
475         }
476
477         ev = samba_tevent_context_init(talloc_tos());
478         if (ev == NULL) {
479                 printf("samba_tevent_context_init() returned NULL\n");
480                 return false;
481         }
482
483         status = gensec_update(auth_generic_state->gensec_security,
484                                talloc_tos(), data_blob_null, &in_blob);
485         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
486                 printf("gensec_update returned %s\n", nt_errstr(status));
487                 return false;
488         }
489
490         cli2->smb2.session = smbXcli_session_create(cli2, cli2->conn);
491
492         subreq = smb2cli_session_setup_send(talloc_tos(), ev,
493                                             cli2->conn,
494                                             cli2->timeout,
495                                             cli2->smb2.session,
496                                             0x0, /* in_flags */
497                                             SMB2_CAP_DFS, /* in_capabilities */
498                                             0, /* in_channel */
499                                             /* in_previous_session_id: */
500                                             smb2cli_session_current_id(cli1->smb2.session),
501                                             &in_blob); /* in_security_buffer */
502         if (subreq == NULL) {
503                 printf("smb2cli_session_setup_send() returned NULL\n");
504                 return false;
505         }
506
507         ok = tevent_req_poll(subreq, ev);
508         if (!ok) {
509                 printf("tevent_req_poll() returned false\n");
510                 return false;
511         }
512
513         status = smb2cli_session_setup_recv(subreq, talloc_tos(),
514                                             NULL, &out_blob);
515         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
516                 printf("smb2cli_session_setup_recv returned %s\n",
517                         nt_errstr(status));
518                 return false;
519         }
520
521         status = gensec_update(auth_generic_state->gensec_security,
522                                talloc_tos(), out_blob, &in_blob);
523         if (!NT_STATUS_IS_OK(status)) {
524                 printf("auth_generic_update returned %s\n", nt_errstr(status));
525                 return false;
526         }
527
528         subreq = smb2cli_session_setup_send(talloc_tos(), ev,
529                                             cli2->conn,
530                                             cli2->timeout,
531                                             cli2->smb2.session,
532                                             0x0, /* in_flags */
533                                             SMB2_CAP_DFS, /* in_capabilities */
534                                             0, /* in_channel */
535                                             /* in_previous_session_id: */
536                                             smb2cli_session_current_id(cli1->smb2.session),
537                                             &in_blob); /* in_security_buffer */
538         if (subreq == NULL) {
539                 printf("smb2cli_session_setup_send() returned NULL\n");
540                 return false;
541         }
542
543         ok = tevent_req_poll(subreq, ev);
544         if (!ok) {
545                 printf("tevent_req_poll() returned false\n");
546                 return false;
547         }
548
549         status = smb2cli_session_setup_recv(subreq, talloc_tos(),
550                                             &recv_iov, &out_blob);
551         if (!NT_STATUS_IS_OK(status)) {
552                 printf("smb2cli_session_setup_recv returned %s\n",
553                         nt_errstr(status));
554                 return false;
555         }
556
557         status = gensec_session_key(auth_generic_state->gensec_security, talloc_tos(),
558                                     &session_key);
559         if (!NT_STATUS_IS_OK(status)) {
560                 printf("gensec_session_key returned %s\n",
561                         nt_errstr(status));
562                 return false;
563         }
564
565         /* check file operation on the old client */
566
567         status = smb2cli_flush(cli1->conn, cli1->timeout, cli1->smb2.session,
568                                cli1->smb2.tcon, fid_persistent, fid_volatile);
569         if (!NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
570                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
571                 return false;
572         }
573
574         status = cli_tree_connect(cli1, share, "?????", NULL);
575         if (!NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
576                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
577                 return false;
578         }
579
580         /*
581          * checking file operations without signing.
582          * on w2k8r2 at least, flush, read and write also work the same way,
583          * while create gives ACCESS_DENIED without signing
584          */
585         status = smb2cli_flush(cli2->conn, cli2->timeout, cli2->smb2.session,
586                                cli2->smb2.tcon, fid_persistent, fid_volatile);
587         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) &&
588             !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
589         {
590                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
591                 return false;
592         }
593
594         status = smb2cli_write(cli2->conn, cli2->timeout, cli2->smb2.session,
595                                cli2->smb2.tcon, strlen(hello), 0, fid_persistent,
596                                fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
597         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) &&
598             !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
599         {
600                 printf("smb2cli_write returned %s\n", nt_errstr(status));
601                 return false;
602         }
603
604         status = smb2cli_read(cli2->conn, cli2->timeout, cli2->smb2.session,
605                               cli2->smb2.tcon, 0x10000, 0, fid_persistent,
606                               fid_volatile, 2, 0,
607                               talloc_tos(), &result, &nread);
608         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) &&
609             !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
610         {
611                 printf("smb2cli_read returned %s\n", nt_errstr(status));
612                 return false;
613         }
614
615         status = smb2cli_create(
616                 cli2->conn,
617                 cli2->timeout,
618                 cli2->smb2.session,
619                 cli2->smb2.tcon,
620                 "session-reconnect.txt",
621                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
622                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
623                 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
624                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
625                 FILE_SHARE_READ|
626                 FILE_SHARE_WRITE|
627                 FILE_SHARE_DELETE, /* share_access, */
628                 FILE_CREATE, /* create_disposition, */
629                 FILE_DELETE_ON_CLOSE, /* create_options, */
630                 NULL, /* smb2_create_blobs *blobs */
631                 &fid_persistent,
632                 &fid_volatile,
633                 NULL,
634                 NULL,
635                 NULL,
636                 NULL);
637         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
638             !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) {
639                 printf("smb2cli_create on cli2 %s\n", nt_errstr(status));
640                 return false;
641         }
642
643         /* now grab the session key and try with signing */
644
645         status = smb2cli_session_set_session_key(cli2->smb2.session,
646                                                  session_key,
647                                                  recv_iov);
648         if (!NT_STATUS_IS_OK(status)) {
649                 printf("smb2cli_session_set_session_key %s\n", nt_errstr(status));
650                 return false;
651         }
652
653         /* the tid seems to be irrelevant at this stage */
654
655         status = smb2cli_flush(cli2->conn, cli2->timeout, cli2->smb2.session,
656                                cli1->smb2.tcon, fid_persistent, fid_volatile);
657         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) &&
658             !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
659         {
660                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
661                 return false;
662         }
663
664         status = smb2cli_write(cli2->conn, cli2->timeout, cli2->smb2.session,
665                                cli1->smb2.tcon, strlen(hello), 0, fid_persistent,
666                                fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
667         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) &&
668             !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
669         {
670                 printf("smb2cli_write returned %s\n", nt_errstr(status));
671                 return false;
672         }
673
674         status = smb2cli_read(cli2->conn, cli2->timeout, cli2->smb2.session,
675                               cli1->smb2.tcon, 0x10000, 0, fid_persistent,
676                               fid_volatile, 2, 0,
677                               talloc_tos(), &result, &nread);
678         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) &&
679             !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
680         {
681                 printf("smb2cli_read returned %s\n", nt_errstr(status));
682                 return false;
683         }
684
685         status = smb2cli_create(
686                 cli2->conn,
687                 cli2->timeout,
688                 cli2->smb2.session,
689                 cli1->smb2.tcon,
690                 "session-reconnect.txt",
691                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
692                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
693                 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
694                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
695                 FILE_SHARE_READ|
696                 FILE_SHARE_WRITE|
697                 FILE_SHARE_DELETE, /* share_access, */
698                 FILE_CREATE, /* create_disposition, */
699                 FILE_DELETE_ON_CLOSE, /* create_options, */
700                 NULL, /* smb2_create_blobs *blobs */
701                 &fid_persistent,
702                 &fid_volatile,
703                 NULL,
704                 NULL,
705                 NULL,
706                 NULL);
707         if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED) &&
708             !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
709         {
710                 printf("smb2cli_create on cli2 %s\n", nt_errstr(status));
711                 return false;
712         }
713
714         /* now do a new tcon and test file calls again */
715
716         status = cli_tree_connect(cli2, share, "?????", NULL);
717         if (!NT_STATUS_IS_OK(status)) {
718                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
719                 return false;
720         }
721
722         status = smb2cli_create(
723                 cli2->conn,
724                 cli2->timeout,
725                 cli2->smb2.session,
726                 cli2->smb2.tcon,
727                 "session-reconnect.txt",
728                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
729                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
730                 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
731                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
732                 FILE_SHARE_READ|
733                 FILE_SHARE_WRITE|
734                 FILE_SHARE_DELETE, /* share_access, */
735                 FILE_CREATE, /* create_disposition, */
736                 FILE_DELETE_ON_CLOSE, /* create_options, */
737                 NULL, /* smb2_create_blobs *blobs */
738                 &fid_persistent,
739                 &fid_volatile,
740                 NULL,
741                 NULL,
742                 NULL,
743                 NULL);
744         if (!NT_STATUS_IS_OK(status)) {
745                 printf("smb2cli_create on cli2 %s\n", nt_errstr(status));
746                 return false;
747         }
748
749         status = smb2cli_write(cli2->conn, cli2->timeout, cli2->smb2.session,
750                                cli2->smb2.tcon, strlen(hello), 0, fid_persistent,
751                                fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
752         if (!NT_STATUS_IS_OK(status)) {
753                 printf("smb2cli_write returned %s\n", nt_errstr(status));
754                 return false;
755         }
756
757         status = smb2cli_flush(cli2->conn, cli2->timeout, cli2->smb2.session,
758                                cli2->smb2.tcon, fid_persistent, fid_volatile);
759         if (!NT_STATUS_IS_OK(status)) {
760                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
761                 return false;
762         }
763
764         status = smb2cli_read(cli2->conn, cli2->timeout, cli2->smb2.session,
765                               cli2->smb2.tcon, 0x10000, 0, fid_persistent,
766                               fid_volatile, 2, 0,
767                               talloc_tos(), &result, &nread);
768         if (!NT_STATUS_IS_OK(status)) {
769                 printf("smb2cli_read returned %s\n", nt_errstr(status));
770                 return false;
771         }
772
773         if (nread != strlen(hello)) {
774                 printf("smb2cli_read returned %d bytes, expected %d\n",
775                        (int)nread, (int)strlen(hello));
776                 return false;
777         }
778
779         if (memcmp(hello, result, nread) != 0) {
780                 printf("smb2cli_read returned '%s', expected '%s'\n",
781                        result, hello);
782                 return false;
783         }
784
785         return true;
786 }
787
788 bool run_smb2_tcon_dependence(int dummy)
789 {
790         struct cli_state *cli;
791         NTSTATUS status;
792         uint64_t fid_persistent, fid_volatile;
793         const char *hello = "Hello, world\n";
794         uint8_t *result;
795         uint32_t nread;
796         struct smbXcli_tcon *tcon2;
797         uint32_t tcon2_id;
798
799         printf("Starting SMB2-TCON-DEPENDENCE\n");
800
801         if (!torture_init_connection(&cli)) {
802                 return false;
803         }
804
805         status = smbXcli_negprot(cli->conn, cli->timeout,
806                                  PROTOCOL_SMB2_02, PROTOCOL_LATEST);
807         if (!NT_STATUS_IS_OK(status)) {
808                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
809                 return false;
810         }
811
812         status = cli_session_setup_creds(cli, torture_creds);
813         if (!NT_STATUS_IS_OK(status)) {
814                 printf("cli_session_setup returned %s\n", nt_errstr(status));
815                 return false;
816         }
817
818         status = cli_tree_connect(cli, share, "?????", NULL);
819         if (!NT_STATUS_IS_OK(status)) {
820                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
821                 return false;
822         }
823
824         status = smb2cli_create(
825                 cli->conn,
826                 cli->timeout,
827                 cli->smb2.session,
828                 cli->smb2.tcon,
829                 "tcon_depedence.txt",
830                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
831                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
832                 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
833                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
834                 FILE_SHARE_READ|
835                 FILE_SHARE_WRITE|
836                 FILE_SHARE_DELETE, /* share_access, */
837                 FILE_CREATE, /* create_disposition, */
838                 FILE_DELETE_ON_CLOSE, /* create_options, */
839                 NULL, /* smb2_create_blobs *blobs */
840                 &fid_persistent,
841                 &fid_volatile,
842                 NULL,
843                 NULL,
844                 NULL,
845                 NULL);
846         if (!NT_STATUS_IS_OK(status)) {
847                 printf("smb2cli_create on cli %s\n", nt_errstr(status));
848                 return false;
849         }
850
851         status = smb2cli_write(cli->conn, cli->timeout, cli->smb2.session,
852                                cli->smb2.tcon, strlen(hello), 0, fid_persistent,
853                                fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
854         if (!NT_STATUS_IS_OK(status)) {
855                 printf("smb2cli_write returned %s\n", nt_errstr(status));
856                 return false;
857         }
858
859         status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
860                                cli->smb2.tcon, fid_persistent, fid_volatile);
861         if (!NT_STATUS_IS_OK(status)) {
862                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
863                 return false;
864         }
865
866         status = smb2cli_read(cli->conn, cli->timeout, cli->smb2.session,
867                               cli->smb2.tcon, 0x10000, 0, fid_persistent,
868                               fid_volatile, 2, 0,
869                               talloc_tos(), &result, &nread);
870         if (!NT_STATUS_IS_OK(status)) {
871                 printf("smb2cli_read returned %s\n", nt_errstr(status));
872                 return false;
873         }
874
875         if (nread != strlen(hello)) {
876                 printf("smb2cli_read returned %d bytes, expected %d\n",
877                        (int)nread, (int)strlen(hello));
878                 return false;
879         }
880
881         if (memcmp(hello, result, nread) != 0) {
882                 printf("smb2cli_read returned '%s', expected '%s'\n",
883                        result, hello);
884                 return false;
885         }
886
887         /* check behaviour with wrong tid... */
888
889         tcon2 = smbXcli_tcon_create(cli);
890         tcon2_id = smb2cli_tcon_current_id(cli->smb2.tcon);
891         tcon2_id++;
892         smb2cli_tcon_set_values(tcon2,
893                                 NULL, /* session */
894                                 tcon2_id,
895                                 0, /* type */
896                                 0, /* flags */
897                                 0, /* capabilities */
898                                 0  /* maximal_access */);
899
900         status = smb2cli_read(cli->conn, cli->timeout, cli->smb2.session,
901                               tcon2, 0x10000, 0, fid_persistent,
902                               fid_volatile, 2, 0,
903                               talloc_tos(), &result, &nread);
904         if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) {
905                 printf("smb2cli_read returned %s\n", nt_errstr(status));
906                 return false;
907         }
908
909         talloc_free(tcon2);
910
911         return true;
912 }
913
914 bool run_smb2_multi_channel(int dummy)
915 {
916         struct cli_state *cli1;
917         struct cli_state *cli2;
918         struct cli_state *cli3;
919         NTSTATUS status;
920         bool ok;
921         uint64_t fid_persistent, fid_volatile;
922         struct tevent_context *ev;
923         struct tevent_req *subreq;
924         DATA_BLOB in_blob = data_blob_null;
925         DATA_BLOB out_blob;
926         DATA_BLOB channel_session_key;
927         struct auth_generic_state *auth_generic_state;
928         struct iovec *recv_iov;
929         const char *hello = "Hello, world\n";
930         uint8_t *result;
931         uint32_t nread;
932         struct GUID saved_guid = cli_state_client_guid;
933
934         printf("Starting SMB2-MULTI-CHANNEL\n");
935
936         cli_state_client_guid = GUID_random();
937
938         if (!torture_init_connection(&cli1)) {
939                 return false;
940         }
941
942         if (!torture_init_connection(&cli2)) {
943                 return false;
944         }
945
946         if (!torture_init_connection(&cli3)) {
947                 return false;
948         }
949
950         cli_state_client_guid = saved_guid;
951
952         status = smbXcli_negprot(cli1->conn, cli1->timeout,
953                                  PROTOCOL_SMB3_00, PROTOCOL_LATEST);
954         if (!NT_STATUS_IS_OK(status)) {
955                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
956                 return false;
957         }
958
959         status = smbXcli_negprot(cli2->conn, cli2->timeout,
960                                  PROTOCOL_SMB3_00, PROTOCOL_LATEST);
961         if (!NT_STATUS_IS_OK(status)) {
962                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
963                 return false;
964         }
965
966         status = smbXcli_negprot(cli3->conn, cli3->timeout,
967                                  PROTOCOL_SMB3_00, PROTOCOL_LATEST);
968         if (!NT_STATUS_IS_OK(status)) {
969                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
970                 return false;
971         }
972
973         status = cli_session_setup_creds(cli1, torture_creds);
974         if (!NT_STATUS_IS_OK(status)) {
975                 printf("smb2cli_sesssetup returned %s\n", nt_errstr(status));
976                 return false;
977         }
978
979         status = cli_tree_connect(cli1, share, "?????", NULL);
980         if (!NT_STATUS_IS_OK(status)) {
981                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
982                 return false;
983         }
984
985         status = smb2cli_session_create_channel(cli2,
986                                                 cli1->smb2.session,
987                                                 cli2->conn,
988                                                 &cli2->smb2.session);
989         if (!NT_STATUS_IS_OK(status)) {
990                 printf("smb2cli_session_create_channel returned %s\n",
991                         nt_errstr(status));
992                 return false;
993         }
994
995         status = auth_generic_client_prepare(talloc_tos(), &auth_generic_state);
996         if (!NT_STATUS_IS_OK(status)) {
997                 printf("auth_generic_client_prepare returned %s\n", nt_errstr(status));
998                 return false;
999         }
1000
1001         gensec_want_feature(auth_generic_state->gensec_security,
1002                             GENSEC_FEATURE_SESSION_KEY);
1003
1004         status = auth_generic_set_creds(auth_generic_state, torture_creds);
1005         if (!NT_STATUS_IS_OK(status)) {
1006                 printf("auth_generic_set_creds returned %s\n", nt_errstr(status));
1007                 return false;
1008         }
1009
1010         status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
1011         if (!NT_STATUS_IS_OK(status)) {
1012                 printf("auth_generic_client_start returned %s\n", nt_errstr(status));
1013                 return false;
1014         }
1015
1016         ev = samba_tevent_context_init(talloc_tos());
1017         if (ev == NULL) {
1018                 printf("samba_tevent_context_init() returned NULL\n");
1019                 return false;
1020         }
1021
1022         status = gensec_update(auth_generic_state->gensec_security,
1023                                talloc_tos(), data_blob_null, &in_blob);
1024         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1025                 printf("gensec_update returned %s\n", nt_errstr(status));
1026                 return false;
1027         }
1028
1029         subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1030                                             cli2->conn,
1031                                             cli2->timeout,
1032                                             cli2->smb2.session,
1033                                             0x01, /* in_flags */
1034                                             SMB2_CAP_DFS, /* in_capabilities */
1035                                             0, /* in_channel */
1036                                             0, /* in_previous_session_id */
1037                                             &in_blob); /* in_security_buffer */
1038         if (subreq == NULL) {
1039                 printf("smb2cli_session_setup_send() returned NULL\n");
1040                 return false;
1041         }
1042
1043         ok = tevent_req_poll(subreq, ev);
1044         if (!ok) {
1045                 printf("tevent_req_poll() returned false\n");
1046                 return false;
1047         }
1048
1049         status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1050                                             NULL, &out_blob);
1051         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1052                 printf("smb2cli_session_setup_recv returned %s\n",
1053                         nt_errstr(status));
1054                 return false;
1055         }
1056
1057         status = gensec_update(auth_generic_state->gensec_security,
1058                                talloc_tos(), out_blob, &in_blob);
1059         if (!NT_STATUS_IS_OK(status)) {
1060                 printf("auth_generic_update returned %s\n", nt_errstr(status));
1061                 return false;
1062         }
1063
1064         subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1065                                             cli2->conn,
1066                                             cli2->timeout,
1067                                             cli2->smb2.session,
1068                                             0x01, /* in_flags */
1069                                             SMB2_CAP_DFS, /* in_capabilities */
1070                                             0, /* in_channel */
1071                                             0, /* in_previous_session_id */
1072                                             &in_blob); /* in_security_buffer */
1073         if (subreq == NULL) {
1074                 printf("smb2cli_session_setup_send() returned NULL\n");
1075                 return false;
1076         }
1077
1078         ok = tevent_req_poll(subreq, ev);
1079         if (!ok) {
1080                 printf("tevent_req_poll() returned false\n");
1081                 return false;
1082         }
1083
1084         status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1085                                             &recv_iov, &out_blob);
1086         if (!NT_STATUS_IS_OK(status)) {
1087                 printf("smb2cli_session_setup_recv returned %s\n",
1088                         nt_errstr(status));
1089                 return false;
1090         }
1091
1092         status = gensec_session_key(auth_generic_state->gensec_security, talloc_tos(),
1093                                     &channel_session_key);
1094         if (!NT_STATUS_IS_OK(status)) {
1095                 printf("gensec_session_key returned %s\n",
1096                         nt_errstr(status));
1097                 return false;
1098         }
1099
1100         status = smb2cli_session_set_channel_key(cli2->smb2.session,
1101                                                  channel_session_key,
1102                                                  recv_iov);
1103         if (!NT_STATUS_IS_OK(status)) {
1104                 printf("smb2cli_session_set_channel_key %s\n", nt_errstr(status));
1105                 return false;
1106         }
1107
1108         status = smb2cli_session_create_channel(cli3,
1109                                                 cli1->smb2.session,
1110                                                 cli3->conn,
1111                                                 &cli3->smb2.session);
1112         if (!NT_STATUS_IS_OK(status)) {
1113                 printf("smb2cli_session_create_channel returned %s\n",
1114                         nt_errstr(status));
1115                 return false;
1116         }
1117
1118         status = auth_generic_client_prepare(talloc_tos(), &auth_generic_state);
1119         if (!NT_STATUS_IS_OK(status)) {
1120                 printf("auth_generic_client_prepare returned %s\n", nt_errstr(status));
1121                 return false;
1122         }
1123
1124         gensec_want_feature(auth_generic_state->gensec_security,
1125                             GENSEC_FEATURE_SESSION_KEY);
1126
1127         status = auth_generic_set_creds(auth_generic_state, torture_creds);
1128         if (!NT_STATUS_IS_OK(status)) {
1129                 printf("auth_generic_set_creds returned %s\n", nt_errstr(status));
1130                 return false;
1131         }
1132
1133         status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
1134         if (!NT_STATUS_IS_OK(status)) {
1135                 printf("auth_generic_client_start returned %s\n", nt_errstr(status));
1136                 return false;
1137         }
1138
1139         status = gensec_update(auth_generic_state->gensec_security,
1140                                talloc_tos(), data_blob_null, &in_blob);
1141         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1142                 printf("gensec_update returned %s\n", nt_errstr(status));
1143                 return false;
1144         }
1145
1146         subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1147                                             cli3->conn,
1148                                             cli3->timeout,
1149                                             cli3->smb2.session,
1150                                             0x01, /* in_flags */
1151                                             SMB2_CAP_DFS, /* in_capabilities */
1152                                             0, /* in_channel */
1153                                             0, /* in_previous_session_id */
1154                                             &in_blob); /* in_security_buffer */
1155         if (subreq == NULL) {
1156                 printf("smb2cli_session_setup_send() returned NULL\n");
1157                 return false;
1158         }
1159
1160         ok = tevent_req_poll(subreq, ev);
1161         if (!ok) {
1162                 printf("tevent_req_poll() returned false\n");
1163                 return false;
1164         }
1165
1166         status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1167                                             NULL, &out_blob);
1168         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1169                 printf("smb2cli_session_setup_recv returned %s\n",
1170                         nt_errstr(status));
1171                 return false;
1172         }
1173
1174         status = gensec_update(auth_generic_state->gensec_security,
1175                                talloc_tos(), out_blob, &in_blob);
1176         if (!NT_STATUS_IS_OK(status)) {
1177                 printf("auth_generic_update returned %s\n", nt_errstr(status));
1178                 return false;
1179         }
1180
1181         subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1182                                             cli3->conn,
1183                                             cli3->timeout,
1184                                             cli3->smb2.session,
1185                                             0x01, /* in_flags */
1186                                             SMB2_CAP_DFS, /* in_capabilities */
1187                                             0, /* in_channel */
1188                                             0, /* in_previous_session_id */
1189                                             &in_blob); /* in_security_buffer */
1190         if (subreq == NULL) {
1191                 printf("smb2cli_session_setup_send() returned NULL\n");
1192                 return false;
1193         }
1194
1195         ok = tevent_req_poll(subreq, ev);
1196         if (!ok) {
1197                 printf("tevent_req_poll() returned false\n");
1198                 return false;
1199         }
1200
1201         status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1202                                             &recv_iov, &out_blob);
1203         if (!NT_STATUS_IS_OK(status)) {
1204                 printf("smb2cli_session_setup_recv returned %s\n",
1205                         nt_errstr(status));
1206                 return false;
1207         }
1208
1209         status = gensec_session_key(auth_generic_state->gensec_security, talloc_tos(),
1210                                     &channel_session_key);
1211         if (!NT_STATUS_IS_OK(status)) {
1212                 printf("gensec_session_key returned %s\n",
1213                         nt_errstr(status));
1214                 return false;
1215         }
1216
1217         status = smb2cli_session_set_channel_key(cli3->smb2.session,
1218                                                  channel_session_key,
1219                                                  recv_iov);
1220         if (!NT_STATUS_IS_OK(status)) {
1221                 printf("smb2cli_session_set_channel_key %s\n", nt_errstr(status));
1222                 return false;
1223         }
1224
1225         status = smb2cli_create(
1226                 cli2->conn,
1227                 cli2->timeout,
1228                 cli2->smb2.session,
1229                 cli1->smb2.tcon,
1230                 "multi-channel.txt",
1231                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1232                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1233                 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1234                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1235                 FILE_SHARE_READ|
1236                 FILE_SHARE_WRITE|
1237                 FILE_SHARE_DELETE, /* share_access, */
1238                 FILE_CREATE, /* create_disposition, */
1239                 FILE_DELETE_ON_CLOSE, /* create_options, */
1240                 NULL, /* smb2_create_blobs *blobs */
1241                 &fid_persistent,
1242                 &fid_volatile,
1243                 NULL,
1244                 NULL,
1245                 NULL,
1246                 NULL);
1247         if (!NT_STATUS_IS_OK(status)) {
1248                 printf("smb2cli_create on cli2 %s\n", nt_errstr(status));
1249                 return false;
1250         }
1251
1252         status = smb2cli_write(cli1->conn, cli1->timeout, cli1->smb2.session,
1253                                cli1->smb2.tcon, strlen(hello), 0, fid_persistent,
1254                                fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
1255         if (!NT_STATUS_IS_OK(status)) {
1256                 printf("smb2cli_write returned %s\n", nt_errstr(status));
1257                 return false;
1258         }
1259
1260         status = smb2cli_flush(cli2->conn, cli2->timeout, cli2->smb2.session,
1261                                cli1->smb2.tcon, fid_persistent, fid_volatile);
1262         if (!NT_STATUS_IS_OK(status)) {
1263                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1264                 return false;
1265         }
1266
1267         status = smb2cli_flush(cli1->conn, cli1->timeout, cli1->smb2.session,
1268                                cli1->smb2.tcon, fid_persistent, fid_volatile);
1269         if (!NT_STATUS_IS_OK(status)) {
1270                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1271                 return false;
1272         }
1273
1274         status = smb2cli_flush(cli3->conn, cli3->timeout, cli3->smb2.session,
1275                                cli1->smb2.tcon, fid_persistent, fid_volatile);
1276         if (!NT_STATUS_IS_OK(status)) {
1277                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1278                 return false;
1279         }
1280
1281         status = smb2cli_read(cli2->conn, cli2->timeout, cli2->smb2.session,
1282                               cli1->smb2.tcon, 0x10000, 0, fid_persistent,
1283                               fid_volatile, 2, 0,
1284                               talloc_tos(), &result, &nread);
1285         if (!NT_STATUS_IS_OK(status)) {
1286                 printf("smb2cli_read returned %s\n", nt_errstr(status));
1287                 return false;
1288         }
1289
1290         if (nread != strlen(hello)) {
1291                 printf("smb2cli_read returned %d bytes, expected %d\n",
1292                        (int)nread, (int)strlen(hello));
1293                 return false;
1294         }
1295
1296         if (memcmp(hello, result, nread) != 0) {
1297                 printf("smb2cli_read returned '%s', expected '%s'\n",
1298                        result, hello);
1299                 return false;
1300         }
1301
1302         status = auth_generic_client_prepare(talloc_tos(), &auth_generic_state);
1303         if (!NT_STATUS_IS_OK(status)) {
1304                 printf("auth_generic_client_prepare returned %s\n", nt_errstr(status));
1305                 return false;
1306         }
1307
1308         gensec_want_feature(auth_generic_state->gensec_security,
1309                             GENSEC_FEATURE_SESSION_KEY);
1310
1311         status = auth_generic_set_creds(auth_generic_state, torture_creds);
1312         if (!NT_STATUS_IS_OK(status)) {
1313                 printf("auth_generic_set_creds returned %s\n", nt_errstr(status));
1314                 return false;
1315         }
1316
1317         status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
1318         if (!NT_STATUS_IS_OK(status)) {
1319                 printf("auth_generic_client_start returned %s\n", nt_errstr(status));
1320                 return false;
1321         }
1322
1323         status = gensec_update(auth_generic_state->gensec_security,
1324                                talloc_tos(), data_blob_null, &in_blob);
1325         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1326                 printf("gensec_update returned %s\n", nt_errstr(status));
1327                 return false;
1328         }
1329
1330         subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1331                                             cli3->conn,
1332                                             cli3->timeout,
1333                                             cli3->smb2.session,
1334                                             0x0, /* in_flags */
1335                                             SMB2_CAP_DFS, /* in_capabilities */
1336                                             0, /* in_channel */
1337                                             0, /* in_previous_session_id */
1338                                             &in_blob); /* in_security_buffer */
1339         if (subreq == NULL) {
1340                 printf("smb2cli_session_setup_send() returned NULL\n");
1341                 return false;
1342         }
1343
1344         ok = tevent_req_poll(subreq, ev);
1345         if (!ok) {
1346                 printf("tevent_req_poll() returned false\n");
1347                 return false;
1348         }
1349
1350         status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1351                                             NULL, &out_blob);
1352         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1353                 printf("smb2cli_session_setup_recv returned %s\n",
1354                         nt_errstr(status));
1355                 return false;
1356         }
1357
1358         status = gensec_update(auth_generic_state->gensec_security,
1359                                talloc_tos(), out_blob, &in_blob);
1360         if (!NT_STATUS_IS_OK(status)) {
1361                 printf("auth_generic_update returned %s\n", nt_errstr(status));
1362                 return false;
1363         }
1364
1365         status = smb2cli_flush(cli1->conn, cli1->timeout, cli1->smb2.session,
1366                                cli1->smb2.tcon, fid_persistent, fid_volatile);
1367         if (!NT_STATUS_IS_OK(status)) {
1368                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1369                 return false;
1370         }
1371
1372         status = smb2cli_flush(cli2->conn, cli2->timeout, cli2->smb2.session,
1373                                cli1->smb2.tcon, fid_persistent, fid_volatile);
1374         if (!NT_STATUS_IS_OK(status)) {
1375                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1376                 return false;
1377         }
1378
1379         status = smb2cli_flush(cli3->conn, cli3->timeout, cli3->smb2.session,
1380                                cli1->smb2.tcon, fid_persistent, fid_volatile);
1381         if (!NT_STATUS_IS_OK(status)) {
1382                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1383                 return false;
1384         }
1385
1386         status = smb2cli_create(
1387                 cli1->conn,
1388                 cli1->timeout,
1389                 cli1->smb2.session,
1390                 cli1->smb2.tcon,
1391                 "multi-channel-invalid.txt",
1392                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1393                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1394                 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1395                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1396                 FILE_SHARE_READ|
1397                 FILE_SHARE_WRITE|
1398                 FILE_SHARE_DELETE, /* share_access, */
1399                 FILE_CREATE, /* create_disposition, */
1400                 FILE_DELETE_ON_CLOSE, /* create_options, */
1401                 NULL, /* smb2_create_blobs *blobs */
1402                 &fid_persistent,
1403                 &fid_volatile,
1404                 NULL,
1405                 NULL,
1406                 NULL,
1407                 NULL);
1408         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1409                 printf("smb2cli_create %s\n", nt_errstr(status));
1410                 return false;
1411         }
1412
1413         status = smb2cli_create(
1414                 cli2->conn,
1415                 cli2->timeout,
1416                 cli2->smb2.session,
1417                 cli1->smb2.tcon,
1418                 "multi-channel-invalid.txt",
1419                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1420                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1421                 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1422                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1423                 FILE_SHARE_READ|
1424                 FILE_SHARE_WRITE|
1425                 FILE_SHARE_DELETE, /* share_access, */
1426                 FILE_CREATE, /* create_disposition, */
1427                 FILE_DELETE_ON_CLOSE, /* create_options, */
1428                 NULL, /* smb2_create_blobs *blobs */
1429                 &fid_persistent,
1430                 &fid_volatile,
1431                 NULL,
1432                 NULL,
1433                 NULL,
1434                 NULL);
1435         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1436                 printf("smb2cli_create %s\n", nt_errstr(status));
1437                 return false;
1438         }
1439
1440         status = smb2cli_create(
1441                 cli3->conn,
1442                 cli3->timeout,
1443                 cli3->smb2.session,
1444                 cli1->smb2.tcon,
1445                 "multi-channel-invalid.txt",
1446                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1447                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1448                 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1449                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1450                 FILE_SHARE_READ|
1451                 FILE_SHARE_WRITE|
1452                 FILE_SHARE_DELETE, /* share_access, */
1453                 FILE_CREATE, /* create_disposition, */
1454                 FILE_DELETE_ON_CLOSE, /* create_options, */
1455                 NULL, /* smb2_create_blobs *blobs */
1456                 &fid_persistent,
1457                 &fid_volatile,
1458                 NULL,
1459                 NULL,
1460                 NULL,
1461                 NULL);
1462         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1463                 printf("smb2cli_create %s\n", nt_errstr(status));
1464                 return false;
1465         }
1466
1467         subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1468                                             cli2->conn,
1469                                             cli2->timeout,
1470                                             cli2->smb2.session,
1471                                             0x0, /* in_flags */
1472                                             SMB2_CAP_DFS, /* in_capabilities */
1473                                             0, /* in_channel */
1474                                             0, /* in_previous_session_id */
1475                                             &in_blob); /* in_security_buffer */
1476         if (subreq == NULL) {
1477                 printf("smb2cli_session_setup_send() returned NULL\n");
1478                 return false;
1479         }
1480
1481         ok = tevent_req_poll(subreq, ev);
1482         if (!ok) {
1483                 printf("tevent_req_poll() returned false\n");
1484                 return false;
1485         }
1486
1487         status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1488                                             &recv_iov, &out_blob);
1489         if (!NT_STATUS_IS_OK(status)) {
1490                 printf("smb2cli_session_setup_recv returned %s\n",
1491                         nt_errstr(status));
1492                 return false;
1493         }
1494
1495         status = smb2cli_close(cli3->conn, cli3->timeout, cli3->smb2.session,
1496                                cli1->smb2.tcon, 0, fid_persistent, fid_volatile);
1497         if (!NT_STATUS_IS_OK(status)) {
1498                 printf("smb2cli_close returned %s\n", nt_errstr(status));
1499                 return false;
1500         }
1501
1502         status = smb2cli_flush(cli3->conn, cli3->timeout, cli3->smb2.session,
1503                                cli1->smb2.tcon, fid_persistent, fid_volatile);
1504         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED)) {
1505                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1506                 return false;
1507         }
1508
1509         status = smb2cli_flush(cli2->conn, cli2->timeout, cli2->smb2.session,
1510                                cli1->smb2.tcon, fid_persistent, fid_volatile);
1511         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED)) {
1512                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1513                 return false;
1514         }
1515
1516         status = smb2cli_flush(cli1->conn, cli1->timeout, cli1->smb2.session,
1517                                cli1->smb2.tcon, fid_persistent, fid_volatile);
1518         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED)) {
1519                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1520                 return false;
1521         }
1522
1523         return true;
1524 }
1525
1526 bool run_smb2_session_reauth(int dummy)
1527 {
1528         struct cli_state *cli;
1529         NTSTATUS status;
1530         bool ok;
1531         uint64_t fid_persistent, fid_volatile;
1532         uint64_t dir_persistent, dir_volatile;
1533         uint8_t *dir_data;
1534         uint32_t dir_data_length;
1535         struct tevent_context *ev;
1536         struct tevent_req *subreq;
1537         DATA_BLOB in_blob = data_blob_null;
1538         DATA_BLOB out_blob;
1539         DATA_BLOB in_input_buffer;
1540         DATA_BLOB out_output_buffer;
1541         uint8_t in_file_info_class;
1542         struct auth_generic_state *auth_generic_state;
1543         struct iovec *recv_iov;
1544         uint32_t saved_tid;
1545         struct smbXcli_tcon *saved_tcon;
1546
1547         printf("Starting SMB2-SESSION_REAUTH\n");
1548
1549         if (!torture_init_connection(&cli)) {
1550                 return false;
1551         }
1552
1553         /*
1554          * PROTOCOL_SMB2_22 has a bug in win8pre0
1555          * it behaves like PROTOCOL_SMB2_02
1556          * and returns NT_STATUS_REQUEST_NOT_ACCEPTED,
1557          * while it allows it on PROTOCOL_SMB2_10.
1558          */
1559         status = smbXcli_negprot(cli->conn, cli->timeout,
1560                                  PROTOCOL_SMB2_10, PROTOCOL_SMB2_10);
1561         if (!NT_STATUS_IS_OK(status)) {
1562                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
1563                 return false;
1564         }
1565
1566         status = cli_session_setup_creds(cli, torture_creds);
1567         if (!NT_STATUS_IS_OK(status)) {
1568                 printf("smb2cli_sesssetup returned %s\n", nt_errstr(status));
1569                 return false;
1570         }
1571
1572         status = cli_tree_connect(cli, share, "?????", NULL);
1573         if (!NT_STATUS_IS_OK(status)) {
1574                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
1575                 return false;
1576         }
1577
1578         status = smb2cli_create(
1579                 cli->conn,
1580                 cli->timeout,
1581                 cli->smb2.session,
1582                 cli->smb2.tcon,
1583                 "session-reauth.txt",
1584                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1585                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1586                 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1587                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1588                 FILE_SHARE_READ|
1589                 FILE_SHARE_WRITE|
1590                 FILE_SHARE_DELETE, /* share_access, */
1591                 FILE_CREATE, /* create_disposition, */
1592                 FILE_DELETE_ON_CLOSE, /* create_options, */
1593                 NULL, /* smb2_create_blobs *blobs */
1594                 &fid_persistent,
1595                 &fid_volatile,
1596                 NULL,
1597                 NULL,
1598                 NULL,
1599                 NULL);
1600         if (!NT_STATUS_IS_OK(status)) {
1601                 printf("smb2cli_create %s\n", nt_errstr(status));
1602                 return false;
1603         }
1604
1605         status = smb2cli_create(
1606                 cli->conn,
1607                 cli->timeout,
1608                 cli->smb2.session,
1609                 cli->smb2.tcon,
1610                 "",
1611                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1612                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1613                 SEC_STD_SYNCHRONIZE|
1614                 SEC_DIR_LIST|
1615                 SEC_DIR_READ_ATTRIBUTE, /* desired_access, */
1616                 0, /* file_attributes, */
1617                 FILE_SHARE_READ|
1618                 FILE_SHARE_WRITE|
1619                 FILE_SHARE_DELETE, /* share_access, */
1620                 FILE_OPEN, /* create_disposition, */
1621                 FILE_SYNCHRONOUS_IO_NONALERT|
1622                 FILE_DIRECTORY_FILE, /* create_options, */
1623                 NULL, /* smb2_create_blobs *blobs */
1624                 &dir_persistent,
1625                 &dir_volatile,
1626                 NULL,
1627                 NULL,
1628                 NULL,
1629                 NULL);
1630         if (!NT_STATUS_IS_OK(status)) {
1631                 printf("smb2cli_create returned %s\n", nt_errstr(status));
1632                 return false;
1633         }
1634
1635         status = smb2cli_query_directory(
1636                 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
1637                 1, 0x3, 0, dir_persistent, dir_volatile,
1638                 "session-reauth.txt", 0xffff,
1639                 talloc_tos(), &dir_data, &dir_data_length);
1640         if (!NT_STATUS_IS_OK(status)) {
1641                 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
1642                 return false;
1643         }
1644
1645         status = auth_generic_client_prepare(talloc_tos(), &auth_generic_state);
1646         if (!NT_STATUS_IS_OK(status)) {
1647                 printf("auth_generic_client_prepare returned %s\n", nt_errstr(status));
1648                 return false;
1649         }
1650
1651         gensec_want_feature(auth_generic_state->gensec_security,
1652                             GENSEC_FEATURE_SESSION_KEY);
1653
1654         status = auth_generic_set_creds(auth_generic_state, torture_creds);
1655         if (!NT_STATUS_IS_OK(status)) {
1656                 printf("auth_generic_set_creds returned %s\n", nt_errstr(status));
1657                 return false;
1658         }
1659
1660         status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
1661         if (!NT_STATUS_IS_OK(status)) {
1662                 printf("auth_generic_client_start returned %s\n", nt_errstr(status));
1663                 return false;
1664         }
1665
1666         ev = samba_tevent_context_init(talloc_tos());
1667         if (ev == NULL) {
1668                 printf("samba_tevent_context_init() returned NULL\n");
1669                 return false;
1670         }
1671
1672         status = gensec_update(auth_generic_state->gensec_security,
1673                                talloc_tos(), data_blob_null, &in_blob);
1674         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1675                 printf("gensec_update returned %s\n", nt_errstr(status));
1676                 return false;
1677         }
1678
1679         subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1680                                             cli->conn,
1681                                             cli->timeout,
1682                                             cli->smb2.session,
1683                                             0x0, /* in_flags */
1684                                             SMB2_CAP_DFS, /* in_capabilities */
1685                                             0, /* in_channel */
1686                                             0, /* in_previous_session_id */
1687                                             &in_blob); /* in_security_buffer */
1688         if (subreq == NULL) {
1689                 printf("smb2cli_session_setup_send() returned NULL\n");
1690                 return false;
1691         }
1692
1693         ok = tevent_req_poll(subreq, ev);
1694         if (!ok) {
1695                 printf("tevent_req_poll() returned false\n");
1696                 return false;
1697         }
1698
1699         status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1700                                             NULL, &out_blob);
1701         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1702                 printf("smb2cli_session_setup_recv returned %s\n",
1703                         nt_errstr(status));
1704                 return false;
1705         }
1706
1707         status = gensec_update(auth_generic_state->gensec_security,
1708                                talloc_tos(), out_blob, &in_blob);
1709         if (!NT_STATUS_IS_OK(status)) {
1710                 printf("auth_generic_update returned %s\n", nt_errstr(status));
1711                 return false;
1712         }
1713
1714         status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
1715                                cli->smb2.tcon, fid_persistent, fid_volatile);
1716         if (!NT_STATUS_IS_OK(status)) {
1717                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1718                 return false;
1719         }
1720
1721         status = smb2cli_query_directory(
1722                 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
1723                 1, 0x3, 0, dir_persistent, dir_volatile,
1724                 "session-reauth.txt", 0xffff,
1725                 talloc_tos(), &dir_data, &dir_data_length);
1726         if (!NT_STATUS_IS_OK(status)) {
1727                 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
1728                 return false;
1729         }
1730
1731         /*
1732          * query_info seems to be a path based operation on Windows...
1733          */
1734         status = smb2cli_query_info(cli->conn,
1735                                     cli->timeout,
1736                                     cli->smb2.session,
1737                                     cli->smb2.tcon,
1738                                     SMB2_0_INFO_SECURITY,
1739                                     0, /* in_file_info_class */
1740                                     1024, /* in_max_output_length */
1741                                     NULL, /* in_input_buffer */
1742                                     SECINFO_OWNER, /* in_additional_info */
1743                                     0, /* in_flags */
1744                                     fid_persistent,
1745                                     fid_volatile,
1746                                     talloc_tos(),
1747                                     &out_output_buffer);
1748         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1749                 printf("smb2cli_query_info (security) returned %s\n", nt_errstr(status));
1750                 return false;
1751         }
1752
1753         in_file_info_class = SMB_FILE_POSITION_INFORMATION - 1000;
1754         status = smb2cli_query_info(cli->conn,
1755                                     cli->timeout,
1756                                     cli->smb2.session,
1757                                     cli->smb2.tcon,
1758                                     SMB2_0_INFO_FILE,
1759                                     in_file_info_class,
1760                                     1024, /* in_max_output_length */
1761                                     NULL, /* in_input_buffer */
1762                                     0, /* in_additional_info */
1763                                     0, /* in_flags */
1764                                     fid_persistent,
1765                                     fid_volatile,
1766                                     talloc_tos(),
1767                                     &out_output_buffer);
1768         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1769                 printf("smb2cli_query_info (position) returned %s\n", nt_errstr(status));
1770                 return false;
1771         }
1772
1773         in_input_buffer = data_blob_talloc(talloc_tos(), NULL, 8);
1774         SBVAL(in_input_buffer.data, 0, 512);
1775
1776         in_file_info_class = SMB_FILE_POSITION_INFORMATION - 1000;
1777         status = smb2cli_set_info(cli->conn,
1778                                   cli->timeout,
1779                                   cli->smb2.session,
1780                                   cli->smb2.tcon,
1781                                   SMB2_0_INFO_FILE,
1782                                   in_file_info_class,
1783                                   &in_input_buffer,
1784                                   0, /* in_additional_info */
1785                                   fid_persistent,
1786                                   fid_volatile);
1787         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1788                 printf("smb2cli_set_info (position) returned %s\n", nt_errstr(status));
1789                 return false;
1790         }
1791
1792         status = smb2cli_create(
1793                 cli->conn,
1794                 cli->timeout,
1795                 cli->smb2.session,
1796                 cli->smb2.tcon,
1797                 "session-reauth-invalid.txt",
1798                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1799                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1800                 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1801                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1802                 FILE_SHARE_READ|
1803                 FILE_SHARE_WRITE|
1804                 FILE_SHARE_DELETE, /* share_access, */
1805                 FILE_CREATE, /* create_disposition, */
1806                 FILE_DELETE_ON_CLOSE, /* create_options, */
1807                 NULL, /* smb2_create_blobs *blobs */
1808                 &fid_persistent,
1809                 &fid_volatile,
1810                 NULL,
1811                 NULL,
1812                 NULL,
1813                 NULL);
1814         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1815                 printf("smb2cli_create %s\n", nt_errstr(status));
1816                 return false;
1817         }
1818
1819         status = smb2cli_create(
1820                 cli->conn,
1821                 cli->timeout,
1822                 cli->smb2.session,
1823                 cli->smb2.tcon,
1824                 "",
1825                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1826                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1827                 SEC_STD_SYNCHRONIZE|
1828                 SEC_DIR_LIST|
1829                 SEC_DIR_READ_ATTRIBUTE, /* desired_access, */
1830                 0, /* file_attributes, */
1831                 FILE_SHARE_READ|
1832                 FILE_SHARE_WRITE|
1833                 FILE_SHARE_DELETE, /* share_access, */
1834                 FILE_OPEN, /* create_disposition, */
1835                 FILE_SYNCHRONOUS_IO_NONALERT|
1836                 FILE_DIRECTORY_FILE, /* create_options, */
1837                 NULL, /* smb2_create_blobs *blobs */
1838                 &dir_persistent,
1839                 &dir_volatile,
1840                 NULL,
1841                 NULL,
1842                 NULL,
1843                 NULL);
1844         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1845                 printf("smb2cli_create returned %s\n", nt_errstr(status));
1846                 return false;
1847         }
1848
1849         saved_tid = smb2cli_tcon_current_id(cli->smb2.tcon);
1850         saved_tcon = cli->smb2.tcon;
1851         cli->smb2.tcon = smbXcli_tcon_create(cli);
1852         smb2cli_tcon_set_values(cli->smb2.tcon,
1853                                 NULL, /* session */
1854                                 saved_tid,
1855                                 0, /* type */
1856                                 0, /* flags */
1857                                 0, /* capabilities */
1858                                 0  /* maximal_access */);
1859         status = cli_tree_connect(cli, share, "?????", NULL);
1860         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1861                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
1862                 return false;
1863         }
1864         talloc_free(cli->smb2.tcon);
1865         cli->smb2.tcon = saved_tcon;
1866
1867         subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1868                                             cli->conn,
1869                                             cli->timeout,
1870                                             cli->smb2.session,
1871                                             0x0, /* in_flags */
1872                                             SMB2_CAP_DFS, /* in_capabilities */
1873                                             0, /* in_channel */
1874                                             0, /* in_previous_session_id */
1875                                             &in_blob); /* in_security_buffer */
1876         if (subreq == NULL) {
1877                 printf("smb2cli_session_setup_send() returned NULL\n");
1878                 return false;
1879         }
1880
1881         ok = tevent_req_poll(subreq, ev);
1882         if (!ok) {
1883                 printf("tevent_req_poll() returned false\n");
1884                 return false;
1885         }
1886
1887         status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1888                                             &recv_iov, &out_blob);
1889         if (!NT_STATUS_IS_OK(status)) {
1890                 printf("smb2cli_session_setup_recv returned %s\n",
1891                         nt_errstr(status));
1892                 return false;
1893         }
1894
1895         status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
1896                                cli->smb2.tcon, fid_persistent, fid_volatile);
1897         if (!NT_STATUS_IS_OK(status)) {
1898                 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1899                 return false;
1900         }
1901
1902         status = smb2cli_query_info(cli->conn,
1903                                     cli->timeout,
1904                                     cli->smb2.session,
1905                                     cli->smb2.tcon,
1906                                     SMB2_0_INFO_SECURITY,
1907                                     0, /* in_file_info_class */
1908                                     1024, /* in_max_output_length */
1909                                     NULL, /* in_input_buffer */
1910                                     SECINFO_OWNER, /* in_additional_info */
1911                                     0, /* in_flags */
1912                                     fid_persistent,
1913                                     fid_volatile,
1914                                     talloc_tos(),
1915                                     &out_output_buffer);
1916         if (!NT_STATUS_IS_OK(status)) {
1917                 printf("smb2cli_query_info (security) returned %s\n", nt_errstr(status));
1918                 return false;
1919         }
1920
1921         in_file_info_class = SMB_FILE_POSITION_INFORMATION - 1000;
1922         status = smb2cli_query_info(cli->conn,
1923                                     cli->timeout,
1924                                     cli->smb2.session,
1925                                     cli->smb2.tcon,
1926                                     SMB2_0_INFO_FILE,
1927                                     in_file_info_class,
1928                                     1024, /* in_max_output_length */
1929                                     NULL, /* in_input_buffer */
1930                                     0, /* in_additional_info */
1931                                     0, /* in_flags */
1932                                     fid_persistent,
1933                                     fid_volatile,
1934                                     talloc_tos(),
1935                                     &out_output_buffer);
1936         if (!NT_STATUS_IS_OK(status)) {
1937                 printf("smb2cli_query_info (position) returned %s\n", nt_errstr(status));
1938                 return false;
1939         }
1940
1941         in_input_buffer = data_blob_talloc(talloc_tos(), NULL, 8);
1942         SBVAL(in_input_buffer.data, 0, 512);
1943
1944         in_file_info_class = SMB_FILE_POSITION_INFORMATION - 1000;
1945         status = smb2cli_set_info(cli->conn,
1946                                   cli->timeout,
1947                                   cli->smb2.session,
1948                                   cli->smb2.tcon,
1949                                   SMB2_0_INFO_FILE,
1950                                   in_file_info_class,
1951                                   &in_input_buffer,
1952                                   0, /* in_additional_info */
1953                                   fid_persistent,
1954                                   fid_volatile);
1955         if (!NT_STATUS_IS_OK(status)) {
1956                 printf("smb2cli_set_info (position) returned %s\n", nt_errstr(status));
1957                 return false;
1958         }
1959
1960         in_file_info_class = SMB_FILE_POSITION_INFORMATION - 1000;
1961         status = smb2cli_query_info(cli->conn,
1962                                     cli->timeout,
1963                                     cli->smb2.session,
1964                                     cli->smb2.tcon,
1965                                     SMB2_0_INFO_FILE,
1966                                     in_file_info_class,
1967                                     1024, /* in_max_output_length */
1968                                     NULL, /* in_input_buffer */
1969                                     0, /* in_additional_info */
1970                                     0, /* in_flags */
1971                                     fid_persistent,
1972                                     fid_volatile,
1973                                     talloc_tos(),
1974                                     &out_output_buffer);
1975         if (!NT_STATUS_IS_OK(status)) {
1976                 printf("smb2cli_query_info (position) returned %s\n", nt_errstr(status));
1977                 return false;
1978         }
1979
1980         status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
1981                                cli->smb2.tcon, 0, fid_persistent, fid_volatile);
1982         if (!NT_STATUS_IS_OK(status)) {
1983                 printf("smb2cli_close returned %s\n", nt_errstr(status));
1984                 return false;
1985         }
1986
1987         status = smb2cli_create(
1988                 cli->conn,
1989                 cli->timeout,
1990                 cli->smb2.session,
1991                 cli->smb2.tcon,
1992                 "session-reauth.txt",
1993                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1994                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1995                 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1996                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1997                 FILE_SHARE_READ|
1998                 FILE_SHARE_WRITE|
1999                 FILE_SHARE_DELETE, /* share_access, */
2000                 FILE_CREATE, /* create_disposition, */
2001                 FILE_DELETE_ON_CLOSE, /* create_options, */
2002                 NULL, /* smb2_create_blobs *blobs */
2003                 &fid_persistent,
2004                 &fid_volatile,
2005                 NULL,
2006                 NULL,
2007                 NULL,
2008                 NULL);
2009         if (!NT_STATUS_IS_OK(status)) {
2010                 printf("smb2cli_create %s\n", nt_errstr(status));
2011                 return false;
2012         }
2013
2014         status = smb2cli_query_directory(
2015                 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
2016                 1, 0x3, 0, dir_persistent, dir_volatile,
2017                 "session-reauth.txt", 0xffff,
2018                 talloc_tos(), &dir_data, &dir_data_length);
2019         if (!NT_STATUS_IS_OK(status)) {
2020                 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
2021                 return false;
2022         }
2023
2024         status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
2025                                cli->smb2.tcon, 0, dir_persistent, dir_volatile);
2026         if (!NT_STATUS_IS_OK(status)) {
2027                 printf("smb2cli_close returned %s\n", nt_errstr(status));
2028                 return false;
2029         }
2030
2031         status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
2032                                cli->smb2.tcon, 0, fid_persistent, fid_volatile);
2033         if (!NT_STATUS_IS_OK(status)) {
2034                 printf("smb2cli_close returned %s\n", nt_errstr(status));
2035                 return false;
2036         }
2037
2038         saved_tid = smb2cli_tcon_current_id(cli->smb2.tcon);
2039         saved_tcon = cli->smb2.tcon;
2040         cli->smb2.tcon = smbXcli_tcon_create(cli);
2041         smb2cli_tcon_set_values(cli->smb2.tcon,
2042                                 NULL, /* session */
2043                                 saved_tid,
2044                                 0, /* type */
2045                                 0, /* flags */
2046                                 0, /* capabilities */
2047                                 0  /* maximal_access */);
2048         status = cli_tree_connect(cli, share, "?????", NULL);
2049         if (!NT_STATUS_IS_OK(status)) {
2050                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
2051                 return false;
2052         }
2053         talloc_free(cli->smb2.tcon);
2054         cli->smb2.tcon = saved_tcon;
2055
2056         return true;
2057 }
2058
2059 static NTSTATUS check_size(struct cli_state *cli,
2060                                 uint16_t fnum,
2061                                 const char *fname,
2062                                 size_t size)
2063 {
2064         off_t size_read = 0;
2065
2066         NTSTATUS status = cli_qfileinfo_basic(cli,
2067                                 fnum,
2068                                 NULL,
2069                                 &size_read,
2070                                 NULL,
2071                                 NULL,
2072                                 NULL,
2073                                 NULL,
2074                                 NULL);
2075
2076         if (!NT_STATUS_IS_OK(status)) {
2077                 printf("cli_qfileinfo_basic of %s failed (%s)\n",
2078                         fname,
2079                         nt_errstr(status));
2080                 return status;
2081         }
2082
2083         if (size != size_read) {
2084                 printf("size (%u) != size_read(%u) for %s\n",
2085                         (unsigned int)size,
2086                         (unsigned int)size_read,
2087                         fname);
2088                 /* Use EOF to mean bad size. */
2089                 return NT_STATUS_END_OF_FILE;
2090         }
2091         return NT_STATUS_OK;
2092 }
2093
2094 /* Ensure cli_ftruncate() works for SMB2. */
2095
2096 bool run_smb2_ftruncate(int dummy)
2097 {
2098         struct cli_state *cli = NULL;
2099         const char *fname = "smb2_ftruncate.txt";
2100         uint16_t fnum = (uint16_t)-1;
2101         bool correct = false;
2102         size_t buflen = 1024*1024;
2103         uint8_t *buf = NULL;
2104         unsigned int i;
2105         NTSTATUS status;
2106
2107         printf("Starting SMB2-FTRUNCATE\n");
2108
2109         if (!torture_init_connection(&cli)) {
2110                 goto fail;
2111         }
2112
2113         status = smbXcli_negprot(cli->conn, cli->timeout,
2114                                  PROTOCOL_SMB2_02, PROTOCOL_SMB2_02);
2115         if (!NT_STATUS_IS_OK(status)) {
2116                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
2117                 goto fail;
2118         }
2119
2120         status = cli_session_setup_creds(cli, torture_creds);
2121         if (!NT_STATUS_IS_OK(status)) {
2122                 printf("cli_session_setup returned %s\n", nt_errstr(status));
2123                 goto fail;
2124         }
2125
2126         status = cli_tree_connect(cli, share, "?????", NULL);
2127         if (!NT_STATUS_IS_OK(status)) {
2128                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
2129                 goto fail;
2130         }
2131
2132         cli_setatr(cli, fname, 0, 0);
2133         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2134
2135         status = cli_ntcreate(cli,
2136                                 fname,
2137                                 0,
2138                                 GENERIC_ALL_ACCESS,
2139                                 FILE_ATTRIBUTE_NORMAL,
2140                                 FILE_SHARE_NONE,
2141                                 FILE_CREATE,
2142                                 0,
2143                                 0,
2144                                 &fnum,
2145                                 NULL);
2146
2147         if (!NT_STATUS_IS_OK(status)) {
2148                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2149                 goto fail;
2150         }
2151
2152         buf = talloc_zero_array(cli, uint8_t, buflen);
2153         if (buf == NULL) {
2154                 goto fail;
2155         }
2156
2157         /* Write 1MB. */
2158         status = cli_writeall(cli,
2159                                 fnum,
2160                                 0,
2161                                 buf,
2162                                 0,
2163                                 buflen,
2164                                 NULL);
2165
2166         if (!NT_STATUS_IS_OK(status)) {
2167                 printf("write of %u to %s failed (%s)\n",
2168                         (unsigned int)buflen,
2169                         fname,
2170                         nt_errstr(status));
2171                 goto fail;
2172         }
2173
2174         status = check_size(cli, fnum, fname, buflen);
2175         if (!NT_STATUS_IS_OK(status)) {
2176                 goto fail;
2177         }
2178
2179         /* Now ftruncate. */
2180         for ( i = 0; i < 10; i++) {
2181                 status = cli_ftruncate(cli, fnum, i*1024);
2182                 if (!NT_STATUS_IS_OK(status)) {
2183                         printf("cli_ftruncate %u of %s failed (%s)\n",
2184                                 (unsigned int)i*1024,
2185                                 fname,
2186                                 nt_errstr(status));
2187                         goto fail;
2188                 }
2189                 status = check_size(cli, fnum, fname, i*1024);
2190                 if (!NT_STATUS_IS_OK(status)) {
2191                         goto fail;
2192                 }
2193         }
2194
2195         correct = true;
2196
2197   fail:
2198
2199         if (cli == NULL) {
2200                 return false;
2201         }
2202
2203         if (fnum != (uint16_t)-1) {
2204                 cli_close(cli, fnum);
2205         }
2206         cli_setatr(cli, fname, 0, 0);
2207         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2208
2209         if (!torture_close_connection(cli)) {
2210                 correct = false;
2211         }
2212         return correct;
2213 }
2214
2215 /* Ensure SMB2 flush on directories behaves correctly. */
2216
2217 static bool test_dir_fsync(struct cli_state *cli, const char *path)
2218 {
2219         NTSTATUS status;
2220         uint64_t fid_persistent, fid_volatile;
2221         uint8_t *dir_data = NULL;
2222         uint32_t dir_data_length = 0;
2223
2224         /* Open directory - no write abilities. */
2225         status = smb2cli_create(
2226                 cli->conn,
2227                 cli->timeout,
2228                 cli->smb2.session,
2229                 cli->smb2.tcon,
2230                 path,
2231                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2232                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2233                 SEC_STD_SYNCHRONIZE|
2234                 SEC_DIR_LIST|
2235                 SEC_DIR_READ_ATTRIBUTE, /* desired_access, */
2236                 0, /* file_attributes, */
2237                 FILE_SHARE_READ|
2238                 FILE_SHARE_WRITE|
2239                 FILE_SHARE_DELETE, /* share_access, */
2240                 FILE_OPEN, /* create_disposition, */
2241                 FILE_SYNCHRONOUS_IO_NONALERT|
2242                 FILE_DIRECTORY_FILE, /* create_options, */
2243                 NULL, /* smb2_create_blobs *blobs */
2244                 &fid_persistent,
2245                 &fid_volatile,
2246                 NULL,
2247                 NULL,
2248                 NULL,
2249                 NULL);
2250         if (!NT_STATUS_IS_OK(status)) {
2251                 printf("smb2cli_create '%s' (readonly) returned %s\n",
2252                         path,
2253                         nt_errstr(status));
2254                 return false;
2255         }
2256
2257         status = smb2cli_query_directory(
2258                 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
2259                 1, 0, 0, fid_persistent, fid_volatile, "*", 0xffff,
2260                 talloc_tos(), &dir_data, &dir_data_length);
2261
2262         if (!NT_STATUS_IS_OK(status)) {
2263                 printf("smb2cli_query_directory returned %s\n",
2264                         nt_errstr(status));
2265                 return false;
2266         }
2267
2268         /* Open directory no write access. Flush should fail. */
2269
2270         status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
2271                                cli->smb2.tcon, fid_persistent, fid_volatile);
2272         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2273                 printf("smb2cli_flush on a read-only directory returned %s\n",
2274                         nt_errstr(status));
2275                 return false;
2276         }
2277
2278         status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
2279                                cli->smb2.tcon, 0, fid_persistent, fid_volatile);
2280         if (!NT_STATUS_IS_OK(status)) {
2281                 printf("smb2cli_close returned %s\n", nt_errstr(status));
2282                 return false;
2283         }
2284
2285         /* Open directory write-attributes only. Flush should still fail. */
2286
2287         status = smb2cli_create(
2288                 cli->conn,
2289                 cli->timeout,
2290                 cli->smb2.session,
2291                 cli->smb2.tcon,
2292                 path,
2293                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2294                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2295                 SEC_STD_SYNCHRONIZE|
2296                 SEC_DIR_LIST|
2297                 SEC_DIR_WRITE_ATTRIBUTE|
2298                 SEC_DIR_READ_ATTRIBUTE, /* desired_access, */
2299                 0, /* file_attributes, */
2300                 FILE_SHARE_READ|
2301                 FILE_SHARE_WRITE|
2302                 FILE_SHARE_DELETE, /* share_access, */
2303                 FILE_OPEN, /* create_disposition, */
2304                 FILE_SYNCHRONOUS_IO_NONALERT|
2305                 FILE_DIRECTORY_FILE, /* create_options, */
2306                 NULL, /* smb2_create_blobs *blobs */
2307                 &fid_persistent,
2308                 &fid_volatile,
2309                 NULL,
2310                 NULL,
2311                 NULL,
2312                 NULL);
2313         if (!NT_STATUS_IS_OK(status)) {
2314                 printf("smb2cli_create '%s' (write attr) returned %s\n",
2315                         path,
2316                         nt_errstr(status));
2317                 return false;
2318         }
2319
2320         status = smb2cli_query_directory(
2321                 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
2322                 1, 0, 0, fid_persistent, fid_volatile, "*", 0xffff,
2323                 talloc_tos(), &dir_data, &dir_data_length);
2324
2325         if (!NT_STATUS_IS_OK(status)) {
2326                 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
2327                 return false;
2328         }
2329
2330         status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
2331                                cli->smb2.tcon, fid_persistent, fid_volatile);
2332         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2333                 printf("smb2cli_flush on a write-attributes directory "
2334                         "returned %s\n",
2335                         nt_errstr(status));
2336                 return false;
2337         }
2338
2339         status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
2340                                cli->smb2.tcon, 0, fid_persistent, fid_volatile);
2341         if (!NT_STATUS_IS_OK(status)) {
2342                 printf("smb2cli_close returned %s\n", nt_errstr(status));
2343                 return false;
2344         }
2345
2346         /* Open directory with SEC_DIR_ADD_FILE access. Flush should now succeed. */
2347
2348         status = smb2cli_create(
2349                 cli->conn,
2350                 cli->timeout,
2351                 cli->smb2.session,
2352                 cli->smb2.tcon,
2353                 path,
2354                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2355                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2356                 SEC_STD_SYNCHRONIZE|
2357                 SEC_DIR_LIST|
2358                 SEC_DIR_ADD_FILE, /* desired_access, */
2359                 0, /* file_attributes, */
2360                 FILE_SHARE_READ|
2361                 FILE_SHARE_WRITE|
2362                 FILE_SHARE_DELETE, /* share_access, */
2363                 FILE_OPEN, /* create_disposition, */
2364                 FILE_SYNCHRONOUS_IO_NONALERT|
2365                 FILE_DIRECTORY_FILE, /* create_options, */
2366                 NULL, /* smb2_create_blobs *blobs */
2367                 &fid_persistent,
2368                 &fid_volatile,
2369                 NULL,
2370                 NULL,
2371                 NULL,
2372                 NULL);
2373         if (!NT_STATUS_IS_OK(status)) {
2374                 printf("smb2cli_create '%s' (write FILE access) returned %s\n",
2375                         path,
2376                         nt_errstr(status));
2377                 return false;
2378         }
2379
2380         status = smb2cli_query_directory(
2381                 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
2382                 1, 0, 0, fid_persistent, fid_volatile, "*", 0xffff,
2383                 talloc_tos(), &dir_data, &dir_data_length);
2384
2385         if (!NT_STATUS_IS_OK(status)) {
2386                 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
2387                 return false;
2388         }
2389
2390         status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
2391                                cli->smb2.tcon, fid_persistent, fid_volatile);
2392         if (!NT_STATUS_IS_OK(status)) {
2393                 printf("smb2cli_flush on a directory returned %s\n",
2394                         nt_errstr(status));
2395                 return false;
2396         }
2397
2398         status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
2399                                cli->smb2.tcon, 0, fid_persistent, fid_volatile);
2400         if (!NT_STATUS_IS_OK(status)) {
2401                 printf("smb2cli_close returned %s\n", nt_errstr(status));
2402                 return false;
2403         }
2404
2405         /* Open directory with SEC_DIR_ADD_FILE access. Flush should now succeed. */
2406
2407         status = smb2cli_create(
2408                 cli->conn,
2409                 cli->timeout,
2410                 cli->smb2.session,
2411                 cli->smb2.tcon,
2412                 path,
2413                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2414                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2415                 SEC_STD_SYNCHRONIZE|
2416                 SEC_DIR_LIST|
2417                 SEC_DIR_ADD_SUBDIR, /* desired_access, */
2418                 0, /* file_attributes, */
2419                 FILE_SHARE_READ|
2420                 FILE_SHARE_WRITE|
2421                 FILE_SHARE_DELETE, /* share_access, */
2422                 FILE_OPEN, /* create_disposition, */
2423                 FILE_SYNCHRONOUS_IO_NONALERT|
2424                 FILE_DIRECTORY_FILE, /* create_options, */
2425                 NULL, /* smb2_create_blobs *blobs */
2426                 &fid_persistent,
2427                 &fid_volatile,
2428                 NULL,
2429                 NULL,
2430                 NULL,
2431                 NULL);
2432         if (!NT_STATUS_IS_OK(status)) {
2433                 printf("smb2cli_create '%s' (write DIR access) returned %s\n",
2434                         path,
2435                         nt_errstr(status));
2436                 return false;
2437         }
2438
2439         status = smb2cli_query_directory(
2440                 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
2441                 1, 0, 0, fid_persistent, fid_volatile, "*", 0xffff,
2442                 talloc_tos(), &dir_data, &dir_data_length);
2443
2444         if (!NT_STATUS_IS_OK(status)) {
2445                 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
2446                 return false;
2447         }
2448
2449         status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
2450                                cli->smb2.tcon, fid_persistent, fid_volatile);
2451         if (!NT_STATUS_IS_OK(status)) {
2452                 printf("smb2cli_flush on a directory returned %s\n",
2453                         nt_errstr(status));
2454                 return false;
2455         }
2456
2457         status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
2458                                cli->smb2.tcon, 0, fid_persistent, fid_volatile);
2459         if (!NT_STATUS_IS_OK(status)) {
2460                 printf("smb2cli_close returned %s\n", nt_errstr(status));
2461                 return false;
2462         }
2463
2464
2465         return true;
2466 }
2467
2468 bool run_smb2_dir_fsync(int dummy)
2469 {
2470         struct cli_state *cli = NULL;
2471         NTSTATUS status;
2472         bool bret = false;
2473         const char *dname = "fsync_test_dir";
2474
2475         printf("Starting SMB2-DIR-FSYNC\n");
2476
2477         if (!torture_init_connection(&cli)) {
2478                 return false;
2479         }
2480
2481         status = smbXcli_negprot(cli->conn, cli->timeout,
2482                                  PROTOCOL_SMB2_02, PROTOCOL_SMB2_02);
2483         if (!NT_STATUS_IS_OK(status)) {
2484                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
2485                 return false;
2486         }
2487
2488         status = cli_session_setup_creds(cli, torture_creds);
2489         if (!NT_STATUS_IS_OK(status)) {
2490                 printf("cli_session_setup returned %s\n", nt_errstr(status));
2491                 return false;
2492         }
2493
2494         status = cli_tree_connect(cli, share, "?????", NULL);
2495         if (!NT_STATUS_IS_OK(status)) {
2496                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
2497                 return false;
2498         }
2499
2500         (void)cli_rmdir(cli, dname);
2501         status = cli_mkdir(cli, dname);
2502         if (!NT_STATUS_IS_OK(status)) {
2503                 printf("cli_mkdir(%s) returned %s\n",
2504                         dname,
2505                         nt_errstr(status));
2506                 return false;
2507         }
2508
2509         /* Test on a subdirectory. */
2510         bret = test_dir_fsync(cli, dname);
2511         if (bret == false) {
2512                 (void)cli_rmdir(cli, dname);
2513                 return false;
2514         }
2515         (void)cli_rmdir(cli, dname);
2516
2517         /* Test on the root handle of a share. */
2518         bret = test_dir_fsync(cli, "");
2519         if (bret == false) {
2520                 return false;
2521         }
2522         return true;
2523 }
2524
2525 bool run_smb2_path_slash(int dummy)
2526 {
2527         struct cli_state *cli = NULL;
2528         NTSTATUS status;
2529         uint64_t fid_persistent;
2530         uint64_t fid_volatile;
2531         const char *dname_noslash = "smb2_dir_slash";
2532         const char *dname_backslash = "smb2_dir_slash\\";
2533         const char *dname_slash = "smb2_dir_slash/";
2534         const char *fname_noslash = "smb2_file_slash";
2535         const char *fname_backslash = "smb2_file_slash\\";
2536         const char *fname_slash = "smb2_file_slash/";
2537
2538         printf("Starting SMB2-PATH-SLASH\n");
2539
2540         if (!torture_init_connection(&cli)) {
2541                 return false;
2542         }
2543
2544         status = smbXcli_negprot(cli->conn, cli->timeout,
2545                                  PROTOCOL_SMB2_02, PROTOCOL_SMB2_02);
2546         if (!NT_STATUS_IS_OK(status)) {
2547                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
2548                 return false;
2549         }
2550
2551         status = cli_session_setup_creds(cli, torture_creds);
2552         if (!NT_STATUS_IS_OK(status)) {
2553                 printf("cli_session_setup returned %s\n", nt_errstr(status));
2554                 return false;
2555         }
2556
2557         status = cli_tree_connect(cli, share, "?????", NULL);
2558         if (!NT_STATUS_IS_OK(status)) {
2559                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
2560                 return false;
2561         }
2562
2563         (void)cli_unlink(cli, dname_noslash, 0);
2564         (void)cli_rmdir(cli, dname_noslash);
2565         (void)cli_unlink(cli, fname_noslash, 0);
2566         (void)cli_rmdir(cli, fname_noslash);
2567
2568         /* Try to create a directory with the backslash name. */
2569         status = smb2cli_create(
2570                 cli->conn,
2571                 cli->timeout,
2572                 cli->smb2.session,
2573                 cli->smb2.tcon,
2574                 dname_backslash,
2575                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2576                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2577                 FILE_READ_DATA|FILE_READ_ATTRIBUTES, /* desired_access, */
2578                 0, /* file_attributes, */
2579                 FILE_SHARE_READ|
2580                 FILE_SHARE_WRITE|
2581                 FILE_SHARE_DELETE, /* share_access, */
2582                 FILE_CREATE, /* create_disposition, */
2583                 FILE_DIRECTORY_FILE, /* create_options, */
2584                 NULL, /* smb2_create_blobs *blobs */
2585                 &fid_persistent,
2586                 &fid_volatile,
2587                 NULL,
2588                 NULL,
2589                 NULL,
2590                 NULL);
2591
2592         /* directory ending in '\\' should be success. */
2593
2594         if (!NT_STATUS_IS_OK(status)) {
2595                 printf("smb2cli_create '%s' returned %s - "
2596                         "should be NT_STATUS_OK\n",
2597                         dname_backslash,
2598                         nt_errstr(status));
2599                 return false;
2600         }
2601         status = smb2cli_close(cli->conn,
2602                                 cli->timeout,
2603                                 cli->smb2.session,
2604                                 cli->smb2.tcon,
2605                                 0,
2606                                 fid_persistent,
2607                                 fid_volatile);
2608         if (!NT_STATUS_IS_OK(status)) {
2609                 printf("smb2cli_close returned %s\n", nt_errstr(status));
2610                 return false;
2611         }
2612
2613         (void)cli_rmdir(cli, dname_noslash);
2614
2615         /* Try to create a directory with the slash name. */
2616         status = smb2cli_create(
2617                 cli->conn,
2618                 cli->timeout,
2619                 cli->smb2.session,
2620                 cli->smb2.tcon,
2621                 dname_slash,
2622                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2623                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2624                 FILE_READ_DATA|FILE_READ_ATTRIBUTES, /* desired_access, */
2625                 0, /* file_attributes, */
2626                 FILE_SHARE_READ|
2627                 FILE_SHARE_WRITE|
2628                 FILE_SHARE_DELETE, /* share_access, */
2629                 FILE_CREATE, /* create_disposition, */
2630                 FILE_DIRECTORY_FILE, /* create_options, */
2631                 NULL, /* smb2_create_blobs *blobs */
2632                 &fid_persistent,
2633                 &fid_volatile,
2634                 NULL,
2635                 NULL,
2636                 NULL,
2637                 NULL);
2638
2639         /* directory ending in '/' is an error. */
2640         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
2641                 printf("smb2cli_create '%s' returned %s - "
2642                         "should be NT_STATUS_OBJECT_NAME_INVALID\n",
2643                         dname_slash,
2644                         nt_errstr(status));
2645                 if (NT_STATUS_IS_OK(status)) {
2646                         (void)smb2cli_close(cli->conn,
2647                                         cli->timeout,
2648                                         cli->smb2.session,
2649                                         cli->smb2.tcon,
2650                                         0,
2651                                         fid_persistent,
2652                                         fid_volatile);
2653                 }
2654                 (void)cli_rmdir(cli, dname_noslash);
2655                 return false;
2656         }
2657
2658         (void)cli_rmdir(cli, dname_noslash);
2659
2660         /* Try to create a file with the backslash name. */
2661         status = smb2cli_create(
2662                 cli->conn,
2663                 cli->timeout,
2664                 cli->smb2.session,
2665                 cli->smb2.tcon,
2666                 fname_backslash,
2667                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2668                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2669                 FILE_READ_DATA|FILE_READ_ATTRIBUTES, /* desired_access, */
2670                 0, /* file_attributes, */
2671                 FILE_SHARE_READ|
2672                 FILE_SHARE_WRITE|
2673                 FILE_SHARE_DELETE, /* share_access, */
2674                 FILE_CREATE, /* create_disposition, */
2675                 FILE_NON_DIRECTORY_FILE, /* create_options, */
2676                 NULL, /* smb2_create_blobs *blobs */
2677                 &fid_persistent,
2678                 &fid_volatile,
2679                 NULL,
2680                 NULL,
2681                 NULL,
2682                 NULL);
2683
2684         /* file ending in '\\' should be error. */
2685
2686         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
2687                 printf("smb2cli_create '%s' returned %s - "
2688                         "should be NT_STATUS_OBJECT_NAME_INVALID\n",
2689                         fname_backslash,
2690                         nt_errstr(status));
2691                 if (NT_STATUS_IS_OK(status)) {
2692                         (void)smb2cli_close(cli->conn,
2693                                         cli->timeout,
2694                                         cli->smb2.session,
2695                                         cli->smb2.tcon,
2696                                         0,
2697                                         fid_persistent,
2698                                         fid_volatile);
2699                 }
2700                 (void)cli_unlink(cli, fname_noslash, 0);
2701                 return false;
2702         }
2703
2704         (void)cli_unlink(cli, fname_noslash, 0);
2705
2706         /* Try to create a file with the slash name. */
2707         status = smb2cli_create(
2708                 cli->conn,
2709                 cli->timeout,
2710                 cli->smb2.session,
2711                 cli->smb2.tcon,
2712                 fname_slash,
2713                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2714                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2715                 FILE_READ_DATA|FILE_READ_ATTRIBUTES, /* desired_access, */
2716                 0, /* file_attributes, */
2717                 FILE_SHARE_READ|
2718                 FILE_SHARE_WRITE|
2719                 FILE_SHARE_DELETE, /* share_access, */
2720                 FILE_CREATE, /* create_disposition, */
2721                 FILE_NON_DIRECTORY_FILE, /* create_options, */
2722                 NULL, /* smb2_create_blobs *blobs */
2723                 &fid_persistent,
2724                 &fid_volatile,
2725                 NULL,
2726                 NULL,
2727                 NULL,
2728                 NULL);
2729
2730         /* file ending in '/' should be error. */
2731
2732         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
2733                 printf("smb2cli_create '%s' returned %s - "
2734                         "should be NT_STATUS_OBJECT_NAME_INVALID\n",
2735                         fname_slash,
2736                         nt_errstr(status));
2737                 if (NT_STATUS_IS_OK(status)) {
2738                         (void)smb2cli_close(cli->conn,
2739                                         cli->timeout,
2740                                         cli->smb2.session,
2741                                         cli->smb2.tcon,
2742                                         0,
2743                                         fid_persistent,
2744                                         fid_volatile);
2745                 }
2746                 (void)cli_unlink(cli, fname_noslash, 0);
2747                 return false;
2748         }
2749
2750         (void)cli_unlink(cli, fname_noslash, 0);
2751         return true;
2752 }
2753
2754 /*
2755  * NB. This can only work against a server where
2756  * the connecting user has been granted SeSecurityPrivilege.
2757  *
2758  *  1). Create a test file.
2759  *  2). Open with SEC_FLAG_SYSTEM_SECURITY *only*. ACCESS_DENIED -
2760  *             NB. SMB2-only behavior.
2761  *  3). Open with SEC_FLAG_SYSTEM_SECURITY|FILE_WRITE_ATTRIBUTES.
2762  *  4). Write SACL. Should fail with ACCESS_DENIED (seems to need WRITE_DAC).
2763  *  5). Close (3).
2764  *  6). Open with SEC_FLAG_SYSTEM_SECURITY|SEC_STD_WRITE_DAC.
2765  *  7). Write SACL. Success.
2766  *  8). Close (4).
2767  *  9). Open with SEC_FLAG_SYSTEM_SECURITY|READ_ATTRIBUTES.
2768  *  10). Read SACL. Success.
2769  *  11). Read DACL. Should fail with ACCESS_DENIED (no READ_CONTROL).
2770  *  12). Close (9).
2771  */
2772
2773 bool run_smb2_sacl(int dummy)
2774 {
2775         struct cli_state *cli = NULL;
2776         NTSTATUS status;
2777         struct security_descriptor *sd_dacl = NULL;
2778         struct security_descriptor *sd_sacl = NULL;
2779         const char *fname = "sacl_test_file";
2780         uint16_t fnum = (uint16_t)-1;
2781
2782         printf("Starting SMB2-SACL\n");
2783
2784         if (!torture_init_connection(&cli)) {
2785                 return false;
2786         }
2787
2788         status = smbXcli_negprot(cli->conn,
2789                                 cli->timeout,
2790                                 PROTOCOL_SMB2_02,
2791                                 PROTOCOL_SMB3_11);
2792         if (!NT_STATUS_IS_OK(status)) {
2793                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
2794                 return false;
2795         }
2796
2797         status = cli_session_setup_creds(cli, torture_creds);
2798         if (!NT_STATUS_IS_OK(status)) {
2799                 printf("cli_session_setup returned %s\n", nt_errstr(status));
2800                 return false;
2801         }
2802
2803         status = cli_tree_connect(cli, share, "?????", NULL);
2804         if (!NT_STATUS_IS_OK(status)) {
2805                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
2806                 return false;
2807         }
2808
2809         (void)cli_unlink(cli, fname, 0);
2810
2811         /* First create a file. */
2812         status = cli_ntcreate(cli,
2813                                 fname,
2814                                 0,
2815                                 GENERIC_ALL_ACCESS,
2816                                 FILE_ATTRIBUTE_NORMAL,
2817                                 FILE_SHARE_NONE,
2818                                 FILE_CREATE,
2819                                 0,
2820                                 0,
2821                                 &fnum,
2822                                 NULL);
2823
2824         if (!NT_STATUS_IS_OK(status)) {
2825                 printf("Create of %s failed (%s)\n",
2826                         fname,
2827                         nt_errstr(status));
2828                 goto fail;
2829         }
2830
2831         cli_close(cli, fnum);
2832         fnum = (uint16_t)-1;
2833
2834         /*
2835          * Now try to open with *only* SEC_FLAG_SYSTEM_SECURITY.
2836          * This should fail with NT_STATUS_ACCESS_DENIED - but
2837          * only against an SMB2 server. SMB1 allows this as tested
2838          * in SMB1-SYSTEM-SECURITY.
2839          */
2840
2841         status = cli_smb2_create_fnum(cli,
2842                         fname,
2843                         SMB2_OPLOCK_LEVEL_NONE,
2844                         SMB2_IMPERSONATION_IMPERSONATION,
2845                         SEC_FLAG_SYSTEM_SECURITY, /* desired access */
2846                         0, /* file_attributes, */
2847                         FILE_SHARE_READ|
2848                                 FILE_SHARE_WRITE|
2849                                 FILE_SHARE_DELETE, /* share_access, */
2850                         FILE_OPEN, /* create_disposition, */
2851                         FILE_NON_DIRECTORY_FILE, /* create_options, */
2852                         NULL, /* in_cblobs. */
2853                         &fnum, /* fnum */
2854                         NULL, /* smb_create_returns  */
2855                         talloc_tos(), /* mem_ctx */
2856                         NULL); /* out_cblobs */
2857
2858         if (NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
2859                 printf("SMB2-SACL-TEST can only work with a user "
2860                         "who has been granted SeSecurityPrivilege.\n"
2861                         "This is the "
2862                         "\"Manage auditing and security log\""
2863                         "privilege setting on Windows\n");
2864                 goto fail;
2865         }
2866
2867         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2868                 printf("open file %s with SEC_FLAG_SYSTEM_SECURITY only: "
2869                         "got %s - should fail with ACCESS_DENIED\n",
2870                         fname,
2871                         nt_errstr(status));
2872                 goto fail;
2873         }
2874
2875         /*
2876          * Open with SEC_FLAG_SYSTEM_SECURITY|FILE_WRITE_ATTRIBUTES.
2877          */
2878
2879         status = cli_smb2_create_fnum(cli,
2880                         fname,
2881                         SMB2_OPLOCK_LEVEL_NONE,
2882                         SMB2_IMPERSONATION_IMPERSONATION,
2883                         SEC_FLAG_SYSTEM_SECURITY|
2884                                 FILE_WRITE_ATTRIBUTES, /* desired access */
2885                         0, /* file_attributes, */
2886                         FILE_SHARE_READ|
2887                                 FILE_SHARE_WRITE|
2888                                 FILE_SHARE_DELETE, /* share_access, */
2889                         FILE_OPEN, /* create_disposition, */
2890                         FILE_NON_DIRECTORY_FILE, /* create_options, */
2891                         NULL, /* in_cblobs. */
2892                         &fnum, /* fnum */
2893                         NULL, /* smb_create_returns  */
2894                         talloc_tos(), /* mem_ctx */
2895                         NULL); /* out_cblobs */
2896
2897         if (!NT_STATUS_IS_OK(status)) {
2898                 printf("Open of %s with (SEC_FLAG_SYSTEM_SECURITY|"
2899                         "FILE_WRITE_ATTRIBUTES) failed (%s)\n",
2900                         fname,
2901                         nt_errstr(status));
2902                 goto fail;
2903         }
2904
2905         /* Create an SD with a SACL. */
2906         sd_sacl = security_descriptor_sacl_create(talloc_tos(),
2907                                 0,
2908                                 NULL, /* owner. */
2909                                 NULL, /* group. */
2910                                 /* first ACE. */
2911                                 SID_WORLD,
2912                                 SEC_ACE_TYPE_SYSTEM_AUDIT,
2913                                 SEC_GENERIC_ALL,
2914                                 SEC_ACE_FLAG_FAILED_ACCESS,
2915                                 NULL);
2916
2917         if (sd_sacl == NULL) {
2918                 printf("Out of memory creating SACL\n");
2919                 goto fail;
2920         }
2921
2922         /*
2923          * Write the SACL SD. This should fail
2924          * even though we have SEC_FLAG_SYSTEM_SECURITY,
2925          * as it seems to also need WRITE_DAC access.
2926          */
2927         status = cli_set_security_descriptor(cli,
2928                                 fnum,
2929                                 SECINFO_DACL|SECINFO_SACL,
2930                                 sd_sacl);
2931
2932         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2933                 printf("Writing SACL on file %s got (%s) "
2934                         "should have failed with ACCESS_DENIED.\n",
2935                         fname,
2936                         nt_errstr(status));
2937                 goto fail;
2938         }
2939
2940         /* And close. */
2941         cli_smb2_close_fnum(cli, fnum);
2942         fnum = (uint16_t)-1;
2943
2944         /*
2945          * Open with SEC_FLAG_SYSTEM_SECURITY|SEC_STD_WRITE_DAC.
2946          */
2947
2948         status = cli_smb2_create_fnum(cli,
2949                         fname,
2950                         SMB2_OPLOCK_LEVEL_NONE,
2951                         SMB2_IMPERSONATION_IMPERSONATION,
2952                         SEC_FLAG_SYSTEM_SECURITY|
2953                                 SEC_STD_WRITE_DAC, /* desired access */
2954                         0, /* file_attributes, */
2955                         FILE_SHARE_READ|
2956                                 FILE_SHARE_WRITE|
2957                                 FILE_SHARE_DELETE, /* share_access, */
2958                         FILE_OPEN, /* create_disposition, */
2959                         FILE_NON_DIRECTORY_FILE, /* create_options, */
2960                         NULL, /* in_cblobs. */
2961                         &fnum, /* fnum */
2962                         NULL, /* smb_create_returns  */
2963                         talloc_tos(), /* mem_ctx */
2964                         NULL); /* out_cblobs */
2965
2966         if (!NT_STATUS_IS_OK(status)) {
2967                 printf("Open of %s with (SEC_FLAG_SYSTEM_SECURITY|"
2968                         "FILE_WRITE_ATTRIBUTES) failed (%s)\n",
2969                         fname,
2970                         nt_errstr(status));
2971                 goto fail;
2972         }
2973
2974         /*
2975          * Write the SACL SD. This should now succeed
2976          * as we have both SEC_FLAG_SYSTEM_SECURITY
2977          * and WRITE_DAC access.
2978          */
2979         status = cli_set_security_descriptor(cli,
2980                                 fnum,
2981                                 SECINFO_DACL|SECINFO_SACL,
2982                                 sd_sacl);
2983
2984         if (!NT_STATUS_IS_OK(status)) {
2985                 printf("cli_set_security_descriptor SACL "
2986                         "on file %s failed (%s)\n",
2987                         fname,
2988                         nt_errstr(status));
2989                 goto fail;
2990         }
2991
2992         /* And close. */
2993         cli_smb2_close_fnum(cli, fnum);
2994         fnum = (uint16_t)-1;
2995
2996         /* We're done with the sacl we made. */
2997         TALLOC_FREE(sd_sacl);
2998
2999         /*
3000          * Now try to open with SEC_FLAG_SYSTEM_SECURITY|READ_ATTRIBUTES.
3001          * This gives us access to the SACL.
3002          */
3003
3004         status = cli_smb2_create_fnum(cli,
3005                         fname,
3006                         SMB2_OPLOCK_LEVEL_NONE,
3007                         SMB2_IMPERSONATION_IMPERSONATION,
3008                         SEC_FLAG_SYSTEM_SECURITY|
3009                                 FILE_READ_ATTRIBUTES, /* desired access */
3010                         0, /* file_attributes, */
3011                         FILE_SHARE_READ|
3012                                 FILE_SHARE_WRITE|
3013                                 FILE_SHARE_DELETE, /* share_access, */
3014                         FILE_OPEN, /* create_disposition, */
3015                         FILE_NON_DIRECTORY_FILE, /* create_options, */
3016                         NULL, /* in_cblobs. */
3017                         &fnum, /* fnum */
3018                         NULL, /* smb_create_returns  */
3019                         talloc_tos(), /* mem_ctx */
3020                         NULL); /* out_cblobs */
3021
3022         if (!NT_STATUS_IS_OK(status)) {
3023                 printf("Open of %s with (SEC_FLAG_SYSTEM_SECURITY|"
3024                         "FILE_READ_ATTRIBUTES) failed (%s)\n",
3025                         fname,
3026                         nt_errstr(status));
3027                 goto fail;
3028         }
3029
3030         /* Try and read the SACL - should succeed. */
3031         status = cli_query_security_descriptor(
3032                 cli, fnum, SECINFO_SACL, talloc_tos(), &sd_sacl);
3033
3034         if (!NT_STATUS_IS_OK(status)) {
3035                 printf("Read SACL from file %s failed (%s)\n",
3036                         fname,
3037                         nt_errstr(status));
3038                 goto fail;
3039         }
3040
3041         TALLOC_FREE(sd_sacl);
3042
3043         /*
3044          * Try and read the DACL - should fail as we have
3045          * no READ_DAC access.
3046          */
3047         status = cli_query_security_descriptor(
3048                 cli, fnum, SECINFO_DACL, talloc_tos(), &sd_sacl);
3049
3050         if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
3051                 printf("Reading DACL on file %s got (%s) "
3052                         "should have failed with ACCESS_DENIED.\n",
3053                         fname,
3054                         nt_errstr(status));
3055                 goto fail;
3056         }
3057
3058         if (fnum != (uint16_t)-1) {
3059                 cli_smb2_close_fnum(cli, fnum);
3060                 fnum = (uint16_t)-1;
3061         }
3062
3063         TALLOC_FREE(sd_dacl);
3064         TALLOC_FREE(sd_sacl);
3065
3066         (void)cli_unlink(cli, fname, 0);
3067         return true;
3068
3069   fail:
3070
3071         TALLOC_FREE(sd_dacl);
3072         TALLOC_FREE(sd_sacl);
3073
3074         if (fnum != (uint16_t)-1) {
3075                 cli_smb2_close_fnum(cli, fnum);
3076                 fnum = (uint16_t)-1;
3077         }
3078
3079         (void)cli_unlink(cli, fname, 0);
3080         return false;
3081 }
3082
3083 bool run_smb2_quota1(int dummy)
3084 {
3085         struct cli_state *cli = NULL;
3086         NTSTATUS status;
3087         uint16_t fnum = (uint16_t)-1;
3088         SMB_NTQUOTA_STRUCT qt = {0};
3089
3090         printf("Starting SMB2-QUOTA1\n");
3091
3092         if (!torture_init_connection(&cli)) {
3093                 return false;
3094         }
3095
3096         status = smbXcli_negprot(cli->conn,
3097                                 cli->timeout,
3098                                 PROTOCOL_SMB2_02,
3099                                 PROTOCOL_SMB3_11);
3100         if (!NT_STATUS_IS_OK(status)) {
3101                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
3102                 return false;
3103         }
3104
3105         status = cli_session_setup_creds(cli, torture_creds);
3106         if (!NT_STATUS_IS_OK(status)) {
3107                 printf("cli_session_setup returned %s\n", nt_errstr(status));
3108                 return false;
3109         }
3110
3111         status = cli_tree_connect(cli, share, "?????", NULL);
3112         if (!NT_STATUS_IS_OK(status)) {
3113                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
3114                 return false;
3115         }
3116
3117         status = cli_smb2_create_fnum(
3118                 cli,
3119                 "\\",
3120                 SMB2_OPLOCK_LEVEL_NONE,
3121                 SMB2_IMPERSONATION_IMPERSONATION,
3122                 SEC_GENERIC_READ, /* desired access */
3123                 0, /* file_attributes, */
3124                 FILE_SHARE_READ|
3125                 FILE_SHARE_WRITE|
3126                 FILE_SHARE_DELETE, /* share_access, */
3127                 FILE_OPEN, /* create_disposition, */
3128                 FILE_DIRECTORY_FILE, /* create_options, */
3129                 NULL, /* in_cblobs. */
3130                 &fnum, /* fnum */
3131                 NULL, /* smb_create_returns  */
3132                 NULL, /* mem_ctx */
3133                 NULL); /* out_cblobs */
3134         if (!NT_STATUS_IS_OK(status)) {
3135                 printf("cli_smb2_create_fnum failed: %s\n", nt_errstr(status));
3136                 return false;
3137         }
3138
3139         status = cli_smb2_get_user_quota(cli, fnum, &qt);
3140         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
3141                 printf("cli_smb2_get_user_quota returned %s, expected "
3142                        "NT_STATUS_INVALID_HANDLE\n",
3143                        nt_errstr(status));
3144                 return false;
3145         }
3146
3147         return true;
3148 }
3149
3150 bool run_smb2_stream_acl(int dummy)
3151 {
3152         struct cli_state *cli = NULL;
3153         NTSTATUS status;
3154         uint16_t fnum = (uint16_t)-1;
3155         const char *fname = "stream_acl_test_file";
3156         const char *sname = "stream_acl_test_file:streamname";
3157         struct security_descriptor *sd_dacl = NULL;
3158         bool ret = false;
3159
3160         printf("SMB2 stream acl\n");
3161
3162         if (!torture_init_connection(&cli)) {
3163                 return false;
3164         }
3165
3166         status = smbXcli_negprot(cli->conn,
3167                                 cli->timeout,
3168                                 PROTOCOL_SMB2_02,
3169                                 PROTOCOL_SMB3_11);
3170         if (!NT_STATUS_IS_OK(status)) {
3171                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
3172                 return false;
3173         }
3174
3175         status = cli_session_setup_creds(cli, torture_creds);
3176         if (!NT_STATUS_IS_OK(status)) {
3177                 printf("cli_session_setup returned %s\n", nt_errstr(status));
3178                 return false;
3179         }
3180
3181         status = cli_tree_connect(cli, share, "?????", NULL);
3182         if (!NT_STATUS_IS_OK(status)) {
3183                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
3184                 return false;
3185         }
3186
3187         /* Ensure file doesn't exist. */
3188         (void)cli_unlink(cli, fname, 0);
3189
3190         /* Create the file. */
3191         status = cli_ntcreate(cli,
3192                                 fname,
3193                                 0,
3194                                 GENERIC_ALL_ACCESS,
3195                                 FILE_ATTRIBUTE_NORMAL,
3196                                 FILE_SHARE_NONE,
3197                                 FILE_CREATE,
3198                                 0,
3199                                 0,
3200                                 &fnum,
3201                                 NULL);
3202
3203         if (!NT_STATUS_IS_OK(status)) {
3204                 printf("Create of %s failed (%s)\n",
3205                         fname,
3206                         nt_errstr(status));
3207                 goto fail;
3208         }
3209
3210         /* Close the handle. */
3211         cli_smb2_close_fnum(cli, fnum);
3212         fnum = (uint16_t)-1;
3213
3214         /* Create the stream. */
3215         status = cli_ntcreate(cli,
3216                                 sname,
3217                                 0,
3218                                 FILE_READ_DATA|
3219                                         SEC_STD_READ_CONTROL|
3220                                         SEC_STD_WRITE_DAC,
3221                                 FILE_ATTRIBUTE_NORMAL,
3222                                 FILE_SHARE_NONE,
3223                                 FILE_CREATE,
3224                                 0,
3225                                 0,
3226                                 &fnum,
3227                                 NULL);
3228
3229         if (!NT_STATUS_IS_OK(status)) {
3230                 printf("Create of %s failed (%s)\n",
3231                         sname,
3232                         nt_errstr(status));
3233                 goto fail;
3234         }
3235
3236         /* Close the handle. */
3237         cli_smb2_close_fnum(cli, fnum);
3238         fnum = (uint16_t)-1;
3239
3240         /*
3241          * Open the stream - for Samba this ensures
3242          * we prove we have a pathref fsp.
3243          */
3244         status = cli_ntcreate(cli,
3245                                 sname,
3246                                 0,
3247                                 FILE_READ_DATA|
3248                                         SEC_STD_READ_CONTROL|
3249                                         SEC_STD_WRITE_DAC,
3250                                 FILE_ATTRIBUTE_NORMAL,
3251                                 FILE_SHARE_NONE,
3252                                 FILE_OPEN,
3253                                 0,
3254                                 0,
3255                                 &fnum,
3256                                 NULL);
3257
3258         if (!NT_STATUS_IS_OK(status)) {
3259                 printf("Open of %s failed (%s)\n",
3260                         sname,
3261                         nt_errstr(status));
3262                 goto fail;
3263         }
3264
3265         /* Read the security descriptor off the stream handle. */
3266         status = cli_query_security_descriptor(cli,
3267                                 fnum,
3268                                 SECINFO_DACL,
3269                                 talloc_tos(),
3270                                 &sd_dacl);
3271
3272         if (!NT_STATUS_IS_OK(status)) {
3273                 printf("Reading DACL on stream %s got (%s)\n",
3274                         sname,
3275                         nt_errstr(status));
3276                 goto fail;
3277         }
3278
3279         if (sd_dacl == NULL || sd_dacl->dacl == NULL ||
3280                         sd_dacl->dacl->num_aces < 1) {
3281                 printf("Invalid DACL returned on stream %s "
3282                         "(this should not happen)\n",
3283                         sname);
3284                 goto fail;
3285         }
3286
3287         /*
3288          * Ensure it allows FILE_READ_DATA in the first ace.
3289          * It always should.
3290          */
3291         if ((sd_dacl->dacl->aces[0].access_mask & FILE_READ_DATA) == 0) {
3292                 printf("DACL->ace[0] returned on stream %s "
3293                         "doesn't have read access (should not happen)\n",
3294                         sname);
3295                 goto fail;
3296         }
3297
3298         /* Remove FILE_READ_DATA from the first ace and set. */
3299         sd_dacl->dacl->aces[0].access_mask &= ~FILE_READ_DATA;
3300
3301         status = cli_set_security_descriptor(cli,
3302                                 fnum,
3303                                 SECINFO_DACL,
3304                                 sd_dacl);
3305
3306         if (!NT_STATUS_IS_OK(status)) {
3307                 printf("Setting DACL on stream %s got (%s)\n",
3308                         sname,
3309                         nt_errstr(status));
3310                 goto fail;
3311         }
3312
3313         TALLOC_FREE(sd_dacl);
3314
3315         /* Read again and check it changed. */
3316         status = cli_query_security_descriptor(cli,
3317                                 fnum,
3318                                 SECINFO_DACL,
3319                                 talloc_tos(),
3320                                 &sd_dacl);
3321
3322         if (!NT_STATUS_IS_OK(status)) {
3323                 printf("Reading DACL on stream %s got (%s)\n",
3324                         sname,
3325                         nt_errstr(status));
3326                 goto fail;
3327         }
3328
3329         if (sd_dacl == NULL || sd_dacl->dacl == NULL ||
3330                         sd_dacl->dacl->num_aces < 1) {
3331                 printf("Invalid DACL (1) returned on stream %s "
3332                         "(this should not happen)\n",
3333                         sname);
3334                 goto fail;
3335         }
3336
3337         /* FILE_READ_DATA should be gone from the first ace. */
3338         if ((sd_dacl->dacl->aces[0].access_mask & FILE_READ_DATA) != 0) {
3339                 printf("DACL on stream %s did not change\n",
3340                         sname);
3341                 goto fail;
3342         }
3343
3344         ret = true;
3345
3346   fail:
3347
3348         if (fnum != (uint16_t)-1) {
3349                 cli_smb2_close_fnum(cli, fnum);
3350                 fnum = (uint16_t)-1;
3351         }
3352
3353         (void)cli_unlink(cli, fname, 0);
3354         return ret;
3355 }
3356
3357 static NTSTATUS list_fn(struct file_info *finfo,
3358                         const char *name,
3359                         void *state)
3360 {
3361         bool *matched = (bool *)state;
3362         if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
3363                 *matched = true;
3364         }
3365         return NT_STATUS_OK;
3366 }
3367
3368 /*
3369  * Must be run against a share with "smbd async dosmode = yes".
3370  * Checks we can return DOS attriutes other than "N".
3371  * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14758
3372  */
3373
3374 bool run_list_dir_async_test(int dummy)
3375 {
3376         struct cli_state *cli = NULL;
3377         NTSTATUS status;
3378         const char *dname = "ASYNC_DIR";
3379         bool ret = false;
3380         bool matched = false;
3381
3382         printf("SMB2 list dir async\n");
3383
3384         if (!torture_init_connection(&cli)) {
3385                 return false;
3386         }
3387
3388         status = smbXcli_negprot(cli->conn,
3389                                 cli->timeout,
3390                                 PROTOCOL_SMB2_02,
3391                                 PROTOCOL_SMB3_11);
3392         if (!NT_STATUS_IS_OK(status)) {
3393                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
3394                 return false;
3395         }
3396
3397         status = cli_session_setup_creds(cli, torture_creds);
3398         if (!NT_STATUS_IS_OK(status)) {
3399                 printf("cli_session_setup returned %s\n", nt_errstr(status));
3400                 return false;
3401         }
3402
3403         status = cli_tree_connect(cli, share, "?????", NULL);
3404         if (!NT_STATUS_IS_OK(status)) {
3405                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
3406                 return false;
3407         }
3408
3409         /* Ensure directory doesn't exist. */
3410         (void)cli_rmdir(cli, dname);
3411
3412         status = cli_mkdir(cli, dname);
3413         if (!NT_STATUS_IS_OK(status)) {
3414                 printf("cli_mkdir %s returned %s\n", dname, nt_errstr(status));
3415                 return false;
3416         }
3417
3418         status = cli_list(cli,
3419                           dname,
3420                           FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_DIRECTORY,
3421                           list_fn,
3422                           &matched);
3423         if (!NT_STATUS_IS_OK(status)) {
3424                 printf("cli_list %s returned %s\n", dname, nt_errstr(status));
3425                 goto fail;
3426         }
3427
3428         if (!matched) {
3429                 printf("Failed to find %s\n", dname);
3430                 goto fail;
3431         }
3432
3433         ret = true;
3434
3435   fail:
3436
3437         (void)cli_rmdir(cli, dname);
3438         return ret;
3439 }
3440
3441 /*
3442  * Test delete a directory fails if a file is created
3443  * in a directory after the delete on close is set.
3444  * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14892
3445  */
3446
3447 bool run_delete_on_close_non_empty(int dummy)
3448 {
3449         struct cli_state *cli = NULL;
3450         NTSTATUS status;
3451         const char *dname = "DEL_ON_CLOSE_DIR";
3452         const char *fname = "DEL_ON_CLOSE_DIR\\testfile";
3453         uint16_t fnum = (uint16_t)-1;
3454         uint16_t fnum1 = (uint16_t)-1;
3455         bool ret = false;
3456
3457         printf("SMB2 delete on close nonempty\n");
3458
3459         if (!torture_init_connection(&cli)) {
3460                 return false;
3461         }
3462
3463         status = smbXcli_negprot(cli->conn,
3464                                 cli->timeout,
3465                                 PROTOCOL_SMB2_02,
3466                                 PROTOCOL_SMB3_11);
3467         if (!NT_STATUS_IS_OK(status)) {
3468                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
3469                 return false;
3470         }
3471
3472         status = cli_session_setup_creds(cli, torture_creds);
3473         if (!NT_STATUS_IS_OK(status)) {
3474                 printf("cli_session_setup returned %s\n", nt_errstr(status));
3475                 return false;
3476         }
3477
3478         status = cli_tree_connect(cli, share, "?????", NULL);
3479         if (!NT_STATUS_IS_OK(status)) {
3480                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
3481                 return false;
3482         }
3483
3484         /* Ensure directory doesn't exist. */
3485         (void)cli_unlink(cli,
3486                          fname,
3487                          FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3488         (void)cli_rmdir(cli, dname);
3489
3490         /* Create target directory. */
3491         status = cli_ntcreate(cli,
3492                                 dname,
3493                                 0,
3494                                 DELETE_ACCESS|FILE_READ_DATA,
3495                                 FILE_ATTRIBUTE_DIRECTORY,
3496                                 FILE_SHARE_READ|
3497                                         FILE_SHARE_WRITE|
3498                                         FILE_SHARE_DELETE,
3499                                 FILE_CREATE,
3500                                 FILE_DIRECTORY_FILE,
3501                                 0,
3502                                 &fnum,
3503                                 NULL);
3504         if (!NT_STATUS_IS_OK(status)) {
3505                 printf("cli_ntcreate for directory %s returned %s\n",
3506                                 dname,
3507                                 nt_errstr(status));
3508                 goto out;
3509         }
3510
3511         /* Now set the delete on close bit. */
3512         status = cli_nt_delete_on_close(cli, fnum, 1);
3513         if (!NT_STATUS_IS_OK(status)) {
3514                 printf("cli_cli_nt_delete_on_close set for directory "
3515                         "%s returned %s\n",
3516                         dname,
3517                         nt_errstr(status));
3518                 goto out;
3519         }
3520
3521         /* Create file inside target directory. */
3522         /*
3523          * NB. On Windows this will return NT_STATUS_DELETE_PENDING.  Only on
3524          * Samba will this succeed by default (the option "check parent
3525          * directory delete on close" configures behaviour), but we're using
3526          * this to test a race condition.
3527          */
3528         status = cli_ntcreate(cli,
3529                                 fname,
3530                                 0,
3531                                 FILE_READ_DATA,
3532                                 FILE_ATTRIBUTE_NORMAL,
3533                                 FILE_SHARE_READ|
3534                                         FILE_SHARE_WRITE|
3535                                         FILE_SHARE_DELETE,
3536                                 FILE_CREATE,
3537                                 0,
3538                                 0,
3539                                 &fnum1,
3540                                 NULL);
3541         if (!NT_STATUS_IS_OK(status)) {
3542                 printf("cli_ntcreate for file %s returned %s\n",
3543                                 fname,
3544                                 nt_errstr(status));
3545                 goto out;
3546         }
3547         cli_close(cli, fnum1);
3548         fnum1 = (uint16_t)-1;
3549
3550         /* Now the close should fail. */
3551         status = cli_close(cli, fnum);
3552         if (!NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
3553                 printf("cli_close for directory %s returned %s\n",
3554                                 dname,
3555                                 nt_errstr(status));
3556                 goto out;
3557         }
3558
3559         ret = true;
3560
3561   out:
3562
3563         if (fnum1 != (uint16_t)-1) {
3564                 cli_close(cli, fnum1);
3565         }
3566         if (fnum != (uint16_t)-1) {
3567                 cli_nt_delete_on_close(cli, fnum, 0);
3568                 cli_close(cli, fnum);
3569         }
3570         (void)cli_unlink(cli,
3571                          fname,
3572                          FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3573         (void)cli_rmdir(cli, dname);
3574         return ret;
3575 }
3576
3577 static NTSTATUS check_empty_fn(struct file_info *finfo,
3578                                 const char *mask,
3579                                 void *private_data)
3580 {
3581         unsigned int *pcount = (unsigned int *)private_data;
3582
3583         if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
3584                 (*pcount)++;
3585                 return NT_STATUS_OK;
3586         }
3587         return NT_STATUS_DIRECTORY_NOT_EMPTY;
3588 }
3589
3590 /*
3591  * Test setting the delete on close bit on a directory
3592  * containing an unwritable file fails or succeeds
3593  * an a share set with "hide unwritable = yes"
3594  * depending on the setting of "delete veto files".
3595  * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15023
3596  *
3597  * First version. With "delete veto files = yes"
3598  * setting the delete on close should succeed.
3599  */
3600
3601 bool run_delete_on_close_nonwrite_delete_yes_test(int dummy)
3602 {
3603         struct cli_state *cli = NULL;
3604         NTSTATUS status;
3605         const char *dname = "delete_veto_yes";
3606         const char *list_dname = "delete_veto_yes\\*";
3607         uint16_t fnum = (uint16_t)-1;
3608         bool ret = false;
3609         unsigned int list_count = 0;
3610
3611         printf("SMB2 delete on close nonwrite - delete veto yes\n");
3612
3613         if (!torture_init_connection(&cli)) {
3614                 return false;
3615         }
3616
3617         status = smbXcli_negprot(cli->conn,
3618                                 cli->timeout,
3619                                 PROTOCOL_SMB2_02,
3620                                 PROTOCOL_SMB3_11);
3621         if (!NT_STATUS_IS_OK(status)) {
3622                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
3623                 return false;
3624         }
3625
3626         status = cli_session_setup_creds(cli, torture_creds);
3627         if (!NT_STATUS_IS_OK(status)) {
3628                 printf("cli_session_setup returned %s\n", nt_errstr(status));
3629                 return false;
3630         }
3631
3632         status = cli_tree_connect(cli, share, "?????", NULL);
3633         if (!NT_STATUS_IS_OK(status)) {
3634                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
3635                 return false;
3636         }
3637
3638         /* Ensure target directory is seen as empty. */
3639         status = cli_list(cli,
3640                         list_dname,
3641                         FILE_ATTRIBUTE_DIRECTORY |
3642                                 FILE_ATTRIBUTE_HIDDEN |
3643                                 FILE_ATTRIBUTE_SYSTEM,
3644                         check_empty_fn,
3645                         &list_count);
3646         if (!NT_STATUS_IS_OK(status)) {
3647                 printf("cli_list of %s returned %s\n",
3648                         dname,
3649                         nt_errstr(status));
3650                 return false;
3651         }
3652         if (list_count != 2) {
3653                 printf("cli_list of %s returned a count of %u\n",
3654                         dname,
3655                         list_count);
3656                 return false;
3657         }
3658
3659         /* Open target directory. */
3660         status = cli_ntcreate(cli,
3661                                 dname,
3662                                 0,
3663                                 DELETE_ACCESS|FILE_READ_DATA,
3664                                 FILE_ATTRIBUTE_DIRECTORY,
3665                                 FILE_SHARE_READ|
3666                                         FILE_SHARE_WRITE|
3667                                         FILE_SHARE_DELETE,
3668                                 FILE_OPEN,
3669                                 FILE_DIRECTORY_FILE,
3670                                 0,
3671                                 &fnum,
3672                                 NULL);
3673         if (!NT_STATUS_IS_OK(status)) {
3674                 printf("cli_ntcreate for directory %s returned %s\n",
3675                                 dname,
3676                                 nt_errstr(status));
3677                 goto out;
3678         }
3679
3680         /* Now set the delete on close bit. */
3681         status = cli_nt_delete_on_close(cli, fnum, 1);
3682         if (!NT_STATUS_IS_OK(status)) {
3683                 printf("cli_cli_nt_delete_on_close set for directory "
3684                         "%s returned %s (should have succeeded)\n",
3685                         dname,
3686                         nt_errstr(status));
3687                 goto out;
3688         }
3689
3690         ret = true;
3691
3692   out:
3693
3694         if (fnum != (uint16_t)-1) {
3695                 (void)cli_nt_delete_on_close(cli, fnum, 0);
3696                 (void)cli_close(cli, fnum);
3697         }
3698         return ret;
3699 }
3700
3701 /*
3702  * Test setting the delete on close bit on a directory
3703  * containing an unwritable file fails or succeeds
3704  * an a share set with "hide unwritable = yes"
3705  * depending on the setting of "delete veto files".
3706  * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15023
3707  *
3708  * Second version. With "delete veto files = no"
3709  * setting the delete on close should fail.
3710  */
3711
3712 bool run_delete_on_close_nonwrite_delete_no_test(int dummy)
3713 {
3714         struct cli_state *cli = NULL;
3715         NTSTATUS status;
3716         const char *dname = "delete_veto_no";
3717         const char *list_dname = "delete_veto_no\\*";
3718         uint16_t fnum = (uint16_t)-1;
3719         bool ret = false;
3720         unsigned int list_count = 0;
3721
3722         printf("SMB2 delete on close nonwrite - delete veto yes\n");
3723
3724         if (!torture_init_connection(&cli)) {
3725                 return false;
3726         }
3727
3728         status = smbXcli_negprot(cli->conn,
3729                                 cli->timeout,
3730                                 PROTOCOL_SMB2_02,
3731                                 PROTOCOL_SMB3_11);
3732         if (!NT_STATUS_IS_OK(status)) {
3733                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
3734                 return false;
3735         }
3736
3737         status = cli_session_setup_creds(cli, torture_creds);
3738         if (!NT_STATUS_IS_OK(status)) {
3739                 printf("cli_session_setup returned %s\n", nt_errstr(status));
3740                 return false;
3741         }
3742
3743         status = cli_tree_connect(cli, share, "?????", NULL);
3744         if (!NT_STATUS_IS_OK(status)) {
3745                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
3746                 return false;
3747         }
3748
3749         /* Ensure target directory is seen as empty. */
3750         status = cli_list(cli,
3751                         list_dname,
3752                         FILE_ATTRIBUTE_DIRECTORY |
3753                                 FILE_ATTRIBUTE_HIDDEN |
3754                                 FILE_ATTRIBUTE_SYSTEM,
3755                         check_empty_fn,
3756                         &list_count);
3757         if (!NT_STATUS_IS_OK(status)) {
3758                 printf("cli_list of %s returned %s\n",
3759                         dname,
3760                         nt_errstr(status));
3761                 return false;
3762         }
3763         if (list_count != 2) {
3764                 printf("cli_list of %s returned a count of %u\n",
3765                         dname,
3766                         list_count);
3767                 return false;
3768         }
3769
3770         /* Open target directory. */
3771         status = cli_ntcreate(cli,
3772                                 dname,
3773                                 0,
3774                                 DELETE_ACCESS|FILE_READ_DATA,
3775                                 FILE_ATTRIBUTE_DIRECTORY,
3776                                 FILE_SHARE_READ|
3777                                         FILE_SHARE_WRITE|
3778                                         FILE_SHARE_DELETE,
3779                                 FILE_OPEN,
3780                                 FILE_DIRECTORY_FILE,
3781                                 0,
3782                                 &fnum,
3783                                 NULL);
3784         if (!NT_STATUS_IS_OK(status)) {
3785                 printf("cli_ntcreate for directory %s returned %s\n",
3786                                 dname,
3787                                 nt_errstr(status));
3788                 goto out;
3789         }
3790
3791         /* Now set the delete on close bit. */
3792         status = cli_nt_delete_on_close(cli, fnum, 1);
3793         if (NT_STATUS_IS_OK(status)) {
3794                 printf("cli_cli_nt_delete_on_close set for directory "
3795                         "%s returned NT_STATUS_OK "
3796                         "(should have failed)\n",
3797                         dname);
3798                 goto out;
3799         }
3800         if (!NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
3801                 printf("cli_cli_nt_delete_on_close set for directory "
3802                         "%s returned %s "
3803                         "(should have returned "
3804                         "NT_STATUS_DIRECTORY_NOT_EMPTY)\n",
3805                         dname,
3806                         nt_errstr(status));
3807                 goto out;
3808         }
3809
3810         ret = true;
3811
3812   out:
3813
3814         if (fnum != (uint16_t)-1) {
3815                 (void)cli_nt_delete_on_close(cli, fnum, 0);
3816                 (void)cli_close(cli, fnum);
3817         }
3818         return ret;
3819 }
3820
3821 /*
3822  * Open an SMB2 file readonly and return the inode number.
3823  */
3824 static NTSTATUS get_smb2_inode(struct cli_state *cli,
3825                                 const char *pathname,
3826                                 uint64_t *ino_ret)
3827 {
3828         NTSTATUS status;
3829         uint64_t fid_persistent = 0;
3830         uint64_t fid_volatile = 0;
3831         DATA_BLOB outbuf = data_blob_null;
3832         /*
3833          * Open the file.
3834          */
3835         status = smb2cli_create(cli->conn,
3836                                 cli->timeout,
3837                                 cli->smb2.session,
3838                                 cli->smb2.tcon,
3839                                 pathname,
3840                                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
3841                                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
3842                                 SEC_STD_SYNCHRONIZE|
3843                                         SEC_FILE_READ_DATA|
3844                                         SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
3845                                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
3846                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
3847                                 FILE_OPEN, /* create_disposition, */
3848                                 0, /* create_options, */
3849                                 NULL, /* smb2_create_blobs *blobs */
3850                                 &fid_persistent,
3851                                 &fid_volatile,
3852                                 NULL, /* struct smb_create_returns * */
3853                                 talloc_tos(), /* mem_ctx. */
3854                                 NULL, /* struct smb2_create_blobs * */
3855                                 NULL); /* struct symlink_reparse_struct */
3856         if (!NT_STATUS_IS_OK(status)) {
3857                 return status;
3858         }
3859
3860         /*
3861          * Get the inode.
3862          */
3863         status = smb2cli_query_info(cli->conn,
3864                                     cli->timeout,
3865                                     cli->smb2.session,
3866                                     cli->smb2.tcon,
3867                                     SMB2_0_INFO_FILE,
3868                                     (SMB_FILE_ALL_INFORMATION - 1000), /* in_file_info_class */
3869                                     1024, /* in_max_output_length */
3870                                     NULL, /* in_input_buffer */
3871                                     0, /* in_additional_info */
3872                                     0, /* in_flags */
3873                                     fid_persistent,
3874                                     fid_volatile,
3875                                     talloc_tos(),
3876                                     &outbuf);
3877
3878         if (NT_STATUS_IS_OK(status)) {
3879                 *ino_ret = PULL_LE_U64(outbuf.data, 0x40);
3880         }
3881
3882         (void)smb2cli_close(cli->conn,
3883                             cli->timeout,
3884                             cli->smb2.session,
3885                             cli->smb2.tcon,
3886                             0,
3887                             fid_persistent,
3888                             fid_volatile);
3889         return status;
3890 }
3891
3892 /*
3893  * Check an inode matches a given SMB2 path.
3894  */
3895 static bool smb2_inode_matches(struct cli_state *cli,
3896                                 const char *match_pathname,
3897                                 uint64_t ino_tomatch,
3898                                 const char *test_pathname)
3899 {
3900         uint64_t test_ino = 0;
3901         NTSTATUS status;
3902
3903         status = get_smb2_inode(cli,
3904                                 test_pathname,
3905                                 &test_ino);
3906         if (!NT_STATUS_IS_OK(status)) {
3907                 printf("%s: Failed to get ino "
3908                         "number for %s, (%s)\n",
3909                         __func__,
3910                         test_pathname,
3911                         nt_errstr(status));
3912                 return false;
3913         }
3914         if (test_ino != ino_tomatch) {
3915                 printf("%s: Inode missmatch, ino_tomatch (%s) "
3916                         "ino=%"PRIu64" test (%s) "
3917                         "ino=%"PRIu64"\n",
3918                         __func__,
3919                         match_pathname,
3920                         ino_tomatch,
3921                         test_pathname,
3922                         test_ino);
3923                 return false;
3924         }
3925         return true;
3926 }
3927
3928 /*
3929  * Delete an SMB2 file on a DFS share.
3930  */
3931 static NTSTATUS smb2_dfs_delete(struct cli_state *cli,
3932                                 const char *pathname)
3933 {
3934         NTSTATUS status;
3935         uint64_t fid_persistent = 0;
3936         uint64_t fid_volatile = 0;
3937         uint8_t data[1];
3938         DATA_BLOB inbuf;
3939
3940         /*
3941          * Open the file.
3942          */
3943         status = smb2cli_create(cli->conn,
3944                                 cli->timeout,
3945                                 cli->smb2.session,
3946                                 cli->smb2.tcon,
3947                                 pathname,
3948                                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
3949                                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
3950                                 SEC_STD_SYNCHRONIZE|
3951                                         SEC_STD_DELETE, /* desired_access, */
3952                                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
3953                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
3954                                 FILE_OPEN, /* create_disposition, */
3955                                 0, /* create_options, */
3956                                 NULL, /* smb2_create_blobs *blobs */
3957                                 &fid_persistent,
3958                                 &fid_volatile,
3959                                 NULL, /* struct smb_create_returns * */
3960                                 talloc_tos(), /* mem_ctx. */
3961                                 NULL, /* struct smb2_create_blobs * */
3962                                 NULL); /* struct symlink_reparse_struct */
3963         if (!NT_STATUS_IS_OK(status)) {
3964                 return status;
3965         }
3966
3967         /*
3968          * Set delete on close.
3969          */
3970         PUSH_LE_U8(&data[0], 0, 1);
3971         inbuf.data = &data[0];
3972         inbuf.length = 1;
3973
3974         status = smb2cli_set_info(cli->conn,
3975                                   cli->timeout,
3976                                   cli->smb2.session,
3977                                   cli->smb2.tcon,
3978                                   SMB2_0_INFO_FILE, /* info_type. */
3979                                   SMB_FILE_DISPOSITION_INFORMATION - 1000, /* info_class */
3980                                   &inbuf,
3981                                   0, /* additional_info. */
3982                                   fid_persistent,
3983                                   fid_volatile);
3984         if (!NT_STATUS_IS_OK(status)) {
3985                 return status;
3986         }
3987         status = smb2cli_close(cli->conn,
3988                                cli->timeout,
3989                                cli->smb2.session,
3990                                cli->smb2.tcon,
3991                                0,
3992                                fid_persistent,
3993                                fid_volatile);
3994         return status;
3995 }
3996
3997 /*
3998  * Rename or hardlink an SMB2 file on a DFS share.
3999  */
4000 static NTSTATUS smb2_dfs_setinfo_name(struct cli_state *cli,
4001                                       uint64_t fid_persistent,
4002                                       uint64_t fid_volatile,
4003                                       const char *newname,
4004                                       bool do_rename)
4005 {
4006         NTSTATUS status;
4007         DATA_BLOB inbuf;
4008         smb_ucs2_t *converted_str = NULL;
4009         size_t converted_size_bytes = 0;
4010         size_t inbuf_size;
4011         uint8_t info_class = 0;
4012         bool ok;
4013
4014         ok = push_ucs2_talloc(talloc_tos(),
4015                               &converted_str,
4016                               newname,
4017                               &converted_size_bytes);
4018         if (!ok) {
4019                 return NT_STATUS_INVALID_PARAMETER;
4020         }
4021         /*
4022          * W2K8 insists the dest name is not null terminated. Remove
4023          * the last 2 zero bytes and reduce the name length.
4024          */
4025         if (converted_size_bytes < 2) {
4026                 return NT_STATUS_INVALID_PARAMETER;
4027         }
4028         converted_size_bytes -= 2;
4029         inbuf_size = 20 + converted_size_bytes;
4030         if (inbuf_size < 20) {
4031                 /* Integer wrap check. */
4032                 return NT_STATUS_INVALID_PARAMETER;
4033         }
4034
4035         /*
4036          * The Windows 10 SMB2 server has a minimum length
4037          * for a SMB2_FILE_RENAME_INFORMATION buffer of
4038          * 24 bytes. It returns NT_STATUS_INFO_LENGTH_MISMATCH
4039          * if the length is less.
4040          */
4041         inbuf_size = MAX(inbuf_size, 24);
4042         inbuf = data_blob_talloc_zero(talloc_tos(), inbuf_size);
4043         if (inbuf.data == NULL) {
4044                 return NT_STATUS_NO_MEMORY;
4045         }
4046         PUSH_LE_U32(inbuf.data, 16, converted_size_bytes);
4047         memcpy(inbuf.data + 20, converted_str, converted_size_bytes);
4048         TALLOC_FREE(converted_str);
4049
4050         if (do_rename == true) {
4051                 info_class = SMB_FILE_RENAME_INFORMATION - 1000;
4052         } else {
4053                 /* Hardlink. */
4054                 info_class = SMB_FILE_LINK_INFORMATION - 1000;
4055         }
4056
4057         status = smb2cli_set_info(cli->conn,
4058                                   cli->timeout,
4059                                   cli->smb2.session,
4060                                   cli->smb2.tcon,
4061                                   SMB2_0_INFO_FILE, /* info_type. */
4062                                   info_class, /* info_class */
4063                                   &inbuf,
4064                                   0, /* additional_info. */
4065                                   fid_persistent,
4066                                   fid_volatile);
4067         return status;
4068 }
4069
4070 static NTSTATUS smb2_dfs_rename(struct cli_state *cli,
4071                                       uint64_t fid_persistent,
4072                                       uint64_t fid_volatile,
4073                                       const char *newname)
4074 {
4075         return smb2_dfs_setinfo_name(cli,
4076                                      fid_persistent,
4077                                      fid_volatile,
4078                                      newname,
4079                                      true); /* do_rename */
4080 }
4081
4082 static NTSTATUS smb2_dfs_hlink(struct cli_state *cli,
4083                                uint64_t fid_persistent,
4084                                uint64_t fid_volatile,
4085                                const char *newname)
4086 {
4087         return smb2_dfs_setinfo_name(cli,
4088                                      fid_persistent,
4089                                      fid_volatile,
4090                                      newname,
4091                                      false); /* do_rename */
4092 }
4093
4094 /*
4095  * According to:
4096
4097  * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/dc9978d7-6299-4c5a-a22d-a039cdc716ea
4098  *
4099  *  (Characters " \ / [ ] : | < > + = ; , * ?,
4100  *  and control characters in range 0x00 through
4101  *  0x1F, inclusive, are illegal in a share name)
4102  *
4103  * But Windows server only checks in DFS sharenames ':'. All other
4104  * share names are allowed.
4105  */
4106
4107 static bool test_smb2_dfs_sharenames(struct cli_state *cli,
4108                                      const char *dfs_root_share_name,
4109                                      uint64_t root_ino)
4110 {
4111         char test_path[9];
4112         const char *test_str = "/[]:|<>+=;,*?";
4113         const char *p;
4114         unsigned int i;
4115         bool ino_matched = false;
4116
4117         /* Setup template pathname. */
4118         memcpy(test_path, "SERVER\\X", 9);
4119
4120         /* Test invalid control characters. */
4121         for (i = 1; i < 0x20; i++) {
4122                 test_path[7] = i;
4123                 ino_matched = smb2_inode_matches(cli,
4124                                          dfs_root_share_name,
4125                                          root_ino,
4126                                          test_path);
4127                 if (!ino_matched) {
4128                         return false;
4129                 }
4130         }
4131
4132         /* Test explicit invalid characters. */
4133         for (p = test_str; *p != '\0'; p++) {
4134                 test_path[7] = *p;
4135                 if (*p == ':') {
4136                         /*
4137                          * Only ':' is treated as an INVALID sharename
4138                          * for a DFS SERVER\\SHARE path.
4139                          */
4140                         uint64_t test_ino = 0;
4141                         NTSTATUS status = get_smb2_inode(cli,
4142                                                          test_path,
4143                                                          &test_ino);
4144                         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
4145                                 printf("%s:%d Open of %s should get "
4146                                         "NT_STATUS_OBJECT_NAME_INVALID, got %s\n",
4147                                         __FILE__,
4148                                         __LINE__,
4149                                         test_path,
4150                                         nt_errstr(status));
4151                                 return false;
4152                         }
4153                 } else {
4154                         ino_matched = smb2_inode_matches(cli,
4155                                                  dfs_root_share_name,
4156                                                  root_ino,
4157                                                  test_path);
4158                         if (!ino_matched) {
4159                                 return false;
4160                         }
4161                 }
4162         }
4163         return true;
4164 }
4165
4166 /*
4167  * "Raw" test of SMB2 paths to a DFS share.
4168  * We must use the lower level smb2cli_XXXX() interfaces,
4169  * not the cli_XXX() ones here as the ultimate goal is to fix our
4170  * cli_XXX() interfaces to work transparently over DFS.
4171  *
4172  * So here, we're testing the server code, not the client code.
4173  *
4174  * Passes cleanly against Windows.
4175  */
4176
4177 bool run_smb2_dfs_paths(int dummy)
4178 {
4179         struct cli_state *cli = NULL;
4180         NTSTATUS status;
4181         bool dfs_supported = false;
4182         char *dfs_root_share_name = NULL;
4183         uint64_t root_ino = 0;
4184         uint64_t test_ino = 0;
4185         bool ino_matched = false;
4186         uint64_t fid_persistent = 0;
4187         uint64_t fid_volatile = 0;
4188         bool retval = false;
4189         bool ok = false;
4190
4191         printf("Starting SMB2-DFS-PATHS\n");
4192
4193         if (!torture_init_connection(&cli)) {
4194                 return false;
4195         }
4196
4197         status = smbXcli_negprot(cli->conn,
4198                                 cli->timeout,
4199                                 PROTOCOL_SMB2_02,
4200                                 PROTOCOL_SMB3_11);
4201         if (!NT_STATUS_IS_OK(status)) {
4202                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
4203                 return false;
4204         }
4205
4206         status = cli_session_setup_creds(cli, torture_creds);
4207         if (!NT_STATUS_IS_OK(status)) {
4208                 printf("cli_session_setup returned %s\n", nt_errstr(status));
4209                 return false;
4210         }
4211
4212         status = cli_tree_connect(cli, share, "?????", NULL);
4213         if (!NT_STATUS_IS_OK(status)) {
4214                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
4215                 return false;
4216         }
4217
4218         /* Ensure this is a DFS share. */
4219         dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
4220         if (!dfs_supported) {
4221                 printf("Server %s does not support DFS\n",
4222                         smbXcli_conn_remote_name(cli->conn));
4223                 return false;
4224         }
4225         dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb2.tcon);
4226         if (!dfs_supported) {
4227                 printf("Share %s does not support DFS\n",
4228                         cli->share);
4229                 return false;
4230         }
4231         /*
4232          * Create the "official" DFS share root name.
4233          * No SMB2 paths can start with '\\'.
4234          */
4235         dfs_root_share_name = talloc_asprintf(talloc_tos(),
4236                                         "%s\\%s",
4237                                         smbXcli_conn_remote_name(cli->conn),
4238                                         cli->share);
4239         if (dfs_root_share_name == NULL) {
4240                 printf("Out of memory\n");
4241                 return false;
4242         }
4243
4244         /* Get the share root inode number. */
4245         status = get_smb2_inode(cli,
4246                                 dfs_root_share_name,
4247                                 &root_ino);
4248         if (!NT_STATUS_IS_OK(status)) {
4249                 printf("%s:%d Failed to get ino number for share root %s, (%s)\n",
4250                         __FILE__,
4251                         __LINE__,
4252                         dfs_root_share_name,
4253                         nt_errstr(status));
4254                 return false;
4255         }
4256
4257         /*
4258          * Test the Windows algorithm for parsing DFS names.
4259          */
4260         /*
4261          * A single "SERVER" element should open and match the share root.
4262          */
4263         ino_matched = smb2_inode_matches(cli,
4264                                          dfs_root_share_name,
4265                                          root_ino,
4266                                          smbXcli_conn_remote_name(cli->conn));
4267         if (!ino_matched) {
4268                 printf("%s:%d Failed to match ino number for %s\n",
4269                         __FILE__,
4270                         __LINE__,
4271                         smbXcli_conn_remote_name(cli->conn));
4272                 return false;
4273         }
4274
4275         /*
4276          * An "" DFS empty server name should open and match the share root on
4277          * Windows 2008. Windows 2022 returns NT_STATUS_INVALID_PARAMETER
4278          * for a DFS empty server name.
4279          */
4280         status = get_smb2_inode(cli,
4281                                 "",
4282                                 &test_ino);
4283         if (NT_STATUS_IS_OK(status)) {
4284                 /*
4285                  * Windows 2008 - open succeeded. Proceed to
4286                  * check ino number.
4287                  */
4288                 ino_matched = smb2_inode_matches(cli,
4289                                                  dfs_root_share_name,
4290                                                  root_ino,
4291                                                  "");
4292                 if (!ino_matched) {
4293                         printf("%s:%d Failed to match ino number for %s\n",
4294                                 __FILE__,
4295                                 __LINE__,
4296                                 "");
4297                         return false;
4298                 }
4299         }
4300         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4301                 /*
4302                  * For Windows 2022 we expect to fail with
4303                  * NT_STATUS_INVALID_PARAMETER. Anything else is
4304                  * unexpected.
4305                  */
4306                 printf("%s:%d Unexpected error (%s) getting ino number for %s\n",
4307                         __FILE__,
4308                         __LINE__,
4309                         nt_errstr(status),
4310                         "");
4311                 return false;
4312         }
4313         /* A "BAD" server name should open and match the share root. */
4314         ino_matched = smb2_inode_matches(cli,
4315                                          dfs_root_share_name,
4316                                          root_ino,
4317                                          "BAD");
4318         if (!ino_matched) {
4319                 printf("%s:%d Failed to match ino number for %s\n",
4320                         __FILE__,
4321                         __LINE__,
4322                         "BAD");
4323                 return false;
4324         }
4325         /*
4326          * A "BAD\\BAD" server and share name should open
4327          * and match the share root.
4328          */
4329         ino_matched = smb2_inode_matches(cli,
4330                                          dfs_root_share_name,
4331                                          root_ino,
4332                                          "BAD\\BAD");
4333         if (!ino_matched) {
4334                 printf("%s:%d Failed to match ino number for %s\n",
4335                         __FILE__,
4336                         __LINE__,
4337                         "BAD\\BAD");
4338                 return false;
4339         }
4340         /*
4341          * Trying to open "BAD\\BAD\\BAD" should get
4342          * NT_STATUS_OBJECT_NAME_NOT_FOUND.
4343          */
4344         status = get_smb2_inode(cli,
4345                                 "BAD\\BAD\\BAD",
4346                                 &test_ino);
4347         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4348                 printf("%s:%d Open of %s should get "
4349                         "STATUS_OBJECT_NAME_NOT_FOUND, got %s\n",
4350                         __FILE__,
4351                         __LINE__,
4352                         "BAD\\BAD\\BAD",
4353                         nt_errstr(status));
4354                 return false;
4355         }
4356         /*
4357          * Trying to open "BAD\\BAD\\BAD\\BAD" should get
4358          * NT_STATUS_OBJECT_PATH_NOT_FOUND.
4359          */
4360         status = get_smb2_inode(cli,
4361                                 "BAD\\BAD\\BAD\\BAD",
4362                                 &test_ino);
4363         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4364                 printf("%s:%d Open of %s should get "
4365                         "STATUS_OBJECT_NAME_NOT_FOUND, got %s\n",
4366                         __FILE__,
4367                         __LINE__,
4368                         "BAD\\BAD\\BAD\\BAD",
4369                         nt_errstr(status));
4370                 return false;
4371         }
4372         /*
4373          * Test for invalid pathname characters in the servername.
4374          * They are ignored, and it still opens the share root.
4375          */
4376         ino_matched = smb2_inode_matches(cli,
4377                                          dfs_root_share_name,
4378                                          root_ino,
4379                                          "::::");
4380         if (!ino_matched) {
4381                 printf("%s:%d Failed to match ino number for %s\n",
4382                         __FILE__,
4383                         __LINE__,
4384                         "::::");
4385                 return false;
4386         }
4387
4388         /*
4389          * Test for invalid pathname characters in the sharename.
4390          * Invalid sharename characters should still be flagged as
4391          * NT_STATUS_OBJECT_NAME_INVALID. It turns out only ':'
4392          * is considered an invalid sharename character.
4393          */
4394         ok = test_smb2_dfs_sharenames(cli,
4395                                       dfs_root_share_name,
4396                                       root_ino);
4397         if (!ok) {
4398                 return false;
4399         }
4400
4401         /* Now create a file called "file". */
4402         status = smb2cli_create(cli->conn,
4403                                 cli->timeout,
4404                                 cli->smb2.session,
4405                                 cli->smb2.tcon,
4406                                 "BAD\\BAD\\file",
4407                                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4408                                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4409                                 SEC_STD_SYNCHRONIZE|
4410                                         SEC_STD_DELETE |
4411                                         SEC_FILE_READ_DATA|
4412                                         SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4413                                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4414                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4415                                 FILE_CREATE, /* create_disposition, */
4416                                 0, /* create_options, */
4417                                 NULL, /* smb2_create_blobs *blobs */
4418                                 &fid_persistent,
4419                                 &fid_volatile,
4420                                 NULL, /* struct smb_create_returns * */
4421                                 talloc_tos(), /* mem_ctx. */
4422                                 NULL, /* struct smb2_create_blobs * */
4423                                 NULL); /* struct symlink_reparse_struct */
4424         if (!NT_STATUS_IS_OK(status)) {
4425                 printf("%s:%d smb2cli_create on %s returned %s\n",
4426                         __FILE__,
4427                         __LINE__,
4428                         "BAD\\BAD\\file",
4429                         nt_errstr(status));
4430                 return false;
4431         }
4432
4433         /*
4434          * Trying to open "BAD\\BAD\\file" should now get
4435          * a valid inode.
4436          */
4437         status = get_smb2_inode(cli,
4438                                 "BAD\\BAD\\file",
4439                                 &test_ino);
4440         if (!NT_STATUS_IS_OK(status)) {
4441                 printf("%s:%d Open of %s should succeed "
4442                         "got %s\n",
4443                         __FILE__,
4444                         __LINE__,
4445                         "BAD\\BAD\\file",
4446                         nt_errstr(status));
4447                 goto err;
4448         }
4449
4450         /*
4451          * Now show that renames use relative,
4452          * not full DFS paths.
4453          */
4454
4455         /* Full DFS path should fail. */
4456         status = smb2_dfs_rename(cli,
4457                                  fid_persistent,
4458                                  fid_volatile,
4459                                  "ANY\\NAME\\renamed_file");
4460         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4461                 printf("%s:%d Rename of %s -> %s should fail "
4462                         "with NT_STATUS_OBJECT_PATH_NOT_FOUND. Got %s\n",
4463                         __FILE__,
4464                         __LINE__,
4465                         "BAD\\BAD\\file",
4466                         "ANY\\NAME\\renamed_file",
4467                         nt_errstr(status));
4468                 goto err;
4469         }
4470         /* Relative DFS path should succeed. */
4471         status = smb2_dfs_rename(cli,
4472                                  fid_persistent,
4473                                  fid_volatile,
4474                                  "renamed_file");
4475         if (!NT_STATUS_IS_OK(status)) {
4476                 printf("%s:%d: Rename of %s -> %s should succeed. "
4477                         "Got %s\n",
4478                         __FILE__,
4479                         __LINE__,
4480                         "BAD\\BAD\\file",
4481                         "renamed_file",
4482                         nt_errstr(status));
4483                 goto err;
4484         }
4485
4486         /*
4487          * Trying to open "BAD\\BAD\\renamed_file" should now get
4488          * a valid inode.
4489          */
4490         status = get_smb2_inode(cli,
4491                                 "BAD\\BAD\\renamed_file",
4492                                 &test_ino);
4493         if (!NT_STATUS_IS_OK(status)) {
4494                 printf("%s:%d: Open of %s should succeed "
4495                         "got %s\n",
4496                         __FILE__,
4497                         __LINE__,
4498                         "BAD\\BAD\\renamed_file",
4499                         nt_errstr(status));
4500                 goto err;
4501         }
4502
4503         /*
4504          * Now show that hard links use relative,
4505          * not full DFS paths.
4506          */
4507
4508         /* Full DFS path should fail. */
4509         status = smb2_dfs_hlink(cli,
4510                                  fid_persistent,
4511                                  fid_volatile,
4512                                  "ANY\\NAME\\hlink");
4513         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4514                 printf("%s:%d Hlink of %s -> %s should fail "
4515                         "with NT_STATUS_OBJECT_PATH_NOT_FOUND. Got %s\n",
4516                         __FILE__,
4517                         __LINE__,
4518                         "ANY\\NAME\\renamed_file",
4519                         "ANY\\NAME\\hlink",
4520                         nt_errstr(status));
4521                 goto err;
4522         }
4523         /* Relative DFS path should succeed. */
4524         status = smb2_dfs_hlink(cli,
4525                                  fid_persistent,
4526                                  fid_volatile,
4527                                  "hlink");
4528         if (!NT_STATUS_IS_OK(status)) {
4529                 printf("%s:%d: Hlink of %s -> %s should succeed. "
4530                         "Got %s\n",
4531                         __FILE__,
4532                         __LINE__,
4533                         "ANY\\NAME\\renamed_file",
4534                         "hlink",
4535                         nt_errstr(status));
4536                 goto err;
4537         }
4538
4539         /*
4540          * Trying to open "BAD\\BAD\\hlink" should now get
4541          * a valid inode.
4542          */
4543         status = get_smb2_inode(cli,
4544                                 "BAD\\BAD\\hlink",
4545                                 &test_ino);
4546         if (!NT_STATUS_IS_OK(status)) {
4547                 printf("%s:%d Open of %s should succeed "
4548                         "got %s\n",
4549                         __FILE__,
4550                         __LINE__,
4551                         "BAD\\BAD\\hlink",
4552                         nt_errstr(status));
4553                 goto err;
4554         }
4555
4556         retval = true;
4557
4558   err:
4559
4560         if (fid_persistent != 0 || fid_volatile != 0) {
4561                 smb2cli_close(cli->conn,
4562                               cli->timeout,
4563                               cli->smb2.session,
4564                               cli->smb2.tcon,
4565                               0, /* flags */
4566                               fid_persistent,
4567                               fid_volatile);
4568         }
4569         /* Delete anything we made. */
4570         (void)smb2_dfs_delete(cli, "BAD\\BAD\\BAD");
4571         (void)smb2_dfs_delete(cli, "BAD\\BAD\\file");
4572         (void)smb2_dfs_delete(cli, "BAD\\BAD\\renamed_file");
4573         (void)smb2_dfs_delete(cli, "BAD\\BAD\\hlink");
4574         return retval;
4575 }
4576
4577 /*
4578  * Add a test that sends DFS paths and sets the
4579  * SMB2 flag FLAGS2_DFS_PATHNAMES, but to a non-DFS
4580  * share. Windows passes this (it just treats the
4581  * pathnames as non-DFS and ignores the FLAGS2_DFS_PATHNAMES
4582  * bit).
4583  */
4584
4585 bool run_smb2_non_dfs_share(int dummy)
4586 {
4587         struct cli_state *cli = NULL;
4588         NTSTATUS status;
4589         bool dfs_supported = false;
4590         uint64_t fid_persistent = 0;
4591         uint64_t fid_volatile = 0;
4592         bool retval = false;
4593         char *dfs_filename = NULL;
4594
4595         printf("Starting SMB2-DFS-NON-DFS-SHARE\n");
4596
4597         if (!torture_init_connection(&cli)) {
4598                 return false;
4599         }
4600
4601         status = smbXcli_negprot(cli->conn,
4602                                 cli->timeout,
4603                                 PROTOCOL_SMB2_02,
4604                                 PROTOCOL_SMB3_11);
4605         if (!NT_STATUS_IS_OK(status)) {
4606                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
4607                 return false;
4608         }
4609
4610         status = cli_session_setup_creds(cli, torture_creds);
4611         if (!NT_STATUS_IS_OK(status)) {
4612                 printf("cli_session_setup returned %s\n", nt_errstr(status));
4613                 return false;
4614         }
4615
4616         status = cli_tree_connect(cli, share, "?????", NULL);
4617         if (!NT_STATUS_IS_OK(status)) {
4618                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
4619                 return false;
4620         }
4621
4622         dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
4623         if (!dfs_supported) {
4624                 printf("Server %s does not support DFS\n",
4625                         smbXcli_conn_remote_name(cli->conn));
4626                 return false;
4627         }
4628         /* Ensure this is *NOT* a DFS share. */
4629         dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb2.tcon);
4630         if (dfs_supported) {
4631                 printf("Share %s is a DFS share.\n",
4632                         cli->share);
4633                 return false;
4634         }
4635         /*
4636          * Force the share to be DFS, as far as the client
4637          * is concerned.
4638          */
4639         smb2cli_tcon_set_values(cli->smb2.tcon,
4640                                 cli->smb2.session,
4641                                 smb2cli_tcon_current_id(cli->smb2.tcon),
4642                                 0,
4643                                 smb2cli_tcon_flags(cli->smb2.tcon),
4644                                 smb2cli_tcon_capabilities(cli->smb2.tcon) |
4645                                         SMB2_SHARE_CAP_DFS,
4646                                 0);
4647
4648         /* Come up with a "valid" SMB2 DFS name. */
4649         dfs_filename = talloc_asprintf(talloc_tos(),
4650                                        "%s\\%s\\file",
4651                                        smbXcli_conn_remote_name(cli->conn),
4652                                        cli->share);
4653         if (dfs_filename == NULL) {
4654                 printf("Out of memory\n");
4655                 return false;
4656         }
4657
4658         /* Now try create dfs_filename. */
4659         status = smb2cli_create(cli->conn,
4660                                 cli->timeout,
4661                                 cli->smb2.session,
4662                                 cli->smb2.tcon,
4663                                 dfs_filename,
4664                                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4665                                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4666                                 SEC_STD_SYNCHRONIZE|
4667                                         SEC_STD_DELETE |
4668                                         SEC_FILE_READ_DATA|
4669                                         SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4670                                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4671                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4672                                 FILE_CREATE, /* create_disposition, */
4673                                 0, /* create_options, */
4674                                 NULL, /* smb2_create_blobs *blobs */
4675                                 &fid_persistent,
4676                                 &fid_volatile,
4677                                 NULL, /* struct smb_create_returns * */
4678                                 talloc_tos(), /* mem_ctx. */
4679                                 NULL, /* struct smb2_create_blobs */
4680                                 NULL); /* struct symlink_reparse_struct */
4681         /*
4682          * Should fail with NT_STATUS_OBJECT_PATH_NOT_FOUND, as
4683          * even though we set the FLAGS2_DFS_PATHNAMES the server
4684          * knows this isn't a DFS share and so treats BAD\\BAD as
4685          * part of the filename.
4686          */
4687         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4688                 printf("%s:%d create of %s should fail "
4689                         "with NT_STATUS_OBJECT_PATH_NOT_FOUND. Got %s\n",
4690                         __FILE__,
4691                         __LINE__,
4692                         dfs_filename,
4693                         nt_errstr(status));
4694                 goto err;
4695         }
4696         /*
4697          * Prove we can still use non-DFS pathnames, even though
4698          * we are setting the FLAGS2_DFS_PATHNAMES in the SMB2
4699          * request.
4700          */
4701         status = smb2cli_create(cli->conn,
4702                                 cli->timeout,
4703                                 cli->smb2.session,
4704                                 cli->smb2.tcon,
4705                                 "file",
4706                                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4707                                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4708                                 SEC_STD_SYNCHRONIZE|
4709                                         SEC_STD_DELETE |
4710                                         SEC_FILE_READ_DATA|
4711                                         SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4712                                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4713                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4714                                 FILE_CREATE, /* create_disposition, */
4715                                 0, /* create_options, */
4716                                 NULL, /* smb2_create_blobs *blobs */
4717                                 &fid_persistent,
4718                                 &fid_volatile,
4719                                 NULL, /* struct smb_create_returns * */
4720                                 talloc_tos(), /* mem_ctx. */
4721                                 NULL, /* struct smb2_create_blobs * */
4722                                 NULL); /* struct symlink_reparse_struct */
4723         if (!NT_STATUS_IS_OK(status)) {
4724                 printf("%s:%d smb2cli_create on %s returned %s\n",
4725                         __FILE__,
4726                         __LINE__,
4727                         "file",
4728                         nt_errstr(status));
4729                 return false;
4730         }
4731
4732         retval = true;
4733
4734   err:
4735
4736         (void)smb2_dfs_delete(cli, dfs_filename);
4737         (void)smb2_dfs_delete(cli, "file");
4738         return retval;
4739 }
4740
4741 /*
4742  * Add a test that sends a non-DFS path and does not set the
4743  * SMB2 flag FLAGS2_DFS_PATHNAMES to a DFS
4744  * share. Windows passes this (it just treats the
4745  * pathnames as non-DFS).
4746  */
4747
4748 bool run_smb2_dfs_share_non_dfs_path(int dummy)
4749 {
4750         struct cli_state *cli = NULL;
4751         NTSTATUS status;
4752         bool dfs_supported = false;
4753         uint64_t fid_persistent = 0;
4754         uint64_t fid_volatile = 0;
4755         bool retval = false;
4756         char *dfs_filename = NULL;
4757         uint64_t root_ino = (uint64_t)-1;
4758         bool ino_matched = false;
4759
4760         printf("Starting SMB2-DFS-SHARE-NON-DFS-PATH\n");
4761
4762         if (!torture_init_connection(&cli)) {
4763                 return false;
4764         }
4765
4766         status = smbXcli_negprot(cli->conn,
4767                                 cli->timeout,
4768                                 PROTOCOL_SMB2_02,
4769                                 PROTOCOL_SMB3_11);
4770         if (!NT_STATUS_IS_OK(status)) {
4771                 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
4772                 return false;
4773         }
4774
4775         status = cli_session_setup_creds(cli, torture_creds);
4776         if (!NT_STATUS_IS_OK(status)) {
4777                 printf("cli_session_setup returned %s\n", nt_errstr(status));
4778                 return false;
4779         }
4780
4781         status = cli_tree_connect(cli, share, "?????", NULL);
4782         if (!NT_STATUS_IS_OK(status)) {
4783                 printf("cli_tree_connect returned %s\n", nt_errstr(status));
4784                 return false;
4785         }
4786
4787         dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
4788         if (!dfs_supported) {
4789                 printf("Server %s does not support DFS\n",
4790                         smbXcli_conn_remote_name(cli->conn));
4791                 return false;
4792         }
4793         /* Ensure this is a DFS share. */
4794         dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb2.tcon);
4795         if (!dfs_supported) {
4796                 printf("Share %s is not a DFS share.\n",
4797                         cli->share);
4798                 return false;
4799         }
4800         /* Come up with a "valid" SMB2 DFS name. */
4801         dfs_filename = talloc_asprintf(talloc_tos(),
4802                                        "%s\\%s\\file",
4803                                        smbXcli_conn_remote_name(cli->conn),
4804                                        cli->share);
4805         if (dfs_filename == NULL) {
4806                 printf("Out of memory\n");
4807                 return false;
4808         }
4809
4810         /* Get the root of the share ino. */
4811         status = get_smb2_inode(cli,
4812                                 "SERVER\\SHARE",
4813                                 &root_ino);
4814         if (!NT_STATUS_IS_OK(status)) {
4815                 printf("%s:%d get_smb2_inode on %s returned %s\n",
4816                         __FILE__,
4817                         __LINE__,
4818                         "SERVER\\SHARE",
4819                         nt_errstr(status));
4820                 goto err;
4821         }
4822
4823         /* Create a dfs_filename. */
4824         status = smb2cli_create(cli->conn,
4825                                 cli->timeout,
4826                                 cli->smb2.session,
4827                                 cli->smb2.tcon,
4828                                 dfs_filename,
4829                                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4830                                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4831                                 SEC_STD_SYNCHRONIZE|
4832                                         SEC_STD_DELETE |
4833                                         SEC_FILE_READ_DATA|
4834                                         SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4835                                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4836                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4837                                 FILE_CREATE, /* create_disposition, */
4838                                 0, /* create_options, */
4839                                 NULL, /* smb2_create_blobs *blobs */
4840                                 &fid_persistent,
4841                                 &fid_volatile,
4842                                 NULL, /* struct smb_create_returns * */
4843                                 talloc_tos(), /* mem_ctx. */
4844                                 NULL, /* struct smb2_create_blobs * */
4845                                 NULL); /* psymlink */
4846         if (!NT_STATUS_IS_OK(status)) {
4847                 printf("%s:%d smb2cli_create on %s returned %s\n",
4848                         __FILE__,
4849                         __LINE__,
4850                         dfs_filename,
4851                         nt_errstr(status));
4852                 goto err;
4853         }
4854
4855         /* Close the handle we just opened. */
4856         smb2cli_close(cli->conn,
4857                       cli->timeout,
4858                       cli->smb2.session,
4859                       cli->smb2.tcon,
4860                       0, /* flags */
4861                       fid_persistent,
4862                       fid_volatile);
4863
4864         fid_persistent = 0;
4865         fid_volatile = 0;
4866
4867         /*
4868          * Force the share to be non-DFS, as far as the client
4869          * is concerned.
4870          */
4871         smb2cli_tcon_set_values(cli->smb2.tcon,
4872                         cli->smb2.session,
4873                         smb2cli_tcon_current_id(cli->smb2.tcon),
4874                         0,
4875                         smb2cli_tcon_flags(cli->smb2.tcon),
4876                         smb2cli_tcon_capabilities(cli->smb2.tcon) &
4877                                 ~SMB2_SHARE_CAP_DFS,
4878                         0);
4879
4880         /*
4881          * Prove we can still use non-DFS pathnames on a DFS
4882          * share so long as we don't set the FLAGS2_DFS_PATHNAMES
4883          * in the SMB2 request.
4884          */
4885         status = smb2cli_create(cli->conn,
4886                                 cli->timeout,
4887                                 cli->smb2.session,
4888                                 cli->smb2.tcon,
4889                                 "file",
4890                                 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4891                                 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4892                                 SEC_STD_SYNCHRONIZE|
4893                                         SEC_STD_DELETE |
4894                                         SEC_FILE_READ_DATA|
4895                                         SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4896                                 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4897                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4898                                 FILE_OPEN, /* create_disposition, */
4899                                 0, /* create_options, */
4900                                 NULL, /* smb2_create_blobs *blobs */
4901                                 &fid_persistent,
4902                                 &fid_volatile,
4903                                 NULL, /* struct smb_create_returns * */
4904                                 talloc_tos(), /* mem_ctx. */
4905                                 NULL, /* struct smb2_create_blobs * */
4906                                 NULL); /* psymlink */
4907         if (!NT_STATUS_IS_OK(status)) {
4908                 printf("%s:%d smb2cli_create on %s returned %s\n",
4909                         __FILE__,
4910                         __LINE__,
4911                         "file",
4912                         nt_errstr(status));
4913                 goto err;
4914         }
4915
4916         /*
4917          * Show that now we're using non-DFS pathnames
4918          * on a DFS share, "" opens the root of the share.
4919          */
4920         ino_matched = smb2_inode_matches(cli,
4921                                          "SERVER\\SHARE",
4922                                          root_ino,
4923                                          "");
4924         if (!ino_matched) {
4925                 printf("%s:%d Failed to match ino number for %s\n",
4926                         __FILE__,
4927                         __LINE__,
4928                         "");
4929                 goto err;
4930         }
4931
4932         retval = true;
4933
4934   err:
4935
4936         if (fid_volatile != 0) {
4937                 smb2cli_close(cli->conn,
4938                               cli->timeout,
4939                               cli->smb2.session,
4940                               cli->smb2.tcon,
4941                               0, /* flags */
4942                               fid_persistent,
4943                               fid_volatile);
4944         }
4945         (void)smb2_dfs_delete(cli, "file");
4946         (void)smb2_dfs_delete(cli, dfs_filename);
4947         return retval;
4948 }