libsmb: Use clistr_smb2_extract_snapshot_token() in cli_smb2_create_fnum_send()
[Samba.git] / source3 / torture / test_smb2.c
blob22918d39ccdc78210d3e83cfae550d4136223d15
1 /*
2 Unix SMB/CIFS implementation.
3 Initial test for the smb2 client lib
4 Copyright (C) Volker Lendecke 2011
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.
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.
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/>.
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"
34 extern fstring host, workgroup, share, password, username, myname;
35 extern struct cli_credentials *torture_creds;
37 bool run_smb2_basic(int dummy)
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;
52 printf("Starting SMB2-BASIC\n");
54 if (!torture_init_connection(&cli)) {
55 return false;
58 status = smbXcli_negprot(cli->conn, cli->timeout,
59 PROTOCOL_SMB2_02, PROTOCOL_SMB2_02);
60 if (!NT_STATUS_IS_OK(status)) {
61 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
62 return false;
65 status = cli_session_setup_creds(cli, torture_creds);
66 if (!NT_STATUS_IS_OK(status)) {
67 printf("cli_session_setup returned %s\n", nt_errstr(status));
68 return false;
71 status = cli_tree_connect(cli, share, "?????", NULL);
72 if (!NT_STATUS_IS_OK(status)) {
73 printf("cli_tree_connect returned %s\n", nt_errstr(status));
74 return false;
77 status = smb2cli_create(
78 cli->conn,
79 cli->timeout,
80 cli->smb2.session,
81 cli->smb2.tcon,
82 "smb2-basic.txt",
83 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
84 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
85 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
86 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
87 FILE_SHARE_READ|
88 FILE_SHARE_WRITE|
89 FILE_SHARE_DELETE, /* share_access, */
90 FILE_CREATE, /* create_disposition, */
91 FILE_DELETE_ON_CLOSE, /* create_options, */
92 NULL, /* smb2_create_blobs *blobs */
93 &fid_persistent,
94 &fid_volatile,
95 NULL,
96 NULL,
97 NULL,
98 NULL);
99 if (!NT_STATUS_IS_OK(status)) {
100 printf("smb2cli_create returned %s\n", nt_errstr(status));
101 return false;
104 status = smb2cli_write(cli->conn, cli->timeout, cli->smb2.session,
105 cli->smb2.tcon, strlen(hello), 0, fid_persistent,
106 fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
107 if (!NT_STATUS_IS_OK(status)) {
108 printf("smb2cli_write returned %s\n", nt_errstr(status));
109 return false;
112 status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
113 cli->smb2.tcon, fid_persistent, fid_volatile);
114 if (!NT_STATUS_IS_OK(status)) {
115 printf("smb2cli_flush returned %s\n", nt_errstr(status));
116 return false;
119 status = smb2cli_read(cli->conn, cli->timeout, cli->smb2.session,
120 cli->smb2.tcon, 0x10000, 0, fid_persistent,
121 fid_volatile, 2, 0,
122 talloc_tos(), &result, &nread);
123 if (!NT_STATUS_IS_OK(status)) {
124 printf("smb2cli_read returned %s\n", nt_errstr(status));
125 return false;
128 if (nread != strlen(hello)) {
129 printf("smb2cli_read returned %d bytes, expected %d\n",
130 (int)nread, (int)strlen(hello));
131 return false;
134 if (memcmp(hello, result, nread) != 0) {
135 printf("smb2cli_read returned '%s', expected '%s'\n",
136 result, hello);
137 return false;
140 status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
141 cli->smb2.tcon, 0, fid_persistent, fid_volatile);
142 if (!NT_STATUS_IS_OK(status)) {
143 printf("smb2cli_close returned %s\n", nt_errstr(status));
144 return false;
147 status = smb2cli_create(
148 cli->conn,
149 cli->timeout,
150 cli->smb2.session,
151 cli->smb2.tcon,
153 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
154 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
155 SEC_STD_SYNCHRONIZE|
156 SEC_DIR_LIST|
157 SEC_DIR_READ_ATTRIBUTE, /* desired_access, */
158 0, /* file_attributes, */
159 FILE_SHARE_READ|
160 FILE_SHARE_WRITE|
161 FILE_SHARE_DELETE, /* share_access, */
162 FILE_OPEN, /* create_disposition, */
163 FILE_SYNCHRONOUS_IO_NONALERT|
164 FILE_DIRECTORY_FILE, /* create_options, */
165 NULL, /* smb2_create_blobs *blobs */
166 &fid_persistent,
167 &fid_volatile,
168 NULL,
169 NULL,
170 NULL,
171 NULL);
172 if (!NT_STATUS_IS_OK(status)) {
173 printf("smb2cli_create returned %s\n", nt_errstr(status));
174 return false;
177 status = smb2cli_query_directory(
178 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
179 1, 0, 0, fid_persistent, fid_volatile, "*", 0xffff,
180 talloc_tos(), &dir_data, &dir_data_length);
182 if (!NT_STATUS_IS_OK(status)) {
183 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
184 return false;
187 status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
188 cli->smb2.tcon, 0, fid_persistent, fid_volatile);
189 if (!NT_STATUS_IS_OK(status)) {
190 printf("smb2cli_close returned %s\n", nt_errstr(status));
191 return false;
194 saved_tid = smb2cli_tcon_current_id(cli->smb2.tcon);
195 cli_state_save_tcon_share(cli, &saved_tcon, &saved_share);
196 cli->smb2.tcon = smbXcli_tcon_create(cli);
197 smb2cli_tcon_set_values(cli->smb2.tcon,
198 NULL, /* session */
199 saved_tid,
200 0, /* type */
201 0, /* flags */
202 0, /* capabilities */
203 0 /* maximal_access */);
204 status = smb2cli_tdis(cli->conn,
205 cli->timeout,
206 cli->smb2.session,
207 cli->smb2.tcon);
208 cli_state_restore_tcon_share(cli, saved_tcon, saved_share);
209 if (!NT_STATUS_IS_OK(status)) {
210 printf("smb2cli_tdis returned %s\n", nt_errstr(status));
211 return false;
214 status = smb2cli_tdis(cli->conn,
215 cli->timeout,
216 cli->smb2.session,
217 cli->smb2.tcon);
218 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) {
219 printf("2nd smb2cli_tdis returned %s\n", nt_errstr(status));
220 return false;
223 saved_uid = smb2cli_session_current_id(cli->smb2.session);
224 status = smb2cli_logoff(cli->conn, cli->timeout, cli->smb2.session);
225 if (!NT_STATUS_IS_OK(status)) {
226 printf("smb2cli_logoff returned %s\n", nt_errstr(status));
227 return false;
230 cli->smb2.session = smbXcli_session_create(cli, cli->conn);
231 if (cli->smb2.session == NULL) {
232 printf("smbXcli_session_create() returned NULL\n");
233 return false;
236 smb2cli_session_set_id_and_flags(cli->smb2.session, saved_uid, 0);
238 status = smb2cli_logoff(cli->conn, cli->timeout, cli->smb2.session);
239 if (!NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
240 printf("2nd smb2cli_logoff returned %s\n", nt_errstr(status));
241 return false;
244 return true;
247 bool run_smb2_negprot(int dummy)
249 struct cli_state *cli;
250 NTSTATUS status;
251 enum protocol_types protocol;
252 const char *name = NULL;
254 printf("Starting SMB2-NEGPROT\n");
256 if (!torture_init_connection(&cli)) {
257 return false;
260 status = smbXcli_negprot(cli->conn, cli->timeout,
261 PROTOCOL_CORE, PROTOCOL_LATEST);
262 if (!NT_STATUS_IS_OK(status)) {
263 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
264 return false;
267 protocol = smbXcli_conn_protocol(cli->conn);
268 name = smb_protocol_types_string(protocol);
270 if (protocol >= PROTOCOL_SMB2_02) {
271 printf("Server supports %s\n", name);
272 } else {
273 printf("Server DOES NOT support SMB2, only %s\n", name);
274 return false;
277 status = smbXcli_negprot(cli->conn, cli->timeout,
278 protocol, protocol);
279 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET) &&
280 !NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_DISCONNECTED) &&
281 !NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_ABORTED)) {
282 printf("2nd smbXcli_negprot should disconnect - returned %s\n",
283 nt_errstr(status));
284 return false;
287 if (smbXcli_conn_is_connected(cli->conn)) {
288 printf("2nd smbXcli_negprot should disconnect "
289 "- still connected\n");
290 return false;
293 return true;
296 bool run_smb2_anonymous(int dummy)
298 struct cli_state *cli = NULL;
299 NTSTATUS status;
300 struct cli_credentials *anon_creds = NULL;
301 bool guest = false;
303 printf("Starting SMB2-ANONYMOUS\n");
305 if (!torture_init_connection(&cli)) {
306 return false;
309 status = smbXcli_negprot(cli->conn, cli->timeout,
310 PROTOCOL_SMB2_02, PROTOCOL_LATEST);
311 if (!NT_STATUS_IS_OK(status)) {
312 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
313 return false;
316 anon_creds = cli_credentials_init_anon(talloc_tos());
317 if (anon_creds == NULL) {
318 printf("cli_credentials_init_anon failed\n");
319 return false;
322 status = cli_session_setup_creds(cli, anon_creds);
323 if (!NT_STATUS_IS_OK(status)) {
324 printf("cli_session_setup returned %s\n", nt_errstr(status));
325 return false;
328 guest = smbXcli_session_is_guest(cli->smb2.session);
329 if (guest) {
330 printf("anonymous session should not have guest authentication\n");
331 return false;
334 return true;
337 bool run_smb2_session_reconnect(int dummy)
339 struct cli_state *cli1;
340 struct cli_state *cli2;
341 NTSTATUS status;
342 bool ok;
343 uint64_t fid_persistent, fid_volatile;
344 struct tevent_context *ev;
345 struct tevent_req *subreq;
346 DATA_BLOB in_blob = data_blob_null;
347 DATA_BLOB out_blob;
348 DATA_BLOB session_key;
349 struct auth_generic_state *auth_generic_state;
350 struct iovec *recv_iov;
351 const char *hello = "Hello, world\n";
352 uint8_t *result;
353 uint32_t nread;
355 printf("Starting SMB2-SESSION-RECONNECT\n");
357 if (!torture_init_connection(&cli1)) {
358 return false;
361 status = smbXcli_negprot(cli1->conn, cli1->timeout,
362 PROTOCOL_SMB2_02, PROTOCOL_LATEST);
363 if (!NT_STATUS_IS_OK(status)) {
364 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
365 return false;
368 status = cli_session_setup_creds(cli1, torture_creds);
369 if (!NT_STATUS_IS_OK(status)) {
370 printf("cli_session_setup returned %s\n", nt_errstr(status));
371 return false;
374 status = cli_tree_connect(cli1, share, "?????", NULL);
375 if (!NT_STATUS_IS_OK(status)) {
376 printf("cli_tree_connect returned %s\n", nt_errstr(status));
377 return false;
380 status = smb2cli_create(
381 cli1->conn,
382 cli1->timeout,
383 cli1->smb2.session,
384 cli1->smb2.tcon,
385 "session-reconnect.txt",
386 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
387 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
388 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
389 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
390 FILE_SHARE_READ|
391 FILE_SHARE_WRITE|
392 FILE_SHARE_DELETE, /* share_access, */
393 FILE_CREATE, /* create_disposition, */
394 FILE_DELETE_ON_CLOSE, /* create_options, */
395 NULL, /* smb2_create_blobs *blobs */
396 &fid_persistent,
397 &fid_volatile,
398 NULL,
399 NULL,
400 NULL,
401 NULL);
402 if (!NT_STATUS_IS_OK(status)) {
403 printf("smb2cli_create on cli1 %s\n", nt_errstr(status));
404 return false;
407 status = smb2cli_write(cli1->conn, cli1->timeout, cli1->smb2.session,
408 cli1->smb2.tcon, strlen(hello), 0, fid_persistent,
409 fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
410 if (!NT_STATUS_IS_OK(status)) {
411 printf("smb2cli_write returned %s\n", nt_errstr(status));
412 return false;
415 status = smb2cli_flush(cli1->conn, cli1->timeout, cli1->smb2.session,
416 cli1->smb2.tcon, fid_persistent, fid_volatile);
417 if (!NT_STATUS_IS_OK(status)) {
418 printf("smb2cli_flush returned %s\n", nt_errstr(status));
419 return false;
422 status = smb2cli_read(cli1->conn, cli1->timeout, cli1->smb2.session,
423 cli1->smb2.tcon, 0x10000, 0, fid_persistent,
424 fid_volatile, 2, 0,
425 talloc_tos(), &result, &nread);
426 if (!NT_STATUS_IS_OK(status)) {
427 printf("smb2cli_read returned %s\n", nt_errstr(status));
428 return false;
431 if (nread != strlen(hello)) {
432 printf("smb2cli_read returned %d bytes, expected %d\n",
433 (int)nread, (int)strlen(hello));
434 return false;
437 if (memcmp(hello, result, nread) != 0) {
438 printf("smb2cli_read returned '%s', expected '%s'\n",
439 result, hello);
440 return false;
443 /* prepare second session */
445 if (!torture_init_connection(&cli2)) {
446 return false;
449 status = smbXcli_negprot(cli2->conn, cli2->timeout,
450 PROTOCOL_SMB2_02, PROTOCOL_LATEST);
451 if (!NT_STATUS_IS_OK(status)) {
452 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
453 return false;
456 status = auth_generic_client_prepare(talloc_tos(), &auth_generic_state);
457 if (!NT_STATUS_IS_OK(status)) {
458 printf("auth_generic_client_prepare returned %s\n", nt_errstr(status));
459 return false;
462 gensec_want_feature(auth_generic_state->gensec_security,
463 GENSEC_FEATURE_SESSION_KEY);
465 status = auth_generic_set_creds(auth_generic_state, torture_creds);
466 if (!NT_STATUS_IS_OK(status)) {
467 printf("auth_generic_set_creds returned %s\n", nt_errstr(status));
468 return false;
471 status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
472 if (!NT_STATUS_IS_OK(status)) {
473 printf("auth_generic_client_start returned %s\n", nt_errstr(status));
474 return false;
477 ev = samba_tevent_context_init(talloc_tos());
478 if (ev == NULL) {
479 printf("samba_tevent_context_init() returned NULL\n");
480 return false;
483 status = gensec_update(auth_generic_state->gensec_security,
484 talloc_tos(), data_blob_null, &in_blob);
485 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
486 printf("gensec_update returned %s\n", nt_errstr(status));
487 return false;
490 cli2->smb2.session = smbXcli_session_create(cli2, cli2->conn);
492 subreq = smb2cli_session_setup_send(talloc_tos(), ev,
493 cli2->conn,
494 cli2->timeout,
495 cli2->smb2.session,
496 0x0, /* in_flags */
497 SMB2_CAP_DFS, /* in_capabilities */
498 0, /* in_channel */
499 /* in_previous_session_id: */
500 smb2cli_session_current_id(cli1->smb2.session),
501 &in_blob); /* in_security_buffer */
502 if (subreq == NULL) {
503 printf("smb2cli_session_setup_send() returned NULL\n");
504 return false;
507 ok = tevent_req_poll(subreq, ev);
508 if (!ok) {
509 printf("tevent_req_poll() returned false\n");
510 return false;
513 status = smb2cli_session_setup_recv(subreq, talloc_tos(),
514 NULL, &out_blob);
515 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
516 printf("smb2cli_session_setup_recv returned %s\n",
517 nt_errstr(status));
518 return false;
521 status = gensec_update(auth_generic_state->gensec_security,
522 talloc_tos(), out_blob, &in_blob);
523 if (!NT_STATUS_IS_OK(status)) {
524 printf("auth_generic_update returned %s\n", nt_errstr(status));
525 return false;
528 subreq = smb2cli_session_setup_send(talloc_tos(), ev,
529 cli2->conn,
530 cli2->timeout,
531 cli2->smb2.session,
532 0x0, /* in_flags */
533 SMB2_CAP_DFS, /* in_capabilities */
534 0, /* in_channel */
535 /* in_previous_session_id: */
536 smb2cli_session_current_id(cli1->smb2.session),
537 &in_blob); /* in_security_buffer */
538 if (subreq == NULL) {
539 printf("smb2cli_session_setup_send() returned NULL\n");
540 return false;
543 ok = tevent_req_poll(subreq, ev);
544 if (!ok) {
545 printf("tevent_req_poll() returned false\n");
546 return false;
549 status = smb2cli_session_setup_recv(subreq, talloc_tos(),
550 &recv_iov, &out_blob);
551 if (!NT_STATUS_IS_OK(status)) {
552 printf("smb2cli_session_setup_recv returned %s\n",
553 nt_errstr(status));
554 return false;
557 status = gensec_session_key(auth_generic_state->gensec_security, talloc_tos(),
558 &session_key);
559 if (!NT_STATUS_IS_OK(status)) {
560 printf("gensec_session_key returned %s\n",
561 nt_errstr(status));
562 return false;
565 /* check file operation on the old client */
567 status = smb2cli_flush(cli1->conn, cli1->timeout, cli1->smb2.session,
568 cli1->smb2.tcon, fid_persistent, fid_volatile);
569 if (!NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
570 printf("smb2cli_flush returned %s\n", nt_errstr(status));
571 return false;
574 status = cli_tree_connect(cli1, share, "?????", NULL);
575 if (!NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
576 printf("cli_tree_connect returned %s\n", nt_errstr(status));
577 return false;
581 * checking file operations without signing.
582 * on w2k8r2 at least, flush, read and write also work the same way,
583 * while create gives ACCESS_DENIED without signing
585 status = smb2cli_flush(cli2->conn, cli2->timeout, cli2->smb2.session,
586 cli2->smb2.tcon, fid_persistent, fid_volatile);
587 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) &&
588 !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
590 printf("smb2cli_flush returned %s\n", nt_errstr(status));
591 return false;
594 status = smb2cli_write(cli2->conn, cli2->timeout, cli2->smb2.session,
595 cli2->smb2.tcon, strlen(hello), 0, fid_persistent,
596 fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
597 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) &&
598 !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
600 printf("smb2cli_write returned %s\n", nt_errstr(status));
601 return false;
604 status = smb2cli_read(cli2->conn, cli2->timeout, cli2->smb2.session,
605 cli2->smb2.tcon, 0x10000, 0, fid_persistent,
606 fid_volatile, 2, 0,
607 talloc_tos(), &result, &nread);
608 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) &&
609 !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
611 printf("smb2cli_read returned %s\n", nt_errstr(status));
612 return false;
615 status = smb2cli_create(
616 cli2->conn,
617 cli2->timeout,
618 cli2->smb2.session,
619 cli2->smb2.tcon,
620 "session-reconnect.txt",
621 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
622 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
623 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
624 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
625 FILE_SHARE_READ|
626 FILE_SHARE_WRITE|
627 FILE_SHARE_DELETE, /* share_access, */
628 FILE_CREATE, /* create_disposition, */
629 FILE_DELETE_ON_CLOSE, /* create_options, */
630 NULL, /* smb2_create_blobs *blobs */
631 &fid_persistent,
632 &fid_volatile,
633 NULL,
634 NULL,
635 NULL,
636 NULL);
637 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
638 !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) {
639 printf("smb2cli_create on cli2 %s\n", nt_errstr(status));
640 return false;
643 /* now grab the session key and try with signing */
645 status = smb2cli_session_set_session_key(cli2->smb2.session,
646 session_key,
647 recv_iov);
648 if (!NT_STATUS_IS_OK(status)) {
649 printf("smb2cli_session_set_session_key %s\n", nt_errstr(status));
650 return false;
653 /* the tid seems to be irrelevant at this stage */
655 status = smb2cli_flush(cli2->conn, cli2->timeout, cli2->smb2.session,
656 cli1->smb2.tcon, fid_persistent, fid_volatile);
657 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) &&
658 !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
660 printf("smb2cli_flush returned %s\n", nt_errstr(status));
661 return false;
664 status = smb2cli_write(cli2->conn, cli2->timeout, cli2->smb2.session,
665 cli1->smb2.tcon, strlen(hello), 0, fid_persistent,
666 fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
667 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) &&
668 !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
670 printf("smb2cli_write returned %s\n", nt_errstr(status));
671 return false;
674 status = smb2cli_read(cli2->conn, cli2->timeout, cli2->smb2.session,
675 cli1->smb2.tcon, 0x10000, 0, fid_persistent,
676 fid_volatile, 2, 0,
677 talloc_tos(), &result, &nread);
678 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) &&
679 !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
681 printf("smb2cli_read returned %s\n", nt_errstr(status));
682 return false;
685 status = smb2cli_create(
686 cli2->conn,
687 cli2->timeout,
688 cli2->smb2.session,
689 cli1->smb2.tcon,
690 "session-reconnect.txt",
691 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
692 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
693 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
694 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
695 FILE_SHARE_READ|
696 FILE_SHARE_WRITE|
697 FILE_SHARE_DELETE, /* share_access, */
698 FILE_CREATE, /* create_disposition, */
699 FILE_DELETE_ON_CLOSE, /* create_options, */
700 NULL, /* smb2_create_blobs *blobs */
701 &fid_persistent,
702 &fid_volatile,
703 NULL,
704 NULL,
705 NULL,
706 NULL);
707 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED) &&
708 !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED))
710 printf("smb2cli_create on cli2 %s\n", nt_errstr(status));
711 return false;
714 /* now do a new tcon and test file calls again */
716 status = cli_tree_connect(cli2, share, "?????", NULL);
717 if (!NT_STATUS_IS_OK(status)) {
718 printf("cli_tree_connect returned %s\n", nt_errstr(status));
719 return false;
722 status = smb2cli_create(
723 cli2->conn,
724 cli2->timeout,
725 cli2->smb2.session,
726 cli2->smb2.tcon,
727 "session-reconnect.txt",
728 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
729 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
730 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
731 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
732 FILE_SHARE_READ|
733 FILE_SHARE_WRITE|
734 FILE_SHARE_DELETE, /* share_access, */
735 FILE_CREATE, /* create_disposition, */
736 FILE_DELETE_ON_CLOSE, /* create_options, */
737 NULL, /* smb2_create_blobs *blobs */
738 &fid_persistent,
739 &fid_volatile,
740 NULL,
741 NULL,
742 NULL,
743 NULL);
744 if (!NT_STATUS_IS_OK(status)) {
745 printf("smb2cli_create on cli2 %s\n", nt_errstr(status));
746 return false;
749 status = smb2cli_write(cli2->conn, cli2->timeout, cli2->smb2.session,
750 cli2->smb2.tcon, strlen(hello), 0, fid_persistent,
751 fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
752 if (!NT_STATUS_IS_OK(status)) {
753 printf("smb2cli_write returned %s\n", nt_errstr(status));
754 return false;
757 status = smb2cli_flush(cli2->conn, cli2->timeout, cli2->smb2.session,
758 cli2->smb2.tcon, fid_persistent, fid_volatile);
759 if (!NT_STATUS_IS_OK(status)) {
760 printf("smb2cli_flush returned %s\n", nt_errstr(status));
761 return false;
764 status = smb2cli_read(cli2->conn, cli2->timeout, cli2->smb2.session,
765 cli2->smb2.tcon, 0x10000, 0, fid_persistent,
766 fid_volatile, 2, 0,
767 talloc_tos(), &result, &nread);
768 if (!NT_STATUS_IS_OK(status)) {
769 printf("smb2cli_read returned %s\n", nt_errstr(status));
770 return false;
773 if (nread != strlen(hello)) {
774 printf("smb2cli_read returned %d bytes, expected %d\n",
775 (int)nread, (int)strlen(hello));
776 return false;
779 if (memcmp(hello, result, nread) != 0) {
780 printf("smb2cli_read returned '%s', expected '%s'\n",
781 result, hello);
782 return false;
785 return true;
788 bool run_smb2_tcon_dependence(int dummy)
790 struct cli_state *cli;
791 NTSTATUS status;
792 uint64_t fid_persistent, fid_volatile;
793 const char *hello = "Hello, world\n";
794 uint8_t *result;
795 uint32_t nread;
796 struct smbXcli_tcon *tcon2;
797 uint32_t tcon2_id;
799 printf("Starting SMB2-TCON-DEPENDENCE\n");
801 if (!torture_init_connection(&cli)) {
802 return false;
805 status = smbXcli_negprot(cli->conn, cli->timeout,
806 PROTOCOL_SMB2_02, PROTOCOL_LATEST);
807 if (!NT_STATUS_IS_OK(status)) {
808 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
809 return false;
812 status = cli_session_setup_creds(cli, torture_creds);
813 if (!NT_STATUS_IS_OK(status)) {
814 printf("cli_session_setup returned %s\n", nt_errstr(status));
815 return false;
818 status = cli_tree_connect(cli, share, "?????", NULL);
819 if (!NT_STATUS_IS_OK(status)) {
820 printf("cli_tree_connect returned %s\n", nt_errstr(status));
821 return false;
824 status = smb2cli_create(
825 cli->conn,
826 cli->timeout,
827 cli->smb2.session,
828 cli->smb2.tcon,
829 "tcon_depedence.txt",
830 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
831 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
832 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
833 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
834 FILE_SHARE_READ|
835 FILE_SHARE_WRITE|
836 FILE_SHARE_DELETE, /* share_access, */
837 FILE_CREATE, /* create_disposition, */
838 FILE_DELETE_ON_CLOSE, /* create_options, */
839 NULL, /* smb2_create_blobs *blobs */
840 &fid_persistent,
841 &fid_volatile,
842 NULL,
843 NULL,
844 NULL,
845 NULL);
846 if (!NT_STATUS_IS_OK(status)) {
847 printf("smb2cli_create on cli %s\n", nt_errstr(status));
848 return false;
851 status = smb2cli_write(cli->conn, cli->timeout, cli->smb2.session,
852 cli->smb2.tcon, strlen(hello), 0, fid_persistent,
853 fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
854 if (!NT_STATUS_IS_OK(status)) {
855 printf("smb2cli_write returned %s\n", nt_errstr(status));
856 return false;
859 status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
860 cli->smb2.tcon, fid_persistent, fid_volatile);
861 if (!NT_STATUS_IS_OK(status)) {
862 printf("smb2cli_flush returned %s\n", nt_errstr(status));
863 return false;
866 status = smb2cli_read(cli->conn, cli->timeout, cli->smb2.session,
867 cli->smb2.tcon, 0x10000, 0, fid_persistent,
868 fid_volatile, 2, 0,
869 talloc_tos(), &result, &nread);
870 if (!NT_STATUS_IS_OK(status)) {
871 printf("smb2cli_read returned %s\n", nt_errstr(status));
872 return false;
875 if (nread != strlen(hello)) {
876 printf("smb2cli_read returned %d bytes, expected %d\n",
877 (int)nread, (int)strlen(hello));
878 return false;
881 if (memcmp(hello, result, nread) != 0) {
882 printf("smb2cli_read returned '%s', expected '%s'\n",
883 result, hello);
884 return false;
887 /* check behaviour with wrong tid... */
889 tcon2 = smbXcli_tcon_create(cli);
890 tcon2_id = smb2cli_tcon_current_id(cli->smb2.tcon);
891 tcon2_id++;
892 smb2cli_tcon_set_values(tcon2,
893 NULL, /* session */
894 tcon2_id,
895 0, /* type */
896 0, /* flags */
897 0, /* capabilities */
898 0 /* maximal_access */);
900 status = smb2cli_read(cli->conn, cli->timeout, cli->smb2.session,
901 tcon2, 0x10000, 0, fid_persistent,
902 fid_volatile, 2, 0,
903 talloc_tos(), &result, &nread);
904 if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) {
905 printf("smb2cli_read returned %s\n", nt_errstr(status));
906 return false;
909 talloc_free(tcon2);
911 return true;
914 bool run_smb2_multi_channel(int dummy)
916 struct cli_state *cli1;
917 struct cli_state *cli2;
918 struct cli_state *cli3;
919 NTSTATUS status;
920 bool ok;
921 uint64_t fid_persistent, fid_volatile;
922 struct tevent_context *ev;
923 struct tevent_req *subreq;
924 DATA_BLOB in_blob = data_blob_null;
925 DATA_BLOB out_blob;
926 DATA_BLOB channel_session_key;
927 struct auth_generic_state *auth_generic_state;
928 struct iovec *recv_iov;
929 const char *hello = "Hello, world\n";
930 uint8_t *result;
931 uint32_t nread;
932 struct GUID saved_guid = cli_state_client_guid;
934 printf("Starting SMB2-MULTI-CHANNEL\n");
936 cli_state_client_guid = GUID_random();
938 if (!torture_init_connection(&cli1)) {
939 return false;
942 if (!torture_init_connection(&cli2)) {
943 return false;
946 if (!torture_init_connection(&cli3)) {
947 return false;
950 cli_state_client_guid = saved_guid;
952 status = smbXcli_negprot(cli1->conn, cli1->timeout,
953 PROTOCOL_SMB3_00, PROTOCOL_LATEST);
954 if (!NT_STATUS_IS_OK(status)) {
955 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
956 return false;
959 status = smbXcli_negprot(cli2->conn, cli2->timeout,
960 PROTOCOL_SMB3_00, PROTOCOL_LATEST);
961 if (!NT_STATUS_IS_OK(status)) {
962 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
963 return false;
966 status = smbXcli_negprot(cli3->conn, cli3->timeout,
967 PROTOCOL_SMB3_00, PROTOCOL_LATEST);
968 if (!NT_STATUS_IS_OK(status)) {
969 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
970 return false;
973 status = cli_session_setup_creds(cli1, torture_creds);
974 if (!NT_STATUS_IS_OK(status)) {
975 printf("smb2cli_sesssetup returned %s\n", nt_errstr(status));
976 return false;
979 status = cli_tree_connect(cli1, share, "?????", NULL);
980 if (!NT_STATUS_IS_OK(status)) {
981 printf("cli_tree_connect returned %s\n", nt_errstr(status));
982 return false;
985 status = smb2cli_session_create_channel(cli2,
986 cli1->smb2.session,
987 cli2->conn,
988 &cli2->smb2.session);
989 if (!NT_STATUS_IS_OK(status)) {
990 printf("smb2cli_session_create_channel returned %s\n",
991 nt_errstr(status));
992 return false;
995 status = auth_generic_client_prepare(talloc_tos(), &auth_generic_state);
996 if (!NT_STATUS_IS_OK(status)) {
997 printf("auth_generic_client_prepare returned %s\n", nt_errstr(status));
998 return false;
1001 gensec_want_feature(auth_generic_state->gensec_security,
1002 GENSEC_FEATURE_SESSION_KEY);
1004 status = auth_generic_set_creds(auth_generic_state, torture_creds);
1005 if (!NT_STATUS_IS_OK(status)) {
1006 printf("auth_generic_set_creds returned %s\n", nt_errstr(status));
1007 return false;
1010 status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
1011 if (!NT_STATUS_IS_OK(status)) {
1012 printf("auth_generic_client_start returned %s\n", nt_errstr(status));
1013 return false;
1016 ev = samba_tevent_context_init(talloc_tos());
1017 if (ev == NULL) {
1018 printf("samba_tevent_context_init() returned NULL\n");
1019 return false;
1022 status = gensec_update(auth_generic_state->gensec_security,
1023 talloc_tos(), data_blob_null, &in_blob);
1024 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1025 printf("gensec_update returned %s\n", nt_errstr(status));
1026 return false;
1029 subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1030 cli2->conn,
1031 cli2->timeout,
1032 cli2->smb2.session,
1033 0x01, /* in_flags */
1034 SMB2_CAP_DFS, /* in_capabilities */
1035 0, /* in_channel */
1036 0, /* in_previous_session_id */
1037 &in_blob); /* in_security_buffer */
1038 if (subreq == NULL) {
1039 printf("smb2cli_session_setup_send() returned NULL\n");
1040 return false;
1043 ok = tevent_req_poll(subreq, ev);
1044 if (!ok) {
1045 printf("tevent_req_poll() returned false\n");
1046 return false;
1049 status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1050 NULL, &out_blob);
1051 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1052 printf("smb2cli_session_setup_recv returned %s\n",
1053 nt_errstr(status));
1054 return false;
1057 status = gensec_update(auth_generic_state->gensec_security,
1058 talloc_tos(), out_blob, &in_blob);
1059 if (!NT_STATUS_IS_OK(status)) {
1060 printf("auth_generic_update returned %s\n", nt_errstr(status));
1061 return false;
1064 subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1065 cli2->conn,
1066 cli2->timeout,
1067 cli2->smb2.session,
1068 0x01, /* in_flags */
1069 SMB2_CAP_DFS, /* in_capabilities */
1070 0, /* in_channel */
1071 0, /* in_previous_session_id */
1072 &in_blob); /* in_security_buffer */
1073 if (subreq == NULL) {
1074 printf("smb2cli_session_setup_send() returned NULL\n");
1075 return false;
1078 ok = tevent_req_poll(subreq, ev);
1079 if (!ok) {
1080 printf("tevent_req_poll() returned false\n");
1081 return false;
1084 status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1085 &recv_iov, &out_blob);
1086 if (!NT_STATUS_IS_OK(status)) {
1087 printf("smb2cli_session_setup_recv returned %s\n",
1088 nt_errstr(status));
1089 return false;
1092 status = gensec_session_key(auth_generic_state->gensec_security, talloc_tos(),
1093 &channel_session_key);
1094 if (!NT_STATUS_IS_OK(status)) {
1095 printf("gensec_session_key returned %s\n",
1096 nt_errstr(status));
1097 return false;
1100 status = smb2cli_session_set_channel_key(cli2->smb2.session,
1101 channel_session_key,
1102 recv_iov);
1103 if (!NT_STATUS_IS_OK(status)) {
1104 printf("smb2cli_session_set_channel_key %s\n", nt_errstr(status));
1105 return false;
1108 status = smb2cli_session_create_channel(cli3,
1109 cli1->smb2.session,
1110 cli3->conn,
1111 &cli3->smb2.session);
1112 if (!NT_STATUS_IS_OK(status)) {
1113 printf("smb2cli_session_create_channel returned %s\n",
1114 nt_errstr(status));
1115 return false;
1118 status = auth_generic_client_prepare(talloc_tos(), &auth_generic_state);
1119 if (!NT_STATUS_IS_OK(status)) {
1120 printf("auth_generic_client_prepare returned %s\n", nt_errstr(status));
1121 return false;
1124 gensec_want_feature(auth_generic_state->gensec_security,
1125 GENSEC_FEATURE_SESSION_KEY);
1127 status = auth_generic_set_creds(auth_generic_state, torture_creds);
1128 if (!NT_STATUS_IS_OK(status)) {
1129 printf("auth_generic_set_creds returned %s\n", nt_errstr(status));
1130 return false;
1133 status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
1134 if (!NT_STATUS_IS_OK(status)) {
1135 printf("auth_generic_client_start returned %s\n", nt_errstr(status));
1136 return false;
1139 status = gensec_update(auth_generic_state->gensec_security,
1140 talloc_tos(), data_blob_null, &in_blob);
1141 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1142 printf("gensec_update returned %s\n", nt_errstr(status));
1143 return false;
1146 subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1147 cli3->conn,
1148 cli3->timeout,
1149 cli3->smb2.session,
1150 0x01, /* in_flags */
1151 SMB2_CAP_DFS, /* in_capabilities */
1152 0, /* in_channel */
1153 0, /* in_previous_session_id */
1154 &in_blob); /* in_security_buffer */
1155 if (subreq == NULL) {
1156 printf("smb2cli_session_setup_send() returned NULL\n");
1157 return false;
1160 ok = tevent_req_poll(subreq, ev);
1161 if (!ok) {
1162 printf("tevent_req_poll() returned false\n");
1163 return false;
1166 status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1167 NULL, &out_blob);
1168 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1169 printf("smb2cli_session_setup_recv returned %s\n",
1170 nt_errstr(status));
1171 return false;
1174 status = gensec_update(auth_generic_state->gensec_security,
1175 talloc_tos(), out_blob, &in_blob);
1176 if (!NT_STATUS_IS_OK(status)) {
1177 printf("auth_generic_update returned %s\n", nt_errstr(status));
1178 return false;
1181 subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1182 cli3->conn,
1183 cli3->timeout,
1184 cli3->smb2.session,
1185 0x01, /* in_flags */
1186 SMB2_CAP_DFS, /* in_capabilities */
1187 0, /* in_channel */
1188 0, /* in_previous_session_id */
1189 &in_blob); /* in_security_buffer */
1190 if (subreq == NULL) {
1191 printf("smb2cli_session_setup_send() returned NULL\n");
1192 return false;
1195 ok = tevent_req_poll(subreq, ev);
1196 if (!ok) {
1197 printf("tevent_req_poll() returned false\n");
1198 return false;
1201 status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1202 &recv_iov, &out_blob);
1203 if (!NT_STATUS_IS_OK(status)) {
1204 printf("smb2cli_session_setup_recv returned %s\n",
1205 nt_errstr(status));
1206 return false;
1209 status = gensec_session_key(auth_generic_state->gensec_security, talloc_tos(),
1210 &channel_session_key);
1211 if (!NT_STATUS_IS_OK(status)) {
1212 printf("gensec_session_key returned %s\n",
1213 nt_errstr(status));
1214 return false;
1217 status = smb2cli_session_set_channel_key(cli3->smb2.session,
1218 channel_session_key,
1219 recv_iov);
1220 if (!NT_STATUS_IS_OK(status)) {
1221 printf("smb2cli_session_set_channel_key %s\n", nt_errstr(status));
1222 return false;
1225 status = smb2cli_create(
1226 cli2->conn,
1227 cli2->timeout,
1228 cli2->smb2.session,
1229 cli1->smb2.tcon,
1230 "multi-channel.txt",
1231 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1232 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1233 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1234 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1235 FILE_SHARE_READ|
1236 FILE_SHARE_WRITE|
1237 FILE_SHARE_DELETE, /* share_access, */
1238 FILE_CREATE, /* create_disposition, */
1239 FILE_DELETE_ON_CLOSE, /* create_options, */
1240 NULL, /* smb2_create_blobs *blobs */
1241 &fid_persistent,
1242 &fid_volatile,
1243 NULL,
1244 NULL,
1245 NULL,
1246 NULL);
1247 if (!NT_STATUS_IS_OK(status)) {
1248 printf("smb2cli_create on cli2 %s\n", nt_errstr(status));
1249 return false;
1252 status = smb2cli_write(cli1->conn, cli1->timeout, cli1->smb2.session,
1253 cli1->smb2.tcon, strlen(hello), 0, fid_persistent,
1254 fid_volatile, 0, 0, (const uint8_t *)hello, NULL);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 printf("smb2cli_write returned %s\n", nt_errstr(status));
1257 return false;
1260 status = smb2cli_flush(cli2->conn, cli2->timeout, cli2->smb2.session,
1261 cli1->smb2.tcon, fid_persistent, fid_volatile);
1262 if (!NT_STATUS_IS_OK(status)) {
1263 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1264 return false;
1267 status = smb2cli_flush(cli1->conn, cli1->timeout, cli1->smb2.session,
1268 cli1->smb2.tcon, fid_persistent, fid_volatile);
1269 if (!NT_STATUS_IS_OK(status)) {
1270 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1271 return false;
1274 status = smb2cli_flush(cli3->conn, cli3->timeout, cli3->smb2.session,
1275 cli1->smb2.tcon, fid_persistent, fid_volatile);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1278 return false;
1281 status = smb2cli_read(cli2->conn, cli2->timeout, cli2->smb2.session,
1282 cli1->smb2.tcon, 0x10000, 0, fid_persistent,
1283 fid_volatile, 2, 0,
1284 talloc_tos(), &result, &nread);
1285 if (!NT_STATUS_IS_OK(status)) {
1286 printf("smb2cli_read returned %s\n", nt_errstr(status));
1287 return false;
1290 if (nread != strlen(hello)) {
1291 printf("smb2cli_read returned %d bytes, expected %d\n",
1292 (int)nread, (int)strlen(hello));
1293 return false;
1296 if (memcmp(hello, result, nread) != 0) {
1297 printf("smb2cli_read returned '%s', expected '%s'\n",
1298 result, hello);
1299 return false;
1302 status = auth_generic_client_prepare(talloc_tos(), &auth_generic_state);
1303 if (!NT_STATUS_IS_OK(status)) {
1304 printf("auth_generic_client_prepare returned %s\n", nt_errstr(status));
1305 return false;
1308 gensec_want_feature(auth_generic_state->gensec_security,
1309 GENSEC_FEATURE_SESSION_KEY);
1311 status = auth_generic_set_creds(auth_generic_state, torture_creds);
1312 if (!NT_STATUS_IS_OK(status)) {
1313 printf("auth_generic_set_creds returned %s\n", nt_errstr(status));
1314 return false;
1317 status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
1318 if (!NT_STATUS_IS_OK(status)) {
1319 printf("auth_generic_client_start returned %s\n", nt_errstr(status));
1320 return false;
1323 status = gensec_update(auth_generic_state->gensec_security,
1324 talloc_tos(), data_blob_null, &in_blob);
1325 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1326 printf("gensec_update returned %s\n", nt_errstr(status));
1327 return false;
1330 subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1331 cli3->conn,
1332 cli3->timeout,
1333 cli3->smb2.session,
1334 0x0, /* in_flags */
1335 SMB2_CAP_DFS, /* in_capabilities */
1336 0, /* in_channel */
1337 0, /* in_previous_session_id */
1338 &in_blob); /* in_security_buffer */
1339 if (subreq == NULL) {
1340 printf("smb2cli_session_setup_send() returned NULL\n");
1341 return false;
1344 ok = tevent_req_poll(subreq, ev);
1345 if (!ok) {
1346 printf("tevent_req_poll() returned false\n");
1347 return false;
1350 status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1351 NULL, &out_blob);
1352 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1353 printf("smb2cli_session_setup_recv returned %s\n",
1354 nt_errstr(status));
1355 return false;
1358 status = gensec_update(auth_generic_state->gensec_security,
1359 talloc_tos(), out_blob, &in_blob);
1360 if (!NT_STATUS_IS_OK(status)) {
1361 printf("auth_generic_update returned %s\n", nt_errstr(status));
1362 return false;
1365 status = smb2cli_flush(cli1->conn, cli1->timeout, cli1->smb2.session,
1366 cli1->smb2.tcon, fid_persistent, fid_volatile);
1367 if (!NT_STATUS_IS_OK(status)) {
1368 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1369 return false;
1372 status = smb2cli_flush(cli2->conn, cli2->timeout, cli2->smb2.session,
1373 cli1->smb2.tcon, fid_persistent, fid_volatile);
1374 if (!NT_STATUS_IS_OK(status)) {
1375 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1376 return false;
1379 status = smb2cli_flush(cli3->conn, cli3->timeout, cli3->smb2.session,
1380 cli1->smb2.tcon, fid_persistent, fid_volatile);
1381 if (!NT_STATUS_IS_OK(status)) {
1382 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1383 return false;
1386 status = smb2cli_create(
1387 cli1->conn,
1388 cli1->timeout,
1389 cli1->smb2.session,
1390 cli1->smb2.tcon,
1391 "multi-channel-invalid.txt",
1392 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1393 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1394 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1395 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1396 FILE_SHARE_READ|
1397 FILE_SHARE_WRITE|
1398 FILE_SHARE_DELETE, /* share_access, */
1399 FILE_CREATE, /* create_disposition, */
1400 FILE_DELETE_ON_CLOSE, /* create_options, */
1401 NULL, /* smb2_create_blobs *blobs */
1402 &fid_persistent,
1403 &fid_volatile,
1404 NULL,
1405 NULL,
1406 NULL,
1407 NULL);
1408 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1409 printf("smb2cli_create %s\n", nt_errstr(status));
1410 return false;
1413 status = smb2cli_create(
1414 cli2->conn,
1415 cli2->timeout,
1416 cli2->smb2.session,
1417 cli1->smb2.tcon,
1418 "multi-channel-invalid.txt",
1419 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1420 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1421 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1422 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1423 FILE_SHARE_READ|
1424 FILE_SHARE_WRITE|
1425 FILE_SHARE_DELETE, /* share_access, */
1426 FILE_CREATE, /* create_disposition, */
1427 FILE_DELETE_ON_CLOSE, /* create_options, */
1428 NULL, /* smb2_create_blobs *blobs */
1429 &fid_persistent,
1430 &fid_volatile,
1431 NULL,
1432 NULL,
1433 NULL,
1434 NULL);
1435 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1436 printf("smb2cli_create %s\n", nt_errstr(status));
1437 return false;
1440 status = smb2cli_create(
1441 cli3->conn,
1442 cli3->timeout,
1443 cli3->smb2.session,
1444 cli1->smb2.tcon,
1445 "multi-channel-invalid.txt",
1446 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1447 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1448 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1449 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1450 FILE_SHARE_READ|
1451 FILE_SHARE_WRITE|
1452 FILE_SHARE_DELETE, /* share_access, */
1453 FILE_CREATE, /* create_disposition, */
1454 FILE_DELETE_ON_CLOSE, /* create_options, */
1455 NULL, /* smb2_create_blobs *blobs */
1456 &fid_persistent,
1457 &fid_volatile,
1458 NULL,
1459 NULL,
1460 NULL,
1461 NULL);
1462 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1463 printf("smb2cli_create %s\n", nt_errstr(status));
1464 return false;
1467 subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1468 cli2->conn,
1469 cli2->timeout,
1470 cli2->smb2.session,
1471 0x0, /* in_flags */
1472 SMB2_CAP_DFS, /* in_capabilities */
1473 0, /* in_channel */
1474 0, /* in_previous_session_id */
1475 &in_blob); /* in_security_buffer */
1476 if (subreq == NULL) {
1477 printf("smb2cli_session_setup_send() returned NULL\n");
1478 return false;
1481 ok = tevent_req_poll(subreq, ev);
1482 if (!ok) {
1483 printf("tevent_req_poll() returned false\n");
1484 return false;
1487 status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1488 &recv_iov, &out_blob);
1489 if (!NT_STATUS_IS_OK(status)) {
1490 printf("smb2cli_session_setup_recv returned %s\n",
1491 nt_errstr(status));
1492 return false;
1495 status = smb2cli_close(cli3->conn, cli3->timeout, cli3->smb2.session,
1496 cli1->smb2.tcon, 0, fid_persistent, fid_volatile);
1497 if (!NT_STATUS_IS_OK(status)) {
1498 printf("smb2cli_close returned %s\n", nt_errstr(status));
1499 return false;
1502 status = smb2cli_flush(cli3->conn, cli3->timeout, cli3->smb2.session,
1503 cli1->smb2.tcon, fid_persistent, fid_volatile);
1504 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED)) {
1505 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1506 return false;
1509 status = smb2cli_flush(cli2->conn, cli2->timeout, cli2->smb2.session,
1510 cli1->smb2.tcon, fid_persistent, fid_volatile);
1511 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED)) {
1512 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1513 return false;
1516 status = smb2cli_flush(cli1->conn, cli1->timeout, cli1->smb2.session,
1517 cli1->smb2.tcon, fid_persistent, fid_volatile);
1518 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED)) {
1519 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1520 return false;
1523 return true;
1526 bool run_smb2_session_reauth(int dummy)
1528 struct cli_state *cli;
1529 NTSTATUS status;
1530 bool ok;
1531 uint64_t fid_persistent, fid_volatile;
1532 uint64_t dir_persistent, dir_volatile;
1533 uint8_t *dir_data;
1534 uint32_t dir_data_length;
1535 struct tevent_context *ev;
1536 struct tevent_req *subreq;
1537 DATA_BLOB in_blob = data_blob_null;
1538 DATA_BLOB out_blob;
1539 DATA_BLOB in_input_buffer;
1540 DATA_BLOB out_output_buffer;
1541 uint8_t in_file_info_class;
1542 struct auth_generic_state *auth_generic_state;
1543 struct iovec *recv_iov;
1544 uint32_t saved_tid;
1545 struct smbXcli_tcon *saved_tcon;
1547 printf("Starting SMB2-SESSION_REAUTH\n");
1549 if (!torture_init_connection(&cli)) {
1550 return false;
1554 * PROTOCOL_SMB2_22 has a bug in win8pre0
1555 * it behaves like PROTOCOL_SMB2_02
1556 * and returns NT_STATUS_REQUEST_NOT_ACCEPTED,
1557 * while it allows it on PROTOCOL_SMB2_10.
1559 status = smbXcli_negprot(cli->conn, cli->timeout,
1560 PROTOCOL_SMB2_10, PROTOCOL_SMB2_10);
1561 if (!NT_STATUS_IS_OK(status)) {
1562 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
1563 return false;
1566 status = cli_session_setup_creds(cli, torture_creds);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 printf("smb2cli_sesssetup returned %s\n", nt_errstr(status));
1569 return false;
1572 status = cli_tree_connect(cli, share, "?????", NULL);
1573 if (!NT_STATUS_IS_OK(status)) {
1574 printf("cli_tree_connect returned %s\n", nt_errstr(status));
1575 return false;
1578 status = smb2cli_create(
1579 cli->conn,
1580 cli->timeout,
1581 cli->smb2.session,
1582 cli->smb2.tcon,
1583 "session-reauth.txt",
1584 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1585 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1586 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1587 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1588 FILE_SHARE_READ|
1589 FILE_SHARE_WRITE|
1590 FILE_SHARE_DELETE, /* share_access, */
1591 FILE_CREATE, /* create_disposition, */
1592 FILE_DELETE_ON_CLOSE, /* create_options, */
1593 NULL, /* smb2_create_blobs *blobs */
1594 &fid_persistent,
1595 &fid_volatile,
1596 NULL,
1597 NULL,
1598 NULL,
1599 NULL);
1600 if (!NT_STATUS_IS_OK(status)) {
1601 printf("smb2cli_create %s\n", nt_errstr(status));
1602 return false;
1605 status = smb2cli_create(
1606 cli->conn,
1607 cli->timeout,
1608 cli->smb2.session,
1609 cli->smb2.tcon,
1611 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1612 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1613 SEC_STD_SYNCHRONIZE|
1614 SEC_DIR_LIST|
1615 SEC_DIR_READ_ATTRIBUTE, /* desired_access, */
1616 0, /* file_attributes, */
1617 FILE_SHARE_READ|
1618 FILE_SHARE_WRITE|
1619 FILE_SHARE_DELETE, /* share_access, */
1620 FILE_OPEN, /* create_disposition, */
1621 FILE_SYNCHRONOUS_IO_NONALERT|
1622 FILE_DIRECTORY_FILE, /* create_options, */
1623 NULL, /* smb2_create_blobs *blobs */
1624 &dir_persistent,
1625 &dir_volatile,
1626 NULL,
1627 NULL,
1628 NULL,
1629 NULL);
1630 if (!NT_STATUS_IS_OK(status)) {
1631 printf("smb2cli_create returned %s\n", nt_errstr(status));
1632 return false;
1635 status = smb2cli_query_directory(
1636 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
1637 1, 0x3, 0, dir_persistent, dir_volatile,
1638 "session-reauth.txt", 0xffff,
1639 talloc_tos(), &dir_data, &dir_data_length);
1640 if (!NT_STATUS_IS_OK(status)) {
1641 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
1642 return false;
1645 status = auth_generic_client_prepare(talloc_tos(), &auth_generic_state);
1646 if (!NT_STATUS_IS_OK(status)) {
1647 printf("auth_generic_client_prepare returned %s\n", nt_errstr(status));
1648 return false;
1651 gensec_want_feature(auth_generic_state->gensec_security,
1652 GENSEC_FEATURE_SESSION_KEY);
1654 status = auth_generic_set_creds(auth_generic_state, torture_creds);
1655 if (!NT_STATUS_IS_OK(status)) {
1656 printf("auth_generic_set_creds returned %s\n", nt_errstr(status));
1657 return false;
1660 status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP);
1661 if (!NT_STATUS_IS_OK(status)) {
1662 printf("auth_generic_client_start returned %s\n", nt_errstr(status));
1663 return false;
1666 ev = samba_tevent_context_init(talloc_tos());
1667 if (ev == NULL) {
1668 printf("samba_tevent_context_init() returned NULL\n");
1669 return false;
1672 status = gensec_update(auth_generic_state->gensec_security,
1673 talloc_tos(), data_blob_null, &in_blob);
1674 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1675 printf("gensec_update returned %s\n", nt_errstr(status));
1676 return false;
1679 subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1680 cli->conn,
1681 cli->timeout,
1682 cli->smb2.session,
1683 0x0, /* in_flags */
1684 SMB2_CAP_DFS, /* in_capabilities */
1685 0, /* in_channel */
1686 0, /* in_previous_session_id */
1687 &in_blob); /* in_security_buffer */
1688 if (subreq == NULL) {
1689 printf("smb2cli_session_setup_send() returned NULL\n");
1690 return false;
1693 ok = tevent_req_poll(subreq, ev);
1694 if (!ok) {
1695 printf("tevent_req_poll() returned false\n");
1696 return false;
1699 status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1700 NULL, &out_blob);
1701 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1702 printf("smb2cli_session_setup_recv returned %s\n",
1703 nt_errstr(status));
1704 return false;
1707 status = gensec_update(auth_generic_state->gensec_security,
1708 talloc_tos(), out_blob, &in_blob);
1709 if (!NT_STATUS_IS_OK(status)) {
1710 printf("auth_generic_update returned %s\n", nt_errstr(status));
1711 return false;
1714 status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
1715 cli->smb2.tcon, fid_persistent, fid_volatile);
1716 if (!NT_STATUS_IS_OK(status)) {
1717 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1718 return false;
1721 status = smb2cli_query_directory(
1722 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
1723 1, 0x3, 0, dir_persistent, dir_volatile,
1724 "session-reauth.txt", 0xffff,
1725 talloc_tos(), &dir_data, &dir_data_length);
1726 if (!NT_STATUS_IS_OK(status)) {
1727 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
1728 return false;
1732 * query_info seems to be a path based operation on Windows...
1734 status = smb2cli_query_info(cli->conn,
1735 cli->timeout,
1736 cli->smb2.session,
1737 cli->smb2.tcon,
1738 SMB2_0_INFO_SECURITY,
1739 0, /* in_file_info_class */
1740 1024, /* in_max_output_length */
1741 NULL, /* in_input_buffer */
1742 SECINFO_OWNER, /* in_additional_info */
1743 0, /* in_flags */
1744 fid_persistent,
1745 fid_volatile,
1746 talloc_tos(),
1747 &out_output_buffer);
1748 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1749 printf("smb2cli_query_info (security) returned %s\n", nt_errstr(status));
1750 return false;
1753 in_file_info_class = SMB_FILE_POSITION_INFORMATION - 1000;
1754 status = smb2cli_query_info(cli->conn,
1755 cli->timeout,
1756 cli->smb2.session,
1757 cli->smb2.tcon,
1758 SMB2_0_INFO_FILE,
1759 in_file_info_class,
1760 1024, /* in_max_output_length */
1761 NULL, /* in_input_buffer */
1762 0, /* in_additional_info */
1763 0, /* in_flags */
1764 fid_persistent,
1765 fid_volatile,
1766 talloc_tos(),
1767 &out_output_buffer);
1768 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1769 printf("smb2cli_query_info (position) returned %s\n", nt_errstr(status));
1770 return false;
1773 in_input_buffer = data_blob_talloc(talloc_tos(), NULL, 8);
1774 SBVAL(in_input_buffer.data, 0, 512);
1776 in_file_info_class = SMB_FILE_POSITION_INFORMATION - 1000;
1777 status = smb2cli_set_info(cli->conn,
1778 cli->timeout,
1779 cli->smb2.session,
1780 cli->smb2.tcon,
1781 SMB2_0_INFO_FILE,
1782 in_file_info_class,
1783 &in_input_buffer,
1784 0, /* in_additional_info */
1785 fid_persistent,
1786 fid_volatile);
1787 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1788 printf("smb2cli_set_info (position) returned %s\n", nt_errstr(status));
1789 return false;
1792 status = smb2cli_create(
1793 cli->conn,
1794 cli->timeout,
1795 cli->smb2.session,
1796 cli->smb2.tcon,
1797 "session-reauth-invalid.txt",
1798 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1799 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1800 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1801 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1802 FILE_SHARE_READ|
1803 FILE_SHARE_WRITE|
1804 FILE_SHARE_DELETE, /* share_access, */
1805 FILE_CREATE, /* create_disposition, */
1806 FILE_DELETE_ON_CLOSE, /* create_options, */
1807 NULL, /* smb2_create_blobs *blobs */
1808 &fid_persistent,
1809 &fid_volatile,
1810 NULL,
1811 NULL,
1812 NULL,
1813 NULL);
1814 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1815 printf("smb2cli_create %s\n", nt_errstr(status));
1816 return false;
1819 status = smb2cli_create(
1820 cli->conn,
1821 cli->timeout,
1822 cli->smb2.session,
1823 cli->smb2.tcon,
1825 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1826 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1827 SEC_STD_SYNCHRONIZE|
1828 SEC_DIR_LIST|
1829 SEC_DIR_READ_ATTRIBUTE, /* desired_access, */
1830 0, /* file_attributes, */
1831 FILE_SHARE_READ|
1832 FILE_SHARE_WRITE|
1833 FILE_SHARE_DELETE, /* share_access, */
1834 FILE_OPEN, /* create_disposition, */
1835 FILE_SYNCHRONOUS_IO_NONALERT|
1836 FILE_DIRECTORY_FILE, /* create_options, */
1837 NULL, /* smb2_create_blobs *blobs */
1838 &dir_persistent,
1839 &dir_volatile,
1840 NULL,
1841 NULL,
1842 NULL,
1843 NULL);
1844 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1845 printf("smb2cli_create returned %s\n", nt_errstr(status));
1846 return false;
1849 saved_tid = smb2cli_tcon_current_id(cli->smb2.tcon);
1850 saved_tcon = cli->smb2.tcon;
1851 cli->smb2.tcon = smbXcli_tcon_create(cli);
1852 smb2cli_tcon_set_values(cli->smb2.tcon,
1853 NULL, /* session */
1854 saved_tid,
1855 0, /* type */
1856 0, /* flags */
1857 0, /* capabilities */
1858 0 /* maximal_access */);
1859 status = cli_tree_connect(cli, share, "?????", NULL);
1860 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
1861 printf("cli_tree_connect returned %s\n", nt_errstr(status));
1862 return false;
1864 talloc_free(cli->smb2.tcon);
1865 cli->smb2.tcon = saved_tcon;
1867 subreq = smb2cli_session_setup_send(talloc_tos(), ev,
1868 cli->conn,
1869 cli->timeout,
1870 cli->smb2.session,
1871 0x0, /* in_flags */
1872 SMB2_CAP_DFS, /* in_capabilities */
1873 0, /* in_channel */
1874 0, /* in_previous_session_id */
1875 &in_blob); /* in_security_buffer */
1876 if (subreq == NULL) {
1877 printf("smb2cli_session_setup_send() returned NULL\n");
1878 return false;
1881 ok = tevent_req_poll(subreq, ev);
1882 if (!ok) {
1883 printf("tevent_req_poll() returned false\n");
1884 return false;
1887 status = smb2cli_session_setup_recv(subreq, talloc_tos(),
1888 &recv_iov, &out_blob);
1889 if (!NT_STATUS_IS_OK(status)) {
1890 printf("smb2cli_session_setup_recv returned %s\n",
1891 nt_errstr(status));
1892 return false;
1895 status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
1896 cli->smb2.tcon, fid_persistent, fid_volatile);
1897 if (!NT_STATUS_IS_OK(status)) {
1898 printf("smb2cli_flush returned %s\n", nt_errstr(status));
1899 return false;
1902 status = smb2cli_query_info(cli->conn,
1903 cli->timeout,
1904 cli->smb2.session,
1905 cli->smb2.tcon,
1906 SMB2_0_INFO_SECURITY,
1907 0, /* in_file_info_class */
1908 1024, /* in_max_output_length */
1909 NULL, /* in_input_buffer */
1910 SECINFO_OWNER, /* in_additional_info */
1911 0, /* in_flags */
1912 fid_persistent,
1913 fid_volatile,
1914 talloc_tos(),
1915 &out_output_buffer);
1916 if (!NT_STATUS_IS_OK(status)) {
1917 printf("smb2cli_query_info (security) returned %s\n", nt_errstr(status));
1918 return false;
1921 in_file_info_class = SMB_FILE_POSITION_INFORMATION - 1000;
1922 status = smb2cli_query_info(cli->conn,
1923 cli->timeout,
1924 cli->smb2.session,
1925 cli->smb2.tcon,
1926 SMB2_0_INFO_FILE,
1927 in_file_info_class,
1928 1024, /* in_max_output_length */
1929 NULL, /* in_input_buffer */
1930 0, /* in_additional_info */
1931 0, /* in_flags */
1932 fid_persistent,
1933 fid_volatile,
1934 talloc_tos(),
1935 &out_output_buffer);
1936 if (!NT_STATUS_IS_OK(status)) {
1937 printf("smb2cli_query_info (position) returned %s\n", nt_errstr(status));
1938 return false;
1941 in_input_buffer = data_blob_talloc(talloc_tos(), NULL, 8);
1942 SBVAL(in_input_buffer.data, 0, 512);
1944 in_file_info_class = SMB_FILE_POSITION_INFORMATION - 1000;
1945 status = smb2cli_set_info(cli->conn,
1946 cli->timeout,
1947 cli->smb2.session,
1948 cli->smb2.tcon,
1949 SMB2_0_INFO_FILE,
1950 in_file_info_class,
1951 &in_input_buffer,
1952 0, /* in_additional_info */
1953 fid_persistent,
1954 fid_volatile);
1955 if (!NT_STATUS_IS_OK(status)) {
1956 printf("smb2cli_set_info (position) returned %s\n", nt_errstr(status));
1957 return false;
1960 in_file_info_class = SMB_FILE_POSITION_INFORMATION - 1000;
1961 status = smb2cli_query_info(cli->conn,
1962 cli->timeout,
1963 cli->smb2.session,
1964 cli->smb2.tcon,
1965 SMB2_0_INFO_FILE,
1966 in_file_info_class,
1967 1024, /* in_max_output_length */
1968 NULL, /* in_input_buffer */
1969 0, /* in_additional_info */
1970 0, /* in_flags */
1971 fid_persistent,
1972 fid_volatile,
1973 talloc_tos(),
1974 &out_output_buffer);
1975 if (!NT_STATUS_IS_OK(status)) {
1976 printf("smb2cli_query_info (position) returned %s\n", nt_errstr(status));
1977 return false;
1980 status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
1981 cli->smb2.tcon, 0, fid_persistent, fid_volatile);
1982 if (!NT_STATUS_IS_OK(status)) {
1983 printf("smb2cli_close returned %s\n", nt_errstr(status));
1984 return false;
1987 status = smb2cli_create(
1988 cli->conn,
1989 cli->timeout,
1990 cli->smb2.session,
1991 cli->smb2.tcon,
1992 "session-reauth.txt",
1993 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
1994 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
1995 SEC_STD_ALL | SEC_FILE_ALL, /* desired_access, */
1996 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
1997 FILE_SHARE_READ|
1998 FILE_SHARE_WRITE|
1999 FILE_SHARE_DELETE, /* share_access, */
2000 FILE_CREATE, /* create_disposition, */
2001 FILE_DELETE_ON_CLOSE, /* create_options, */
2002 NULL, /* smb2_create_blobs *blobs */
2003 &fid_persistent,
2004 &fid_volatile,
2005 NULL,
2006 NULL,
2007 NULL,
2008 NULL);
2009 if (!NT_STATUS_IS_OK(status)) {
2010 printf("smb2cli_create %s\n", nt_errstr(status));
2011 return false;
2014 status = smb2cli_query_directory(
2015 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
2016 1, 0x3, 0, dir_persistent, dir_volatile,
2017 "session-reauth.txt", 0xffff,
2018 talloc_tos(), &dir_data, &dir_data_length);
2019 if (!NT_STATUS_IS_OK(status)) {
2020 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
2021 return false;
2024 status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
2025 cli->smb2.tcon, 0, dir_persistent, dir_volatile);
2026 if (!NT_STATUS_IS_OK(status)) {
2027 printf("smb2cli_close returned %s\n", nt_errstr(status));
2028 return false;
2031 status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
2032 cli->smb2.tcon, 0, fid_persistent, fid_volatile);
2033 if (!NT_STATUS_IS_OK(status)) {
2034 printf("smb2cli_close returned %s\n", nt_errstr(status));
2035 return false;
2038 saved_tid = smb2cli_tcon_current_id(cli->smb2.tcon);
2039 saved_tcon = cli->smb2.tcon;
2040 cli->smb2.tcon = smbXcli_tcon_create(cli);
2041 smb2cli_tcon_set_values(cli->smb2.tcon,
2042 NULL, /* session */
2043 saved_tid,
2044 0, /* type */
2045 0, /* flags */
2046 0, /* capabilities */
2047 0 /* maximal_access */);
2048 status = cli_tree_connect(cli, share, "?????", NULL);
2049 if (!NT_STATUS_IS_OK(status)) {
2050 printf("cli_tree_connect returned %s\n", nt_errstr(status));
2051 return false;
2053 talloc_free(cli->smb2.tcon);
2054 cli->smb2.tcon = saved_tcon;
2056 return true;
2059 static NTSTATUS check_size(struct cli_state *cli,
2060 uint16_t fnum,
2061 const char *fname,
2062 size_t size)
2064 off_t size_read = 0;
2066 NTSTATUS status = cli_qfileinfo_basic(cli,
2067 fnum,
2068 NULL,
2069 &size_read,
2070 NULL,
2071 NULL,
2072 NULL,
2073 NULL,
2074 NULL);
2076 if (!NT_STATUS_IS_OK(status)) {
2077 printf("cli_qfileinfo_basic of %s failed (%s)\n",
2078 fname,
2079 nt_errstr(status));
2080 return status;
2083 if (size != size_read) {
2084 printf("size (%u) != size_read(%u) for %s\n",
2085 (unsigned int)size,
2086 (unsigned int)size_read,
2087 fname);
2088 /* Use EOF to mean bad size. */
2089 return NT_STATUS_END_OF_FILE;
2091 return NT_STATUS_OK;
2094 /* Ensure cli_ftruncate() works for SMB2. */
2096 bool run_smb2_ftruncate(int dummy)
2098 struct cli_state *cli = NULL;
2099 const char *fname = "smb2_ftruncate.txt";
2100 uint16_t fnum = (uint16_t)-1;
2101 bool correct = false;
2102 size_t buflen = 1024*1024;
2103 uint8_t *buf = NULL;
2104 unsigned int i;
2105 NTSTATUS status;
2107 printf("Starting SMB2-FTRUNCATE\n");
2109 if (!torture_init_connection(&cli)) {
2110 goto fail;
2113 status = smbXcli_negprot(cli->conn, cli->timeout,
2114 PROTOCOL_SMB2_02, PROTOCOL_SMB2_02);
2115 if (!NT_STATUS_IS_OK(status)) {
2116 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
2117 goto fail;
2120 status = cli_session_setup_creds(cli, torture_creds);
2121 if (!NT_STATUS_IS_OK(status)) {
2122 printf("cli_session_setup returned %s\n", nt_errstr(status));
2123 goto fail;
2126 status = cli_tree_connect(cli, share, "?????", NULL);
2127 if (!NT_STATUS_IS_OK(status)) {
2128 printf("cli_tree_connect returned %s\n", nt_errstr(status));
2129 goto fail;
2132 cli_setatr(cli, fname, 0, 0);
2133 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2135 status = cli_ntcreate(cli,
2136 fname,
2138 GENERIC_ALL_ACCESS,
2139 FILE_ATTRIBUTE_NORMAL,
2140 FILE_SHARE_NONE,
2141 FILE_CREATE,
2144 &fnum,
2145 NULL);
2147 if (!NT_STATUS_IS_OK(status)) {
2148 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2149 goto fail;
2152 buf = talloc_zero_array(cli, uint8_t, buflen);
2153 if (buf == NULL) {
2154 goto fail;
2157 /* Write 1MB. */
2158 status = cli_writeall(cli,
2159 fnum,
2161 buf,
2163 buflen,
2164 NULL);
2166 if (!NT_STATUS_IS_OK(status)) {
2167 printf("write of %u to %s failed (%s)\n",
2168 (unsigned int)buflen,
2169 fname,
2170 nt_errstr(status));
2171 goto fail;
2174 status = check_size(cli, fnum, fname, buflen);
2175 if (!NT_STATUS_IS_OK(status)) {
2176 goto fail;
2179 /* Now ftruncate. */
2180 for ( i = 0; i < 10; i++) {
2181 status = cli_ftruncate(cli, fnum, i*1024);
2182 if (!NT_STATUS_IS_OK(status)) {
2183 printf("cli_ftruncate %u of %s failed (%s)\n",
2184 (unsigned int)i*1024,
2185 fname,
2186 nt_errstr(status));
2187 goto fail;
2189 status = check_size(cli, fnum, fname, i*1024);
2190 if (!NT_STATUS_IS_OK(status)) {
2191 goto fail;
2195 correct = true;
2197 fail:
2199 if (cli == NULL) {
2200 return false;
2203 if (fnum != (uint16_t)-1) {
2204 cli_close(cli, fnum);
2206 cli_setatr(cli, fname, 0, 0);
2207 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2209 if (!torture_close_connection(cli)) {
2210 correct = false;
2212 return correct;
2215 /* Ensure SMB2 flush on directories behaves correctly. */
2217 static bool test_dir_fsync(struct cli_state *cli, const char *path)
2219 NTSTATUS status;
2220 uint64_t fid_persistent, fid_volatile;
2221 uint8_t *dir_data = NULL;
2222 uint32_t dir_data_length = 0;
2224 /* Open directory - no write abilities. */
2225 status = smb2cli_create(
2226 cli->conn,
2227 cli->timeout,
2228 cli->smb2.session,
2229 cli->smb2.tcon,
2230 path,
2231 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2232 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2233 SEC_STD_SYNCHRONIZE|
2234 SEC_DIR_LIST|
2235 SEC_DIR_READ_ATTRIBUTE, /* desired_access, */
2236 0, /* file_attributes, */
2237 FILE_SHARE_READ|
2238 FILE_SHARE_WRITE|
2239 FILE_SHARE_DELETE, /* share_access, */
2240 FILE_OPEN, /* create_disposition, */
2241 FILE_SYNCHRONOUS_IO_NONALERT|
2242 FILE_DIRECTORY_FILE, /* create_options, */
2243 NULL, /* smb2_create_blobs *blobs */
2244 &fid_persistent,
2245 &fid_volatile,
2246 NULL,
2247 NULL,
2248 NULL,
2249 NULL);
2250 if (!NT_STATUS_IS_OK(status)) {
2251 printf("smb2cli_create '%s' (readonly) returned %s\n",
2252 path,
2253 nt_errstr(status));
2254 return false;
2257 status = smb2cli_query_directory(
2258 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
2259 1, 0, 0, fid_persistent, fid_volatile, "*", 0xffff,
2260 talloc_tos(), &dir_data, &dir_data_length);
2262 if (!NT_STATUS_IS_OK(status)) {
2263 printf("smb2cli_query_directory returned %s\n",
2264 nt_errstr(status));
2265 return false;
2268 /* Open directory no write access. Flush should fail. */
2270 status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
2271 cli->smb2.tcon, fid_persistent, fid_volatile);
2272 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2273 printf("smb2cli_flush on a read-only directory returned %s\n",
2274 nt_errstr(status));
2275 return false;
2278 status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
2279 cli->smb2.tcon, 0, fid_persistent, fid_volatile);
2280 if (!NT_STATUS_IS_OK(status)) {
2281 printf("smb2cli_close returned %s\n", nt_errstr(status));
2282 return false;
2285 /* Open directory write-attributes only. Flush should still fail. */
2287 status = smb2cli_create(
2288 cli->conn,
2289 cli->timeout,
2290 cli->smb2.session,
2291 cli->smb2.tcon,
2292 path,
2293 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2294 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2295 SEC_STD_SYNCHRONIZE|
2296 SEC_DIR_LIST|
2297 SEC_DIR_WRITE_ATTRIBUTE|
2298 SEC_DIR_READ_ATTRIBUTE, /* desired_access, */
2299 0, /* file_attributes, */
2300 FILE_SHARE_READ|
2301 FILE_SHARE_WRITE|
2302 FILE_SHARE_DELETE, /* share_access, */
2303 FILE_OPEN, /* create_disposition, */
2304 FILE_SYNCHRONOUS_IO_NONALERT|
2305 FILE_DIRECTORY_FILE, /* create_options, */
2306 NULL, /* smb2_create_blobs *blobs */
2307 &fid_persistent,
2308 &fid_volatile,
2309 NULL,
2310 NULL,
2311 NULL,
2312 NULL);
2313 if (!NT_STATUS_IS_OK(status)) {
2314 printf("smb2cli_create '%s' (write attr) returned %s\n",
2315 path,
2316 nt_errstr(status));
2317 return false;
2320 status = smb2cli_query_directory(
2321 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
2322 1, 0, 0, fid_persistent, fid_volatile, "*", 0xffff,
2323 talloc_tos(), &dir_data, &dir_data_length);
2325 if (!NT_STATUS_IS_OK(status)) {
2326 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
2327 return false;
2330 status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
2331 cli->smb2.tcon, fid_persistent, fid_volatile);
2332 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2333 printf("smb2cli_flush on a write-attributes directory "
2334 "returned %s\n",
2335 nt_errstr(status));
2336 return false;
2339 status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
2340 cli->smb2.tcon, 0, fid_persistent, fid_volatile);
2341 if (!NT_STATUS_IS_OK(status)) {
2342 printf("smb2cli_close returned %s\n", nt_errstr(status));
2343 return false;
2346 /* Open directory with SEC_DIR_ADD_FILE access. Flush should now succeed. */
2348 status = smb2cli_create(
2349 cli->conn,
2350 cli->timeout,
2351 cli->smb2.session,
2352 cli->smb2.tcon,
2353 path,
2354 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2355 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2356 SEC_STD_SYNCHRONIZE|
2357 SEC_DIR_LIST|
2358 SEC_DIR_ADD_FILE, /* desired_access, */
2359 0, /* file_attributes, */
2360 FILE_SHARE_READ|
2361 FILE_SHARE_WRITE|
2362 FILE_SHARE_DELETE, /* share_access, */
2363 FILE_OPEN, /* create_disposition, */
2364 FILE_SYNCHRONOUS_IO_NONALERT|
2365 FILE_DIRECTORY_FILE, /* create_options, */
2366 NULL, /* smb2_create_blobs *blobs */
2367 &fid_persistent,
2368 &fid_volatile,
2369 NULL,
2370 NULL,
2371 NULL,
2372 NULL);
2373 if (!NT_STATUS_IS_OK(status)) {
2374 printf("smb2cli_create '%s' (write FILE access) returned %s\n",
2375 path,
2376 nt_errstr(status));
2377 return false;
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);
2385 if (!NT_STATUS_IS_OK(status)) {
2386 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
2387 return false;
2390 status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
2391 cli->smb2.tcon, fid_persistent, fid_volatile);
2392 if (!NT_STATUS_IS_OK(status)) {
2393 printf("smb2cli_flush on a directory returned %s\n",
2394 nt_errstr(status));
2395 return false;
2398 status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
2399 cli->smb2.tcon, 0, fid_persistent, fid_volatile);
2400 if (!NT_STATUS_IS_OK(status)) {
2401 printf("smb2cli_close returned %s\n", nt_errstr(status));
2402 return false;
2405 /* Open directory with SEC_DIR_ADD_FILE access. Flush should now succeed. */
2407 status = smb2cli_create(
2408 cli->conn,
2409 cli->timeout,
2410 cli->smb2.session,
2411 cli->smb2.tcon,
2412 path,
2413 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2414 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2415 SEC_STD_SYNCHRONIZE|
2416 SEC_DIR_LIST|
2417 SEC_DIR_ADD_SUBDIR, /* desired_access, */
2418 0, /* file_attributes, */
2419 FILE_SHARE_READ|
2420 FILE_SHARE_WRITE|
2421 FILE_SHARE_DELETE, /* share_access, */
2422 FILE_OPEN, /* create_disposition, */
2423 FILE_SYNCHRONOUS_IO_NONALERT|
2424 FILE_DIRECTORY_FILE, /* create_options, */
2425 NULL, /* smb2_create_blobs *blobs */
2426 &fid_persistent,
2427 &fid_volatile,
2428 NULL,
2429 NULL,
2430 NULL,
2431 NULL);
2432 if (!NT_STATUS_IS_OK(status)) {
2433 printf("smb2cli_create '%s' (write DIR access) returned %s\n",
2434 path,
2435 nt_errstr(status));
2436 return false;
2439 status = smb2cli_query_directory(
2440 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
2441 1, 0, 0, fid_persistent, fid_volatile, "*", 0xffff,
2442 talloc_tos(), &dir_data, &dir_data_length);
2444 if (!NT_STATUS_IS_OK(status)) {
2445 printf("smb2cli_query_directory returned %s\n", nt_errstr(status));
2446 return false;
2449 status = smb2cli_flush(cli->conn, cli->timeout, cli->smb2.session,
2450 cli->smb2.tcon, fid_persistent, fid_volatile);
2451 if (!NT_STATUS_IS_OK(status)) {
2452 printf("smb2cli_flush on a directory returned %s\n",
2453 nt_errstr(status));
2454 return false;
2457 status = smb2cli_close(cli->conn, cli->timeout, cli->smb2.session,
2458 cli->smb2.tcon, 0, fid_persistent, fid_volatile);
2459 if (!NT_STATUS_IS_OK(status)) {
2460 printf("smb2cli_close returned %s\n", nt_errstr(status));
2461 return false;
2465 return true;
2468 bool run_smb2_dir_fsync(int dummy)
2470 struct cli_state *cli = NULL;
2471 NTSTATUS status;
2472 bool bret = false;
2473 const char *dname = "fsync_test_dir";
2475 printf("Starting SMB2-DIR-FSYNC\n");
2477 if (!torture_init_connection(&cli)) {
2478 return false;
2481 status = smbXcli_negprot(cli->conn, cli->timeout,
2482 PROTOCOL_SMB2_02, PROTOCOL_SMB2_02);
2483 if (!NT_STATUS_IS_OK(status)) {
2484 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
2485 return false;
2488 status = cli_session_setup_creds(cli, torture_creds);
2489 if (!NT_STATUS_IS_OK(status)) {
2490 printf("cli_session_setup returned %s\n", nt_errstr(status));
2491 return false;
2494 status = cli_tree_connect(cli, share, "?????", NULL);
2495 if (!NT_STATUS_IS_OK(status)) {
2496 printf("cli_tree_connect returned %s\n", nt_errstr(status));
2497 return false;
2500 (void)cli_rmdir(cli, dname);
2501 status = cli_mkdir(cli, dname);
2502 if (!NT_STATUS_IS_OK(status)) {
2503 printf("cli_mkdir(%s) returned %s\n",
2504 dname,
2505 nt_errstr(status));
2506 return false;
2509 /* Test on a subdirectory. */
2510 bret = test_dir_fsync(cli, dname);
2511 if (bret == false) {
2512 (void)cli_rmdir(cli, dname);
2513 return false;
2515 (void)cli_rmdir(cli, dname);
2517 /* Test on the root handle of a share. */
2518 bret = test_dir_fsync(cli, "");
2519 if (bret == false) {
2520 return false;
2522 return true;
2525 bool run_smb2_path_slash(int dummy)
2527 struct cli_state *cli = NULL;
2528 NTSTATUS status;
2529 uint64_t fid_persistent;
2530 uint64_t fid_volatile;
2531 const char *dname_noslash = "smb2_dir_slash";
2532 const char *dname_backslash = "smb2_dir_slash\\";
2533 const char *dname_slash = "smb2_dir_slash/";
2534 const char *fname_noslash = "smb2_file_slash";
2535 const char *fname_backslash = "smb2_file_slash\\";
2536 const char *fname_slash = "smb2_file_slash/";
2538 printf("Starting SMB2-PATH-SLASH\n");
2540 if (!torture_init_connection(&cli)) {
2541 return false;
2544 status = smbXcli_negprot(cli->conn, cli->timeout,
2545 PROTOCOL_SMB2_02, PROTOCOL_SMB2_02);
2546 if (!NT_STATUS_IS_OK(status)) {
2547 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
2548 return false;
2551 status = cli_session_setup_creds(cli, torture_creds);
2552 if (!NT_STATUS_IS_OK(status)) {
2553 printf("cli_session_setup returned %s\n", nt_errstr(status));
2554 return false;
2557 status = cli_tree_connect(cli, share, "?????", NULL);
2558 if (!NT_STATUS_IS_OK(status)) {
2559 printf("cli_tree_connect returned %s\n", nt_errstr(status));
2560 return false;
2563 (void)cli_unlink(cli, dname_noslash, 0);
2564 (void)cli_rmdir(cli, dname_noslash);
2565 (void)cli_unlink(cli, fname_noslash, 0);
2566 (void)cli_rmdir(cli, fname_noslash);
2568 /* Try to create a directory with the backslash name. */
2569 status = smb2cli_create(
2570 cli->conn,
2571 cli->timeout,
2572 cli->smb2.session,
2573 cli->smb2.tcon,
2574 dname_backslash,
2575 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2576 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2577 FILE_READ_DATA|FILE_READ_ATTRIBUTES, /* desired_access, */
2578 0, /* file_attributes, */
2579 FILE_SHARE_READ|
2580 FILE_SHARE_WRITE|
2581 FILE_SHARE_DELETE, /* share_access, */
2582 FILE_CREATE, /* create_disposition, */
2583 FILE_DIRECTORY_FILE, /* create_options, */
2584 NULL, /* smb2_create_blobs *blobs */
2585 &fid_persistent,
2586 &fid_volatile,
2587 NULL,
2588 NULL,
2589 NULL,
2590 NULL);
2592 /* directory ending in '\\' should be success. */
2594 if (!NT_STATUS_IS_OK(status)) {
2595 printf("smb2cli_create '%s' returned %s - "
2596 "should be NT_STATUS_OK\n",
2597 dname_backslash,
2598 nt_errstr(status));
2599 return false;
2601 status = smb2cli_close(cli->conn,
2602 cli->timeout,
2603 cli->smb2.session,
2604 cli->smb2.tcon,
2606 fid_persistent,
2607 fid_volatile);
2608 if (!NT_STATUS_IS_OK(status)) {
2609 printf("smb2cli_close returned %s\n", nt_errstr(status));
2610 return false;
2613 (void)cli_rmdir(cli, dname_noslash);
2615 /* Try to create a directory with the slash name. */
2616 status = smb2cli_create(
2617 cli->conn,
2618 cli->timeout,
2619 cli->smb2.session,
2620 cli->smb2.tcon,
2621 dname_slash,
2622 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2623 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2624 FILE_READ_DATA|FILE_READ_ATTRIBUTES, /* desired_access, */
2625 0, /* file_attributes, */
2626 FILE_SHARE_READ|
2627 FILE_SHARE_WRITE|
2628 FILE_SHARE_DELETE, /* share_access, */
2629 FILE_CREATE, /* create_disposition, */
2630 FILE_DIRECTORY_FILE, /* create_options, */
2631 NULL, /* smb2_create_blobs *blobs */
2632 &fid_persistent,
2633 &fid_volatile,
2634 NULL,
2635 NULL,
2636 NULL,
2637 NULL);
2639 /* directory ending in '/' is an error. */
2640 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
2641 printf("smb2cli_create '%s' returned %s - "
2642 "should be NT_STATUS_OBJECT_NAME_INVALID\n",
2643 dname_slash,
2644 nt_errstr(status));
2645 if (NT_STATUS_IS_OK(status)) {
2646 (void)smb2cli_close(cli->conn,
2647 cli->timeout,
2648 cli->smb2.session,
2649 cli->smb2.tcon,
2651 fid_persistent,
2652 fid_volatile);
2654 (void)cli_rmdir(cli, dname_noslash);
2655 return false;
2658 (void)cli_rmdir(cli, dname_noslash);
2660 /* Try to create a file with the backslash name. */
2661 status = smb2cli_create(
2662 cli->conn,
2663 cli->timeout,
2664 cli->smb2.session,
2665 cli->smb2.tcon,
2666 fname_backslash,
2667 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2668 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2669 FILE_READ_DATA|FILE_READ_ATTRIBUTES, /* desired_access, */
2670 0, /* file_attributes, */
2671 FILE_SHARE_READ|
2672 FILE_SHARE_WRITE|
2673 FILE_SHARE_DELETE, /* share_access, */
2674 FILE_CREATE, /* create_disposition, */
2675 FILE_NON_DIRECTORY_FILE, /* create_options, */
2676 NULL, /* smb2_create_blobs *blobs */
2677 &fid_persistent,
2678 &fid_volatile,
2679 NULL,
2680 NULL,
2681 NULL,
2682 NULL);
2684 /* file ending in '\\' should be error. */
2686 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
2687 printf("smb2cli_create '%s' returned %s - "
2688 "should be NT_STATUS_OBJECT_NAME_INVALID\n",
2689 fname_backslash,
2690 nt_errstr(status));
2691 if (NT_STATUS_IS_OK(status)) {
2692 (void)smb2cli_close(cli->conn,
2693 cli->timeout,
2694 cli->smb2.session,
2695 cli->smb2.tcon,
2697 fid_persistent,
2698 fid_volatile);
2700 (void)cli_unlink(cli, fname_noslash, 0);
2701 return false;
2704 (void)cli_unlink(cli, fname_noslash, 0);
2706 /* Try to create a file with the slash name. */
2707 status = smb2cli_create(
2708 cli->conn,
2709 cli->timeout,
2710 cli->smb2.session,
2711 cli->smb2.tcon,
2712 fname_slash,
2713 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
2714 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
2715 FILE_READ_DATA|FILE_READ_ATTRIBUTES, /* desired_access, */
2716 0, /* file_attributes, */
2717 FILE_SHARE_READ|
2718 FILE_SHARE_WRITE|
2719 FILE_SHARE_DELETE, /* share_access, */
2720 FILE_CREATE, /* create_disposition, */
2721 FILE_NON_DIRECTORY_FILE, /* create_options, */
2722 NULL, /* smb2_create_blobs *blobs */
2723 &fid_persistent,
2724 &fid_volatile,
2725 NULL,
2726 NULL,
2727 NULL,
2728 NULL);
2730 /* file ending in '/' should be error. */
2732 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
2733 printf("smb2cli_create '%s' returned %s - "
2734 "should be NT_STATUS_OBJECT_NAME_INVALID\n",
2735 fname_slash,
2736 nt_errstr(status));
2737 if (NT_STATUS_IS_OK(status)) {
2738 (void)smb2cli_close(cli->conn,
2739 cli->timeout,
2740 cli->smb2.session,
2741 cli->smb2.tcon,
2743 fid_persistent,
2744 fid_volatile);
2746 (void)cli_unlink(cli, fname_noslash, 0);
2747 return false;
2750 (void)cli_unlink(cli, fname_noslash, 0);
2751 return true;
2755 * NB. This can only work against a server where
2756 * the connecting user has been granted SeSecurityPrivilege.
2758 * 1). Create a test file.
2759 * 2). Open with SEC_FLAG_SYSTEM_SECURITY *only*. ACCESS_DENIED -
2760 * NB. SMB2-only behavior.
2761 * 3). Open with SEC_FLAG_SYSTEM_SECURITY|FILE_WRITE_ATTRIBUTES.
2762 * 4). Write SACL. Should fail with ACCESS_DENIED (seems to need WRITE_DAC).
2763 * 5). Close (3).
2764 * 6). Open with SEC_FLAG_SYSTEM_SECURITY|SEC_STD_WRITE_DAC.
2765 * 7). Write SACL. Success.
2766 * 8). Close (4).
2767 * 9). Open with SEC_FLAG_SYSTEM_SECURITY|READ_ATTRIBUTES.
2768 * 10). Read SACL. Success.
2769 * 11). Read DACL. Should fail with ACCESS_DENIED (no READ_CONTROL).
2770 * 12). Close (9).
2773 bool run_smb2_sacl(int dummy)
2775 struct cli_state *cli = NULL;
2776 NTSTATUS status;
2777 struct security_descriptor *sd_dacl = NULL;
2778 struct security_descriptor *sd_sacl = NULL;
2779 const char *fname = "sacl_test_file";
2780 uint16_t fnum = (uint16_t)-1;
2782 printf("Starting SMB2-SACL\n");
2784 if (!torture_init_connection(&cli)) {
2785 return false;
2788 status = smbXcli_negprot(cli->conn,
2789 cli->timeout,
2790 PROTOCOL_SMB2_02,
2791 PROTOCOL_SMB3_11);
2792 if (!NT_STATUS_IS_OK(status)) {
2793 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
2794 return false;
2797 status = cli_session_setup_creds(cli, torture_creds);
2798 if (!NT_STATUS_IS_OK(status)) {
2799 printf("cli_session_setup returned %s\n", nt_errstr(status));
2800 return false;
2803 status = cli_tree_connect(cli, share, "?????", NULL);
2804 if (!NT_STATUS_IS_OK(status)) {
2805 printf("cli_tree_connect returned %s\n", nt_errstr(status));
2806 return false;
2809 (void)cli_unlink(cli, fname, 0);
2811 /* First create a file. */
2812 status = cli_ntcreate(cli,
2813 fname,
2815 GENERIC_ALL_ACCESS,
2816 FILE_ATTRIBUTE_NORMAL,
2817 FILE_SHARE_NONE,
2818 FILE_CREATE,
2821 &fnum,
2822 NULL);
2824 if (!NT_STATUS_IS_OK(status)) {
2825 printf("Create of %s failed (%s)\n",
2826 fname,
2827 nt_errstr(status));
2828 goto fail;
2831 cli_close(cli, fnum);
2832 fnum = (uint16_t)-1;
2835 * Now try to open with *only* SEC_FLAG_SYSTEM_SECURITY.
2836 * This should fail with NT_STATUS_ACCESS_DENIED - but
2837 * only against an SMB2 server. SMB1 allows this as tested
2838 * in SMB1-SYSTEM-SECURITY.
2841 status = cli_smb2_create_fnum(cli,
2842 fname,
2843 SMB2_OPLOCK_LEVEL_NONE,
2844 SMB2_IMPERSONATION_IMPERSONATION,
2845 SEC_FLAG_SYSTEM_SECURITY, /* desired access */
2846 0, /* file_attributes, */
2847 FILE_SHARE_READ|
2848 FILE_SHARE_WRITE|
2849 FILE_SHARE_DELETE, /* share_access, */
2850 FILE_OPEN, /* create_disposition, */
2851 FILE_NON_DIRECTORY_FILE, /* create_options, */
2852 NULL, /* in_cblobs. */
2853 &fnum, /* fnum */
2854 NULL, /* smb_create_returns */
2855 talloc_tos(), /* mem_ctx */
2856 NULL); /* out_cblobs */
2858 if (NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
2859 printf("SMB2-SACL-TEST can only work with a user "
2860 "who has been granted SeSecurityPrivilege.\n"
2861 "This is the "
2862 "\"Manage auditing and security log\""
2863 "privilege setting on Windows\n");
2864 goto fail;
2867 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2868 printf("open file %s with SEC_FLAG_SYSTEM_SECURITY only: "
2869 "got %s - should fail with ACCESS_DENIED\n",
2870 fname,
2871 nt_errstr(status));
2872 goto fail;
2876 * Open with SEC_FLAG_SYSTEM_SECURITY|FILE_WRITE_ATTRIBUTES.
2879 status = cli_smb2_create_fnum(cli,
2880 fname,
2881 SMB2_OPLOCK_LEVEL_NONE,
2882 SMB2_IMPERSONATION_IMPERSONATION,
2883 SEC_FLAG_SYSTEM_SECURITY|
2884 FILE_WRITE_ATTRIBUTES, /* desired access */
2885 0, /* file_attributes, */
2886 FILE_SHARE_READ|
2887 FILE_SHARE_WRITE|
2888 FILE_SHARE_DELETE, /* share_access, */
2889 FILE_OPEN, /* create_disposition, */
2890 FILE_NON_DIRECTORY_FILE, /* create_options, */
2891 NULL, /* in_cblobs. */
2892 &fnum, /* fnum */
2893 NULL, /* smb_create_returns */
2894 talloc_tos(), /* mem_ctx */
2895 NULL); /* out_cblobs */
2897 if (!NT_STATUS_IS_OK(status)) {
2898 printf("Open of %s with (SEC_FLAG_SYSTEM_SECURITY|"
2899 "FILE_WRITE_ATTRIBUTES) failed (%s)\n",
2900 fname,
2901 nt_errstr(status));
2902 goto fail;
2905 /* Create an SD with a SACL. */
2906 sd_sacl = security_descriptor_sacl_create(talloc_tos(),
2908 NULL, /* owner. */
2909 NULL, /* group. */
2910 /* first ACE. */
2911 SID_WORLD,
2912 SEC_ACE_TYPE_SYSTEM_AUDIT,
2913 SEC_GENERIC_ALL,
2914 SEC_ACE_FLAG_FAILED_ACCESS,
2915 NULL);
2917 if (sd_sacl == NULL) {
2918 printf("Out of memory creating SACL\n");
2919 goto fail;
2923 * Write the SACL SD. This should fail
2924 * even though we have SEC_FLAG_SYSTEM_SECURITY,
2925 * as it seems to also need WRITE_DAC access.
2927 status = cli_set_security_descriptor(cli,
2928 fnum,
2929 SECINFO_DACL|SECINFO_SACL,
2930 sd_sacl);
2932 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2933 printf("Writing SACL on file %s got (%s) "
2934 "should have failed with ACCESS_DENIED.\n",
2935 fname,
2936 nt_errstr(status));
2937 goto fail;
2940 /* And close. */
2941 cli_smb2_close_fnum(cli, fnum);
2942 fnum = (uint16_t)-1;
2945 * Open with SEC_FLAG_SYSTEM_SECURITY|SEC_STD_WRITE_DAC.
2948 status = cli_smb2_create_fnum(cli,
2949 fname,
2950 SMB2_OPLOCK_LEVEL_NONE,
2951 SMB2_IMPERSONATION_IMPERSONATION,
2952 SEC_FLAG_SYSTEM_SECURITY|
2953 SEC_STD_WRITE_DAC, /* desired access */
2954 0, /* file_attributes, */
2955 FILE_SHARE_READ|
2956 FILE_SHARE_WRITE|
2957 FILE_SHARE_DELETE, /* share_access, */
2958 FILE_OPEN, /* create_disposition, */
2959 FILE_NON_DIRECTORY_FILE, /* create_options, */
2960 NULL, /* in_cblobs. */
2961 &fnum, /* fnum */
2962 NULL, /* smb_create_returns */
2963 talloc_tos(), /* mem_ctx */
2964 NULL); /* out_cblobs */
2966 if (!NT_STATUS_IS_OK(status)) {
2967 printf("Open of %s with (SEC_FLAG_SYSTEM_SECURITY|"
2968 "FILE_WRITE_ATTRIBUTES) failed (%s)\n",
2969 fname,
2970 nt_errstr(status));
2971 goto fail;
2975 * Write the SACL SD. This should now succeed
2976 * as we have both SEC_FLAG_SYSTEM_SECURITY
2977 * and WRITE_DAC access.
2979 status = cli_set_security_descriptor(cli,
2980 fnum,
2981 SECINFO_DACL|SECINFO_SACL,
2982 sd_sacl);
2984 if (!NT_STATUS_IS_OK(status)) {
2985 printf("cli_set_security_descriptor SACL "
2986 "on file %s failed (%s)\n",
2987 fname,
2988 nt_errstr(status));
2989 goto fail;
2992 /* And close. */
2993 cli_smb2_close_fnum(cli, fnum);
2994 fnum = (uint16_t)-1;
2996 /* We're done with the sacl we made. */
2997 TALLOC_FREE(sd_sacl);
3000 * Now try to open with SEC_FLAG_SYSTEM_SECURITY|READ_ATTRIBUTES.
3001 * This gives us access to the SACL.
3004 status = cli_smb2_create_fnum(cli,
3005 fname,
3006 SMB2_OPLOCK_LEVEL_NONE,
3007 SMB2_IMPERSONATION_IMPERSONATION,
3008 SEC_FLAG_SYSTEM_SECURITY|
3009 FILE_READ_ATTRIBUTES, /* desired access */
3010 0, /* file_attributes, */
3011 FILE_SHARE_READ|
3012 FILE_SHARE_WRITE|
3013 FILE_SHARE_DELETE, /* share_access, */
3014 FILE_OPEN, /* create_disposition, */
3015 FILE_NON_DIRECTORY_FILE, /* create_options, */
3016 NULL, /* in_cblobs. */
3017 &fnum, /* fnum */
3018 NULL, /* smb_create_returns */
3019 talloc_tos(), /* mem_ctx */
3020 NULL); /* out_cblobs */
3022 if (!NT_STATUS_IS_OK(status)) {
3023 printf("Open of %s with (SEC_FLAG_SYSTEM_SECURITY|"
3024 "FILE_READ_ATTRIBUTES) failed (%s)\n",
3025 fname,
3026 nt_errstr(status));
3027 goto fail;
3030 /* Try and read the SACL - should succeed. */
3031 status = cli_query_security_descriptor(
3032 cli, fnum, SECINFO_SACL, talloc_tos(), &sd_sacl);
3034 if (!NT_STATUS_IS_OK(status)) {
3035 printf("Read SACL from file %s failed (%s)\n",
3036 fname,
3037 nt_errstr(status));
3038 goto fail;
3041 TALLOC_FREE(sd_sacl);
3044 * Try and read the DACL - should fail as we have
3045 * no READ_DAC access.
3047 status = cli_query_security_descriptor(
3048 cli, fnum, SECINFO_DACL, talloc_tos(), &sd_sacl);
3050 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
3051 printf("Reading DACL on file %s got (%s) "
3052 "should have failed with ACCESS_DENIED.\n",
3053 fname,
3054 nt_errstr(status));
3055 goto fail;
3058 if (fnum != (uint16_t)-1) {
3059 cli_smb2_close_fnum(cli, fnum);
3060 fnum = (uint16_t)-1;
3063 TALLOC_FREE(sd_dacl);
3064 TALLOC_FREE(sd_sacl);
3066 (void)cli_unlink(cli, fname, 0);
3067 return true;
3069 fail:
3071 TALLOC_FREE(sd_dacl);
3072 TALLOC_FREE(sd_sacl);
3074 if (fnum != (uint16_t)-1) {
3075 cli_smb2_close_fnum(cli, fnum);
3076 fnum = (uint16_t)-1;
3079 (void)cli_unlink(cli, fname, 0);
3080 return false;
3083 bool run_smb2_quota1(int dummy)
3085 struct cli_state *cli = NULL;
3086 NTSTATUS status;
3087 uint16_t fnum = (uint16_t)-1;
3088 SMB_NTQUOTA_STRUCT qt = {0};
3090 printf("Starting SMB2-QUOTA1\n");
3092 if (!torture_init_connection(&cli)) {
3093 return false;
3096 status = smbXcli_negprot(cli->conn,
3097 cli->timeout,
3098 PROTOCOL_SMB2_02,
3099 PROTOCOL_SMB3_11);
3100 if (!NT_STATUS_IS_OK(status)) {
3101 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
3102 return false;
3105 status = cli_session_setup_creds(cli, torture_creds);
3106 if (!NT_STATUS_IS_OK(status)) {
3107 printf("cli_session_setup returned %s\n", nt_errstr(status));
3108 return false;
3111 status = cli_tree_connect(cli, share, "?????", NULL);
3112 if (!NT_STATUS_IS_OK(status)) {
3113 printf("cli_tree_connect returned %s\n", nt_errstr(status));
3114 return false;
3117 status = cli_smb2_create_fnum(
3118 cli,
3119 "\\",
3120 SMB2_OPLOCK_LEVEL_NONE,
3121 SMB2_IMPERSONATION_IMPERSONATION,
3122 SEC_GENERIC_READ, /* desired access */
3123 0, /* file_attributes, */
3124 FILE_SHARE_READ|
3125 FILE_SHARE_WRITE|
3126 FILE_SHARE_DELETE, /* share_access, */
3127 FILE_OPEN, /* create_disposition, */
3128 FILE_DIRECTORY_FILE, /* create_options, */
3129 NULL, /* in_cblobs. */
3130 &fnum, /* fnum */
3131 NULL, /* smb_create_returns */
3132 NULL, /* mem_ctx */
3133 NULL); /* out_cblobs */
3134 if (!NT_STATUS_IS_OK(status)) {
3135 printf("cli_smb2_create_fnum failed: %s\n", nt_errstr(status));
3136 return false;
3139 status = cli_smb2_get_user_quota(cli, fnum, &qt);
3140 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
3141 printf("cli_smb2_get_user_quota returned %s, expected "
3142 "NT_STATUS_INVALID_HANDLE\n",
3143 nt_errstr(status));
3144 return false;
3147 return true;
3150 bool run_smb2_stream_acl(int dummy)
3152 struct cli_state *cli = NULL;
3153 NTSTATUS status;
3154 uint16_t fnum = (uint16_t)-1;
3155 const char *fname = "stream_acl_test_file";
3156 const char *sname = "stream_acl_test_file:streamname";
3157 struct security_descriptor *sd_dacl = NULL;
3158 bool ret = false;
3160 printf("SMB2 stream acl\n");
3162 if (!torture_init_connection(&cli)) {
3163 return false;
3166 status = smbXcli_negprot(cli->conn,
3167 cli->timeout,
3168 PROTOCOL_SMB2_02,
3169 PROTOCOL_SMB3_11);
3170 if (!NT_STATUS_IS_OK(status)) {
3171 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
3172 return false;
3175 status = cli_session_setup_creds(cli, torture_creds);
3176 if (!NT_STATUS_IS_OK(status)) {
3177 printf("cli_session_setup returned %s\n", nt_errstr(status));
3178 return false;
3181 status = cli_tree_connect(cli, share, "?????", NULL);
3182 if (!NT_STATUS_IS_OK(status)) {
3183 printf("cli_tree_connect returned %s\n", nt_errstr(status));
3184 return false;
3187 /* Ensure file doesn't exist. */
3188 (void)cli_unlink(cli, fname, 0);
3190 /* Create the file. */
3191 status = cli_ntcreate(cli,
3192 fname,
3194 GENERIC_ALL_ACCESS,
3195 FILE_ATTRIBUTE_NORMAL,
3196 FILE_SHARE_NONE,
3197 FILE_CREATE,
3200 &fnum,
3201 NULL);
3203 if (!NT_STATUS_IS_OK(status)) {
3204 printf("Create of %s failed (%s)\n",
3205 fname,
3206 nt_errstr(status));
3207 goto fail;
3210 /* Close the handle. */
3211 cli_smb2_close_fnum(cli, fnum);
3212 fnum = (uint16_t)-1;
3214 /* Create the stream. */
3215 status = cli_ntcreate(cli,
3216 sname,
3218 FILE_READ_DATA|
3219 SEC_STD_READ_CONTROL|
3220 SEC_STD_WRITE_DAC,
3221 FILE_ATTRIBUTE_NORMAL,
3222 FILE_SHARE_NONE,
3223 FILE_CREATE,
3226 &fnum,
3227 NULL);
3229 if (!NT_STATUS_IS_OK(status)) {
3230 printf("Create of %s failed (%s)\n",
3231 sname,
3232 nt_errstr(status));
3233 goto fail;
3236 /* Close the handle. */
3237 cli_smb2_close_fnum(cli, fnum);
3238 fnum = (uint16_t)-1;
3241 * Open the stream - for Samba this ensures
3242 * we prove we have a pathref fsp.
3244 status = cli_ntcreate(cli,
3245 sname,
3247 FILE_READ_DATA|
3248 SEC_STD_READ_CONTROL|
3249 SEC_STD_WRITE_DAC,
3250 FILE_ATTRIBUTE_NORMAL,
3251 FILE_SHARE_NONE,
3252 FILE_OPEN,
3255 &fnum,
3256 NULL);
3258 if (!NT_STATUS_IS_OK(status)) {
3259 printf("Open of %s failed (%s)\n",
3260 sname,
3261 nt_errstr(status));
3262 goto fail;
3265 /* Read the security descriptor off the stream handle. */
3266 status = cli_query_security_descriptor(cli,
3267 fnum,
3268 SECINFO_DACL,
3269 talloc_tos(),
3270 &sd_dacl);
3272 if (!NT_STATUS_IS_OK(status)) {
3273 printf("Reading DACL on stream %s got (%s)\n",
3274 sname,
3275 nt_errstr(status));
3276 goto fail;
3279 if (sd_dacl == NULL || sd_dacl->dacl == NULL ||
3280 sd_dacl->dacl->num_aces < 1) {
3281 printf("Invalid DACL returned on stream %s "
3282 "(this should not happen)\n",
3283 sname);
3284 goto fail;
3288 * Ensure it allows FILE_READ_DATA in the first ace.
3289 * It always should.
3291 if ((sd_dacl->dacl->aces[0].access_mask & FILE_READ_DATA) == 0) {
3292 printf("DACL->ace[0] returned on stream %s "
3293 "doesn't have read access (should not happen)\n",
3294 sname);
3295 goto fail;
3298 /* Remove FILE_READ_DATA from the first ace and set. */
3299 sd_dacl->dacl->aces[0].access_mask &= ~FILE_READ_DATA;
3301 status = cli_set_security_descriptor(cli,
3302 fnum,
3303 SECINFO_DACL,
3304 sd_dacl);
3306 if (!NT_STATUS_IS_OK(status)) {
3307 printf("Setting DACL on stream %s got (%s)\n",
3308 sname,
3309 nt_errstr(status));
3310 goto fail;
3313 TALLOC_FREE(sd_dacl);
3315 /* Read again and check it changed. */
3316 status = cli_query_security_descriptor(cli,
3317 fnum,
3318 SECINFO_DACL,
3319 talloc_tos(),
3320 &sd_dacl);
3322 if (!NT_STATUS_IS_OK(status)) {
3323 printf("Reading DACL on stream %s got (%s)\n",
3324 sname,
3325 nt_errstr(status));
3326 goto fail;
3329 if (sd_dacl == NULL || sd_dacl->dacl == NULL ||
3330 sd_dacl->dacl->num_aces < 1) {
3331 printf("Invalid DACL (1) returned on stream %s "
3332 "(this should not happen)\n",
3333 sname);
3334 goto fail;
3337 /* FILE_READ_DATA should be gone from the first ace. */
3338 if ((sd_dacl->dacl->aces[0].access_mask & FILE_READ_DATA) != 0) {
3339 printf("DACL on stream %s did not change\n",
3340 sname);
3341 goto fail;
3344 ret = true;
3346 fail:
3348 if (fnum != (uint16_t)-1) {
3349 cli_smb2_close_fnum(cli, fnum);
3350 fnum = (uint16_t)-1;
3353 (void)cli_unlink(cli, fname, 0);
3354 return ret;
3357 static NTSTATUS list_fn(struct file_info *finfo,
3358 const char *name,
3359 void *state)
3361 bool *matched = (bool *)state;
3362 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
3363 *matched = true;
3365 return NT_STATUS_OK;
3369 * Must be run against a share with "smbd async dosmode = yes".
3370 * Checks we can return DOS attriutes other than "N".
3371 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14758
3374 bool run_list_dir_async_test(int dummy)
3376 struct cli_state *cli = NULL;
3377 NTSTATUS status;
3378 const char *dname = "ASYNC_DIR";
3379 bool ret = false;
3380 bool matched = false;
3382 printf("SMB2 list dir async\n");
3384 if (!torture_init_connection(&cli)) {
3385 return false;
3388 status = smbXcli_negprot(cli->conn,
3389 cli->timeout,
3390 PROTOCOL_SMB2_02,
3391 PROTOCOL_SMB3_11);
3392 if (!NT_STATUS_IS_OK(status)) {
3393 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
3394 return false;
3397 status = cli_session_setup_creds(cli, torture_creds);
3398 if (!NT_STATUS_IS_OK(status)) {
3399 printf("cli_session_setup returned %s\n", nt_errstr(status));
3400 return false;
3403 status = cli_tree_connect(cli, share, "?????", NULL);
3404 if (!NT_STATUS_IS_OK(status)) {
3405 printf("cli_tree_connect returned %s\n", nt_errstr(status));
3406 return false;
3409 /* Ensure directory doesn't exist. */
3410 (void)cli_rmdir(cli, dname);
3412 status = cli_mkdir(cli, dname);
3413 if (!NT_STATUS_IS_OK(status)) {
3414 printf("cli_mkdir %s returned %s\n", dname, nt_errstr(status));
3415 return false;
3418 status = cli_list(cli,
3419 dname,
3420 FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_DIRECTORY,
3421 list_fn,
3422 &matched);
3423 if (!NT_STATUS_IS_OK(status)) {
3424 printf("cli_list %s returned %s\n", dname, nt_errstr(status));
3425 goto fail;
3428 if (!matched) {
3429 printf("Failed to find %s\n", dname);
3430 goto fail;
3433 ret = true;
3435 fail:
3437 (void)cli_rmdir(cli, dname);
3438 return ret;
3442 * Test delete a directory fails if a file is created
3443 * in a directory after the delete on close is set.
3444 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14892
3447 bool run_delete_on_close_non_empty(int dummy)
3449 struct cli_state *cli = NULL;
3450 NTSTATUS status;
3451 const char *dname = "DEL_ON_CLOSE_DIR";
3452 const char *fname = "DEL_ON_CLOSE_DIR\\testfile";
3453 uint16_t fnum = (uint16_t)-1;
3454 uint16_t fnum1 = (uint16_t)-1;
3455 bool ret = false;
3457 printf("SMB2 delete on close nonempty\n");
3459 if (!torture_init_connection(&cli)) {
3460 return false;
3463 status = smbXcli_negprot(cli->conn,
3464 cli->timeout,
3465 PROTOCOL_SMB2_02,
3466 PROTOCOL_SMB3_11);
3467 if (!NT_STATUS_IS_OK(status)) {
3468 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
3469 return false;
3472 status = cli_session_setup_creds(cli, torture_creds);
3473 if (!NT_STATUS_IS_OK(status)) {
3474 printf("cli_session_setup returned %s\n", nt_errstr(status));
3475 return false;
3478 status = cli_tree_connect(cli, share, "?????", NULL);
3479 if (!NT_STATUS_IS_OK(status)) {
3480 printf("cli_tree_connect returned %s\n", nt_errstr(status));
3481 return false;
3484 /* Ensure directory doesn't exist. */
3485 (void)cli_unlink(cli,
3486 fname,
3487 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3488 (void)cli_rmdir(cli, dname);
3490 /* Create target directory. */
3491 status = cli_ntcreate(cli,
3492 dname,
3494 DELETE_ACCESS|FILE_READ_DATA,
3495 FILE_ATTRIBUTE_DIRECTORY,
3496 FILE_SHARE_READ|
3497 FILE_SHARE_WRITE|
3498 FILE_SHARE_DELETE,
3499 FILE_CREATE,
3500 FILE_DIRECTORY_FILE,
3502 &fnum,
3503 NULL);
3504 if (!NT_STATUS_IS_OK(status)) {
3505 printf("cli_ntcreate for directory %s returned %s\n",
3506 dname,
3507 nt_errstr(status));
3508 goto out;
3511 /* Now set the delete on close bit. */
3512 status = cli_nt_delete_on_close(cli, fnum, 1);
3513 if (!NT_STATUS_IS_OK(status)) {
3514 printf("cli_cli_nt_delete_on_close set for directory "
3515 "%s returned %s\n",
3516 dname,
3517 nt_errstr(status));
3518 goto out;
3521 /* Create file inside target directory. */
3523 * NB. On Windows this will return NT_STATUS_DELETE_PENDING. Only on
3524 * Samba will this succeed by default (the option "check parent
3525 * directory delete on close" configures behaviour), but we're using
3526 * this to test a race condition.
3528 status = cli_ntcreate(cli,
3529 fname,
3531 FILE_READ_DATA,
3532 FILE_ATTRIBUTE_NORMAL,
3533 FILE_SHARE_READ|
3534 FILE_SHARE_WRITE|
3535 FILE_SHARE_DELETE,
3536 FILE_CREATE,
3539 &fnum1,
3540 NULL);
3541 if (!NT_STATUS_IS_OK(status)) {
3542 printf("cli_ntcreate for file %s returned %s\n",
3543 fname,
3544 nt_errstr(status));
3545 goto out;
3547 cli_close(cli, fnum1);
3548 fnum1 = (uint16_t)-1;
3550 /* Now the close should fail. */
3551 status = cli_close(cli, fnum);
3552 if (!NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
3553 printf("cli_close for directory %s returned %s\n",
3554 dname,
3555 nt_errstr(status));
3556 goto out;
3559 ret = true;
3561 out:
3563 if (fnum1 != (uint16_t)-1) {
3564 cli_close(cli, fnum1);
3566 if (fnum != (uint16_t)-1) {
3567 cli_nt_delete_on_close(cli, fnum, 0);
3568 cli_close(cli, fnum);
3570 (void)cli_unlink(cli,
3571 fname,
3572 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3573 (void)cli_rmdir(cli, dname);
3574 return ret;
3577 static NTSTATUS check_empty_fn(struct file_info *finfo,
3578 const char *mask,
3579 void *private_data)
3581 unsigned int *pcount = (unsigned int *)private_data;
3583 if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
3584 (*pcount)++;
3585 return NT_STATUS_OK;
3587 return NT_STATUS_DIRECTORY_NOT_EMPTY;
3591 * Test setting the delete on close bit on a directory
3592 * containing an unwritable file fails or succeeds
3593 * an a share set with "hide unwritable = yes"
3594 * depending on the setting of "delete veto files".
3595 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15023
3597 * First version. With "delete veto files = yes"
3598 * setting the delete on close should succeed.
3601 bool run_delete_on_close_nonwrite_delete_yes_test(int dummy)
3603 struct cli_state *cli = NULL;
3604 NTSTATUS status;
3605 const char *dname = "delete_veto_yes";
3606 const char *list_dname = "delete_veto_yes\\*";
3607 uint16_t fnum = (uint16_t)-1;
3608 bool ret = false;
3609 unsigned int list_count = 0;
3611 printf("SMB2 delete on close nonwrite - delete veto yes\n");
3613 if (!torture_init_connection(&cli)) {
3614 return false;
3617 status = smbXcli_negprot(cli->conn,
3618 cli->timeout,
3619 PROTOCOL_SMB2_02,
3620 PROTOCOL_SMB3_11);
3621 if (!NT_STATUS_IS_OK(status)) {
3622 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
3623 return false;
3626 status = cli_session_setup_creds(cli, torture_creds);
3627 if (!NT_STATUS_IS_OK(status)) {
3628 printf("cli_session_setup returned %s\n", nt_errstr(status));
3629 return false;
3632 status = cli_tree_connect(cli, share, "?????", NULL);
3633 if (!NT_STATUS_IS_OK(status)) {
3634 printf("cli_tree_connect returned %s\n", nt_errstr(status));
3635 return false;
3638 /* Ensure target directory is seen as empty. */
3639 status = cli_list(cli,
3640 list_dname,
3641 FILE_ATTRIBUTE_DIRECTORY |
3642 FILE_ATTRIBUTE_HIDDEN |
3643 FILE_ATTRIBUTE_SYSTEM,
3644 check_empty_fn,
3645 &list_count);
3646 if (!NT_STATUS_IS_OK(status)) {
3647 printf("cli_list of %s returned %s\n",
3648 dname,
3649 nt_errstr(status));
3650 return false;
3652 if (list_count != 2) {
3653 printf("cli_list of %s returned a count of %u\n",
3654 dname,
3655 list_count);
3656 return false;
3659 /* Open target directory. */
3660 status = cli_ntcreate(cli,
3661 dname,
3663 DELETE_ACCESS|FILE_READ_DATA,
3664 FILE_ATTRIBUTE_DIRECTORY,
3665 FILE_SHARE_READ|
3666 FILE_SHARE_WRITE|
3667 FILE_SHARE_DELETE,
3668 FILE_OPEN,
3669 FILE_DIRECTORY_FILE,
3671 &fnum,
3672 NULL);
3673 if (!NT_STATUS_IS_OK(status)) {
3674 printf("cli_ntcreate for directory %s returned %s\n",
3675 dname,
3676 nt_errstr(status));
3677 goto out;
3680 /* Now set the delete on close bit. */
3681 status = cli_nt_delete_on_close(cli, fnum, 1);
3682 if (!NT_STATUS_IS_OK(status)) {
3683 printf("cli_cli_nt_delete_on_close set for directory "
3684 "%s returned %s (should have succeeded)\n",
3685 dname,
3686 nt_errstr(status));
3687 goto out;
3690 ret = true;
3692 out:
3694 if (fnum != (uint16_t)-1) {
3695 (void)cli_nt_delete_on_close(cli, fnum, 0);
3696 (void)cli_close(cli, fnum);
3698 return ret;
3702 * Test setting the delete on close bit on a directory
3703 * containing an unwritable file fails or succeeds
3704 * an a share set with "hide unwritable = yes"
3705 * depending on the setting of "delete veto files".
3706 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15023
3708 * Second version. With "delete veto files = no"
3709 * setting the delete on close should fail.
3712 bool run_delete_on_close_nonwrite_delete_no_test(int dummy)
3714 struct cli_state *cli = NULL;
3715 NTSTATUS status;
3716 const char *dname = "delete_veto_no";
3717 const char *list_dname = "delete_veto_no\\*";
3718 uint16_t fnum = (uint16_t)-1;
3719 bool ret = false;
3720 unsigned int list_count = 0;
3722 printf("SMB2 delete on close nonwrite - delete veto yes\n");
3724 if (!torture_init_connection(&cli)) {
3725 return false;
3728 status = smbXcli_negprot(cli->conn,
3729 cli->timeout,
3730 PROTOCOL_SMB2_02,
3731 PROTOCOL_SMB3_11);
3732 if (!NT_STATUS_IS_OK(status)) {
3733 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
3734 return false;
3737 status = cli_session_setup_creds(cli, torture_creds);
3738 if (!NT_STATUS_IS_OK(status)) {
3739 printf("cli_session_setup returned %s\n", nt_errstr(status));
3740 return false;
3743 status = cli_tree_connect(cli, share, "?????", NULL);
3744 if (!NT_STATUS_IS_OK(status)) {
3745 printf("cli_tree_connect returned %s\n", nt_errstr(status));
3746 return false;
3749 /* Ensure target directory is seen as empty. */
3750 status = cli_list(cli,
3751 list_dname,
3752 FILE_ATTRIBUTE_DIRECTORY |
3753 FILE_ATTRIBUTE_HIDDEN |
3754 FILE_ATTRIBUTE_SYSTEM,
3755 check_empty_fn,
3756 &list_count);
3757 if (!NT_STATUS_IS_OK(status)) {
3758 printf("cli_list of %s returned %s\n",
3759 dname,
3760 nt_errstr(status));
3761 return false;
3763 if (list_count != 2) {
3764 printf("cli_list of %s returned a count of %u\n",
3765 dname,
3766 list_count);
3767 return false;
3770 /* Open target directory. */
3771 status = cli_ntcreate(cli,
3772 dname,
3774 DELETE_ACCESS|FILE_READ_DATA,
3775 FILE_ATTRIBUTE_DIRECTORY,
3776 FILE_SHARE_READ|
3777 FILE_SHARE_WRITE|
3778 FILE_SHARE_DELETE,
3779 FILE_OPEN,
3780 FILE_DIRECTORY_FILE,
3782 &fnum,
3783 NULL);
3784 if (!NT_STATUS_IS_OK(status)) {
3785 printf("cli_ntcreate for directory %s returned %s\n",
3786 dname,
3787 nt_errstr(status));
3788 goto out;
3791 /* Now set the delete on close bit. */
3792 status = cli_nt_delete_on_close(cli, fnum, 1);
3793 if (NT_STATUS_IS_OK(status)) {
3794 printf("cli_cli_nt_delete_on_close set for directory "
3795 "%s returned NT_STATUS_OK "
3796 "(should have failed)\n",
3797 dname);
3798 goto out;
3800 if (!NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
3801 printf("cli_cli_nt_delete_on_close set for directory "
3802 "%s returned %s "
3803 "(should have returned "
3804 "NT_STATUS_DIRECTORY_NOT_EMPTY)\n",
3805 dname,
3806 nt_errstr(status));
3807 goto out;
3810 ret = true;
3812 out:
3814 if (fnum != (uint16_t)-1) {
3815 (void)cli_nt_delete_on_close(cli, fnum, 0);
3816 (void)cli_close(cli, fnum);
3818 return ret;
3822 * Open an SMB2 file readonly and return the inode number.
3824 static NTSTATUS get_smb2_inode(struct cli_state *cli,
3825 const char *pathname,
3826 uint64_t *ino_ret)
3828 NTSTATUS status;
3829 uint64_t fid_persistent = 0;
3830 uint64_t fid_volatile = 0;
3831 DATA_BLOB outbuf = data_blob_null;
3833 * Open the file.
3835 status = smb2cli_create(cli->conn,
3836 cli->timeout,
3837 cli->smb2.session,
3838 cli->smb2.tcon,
3839 pathname,
3840 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
3841 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
3842 SEC_STD_SYNCHRONIZE|
3843 SEC_FILE_READ_DATA|
3844 SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
3845 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
3846 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
3847 FILE_OPEN, /* create_disposition, */
3848 0, /* create_options, */
3849 NULL, /* smb2_create_blobs *blobs */
3850 &fid_persistent,
3851 &fid_volatile,
3852 NULL, /* struct smb_create_returns * */
3853 talloc_tos(), /* mem_ctx. */
3854 NULL, /* struct smb2_create_blobs * */
3855 NULL); /* struct symlink_reparse_struct */
3856 if (!NT_STATUS_IS_OK(status)) {
3857 return status;
3861 * Get the inode.
3863 status = smb2cli_query_info(cli->conn,
3864 cli->timeout,
3865 cli->smb2.session,
3866 cli->smb2.tcon,
3867 SMB2_0_INFO_FILE,
3868 (SMB_FILE_ALL_INFORMATION - 1000), /* in_file_info_class */
3869 1024, /* in_max_output_length */
3870 NULL, /* in_input_buffer */
3871 0, /* in_additional_info */
3872 0, /* in_flags */
3873 fid_persistent,
3874 fid_volatile,
3875 talloc_tos(),
3876 &outbuf);
3878 if (NT_STATUS_IS_OK(status)) {
3879 *ino_ret = PULL_LE_U64(outbuf.data, 0x40);
3882 (void)smb2cli_close(cli->conn,
3883 cli->timeout,
3884 cli->smb2.session,
3885 cli->smb2.tcon,
3887 fid_persistent,
3888 fid_volatile);
3889 return status;
3893 * Check an inode matches a given SMB2 path.
3895 static bool smb2_inode_matches(struct cli_state *cli,
3896 const char *match_pathname,
3897 uint64_t ino_tomatch,
3898 const char *test_pathname)
3900 uint64_t test_ino = 0;
3901 NTSTATUS status;
3903 status = get_smb2_inode(cli,
3904 test_pathname,
3905 &test_ino);
3906 if (!NT_STATUS_IS_OK(status)) {
3907 printf("%s: Failed to get ino "
3908 "number for %s, (%s)\n",
3909 __func__,
3910 test_pathname,
3911 nt_errstr(status));
3912 return false;
3914 if (test_ino != ino_tomatch) {
3915 printf("%s: Inode missmatch, ino_tomatch (%s) "
3916 "ino=%"PRIu64" test (%s) "
3917 "ino=%"PRIu64"\n",
3918 __func__,
3919 match_pathname,
3920 ino_tomatch,
3921 test_pathname,
3922 test_ino);
3923 return false;
3925 return true;
3929 * Delete an SMB2 file on a DFS share.
3931 static NTSTATUS smb2_dfs_delete(struct cli_state *cli,
3932 const char *pathname)
3934 NTSTATUS status;
3935 uint64_t fid_persistent = 0;
3936 uint64_t fid_volatile = 0;
3937 uint8_t data[1];
3938 DATA_BLOB inbuf;
3941 * Open the file.
3943 status = smb2cli_create(cli->conn,
3944 cli->timeout,
3945 cli->smb2.session,
3946 cli->smb2.tcon,
3947 pathname,
3948 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
3949 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
3950 SEC_STD_SYNCHRONIZE|
3951 SEC_STD_DELETE, /* desired_access, */
3952 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
3953 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
3954 FILE_OPEN, /* create_disposition, */
3955 0, /* create_options, */
3956 NULL, /* smb2_create_blobs *blobs */
3957 &fid_persistent,
3958 &fid_volatile,
3959 NULL, /* struct smb_create_returns * */
3960 talloc_tos(), /* mem_ctx. */
3961 NULL, /* struct smb2_create_blobs * */
3962 NULL); /* struct symlink_reparse_struct */
3963 if (!NT_STATUS_IS_OK(status)) {
3964 return status;
3968 * Set delete on close.
3970 PUSH_LE_U8(&data[0], 0, 1);
3971 inbuf.data = &data[0];
3972 inbuf.length = 1;
3974 status = smb2cli_set_info(cli->conn,
3975 cli->timeout,
3976 cli->smb2.session,
3977 cli->smb2.tcon,
3978 SMB2_0_INFO_FILE, /* info_type. */
3979 SMB_FILE_DISPOSITION_INFORMATION - 1000, /* info_class */
3980 &inbuf,
3981 0, /* additional_info. */
3982 fid_persistent,
3983 fid_volatile);
3984 if (!NT_STATUS_IS_OK(status)) {
3985 return status;
3987 status = smb2cli_close(cli->conn,
3988 cli->timeout,
3989 cli->smb2.session,
3990 cli->smb2.tcon,
3992 fid_persistent,
3993 fid_volatile);
3994 return status;
3998 * Rename or hardlink an SMB2 file on a DFS share.
4000 static NTSTATUS smb2_dfs_setinfo_name(struct cli_state *cli,
4001 uint64_t fid_persistent,
4002 uint64_t fid_volatile,
4003 const char *newname,
4004 bool do_rename)
4006 NTSTATUS status;
4007 DATA_BLOB inbuf;
4008 smb_ucs2_t *converted_str = NULL;
4009 size_t converted_size_bytes = 0;
4010 size_t inbuf_size;
4011 uint8_t info_class = 0;
4012 bool ok;
4014 ok = push_ucs2_talloc(talloc_tos(),
4015 &converted_str,
4016 newname,
4017 &converted_size_bytes);
4018 if (!ok) {
4019 return NT_STATUS_INVALID_PARAMETER;
4022 * W2K8 insists the dest name is not null terminated. Remove
4023 * the last 2 zero bytes and reduce the name length.
4025 if (converted_size_bytes < 2) {
4026 return NT_STATUS_INVALID_PARAMETER;
4028 converted_size_bytes -= 2;
4029 inbuf_size = 20 + converted_size_bytes;
4030 if (inbuf_size < 20) {
4031 /* Integer wrap check. */
4032 return NT_STATUS_INVALID_PARAMETER;
4036 * The Windows 10 SMB2 server has a minimum length
4037 * for a SMB2_FILE_RENAME_INFORMATION buffer of
4038 * 24 bytes. It returns NT_STATUS_INFO_LENGTH_MISMATCH
4039 * if the length is less.
4041 inbuf_size = MAX(inbuf_size, 24);
4042 inbuf = data_blob_talloc_zero(talloc_tos(), inbuf_size);
4043 if (inbuf.data == NULL) {
4044 return NT_STATUS_NO_MEMORY;
4046 PUSH_LE_U32(inbuf.data, 16, converted_size_bytes);
4047 memcpy(inbuf.data + 20, converted_str, converted_size_bytes);
4048 TALLOC_FREE(converted_str);
4050 if (do_rename == true) {
4051 info_class = SMB_FILE_RENAME_INFORMATION - 1000;
4052 } else {
4053 /* Hardlink. */
4054 info_class = SMB_FILE_LINK_INFORMATION - 1000;
4057 status = smb2cli_set_info(cli->conn,
4058 cli->timeout,
4059 cli->smb2.session,
4060 cli->smb2.tcon,
4061 SMB2_0_INFO_FILE, /* info_type. */
4062 info_class, /* info_class */
4063 &inbuf,
4064 0, /* additional_info. */
4065 fid_persistent,
4066 fid_volatile);
4067 return status;
4070 static NTSTATUS smb2_dfs_rename(struct cli_state *cli,
4071 uint64_t fid_persistent,
4072 uint64_t fid_volatile,
4073 const char *newname)
4075 return smb2_dfs_setinfo_name(cli,
4076 fid_persistent,
4077 fid_volatile,
4078 newname,
4079 true); /* do_rename */
4082 static NTSTATUS smb2_dfs_hlink(struct cli_state *cli,
4083 uint64_t fid_persistent,
4084 uint64_t fid_volatile,
4085 const char *newname)
4087 return smb2_dfs_setinfo_name(cli,
4088 fid_persistent,
4089 fid_volatile,
4090 newname,
4091 false); /* do_rename */
4095 * According to:
4097 * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/dc9978d7-6299-4c5a-a22d-a039cdc716ea
4099 * (Characters " \ / [ ] : | < > + = ; , * ?,
4100 * and control characters in range 0x00 through
4101 * 0x1F, inclusive, are illegal in a share name)
4103 * But Windows server only checks in DFS sharenames ':'. All other
4104 * share names are allowed.
4107 static bool test_smb2_dfs_sharenames(struct cli_state *cli,
4108 const char *dfs_root_share_name,
4109 uint64_t root_ino)
4111 char test_path[9];
4112 const char *test_str = "/[]:|<>+=;,*?";
4113 const char *p;
4114 unsigned int i;
4115 bool ino_matched = false;
4117 /* Setup template pathname. */
4118 memcpy(test_path, "SERVER\\X", 9);
4120 /* Test invalid control characters. */
4121 for (i = 1; i < 0x20; i++) {
4122 test_path[7] = i;
4123 ino_matched = smb2_inode_matches(cli,
4124 dfs_root_share_name,
4125 root_ino,
4126 test_path);
4127 if (!ino_matched) {
4128 return false;
4132 /* Test explicit invalid characters. */
4133 for (p = test_str; *p != '\0'; p++) {
4134 test_path[7] = *p;
4135 if (*p == ':') {
4137 * Only ':' is treated as an INVALID sharename
4138 * for a DFS SERVER\\SHARE path.
4140 uint64_t test_ino = 0;
4141 NTSTATUS status = get_smb2_inode(cli,
4142 test_path,
4143 &test_ino);
4144 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
4145 printf("%s:%d Open of %s should get "
4146 "NT_STATUS_OBJECT_NAME_INVALID, got %s\n",
4147 __FILE__,
4148 __LINE__,
4149 test_path,
4150 nt_errstr(status));
4151 return false;
4153 } else {
4154 ino_matched = smb2_inode_matches(cli,
4155 dfs_root_share_name,
4156 root_ino,
4157 test_path);
4158 if (!ino_matched) {
4159 return false;
4163 return true;
4167 * "Raw" test of SMB2 paths to a DFS share.
4168 * We must use the lower level smb2cli_XXXX() interfaces,
4169 * not the cli_XXX() ones here as the ultimate goal is to fix our
4170 * cli_XXX() interfaces to work transparently over DFS.
4172 * So here, we're testing the server code, not the client code.
4174 * Passes cleanly against Windows.
4177 bool run_smb2_dfs_paths(int dummy)
4179 struct cli_state *cli = NULL;
4180 NTSTATUS status;
4181 bool dfs_supported = false;
4182 char *dfs_root_share_name = NULL;
4183 uint64_t root_ino = 0;
4184 uint64_t test_ino = 0;
4185 bool ino_matched = false;
4186 uint64_t fid_persistent = 0;
4187 uint64_t fid_volatile = 0;
4188 bool retval = false;
4189 bool ok = false;
4191 printf("Starting SMB2-DFS-PATHS\n");
4193 if (!torture_init_connection(&cli)) {
4194 return false;
4197 status = smbXcli_negprot(cli->conn,
4198 cli->timeout,
4199 PROTOCOL_SMB2_02,
4200 PROTOCOL_SMB3_11);
4201 if (!NT_STATUS_IS_OK(status)) {
4202 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
4203 return false;
4206 status = cli_session_setup_creds(cli, torture_creds);
4207 if (!NT_STATUS_IS_OK(status)) {
4208 printf("cli_session_setup returned %s\n", nt_errstr(status));
4209 return false;
4212 status = cli_tree_connect(cli, share, "?????", NULL);
4213 if (!NT_STATUS_IS_OK(status)) {
4214 printf("cli_tree_connect returned %s\n", nt_errstr(status));
4215 return false;
4218 /* Ensure this is a DFS share. */
4219 dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
4220 if (!dfs_supported) {
4221 printf("Server %s does not support DFS\n",
4222 smbXcli_conn_remote_name(cli->conn));
4223 return false;
4225 dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb2.tcon);
4226 if (!dfs_supported) {
4227 printf("Share %s does not support DFS\n",
4228 cli->share);
4229 return false;
4232 * Create the "official" DFS share root name.
4233 * No SMB2 paths can start with '\\'.
4235 dfs_root_share_name = talloc_asprintf(talloc_tos(),
4236 "%s\\%s",
4237 smbXcli_conn_remote_name(cli->conn),
4238 cli->share);
4239 if (dfs_root_share_name == NULL) {
4240 printf("Out of memory\n");
4241 return false;
4244 /* Get the share root inode number. */
4245 status = get_smb2_inode(cli,
4246 dfs_root_share_name,
4247 &root_ino);
4248 if (!NT_STATUS_IS_OK(status)) {
4249 printf("%s:%d Failed to get ino number for share root %s, (%s)\n",
4250 __FILE__,
4251 __LINE__,
4252 dfs_root_share_name,
4253 nt_errstr(status));
4254 return false;
4258 * Test the Windows algorithm for parsing DFS names.
4261 * A single "SERVER" element should open and match the share root.
4263 ino_matched = smb2_inode_matches(cli,
4264 dfs_root_share_name,
4265 root_ino,
4266 smbXcli_conn_remote_name(cli->conn));
4267 if (!ino_matched) {
4268 printf("%s:%d Failed to match ino number for %s\n",
4269 __FILE__,
4270 __LINE__,
4271 smbXcli_conn_remote_name(cli->conn));
4272 return false;
4276 * An "" DFS empty server name should open and match the share root on
4277 * Windows 2008. Windows 2022 returns NT_STATUS_INVALID_PARAMETER
4278 * for a DFS empty server name.
4280 status = get_smb2_inode(cli,
4282 &test_ino);
4283 if (NT_STATUS_IS_OK(status)) {
4285 * Windows 2008 - open succeeded. Proceed to
4286 * check ino number.
4288 ino_matched = smb2_inode_matches(cli,
4289 dfs_root_share_name,
4290 root_ino,
4291 "");
4292 if (!ino_matched) {
4293 printf("%s:%d Failed to match ino number for %s\n",
4294 __FILE__,
4295 __LINE__,
4296 "");
4297 return false;
4300 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4302 * For Windows 2022 we expect to fail with
4303 * NT_STATUS_INVALID_PARAMETER. Anything else is
4304 * unexpected.
4306 printf("%s:%d Unexpected error (%s) getting ino number for %s\n",
4307 __FILE__,
4308 __LINE__,
4309 nt_errstr(status),
4310 "");
4311 return false;
4313 /* A "BAD" server name should open and match the share root. */
4314 ino_matched = smb2_inode_matches(cli,
4315 dfs_root_share_name,
4316 root_ino,
4317 "BAD");
4318 if (!ino_matched) {
4319 printf("%s:%d Failed to match ino number for %s\n",
4320 __FILE__,
4321 __LINE__,
4322 "BAD");
4323 return false;
4326 * A "BAD\\BAD" server and share name should open
4327 * and match the share root.
4329 ino_matched = smb2_inode_matches(cli,
4330 dfs_root_share_name,
4331 root_ino,
4332 "BAD\\BAD");
4333 if (!ino_matched) {
4334 printf("%s:%d Failed to match ino number for %s\n",
4335 __FILE__,
4336 __LINE__,
4337 "BAD\\BAD");
4338 return false;
4341 * Trying to open "BAD\\BAD\\BAD" should get
4342 * NT_STATUS_OBJECT_NAME_NOT_FOUND.
4344 status = get_smb2_inode(cli,
4345 "BAD\\BAD\\BAD",
4346 &test_ino);
4347 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4348 printf("%s:%d Open of %s should get "
4349 "STATUS_OBJECT_NAME_NOT_FOUND, got %s\n",
4350 __FILE__,
4351 __LINE__,
4352 "BAD\\BAD\\BAD",
4353 nt_errstr(status));
4354 return false;
4357 * Trying to open "BAD\\BAD\\BAD\\BAD" should get
4358 * NT_STATUS_OBJECT_PATH_NOT_FOUND.
4360 status = get_smb2_inode(cli,
4361 "BAD\\BAD\\BAD\\BAD",
4362 &test_ino);
4363 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4364 printf("%s:%d Open of %s should get "
4365 "STATUS_OBJECT_NAME_NOT_FOUND, got %s\n",
4366 __FILE__,
4367 __LINE__,
4368 "BAD\\BAD\\BAD\\BAD",
4369 nt_errstr(status));
4370 return false;
4373 * Test for invalid pathname characters in the servername.
4374 * They are ignored, and it still opens the share root.
4376 ino_matched = smb2_inode_matches(cli,
4377 dfs_root_share_name,
4378 root_ino,
4379 "::::");
4380 if (!ino_matched) {
4381 printf("%s:%d Failed to match ino number for %s\n",
4382 __FILE__,
4383 __LINE__,
4384 "::::");
4385 return false;
4389 * Test for invalid pathname characters in the sharename.
4390 * Invalid sharename characters should still be flagged as
4391 * NT_STATUS_OBJECT_NAME_INVALID. It turns out only ':'
4392 * is considered an invalid sharename character.
4394 ok = test_smb2_dfs_sharenames(cli,
4395 dfs_root_share_name,
4396 root_ino);
4397 if (!ok) {
4398 return false;
4401 /* Now create a file called "file". */
4402 status = smb2cli_create(cli->conn,
4403 cli->timeout,
4404 cli->smb2.session,
4405 cli->smb2.tcon,
4406 "BAD\\BAD\\file",
4407 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4408 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4409 SEC_STD_SYNCHRONIZE|
4410 SEC_STD_DELETE |
4411 SEC_FILE_READ_DATA|
4412 SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4413 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4414 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4415 FILE_CREATE, /* create_disposition, */
4416 0, /* create_options, */
4417 NULL, /* smb2_create_blobs *blobs */
4418 &fid_persistent,
4419 &fid_volatile,
4420 NULL, /* struct smb_create_returns * */
4421 talloc_tos(), /* mem_ctx. */
4422 NULL, /* struct smb2_create_blobs * */
4423 NULL); /* struct symlink_reparse_struct */
4424 if (!NT_STATUS_IS_OK(status)) {
4425 printf("%s:%d smb2cli_create on %s returned %s\n",
4426 __FILE__,
4427 __LINE__,
4428 "BAD\\BAD\\file",
4429 nt_errstr(status));
4430 return false;
4434 * Trying to open "BAD\\BAD\\file" should now get
4435 * a valid inode.
4437 status = get_smb2_inode(cli,
4438 "BAD\\BAD\\file",
4439 &test_ino);
4440 if (!NT_STATUS_IS_OK(status)) {
4441 printf("%s:%d Open of %s should succeed "
4442 "got %s\n",
4443 __FILE__,
4444 __LINE__,
4445 "BAD\\BAD\\file",
4446 nt_errstr(status));
4447 goto err;
4451 * Now show that renames use relative,
4452 * not full DFS paths.
4455 /* Full DFS path should fail. */
4456 status = smb2_dfs_rename(cli,
4457 fid_persistent,
4458 fid_volatile,
4459 "ANY\\NAME\\renamed_file");
4460 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4461 printf("%s:%d Rename of %s -> %s should fail "
4462 "with NT_STATUS_OBJECT_PATH_NOT_FOUND. Got %s\n",
4463 __FILE__,
4464 __LINE__,
4465 "BAD\\BAD\\file",
4466 "ANY\\NAME\\renamed_file",
4467 nt_errstr(status));
4468 goto err;
4470 /* Relative DFS path should succeed. */
4471 status = smb2_dfs_rename(cli,
4472 fid_persistent,
4473 fid_volatile,
4474 "renamed_file");
4475 if (!NT_STATUS_IS_OK(status)) {
4476 printf("%s:%d: Rename of %s -> %s should succeed. "
4477 "Got %s\n",
4478 __FILE__,
4479 __LINE__,
4480 "BAD\\BAD\\file",
4481 "renamed_file",
4482 nt_errstr(status));
4483 goto err;
4487 * Trying to open "BAD\\BAD\\renamed_file" should now get
4488 * a valid inode.
4490 status = get_smb2_inode(cli,
4491 "BAD\\BAD\\renamed_file",
4492 &test_ino);
4493 if (!NT_STATUS_IS_OK(status)) {
4494 printf("%s:%d: Open of %s should succeed "
4495 "got %s\n",
4496 __FILE__,
4497 __LINE__,
4498 "BAD\\BAD\\renamed_file",
4499 nt_errstr(status));
4500 goto err;
4504 * Now show that hard links use relative,
4505 * not full DFS paths.
4508 /* Full DFS path should fail. */
4509 status = smb2_dfs_hlink(cli,
4510 fid_persistent,
4511 fid_volatile,
4512 "ANY\\NAME\\hlink");
4513 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4514 printf("%s:%d Hlink of %s -> %s should fail "
4515 "with NT_STATUS_OBJECT_PATH_NOT_FOUND. Got %s\n",
4516 __FILE__,
4517 __LINE__,
4518 "ANY\\NAME\\renamed_file",
4519 "ANY\\NAME\\hlink",
4520 nt_errstr(status));
4521 goto err;
4523 /* Relative DFS path should succeed. */
4524 status = smb2_dfs_hlink(cli,
4525 fid_persistent,
4526 fid_volatile,
4527 "hlink");
4528 if (!NT_STATUS_IS_OK(status)) {
4529 printf("%s:%d: Hlink of %s -> %s should succeed. "
4530 "Got %s\n",
4531 __FILE__,
4532 __LINE__,
4533 "ANY\\NAME\\renamed_file",
4534 "hlink",
4535 nt_errstr(status));
4536 goto err;
4540 * Trying to open "BAD\\BAD\\hlink" should now get
4541 * a valid inode.
4543 status = get_smb2_inode(cli,
4544 "BAD\\BAD\\hlink",
4545 &test_ino);
4546 if (!NT_STATUS_IS_OK(status)) {
4547 printf("%s:%d Open of %s should succeed "
4548 "got %s\n",
4549 __FILE__,
4550 __LINE__,
4551 "BAD\\BAD\\hlink",
4552 nt_errstr(status));
4553 goto err;
4556 retval = true;
4558 err:
4560 if (fid_persistent != 0 || fid_volatile != 0) {
4561 smb2cli_close(cli->conn,
4562 cli->timeout,
4563 cli->smb2.session,
4564 cli->smb2.tcon,
4565 0, /* flags */
4566 fid_persistent,
4567 fid_volatile);
4569 /* Delete anything we made. */
4570 (void)smb2_dfs_delete(cli, "BAD\\BAD\\BAD");
4571 (void)smb2_dfs_delete(cli, "BAD\\BAD\\file");
4572 (void)smb2_dfs_delete(cli, "BAD\\BAD\\renamed_file");
4573 (void)smb2_dfs_delete(cli, "BAD\\BAD\\hlink");
4574 return retval;
4578 * Add a test that sends DFS paths and sets the
4579 * SMB2 flag FLAGS2_DFS_PATHNAMES, but to a non-DFS
4580 * share. Windows passes this (it just treats the
4581 * pathnames as non-DFS and ignores the FLAGS2_DFS_PATHNAMES
4582 * bit).
4585 bool run_smb2_non_dfs_share(int dummy)
4587 struct cli_state *cli = NULL;
4588 NTSTATUS status;
4589 bool dfs_supported = false;
4590 uint64_t fid_persistent = 0;
4591 uint64_t fid_volatile = 0;
4592 bool retval = false;
4593 char *dfs_filename = NULL;
4595 printf("Starting SMB2-DFS-NON-DFS-SHARE\n");
4597 if (!torture_init_connection(&cli)) {
4598 return false;
4601 status = smbXcli_negprot(cli->conn,
4602 cli->timeout,
4603 PROTOCOL_SMB2_02,
4604 PROTOCOL_SMB3_11);
4605 if (!NT_STATUS_IS_OK(status)) {
4606 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
4607 return false;
4610 status = cli_session_setup_creds(cli, torture_creds);
4611 if (!NT_STATUS_IS_OK(status)) {
4612 printf("cli_session_setup returned %s\n", nt_errstr(status));
4613 return false;
4616 status = cli_tree_connect(cli, share, "?????", NULL);
4617 if (!NT_STATUS_IS_OK(status)) {
4618 printf("cli_tree_connect returned %s\n", nt_errstr(status));
4619 return false;
4622 dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
4623 if (!dfs_supported) {
4624 printf("Server %s does not support DFS\n",
4625 smbXcli_conn_remote_name(cli->conn));
4626 return false;
4628 /* Ensure this is *NOT* a DFS share. */
4629 dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb2.tcon);
4630 if (dfs_supported) {
4631 printf("Share %s is a DFS share.\n",
4632 cli->share);
4633 return false;
4636 * Force the share to be DFS, as far as the client
4637 * is concerned.
4639 smb2cli_tcon_set_values(cli->smb2.tcon,
4640 cli->smb2.session,
4641 smb2cli_tcon_current_id(cli->smb2.tcon),
4643 smb2cli_tcon_flags(cli->smb2.tcon),
4644 smb2cli_tcon_capabilities(cli->smb2.tcon) |
4645 SMB2_SHARE_CAP_DFS,
4648 /* Come up with a "valid" SMB2 DFS name. */
4649 dfs_filename = talloc_asprintf(talloc_tos(),
4650 "%s\\%s\\file",
4651 smbXcli_conn_remote_name(cli->conn),
4652 cli->share);
4653 if (dfs_filename == NULL) {
4654 printf("Out of memory\n");
4655 return false;
4658 /* Now try create dfs_filename. */
4659 status = smb2cli_create(cli->conn,
4660 cli->timeout,
4661 cli->smb2.session,
4662 cli->smb2.tcon,
4663 dfs_filename,
4664 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4665 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4666 SEC_STD_SYNCHRONIZE|
4667 SEC_STD_DELETE |
4668 SEC_FILE_READ_DATA|
4669 SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4670 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4671 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4672 FILE_CREATE, /* create_disposition, */
4673 0, /* create_options, */
4674 NULL, /* smb2_create_blobs *blobs */
4675 &fid_persistent,
4676 &fid_volatile,
4677 NULL, /* struct smb_create_returns * */
4678 talloc_tos(), /* mem_ctx. */
4679 NULL, /* struct smb2_create_blobs */
4680 NULL); /* struct symlink_reparse_struct */
4682 * Should fail with NT_STATUS_OBJECT_PATH_NOT_FOUND, as
4683 * even though we set the FLAGS2_DFS_PATHNAMES the server
4684 * knows this isn't a DFS share and so treats BAD\\BAD as
4685 * part of the filename.
4687 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4688 printf("%s:%d create of %s should fail "
4689 "with NT_STATUS_OBJECT_PATH_NOT_FOUND. Got %s\n",
4690 __FILE__,
4691 __LINE__,
4692 dfs_filename,
4693 nt_errstr(status));
4694 goto err;
4697 * Prove we can still use non-DFS pathnames, even though
4698 * we are setting the FLAGS2_DFS_PATHNAMES in the SMB2
4699 * request.
4701 status = smb2cli_create(cli->conn,
4702 cli->timeout,
4703 cli->smb2.session,
4704 cli->smb2.tcon,
4705 "file",
4706 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4707 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4708 SEC_STD_SYNCHRONIZE|
4709 SEC_STD_DELETE |
4710 SEC_FILE_READ_DATA|
4711 SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4712 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4713 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4714 FILE_CREATE, /* create_disposition, */
4715 0, /* create_options, */
4716 NULL, /* smb2_create_blobs *blobs */
4717 &fid_persistent,
4718 &fid_volatile,
4719 NULL, /* struct smb_create_returns * */
4720 talloc_tos(), /* mem_ctx. */
4721 NULL, /* struct smb2_create_blobs * */
4722 NULL); /* struct symlink_reparse_struct */
4723 if (!NT_STATUS_IS_OK(status)) {
4724 printf("%s:%d smb2cli_create on %s returned %s\n",
4725 __FILE__,
4726 __LINE__,
4727 "file",
4728 nt_errstr(status));
4729 return false;
4732 retval = true;
4734 err:
4736 (void)smb2_dfs_delete(cli, dfs_filename);
4737 (void)smb2_dfs_delete(cli, "file");
4738 return retval;
4742 * Add a test that sends a non-DFS path and does not set the
4743 * SMB2 flag FLAGS2_DFS_PATHNAMES to a DFS
4744 * share. Windows passes this (it just treats the
4745 * pathnames as non-DFS).
4748 bool run_smb2_dfs_share_non_dfs_path(int dummy)
4750 struct cli_state *cli = NULL;
4751 NTSTATUS status;
4752 bool dfs_supported = false;
4753 uint64_t fid_persistent = 0;
4754 uint64_t fid_volatile = 0;
4755 bool retval = false;
4756 char *dfs_filename = NULL;
4757 uint64_t root_ino = (uint64_t)-1;
4758 bool ino_matched = false;
4760 printf("Starting SMB2-DFS-SHARE-NON-DFS-PATH\n");
4762 if (!torture_init_connection(&cli)) {
4763 return false;
4766 status = smbXcli_negprot(cli->conn,
4767 cli->timeout,
4768 PROTOCOL_SMB2_02,
4769 PROTOCOL_SMB3_11);
4770 if (!NT_STATUS_IS_OK(status)) {
4771 printf("smbXcli_negprot returned %s\n", nt_errstr(status));
4772 return false;
4775 status = cli_session_setup_creds(cli, torture_creds);
4776 if (!NT_STATUS_IS_OK(status)) {
4777 printf("cli_session_setup returned %s\n", nt_errstr(status));
4778 return false;
4781 status = cli_tree_connect(cli, share, "?????", NULL);
4782 if (!NT_STATUS_IS_OK(status)) {
4783 printf("cli_tree_connect returned %s\n", nt_errstr(status));
4784 return false;
4787 dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
4788 if (!dfs_supported) {
4789 printf("Server %s does not support DFS\n",
4790 smbXcli_conn_remote_name(cli->conn));
4791 return false;
4793 /* Ensure this is a DFS share. */
4794 dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb2.tcon);
4795 if (!dfs_supported) {
4796 printf("Share %s is not a DFS share.\n",
4797 cli->share);
4798 return false;
4800 /* Come up with a "valid" SMB2 DFS name. */
4801 dfs_filename = talloc_asprintf(talloc_tos(),
4802 "%s\\%s\\file",
4803 smbXcli_conn_remote_name(cli->conn),
4804 cli->share);
4805 if (dfs_filename == NULL) {
4806 printf("Out of memory\n");
4807 return false;
4810 /* Get the root of the share ino. */
4811 status = get_smb2_inode(cli,
4812 "SERVER\\SHARE",
4813 &root_ino);
4814 if (!NT_STATUS_IS_OK(status)) {
4815 printf("%s:%d get_smb2_inode on %s returned %s\n",
4816 __FILE__,
4817 __LINE__,
4818 "SERVER\\SHARE",
4819 nt_errstr(status));
4820 goto err;
4823 /* Create a dfs_filename. */
4824 status = smb2cli_create(cli->conn,
4825 cli->timeout,
4826 cli->smb2.session,
4827 cli->smb2.tcon,
4828 dfs_filename,
4829 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4830 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4831 SEC_STD_SYNCHRONIZE|
4832 SEC_STD_DELETE |
4833 SEC_FILE_READ_DATA|
4834 SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4835 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4836 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4837 FILE_CREATE, /* create_disposition, */
4838 0, /* create_options, */
4839 NULL, /* smb2_create_blobs *blobs */
4840 &fid_persistent,
4841 &fid_volatile,
4842 NULL, /* struct smb_create_returns * */
4843 talloc_tos(), /* mem_ctx. */
4844 NULL, /* struct smb2_create_blobs * */
4845 NULL); /* psymlink */
4846 if (!NT_STATUS_IS_OK(status)) {
4847 printf("%s:%d smb2cli_create on %s returned %s\n",
4848 __FILE__,
4849 __LINE__,
4850 dfs_filename,
4851 nt_errstr(status));
4852 goto err;
4855 /* Close the handle we just opened. */
4856 smb2cli_close(cli->conn,
4857 cli->timeout,
4858 cli->smb2.session,
4859 cli->smb2.tcon,
4860 0, /* flags */
4861 fid_persistent,
4862 fid_volatile);
4864 fid_persistent = 0;
4865 fid_volatile = 0;
4868 * Force the share to be non-DFS, as far as the client
4869 * is concerned.
4871 smb2cli_tcon_set_values(cli->smb2.tcon,
4872 cli->smb2.session,
4873 smb2cli_tcon_current_id(cli->smb2.tcon),
4875 smb2cli_tcon_flags(cli->smb2.tcon),
4876 smb2cli_tcon_capabilities(cli->smb2.tcon) &
4877 ~SMB2_SHARE_CAP_DFS,
4881 * Prove we can still use non-DFS pathnames on a DFS
4882 * share so long as we don't set the FLAGS2_DFS_PATHNAMES
4883 * in the SMB2 request.
4885 status = smb2cli_create(cli->conn,
4886 cli->timeout,
4887 cli->smb2.session,
4888 cli->smb2.tcon,
4889 "file",
4890 SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4891 SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4892 SEC_STD_SYNCHRONIZE|
4893 SEC_STD_DELETE |
4894 SEC_FILE_READ_DATA|
4895 SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4896 FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4897 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4898 FILE_OPEN, /* create_disposition, */
4899 0, /* create_options, */
4900 NULL, /* smb2_create_blobs *blobs */
4901 &fid_persistent,
4902 &fid_volatile,
4903 NULL, /* struct smb_create_returns * */
4904 talloc_tos(), /* mem_ctx. */
4905 NULL, /* struct smb2_create_blobs * */
4906 NULL); /* psymlink */
4907 if (!NT_STATUS_IS_OK(status)) {
4908 printf("%s:%d smb2cli_create on %s returned %s\n",
4909 __FILE__,
4910 __LINE__,
4911 "file",
4912 nt_errstr(status));
4913 goto err;
4917 * Show that now we're using non-DFS pathnames
4918 * on a DFS share, "" opens the root of the share.
4920 ino_matched = smb2_inode_matches(cli,
4921 "SERVER\\SHARE",
4922 root_ino,
4923 "");
4924 if (!ino_matched) {
4925 printf("%s:%d Failed to match ino number for %s\n",
4926 __FILE__,
4927 __LINE__,
4928 "");
4929 goto err;
4932 retval = true;
4934 err:
4936 if (fid_volatile != 0) {
4937 smb2cli_close(cli->conn,
4938 cli->timeout,
4939 cli->smb2.session,
4940 cli->smb2.tcon,
4941 0, /* flags */
4942 fid_persistent,
4943 fid_volatile);
4945 (void)smb2_dfs_delete(cli, "file");
4946 (void)smb2_dfs_delete(cli, dfs_filename);
4947 return retval;