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