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/>.
21 #include "torture/proto.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
;
41 uint64_t fid_persistent
, fid_volatile
;
42 const char *hello
= "Hello, world\n";
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
)) {
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
));
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
));
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
));
77 status
= smb2cli_create(
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, */
89 FILE_SHARE_DELETE
, /* share_access, */
90 FILE_CREATE
, /* create_disposition, */
91 FILE_DELETE_ON_CLOSE
, /* create_options, */
92 NULL
, /* smb2_create_blobs *blobs */
99 if (!NT_STATUS_IS_OK(status
)) {
100 printf("smb2cli_create returned %s\n", nt_errstr(status
));
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
));
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
));
119 status
= smb2cli_read(cli
->conn
, cli
->timeout
, cli
->smb2
.session
,
120 cli
->smb2
.tcon
, 0x10000, 0, fid_persistent
,
122 talloc_tos(), &result
, &nread
);
123 if (!NT_STATUS_IS_OK(status
)) {
124 printf("smb2cli_read returned %s\n", nt_errstr(status
));
128 if (nread
!= strlen(hello
)) {
129 printf("smb2cli_read returned %d bytes, expected %d\n",
130 (int)nread
, (int)strlen(hello
));
134 if (memcmp(hello
, result
, nread
) != 0) {
135 printf("smb2cli_read returned '%s', expected '%s'\n",
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
));
147 status
= smb2cli_create(
153 SMB2_OPLOCK_LEVEL_NONE
, /* oplock_level, */
154 SMB2_IMPERSONATION_IMPERSONATION
, /* impersonation_level, */
157 SEC_DIR_READ_ATTRIBUTE
, /* desired_access, */
158 0, /* file_attributes, */
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 */
172 if (!NT_STATUS_IS_OK(status
)) {
173 printf("smb2cli_create returned %s\n", nt_errstr(status
));
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
));
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
));
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
,
202 0, /* capabilities */
203 0 /* maximal_access */);
204 status
= smb2cli_tdis(cli
->conn
,
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
));
214 status
= smb2cli_tdis(cli
->conn
,
218 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_NAME_DELETED
)) {
219 printf("2nd smb2cli_tdis returned %s\n", nt_errstr(status
));
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
));
230 cli
->smb2
.session
= smbXcli_session_create(cli
, cli
->conn
);
231 if (cli
->smb2
.session
== NULL
) {
232 printf("smbXcli_session_create() returned NULL\n");
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
));
247 bool run_smb2_negprot(int dummy
)
249 struct cli_state
*cli
;
251 enum protocol_types protocol
;
252 const char *name
= NULL
;
254 printf("Starting SMB2-NEGPROT\n");
256 if (!torture_init_connection(&cli
)) {
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
));
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
);
273 printf("Server DOES NOT support SMB2, only %s\n", name
);
277 status
= smbXcli_negprot(cli
->conn
, cli
->timeout
,
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",
287 if (smbXcli_conn_is_connected(cli
->conn
)) {
288 printf("2nd smbXcli_negprot should disconnect "
289 "- still connected\n");
296 bool run_smb2_anonymous(int dummy
)
298 struct cli_state
*cli
= NULL
;
300 struct cli_credentials
*anon_creds
= NULL
;
303 printf("Starting SMB2-ANONYMOUS\n");
305 if (!torture_init_connection(&cli
)) {
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
));
316 anon_creds
= cli_credentials_init_anon(talloc_tos());
317 if (anon_creds
== NULL
) {
318 printf("cli_credentials_init_anon failed\n");
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
));
328 guest
= smbXcli_session_is_guest(cli
->smb2
.session
);
330 printf("anonymous session should not have guest authentication\n");
337 bool run_smb2_session_reconnect(int dummy
)
339 struct cli_state
*cli1
;
340 struct cli_state
*cli2
;
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
;
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";
355 printf("Starting SMB2-SESSION-RECONNECT\n");
357 if (!torture_init_connection(&cli1
)) {
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
));
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
));
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
));
380 status
= smb2cli_create(
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, */
392 FILE_SHARE_DELETE
, /* share_access, */
393 FILE_CREATE
, /* create_disposition, */
394 FILE_DELETE_ON_CLOSE
, /* create_options, */
395 NULL
, /* smb2_create_blobs *blobs */
402 if (!NT_STATUS_IS_OK(status
)) {
403 printf("smb2cli_create on cli1 %s\n", nt_errstr(status
));
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
));
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
));
422 status
= smb2cli_read(cli1
->conn
, cli1
->timeout
, cli1
->smb2
.session
,
423 cli1
->smb2
.tcon
, 0x10000, 0, fid_persistent
,
425 talloc_tos(), &result
, &nread
);
426 if (!NT_STATUS_IS_OK(status
)) {
427 printf("smb2cli_read returned %s\n", nt_errstr(status
));
431 if (nread
!= strlen(hello
)) {
432 printf("smb2cli_read returned %d bytes, expected %d\n",
433 (int)nread
, (int)strlen(hello
));
437 if (memcmp(hello
, result
, nread
) != 0) {
438 printf("smb2cli_read returned '%s', expected '%s'\n",
443 /* prepare second session */
445 if (!torture_init_connection(&cli2
)) {
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
));
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
));
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
));
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
));
477 ev
= samba_tevent_context_init(talloc_tos());
479 printf("samba_tevent_context_init() returned NULL\n");
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
));
490 cli2
->smb2
.session
= smbXcli_session_create(cli2
, cli2
->conn
);
492 subreq
= smb2cli_session_setup_send(talloc_tos(), ev
,
497 SMB2_CAP_DFS
, /* in_capabilities */
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");
507 ok
= tevent_req_poll(subreq
, ev
);
509 printf("tevent_req_poll() returned false\n");
513 status
= smb2cli_session_setup_recv(subreq
, talloc_tos(),
515 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
516 printf("smb2cli_session_setup_recv returned %s\n",
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
));
528 subreq
= smb2cli_session_setup_send(talloc_tos(), ev
,
533 SMB2_CAP_DFS
, /* in_capabilities */
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");
543 ok
= tevent_req_poll(subreq
, ev
);
545 printf("tevent_req_poll() returned false\n");
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",
557 status
= gensec_session_key(auth_generic_state
->gensec_security
, talloc_tos(),
559 if (!NT_STATUS_IS_OK(status
)) {
560 printf("gensec_session_key returned %s\n",
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
));
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
));
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
));
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
));
604 status
= smb2cli_read(cli2
->conn
, cli2
->timeout
, cli2
->smb2
.session
,
605 cli2
->smb2
.tcon
, 0x10000, 0, fid_persistent
,
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
));
615 status
= smb2cli_create(
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, */
627 FILE_SHARE_DELETE
, /* share_access, */
628 FILE_CREATE
, /* create_disposition, */
629 FILE_DELETE_ON_CLOSE
, /* create_options, */
630 NULL
, /* smb2_create_blobs *blobs */
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
));
643 /* now grab the session key and try with signing */
645 status
= smb2cli_session_set_session_key(cli2
->smb2
.session
,
648 if (!NT_STATUS_IS_OK(status
)) {
649 printf("smb2cli_session_set_session_key %s\n", nt_errstr(status
));
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
));
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
));
674 status
= smb2cli_read(cli2
->conn
, cli2
->timeout
, cli2
->smb2
.session
,
675 cli1
->smb2
.tcon
, 0x10000, 0, fid_persistent
,
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
));
685 status
= smb2cli_create(
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, */
697 FILE_SHARE_DELETE
, /* share_access, */
698 FILE_CREATE
, /* create_disposition, */
699 FILE_DELETE_ON_CLOSE
, /* create_options, */
700 NULL
, /* smb2_create_blobs *blobs */
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
));
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
));
722 status
= smb2cli_create(
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, */
734 FILE_SHARE_DELETE
, /* share_access, */
735 FILE_CREATE
, /* create_disposition, */
736 FILE_DELETE_ON_CLOSE
, /* create_options, */
737 NULL
, /* smb2_create_blobs *blobs */
744 if (!NT_STATUS_IS_OK(status
)) {
745 printf("smb2cli_create on cli2 %s\n", nt_errstr(status
));
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
));
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
));
764 status
= smb2cli_read(cli2
->conn
, cli2
->timeout
, cli2
->smb2
.session
,
765 cli2
->smb2
.tcon
, 0x10000, 0, fid_persistent
,
767 talloc_tos(), &result
, &nread
);
768 if (!NT_STATUS_IS_OK(status
)) {
769 printf("smb2cli_read returned %s\n", nt_errstr(status
));
773 if (nread
!= strlen(hello
)) {
774 printf("smb2cli_read returned %d bytes, expected %d\n",
775 (int)nread
, (int)strlen(hello
));
779 if (memcmp(hello
, result
, nread
) != 0) {
780 printf("smb2cli_read returned '%s', expected '%s'\n",
788 bool run_smb2_tcon_dependence(int dummy
)
790 struct cli_state
*cli
;
792 uint64_t fid_persistent
, fid_volatile
;
793 const char *hello
= "Hello, world\n";
796 struct smbXcli_tcon
*tcon2
;
799 printf("Starting SMB2-TCON-DEPENDENCE\n");
801 if (!torture_init_connection(&cli
)) {
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
));
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
));
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
));
824 status
= smb2cli_create(
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, */
836 FILE_SHARE_DELETE
, /* share_access, */
837 FILE_CREATE
, /* create_disposition, */
838 FILE_DELETE_ON_CLOSE
, /* create_options, */
839 NULL
, /* smb2_create_blobs *blobs */
846 if (!NT_STATUS_IS_OK(status
)) {
847 printf("smb2cli_create on cli %s\n", nt_errstr(status
));
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
));
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
));
866 status
= smb2cli_read(cli
->conn
, cli
->timeout
, cli
->smb2
.session
,
867 cli
->smb2
.tcon
, 0x10000, 0, fid_persistent
,
869 talloc_tos(), &result
, &nread
);
870 if (!NT_STATUS_IS_OK(status
)) {
871 printf("smb2cli_read returned %s\n", nt_errstr(status
));
875 if (nread
!= strlen(hello
)) {
876 printf("smb2cli_read returned %d bytes, expected %d\n",
877 (int)nread
, (int)strlen(hello
));
881 if (memcmp(hello
, result
, nread
) != 0) {
882 printf("smb2cli_read returned '%s', expected '%s'\n",
887 /* check behaviour with wrong tid... */
889 tcon2
= smbXcli_tcon_create(cli
);
890 tcon2_id
= smb2cli_tcon_current_id(cli
->smb2
.tcon
);
892 smb2cli_tcon_set_values(tcon2
,
897 0, /* capabilities */
898 0 /* maximal_access */);
900 status
= smb2cli_read(cli
->conn
, cli
->timeout
, cli
->smb2
.session
,
901 tcon2
, 0x10000, 0, fid_persistent
,
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
));
914 bool run_smb2_multi_channel(int dummy
)
916 struct cli_state
*cli1
;
917 struct cli_state
*cli2
;
918 struct cli_state
*cli3
;
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
;
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";
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
)) {
942 if (!torture_init_connection(&cli2
)) {
946 if (!torture_init_connection(&cli3
)) {
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
));
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
));
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
));
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
));
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
));
985 status
= smb2cli_session_create_channel(cli2
,
988 &cli2
->smb2
.session
);
989 if (!NT_STATUS_IS_OK(status
)) {
990 printf("smb2cli_session_create_channel returned %s\n",
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
));
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
));
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
));
1016 ev
= samba_tevent_context_init(talloc_tos());
1018 printf("samba_tevent_context_init() returned NULL\n");
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
));
1029 subreq
= smb2cli_session_setup_send(talloc_tos(), ev
,
1033 0x01, /* in_flags */
1034 SMB2_CAP_DFS
, /* in_capabilities */
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");
1043 ok
= tevent_req_poll(subreq
, ev
);
1045 printf("tevent_req_poll() returned false\n");
1049 status
= smb2cli_session_setup_recv(subreq
, talloc_tos(),
1051 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1052 printf("smb2cli_session_setup_recv returned %s\n",
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
));
1064 subreq
= smb2cli_session_setup_send(talloc_tos(), ev
,
1068 0x01, /* in_flags */
1069 SMB2_CAP_DFS
, /* in_capabilities */
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");
1078 ok
= tevent_req_poll(subreq
, ev
);
1080 printf("tevent_req_poll() returned false\n");
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",
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",
1100 status
= smb2cli_session_set_channel_key(cli2
->smb2
.session
,
1101 channel_session_key
,
1103 if (!NT_STATUS_IS_OK(status
)) {
1104 printf("smb2cli_session_set_channel_key %s\n", nt_errstr(status
));
1108 status
= smb2cli_session_create_channel(cli3
,
1111 &cli3
->smb2
.session
);
1112 if (!NT_STATUS_IS_OK(status
)) {
1113 printf("smb2cli_session_create_channel returned %s\n",
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
));
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
));
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
));
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
));
1146 subreq
= smb2cli_session_setup_send(talloc_tos(), ev
,
1150 0x01, /* in_flags */
1151 SMB2_CAP_DFS
, /* in_capabilities */
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");
1160 ok
= tevent_req_poll(subreq
, ev
);
1162 printf("tevent_req_poll() returned false\n");
1166 status
= smb2cli_session_setup_recv(subreq
, talloc_tos(),
1168 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1169 printf("smb2cli_session_setup_recv returned %s\n",
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
));
1181 subreq
= smb2cli_session_setup_send(talloc_tos(), ev
,
1185 0x01, /* in_flags */
1186 SMB2_CAP_DFS
, /* in_capabilities */
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");
1195 ok
= tevent_req_poll(subreq
, ev
);
1197 printf("tevent_req_poll() returned false\n");
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",
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",
1217 status
= smb2cli_session_set_channel_key(cli3
->smb2
.session
,
1218 channel_session_key
,
1220 if (!NT_STATUS_IS_OK(status
)) {
1221 printf("smb2cli_session_set_channel_key %s\n", nt_errstr(status
));
1225 status
= smb2cli_create(
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, */
1237 FILE_SHARE_DELETE
, /* share_access, */
1238 FILE_CREATE
, /* create_disposition, */
1239 FILE_DELETE_ON_CLOSE
, /* create_options, */
1240 NULL
, /* smb2_create_blobs *blobs */
1247 if (!NT_STATUS_IS_OK(status
)) {
1248 printf("smb2cli_create on cli2 %s\n", nt_errstr(status
));
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
));
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
));
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
));
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
));
1281 status
= smb2cli_read(cli2
->conn
, cli2
->timeout
, cli2
->smb2
.session
,
1282 cli1
->smb2
.tcon
, 0x10000, 0, fid_persistent
,
1284 talloc_tos(), &result
, &nread
);
1285 if (!NT_STATUS_IS_OK(status
)) {
1286 printf("smb2cli_read returned %s\n", nt_errstr(status
));
1290 if (nread
!= strlen(hello
)) {
1291 printf("smb2cli_read returned %d bytes, expected %d\n",
1292 (int)nread
, (int)strlen(hello
));
1296 if (memcmp(hello
, result
, nread
) != 0) {
1297 printf("smb2cli_read returned '%s', expected '%s'\n",
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
));
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
));
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
));
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
));
1330 subreq
= smb2cli_session_setup_send(talloc_tos(), ev
,
1335 SMB2_CAP_DFS
, /* in_capabilities */
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");
1344 ok
= tevent_req_poll(subreq
, ev
);
1346 printf("tevent_req_poll() returned false\n");
1350 status
= smb2cli_session_setup_recv(subreq
, talloc_tos(),
1352 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1353 printf("smb2cli_session_setup_recv returned %s\n",
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
));
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
));
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
));
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
));
1386 status
= smb2cli_create(
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, */
1398 FILE_SHARE_DELETE
, /* share_access, */
1399 FILE_CREATE
, /* create_disposition, */
1400 FILE_DELETE_ON_CLOSE
, /* create_options, */
1401 NULL
, /* smb2_create_blobs *blobs */
1408 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_HANDLE
)) {
1409 printf("smb2cli_create %s\n", nt_errstr(status
));
1413 status
= smb2cli_create(
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, */
1425 FILE_SHARE_DELETE
, /* share_access, */
1426 FILE_CREATE
, /* create_disposition, */
1427 FILE_DELETE_ON_CLOSE
, /* create_options, */
1428 NULL
, /* smb2_create_blobs *blobs */
1435 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_HANDLE
)) {
1436 printf("smb2cli_create %s\n", nt_errstr(status
));
1440 status
= smb2cli_create(
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, */
1452 FILE_SHARE_DELETE
, /* share_access, */
1453 FILE_CREATE
, /* create_disposition, */
1454 FILE_DELETE_ON_CLOSE
, /* create_options, */
1455 NULL
, /* smb2_create_blobs *blobs */
1462 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_HANDLE
)) {
1463 printf("smb2cli_create %s\n", nt_errstr(status
));
1467 subreq
= smb2cli_session_setup_send(talloc_tos(), ev
,
1472 SMB2_CAP_DFS
, /* in_capabilities */
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");
1481 ok
= tevent_req_poll(subreq
, ev
);
1483 printf("tevent_req_poll() returned false\n");
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",
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
));
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
));
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
));
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
));
1526 bool run_smb2_session_reauth(int dummy
)
1528 struct cli_state
*cli
;
1531 uint64_t fid_persistent
, fid_volatile
;
1532 uint64_t dir_persistent
, dir_volatile
;
1534 uint32_t dir_data_length
;
1535 struct tevent_context
*ev
;
1536 struct tevent_req
*subreq
;
1537 DATA_BLOB in_blob
= data_blob_null
;
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
;
1545 struct smbXcli_tcon
*saved_tcon
;
1547 printf("Starting SMB2-SESSION_REAUTH\n");
1549 if (!torture_init_connection(&cli
)) {
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
));
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
));
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
));
1578 status
= smb2cli_create(
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, */
1590 FILE_SHARE_DELETE
, /* share_access, */
1591 FILE_CREATE
, /* create_disposition, */
1592 FILE_DELETE_ON_CLOSE
, /* create_options, */
1593 NULL
, /* smb2_create_blobs *blobs */
1600 if (!NT_STATUS_IS_OK(status
)) {
1601 printf("smb2cli_create %s\n", nt_errstr(status
));
1605 status
= smb2cli_create(
1611 SMB2_OPLOCK_LEVEL_NONE
, /* oplock_level, */
1612 SMB2_IMPERSONATION_IMPERSONATION
, /* impersonation_level, */
1613 SEC_STD_SYNCHRONIZE
|
1615 SEC_DIR_READ_ATTRIBUTE
, /* desired_access, */
1616 0, /* file_attributes, */
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 */
1630 if (!NT_STATUS_IS_OK(status
)) {
1631 printf("smb2cli_create returned %s\n", nt_errstr(status
));
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
));
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
));
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
));
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
));
1666 ev
= samba_tevent_context_init(talloc_tos());
1668 printf("samba_tevent_context_init() returned NULL\n");
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
));
1679 subreq
= smb2cli_session_setup_send(talloc_tos(), ev
,
1684 SMB2_CAP_DFS
, /* in_capabilities */
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");
1693 ok
= tevent_req_poll(subreq
, ev
);
1695 printf("tevent_req_poll() returned false\n");
1699 status
= smb2cli_session_setup_recv(subreq
, talloc_tos(),
1701 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1702 printf("smb2cli_session_setup_recv returned %s\n",
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
));
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
));
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
));
1732 * query_info seems to be a path based operation on Windows...
1734 status
= smb2cli_query_info(cli
->conn
,
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 */
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
));
1753 in_file_info_class
= SMB_FILE_POSITION_INFORMATION
- 1000;
1754 status
= smb2cli_query_info(cli
->conn
,
1760 1024, /* in_max_output_length */
1761 NULL
, /* in_input_buffer */
1762 0, /* in_additional_info */
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
));
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
,
1784 0, /* in_additional_info */
1787 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_HANDLE
)) {
1788 printf("smb2cli_set_info (position) returned %s\n", nt_errstr(status
));
1792 status
= smb2cli_create(
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, */
1804 FILE_SHARE_DELETE
, /* share_access, */
1805 FILE_CREATE
, /* create_disposition, */
1806 FILE_DELETE_ON_CLOSE
, /* create_options, */
1807 NULL
, /* smb2_create_blobs *blobs */
1814 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_HANDLE
)) {
1815 printf("smb2cli_create %s\n", nt_errstr(status
));
1819 status
= smb2cli_create(
1825 SMB2_OPLOCK_LEVEL_NONE
, /* oplock_level, */
1826 SMB2_IMPERSONATION_IMPERSONATION
, /* impersonation_level, */
1827 SEC_STD_SYNCHRONIZE
|
1829 SEC_DIR_READ_ATTRIBUTE
, /* desired_access, */
1830 0, /* file_attributes, */
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 */
1844 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_HANDLE
)) {
1845 printf("smb2cli_create returned %s\n", nt_errstr(status
));
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
,
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
));
1864 talloc_free(cli
->smb2
.tcon
);
1865 cli
->smb2
.tcon
= saved_tcon
;
1867 subreq
= smb2cli_session_setup_send(talloc_tos(), ev
,
1872 SMB2_CAP_DFS
, /* in_capabilities */
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");
1881 ok
= tevent_req_poll(subreq
, ev
);
1883 printf("tevent_req_poll() returned false\n");
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",
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
));
1902 status
= smb2cli_query_info(cli
->conn
,
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 */
1915 &out_output_buffer
);
1916 if (!NT_STATUS_IS_OK(status
)) {
1917 printf("smb2cli_query_info (security) returned %s\n", nt_errstr(status
));
1921 in_file_info_class
= SMB_FILE_POSITION_INFORMATION
- 1000;
1922 status
= smb2cli_query_info(cli
->conn
,
1928 1024, /* in_max_output_length */
1929 NULL
, /* in_input_buffer */
1930 0, /* in_additional_info */
1935 &out_output_buffer
);
1936 if (!NT_STATUS_IS_OK(status
)) {
1937 printf("smb2cli_query_info (position) returned %s\n", nt_errstr(status
));
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
,
1952 0, /* in_additional_info */
1955 if (!NT_STATUS_IS_OK(status
)) {
1956 printf("smb2cli_set_info (position) returned %s\n", nt_errstr(status
));
1960 in_file_info_class
= SMB_FILE_POSITION_INFORMATION
- 1000;
1961 status
= smb2cli_query_info(cli
->conn
,
1967 1024, /* in_max_output_length */
1968 NULL
, /* in_input_buffer */
1969 0, /* in_additional_info */
1974 &out_output_buffer
);
1975 if (!NT_STATUS_IS_OK(status
)) {
1976 printf("smb2cli_query_info (position) returned %s\n", nt_errstr(status
));
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
));
1987 status
= smb2cli_create(
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, */
1999 FILE_SHARE_DELETE
, /* share_access, */
2000 FILE_CREATE
, /* create_disposition, */
2001 FILE_DELETE_ON_CLOSE
, /* create_options, */
2002 NULL
, /* smb2_create_blobs *blobs */
2009 if (!NT_STATUS_IS_OK(status
)) {
2010 printf("smb2cli_create %s\n", nt_errstr(status
));
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
));
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
));
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
));
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
,
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
));
2053 talloc_free(cli
->smb2
.tcon
);
2054 cli
->smb2
.tcon
= saved_tcon
;
2059 static NTSTATUS
check_size(struct cli_state
*cli
,
2064 off_t size_read
= 0;
2066 NTSTATUS status
= cli_qfileinfo_basic(cli
,
2076 if (!NT_STATUS_IS_OK(status
)) {
2077 printf("cli_qfileinfo_basic of %s failed (%s)\n",
2083 if (size
!= size_read
) {
2084 printf("size (%u) != size_read(%u) for %s\n",
2086 (unsigned int)size_read
,
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
;
2107 printf("Starting SMB2-FTRUNCATE\n");
2109 if (!torture_init_connection(&cli
)) {
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
));
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
));
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
));
2132 cli_setatr(cli
, fname
, 0, 0);
2133 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2135 status
= cli_ntcreate(cli
,
2139 FILE_ATTRIBUTE_NORMAL
,
2147 if (!NT_STATUS_IS_OK(status
)) {
2148 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
2152 buf
= talloc_zero_array(cli
, uint8_t, buflen
);
2158 status
= cli_writeall(cli
,
2166 if (!NT_STATUS_IS_OK(status
)) {
2167 printf("write of %u to %s failed (%s)\n",
2168 (unsigned int)buflen
,
2174 status
= check_size(cli
, fnum
, fname
, buflen
);
2175 if (!NT_STATUS_IS_OK(status
)) {
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,
2189 status
= check_size(cli
, fnum
, fname
, i
*1024);
2190 if (!NT_STATUS_IS_OK(status
)) {
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
)) {
2215 /* Ensure SMB2 flush on directories behaves correctly. */
2217 static bool test_dir_fsync(struct cli_state
*cli
, const char *path
)
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(
2231 SMB2_OPLOCK_LEVEL_NONE
, /* oplock_level, */
2232 SMB2_IMPERSONATION_IMPERSONATION
, /* impersonation_level, */
2233 SEC_STD_SYNCHRONIZE
|
2235 SEC_DIR_READ_ATTRIBUTE
, /* desired_access, */
2236 0, /* file_attributes, */
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 */
2250 if (!NT_STATUS_IS_OK(status
)) {
2251 printf("smb2cli_create '%s' (readonly) returned %s\n",
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",
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",
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
));
2285 /* Open directory write-attributes only. Flush should still fail. */
2287 status
= smb2cli_create(
2293 SMB2_OPLOCK_LEVEL_NONE
, /* oplock_level, */
2294 SMB2_IMPERSONATION_IMPERSONATION
, /* impersonation_level, */
2295 SEC_STD_SYNCHRONIZE
|
2297 SEC_DIR_WRITE_ATTRIBUTE
|
2298 SEC_DIR_READ_ATTRIBUTE
, /* desired_access, */
2299 0, /* file_attributes, */
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 */
2313 if (!NT_STATUS_IS_OK(status
)) {
2314 printf("smb2cli_create '%s' (write attr) returned %s\n",
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
));
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 "
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
));
2346 /* Open directory with SEC_DIR_ADD_FILE access. Flush should now succeed. */
2348 status
= smb2cli_create(
2354 SMB2_OPLOCK_LEVEL_NONE
, /* oplock_level, */
2355 SMB2_IMPERSONATION_IMPERSONATION
, /* impersonation_level, */
2356 SEC_STD_SYNCHRONIZE
|
2358 SEC_DIR_ADD_FILE
, /* desired_access, */
2359 0, /* file_attributes, */
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 */
2373 if (!NT_STATUS_IS_OK(status
)) {
2374 printf("smb2cli_create '%s' (write FILE access) returned %s\n",
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
));
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",
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
));
2405 /* Open directory with SEC_DIR_ADD_FILE access. Flush should now succeed. */
2407 status
= smb2cli_create(
2413 SMB2_OPLOCK_LEVEL_NONE
, /* oplock_level, */
2414 SMB2_IMPERSONATION_IMPERSONATION
, /* impersonation_level, */
2415 SEC_STD_SYNCHRONIZE
|
2417 SEC_DIR_ADD_SUBDIR
, /* desired_access, */
2418 0, /* file_attributes, */
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 */
2432 if (!NT_STATUS_IS_OK(status
)) {
2433 printf("smb2cli_create '%s' (write DIR access) returned %s\n",
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
));
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",
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
));
2468 bool run_smb2_dir_fsync(int dummy
)
2470 struct cli_state
*cli
= NULL
;
2473 const char *dname
= "fsync_test_dir";
2475 printf("Starting SMB2-DIR-FSYNC\n");
2477 if (!torture_init_connection(&cli
)) {
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
));
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
));
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
));
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",
2509 /* Test on a subdirectory. */
2510 bret
= test_dir_fsync(cli
, dname
);
2511 if (bret
== false) {
2512 (void)cli_rmdir(cli
, dname
);
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) {
2525 bool run_smb2_path_slash(int dummy
)
2527 struct cli_state
*cli
= NULL
;
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
)) {
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
));
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
));
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
));
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(
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, */
2581 FILE_SHARE_DELETE
, /* share_access, */
2582 FILE_CREATE
, /* create_disposition, */
2583 FILE_DIRECTORY_FILE
, /* create_options, */
2584 NULL
, /* smb2_create_blobs *blobs */
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",
2601 status
= smb2cli_close(cli
->conn
,
2608 if (!NT_STATUS_IS_OK(status
)) {
2609 printf("smb2cli_close returned %s\n", nt_errstr(status
));
2613 (void)cli_rmdir(cli
, dname_noslash
);
2615 /* Try to create a directory with the slash name. */
2616 status
= smb2cli_create(
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, */
2628 FILE_SHARE_DELETE
, /* share_access, */
2629 FILE_CREATE
, /* create_disposition, */
2630 FILE_DIRECTORY_FILE
, /* create_options, */
2631 NULL
, /* smb2_create_blobs *blobs */
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",
2645 if (NT_STATUS_IS_OK(status
)) {
2646 (void)smb2cli_close(cli
->conn
,
2654 (void)cli_rmdir(cli
, dname_noslash
);
2658 (void)cli_rmdir(cli
, dname_noslash
);
2660 /* Try to create a file with the backslash name. */
2661 status
= smb2cli_create(
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, */
2673 FILE_SHARE_DELETE
, /* share_access, */
2674 FILE_CREATE
, /* create_disposition, */
2675 FILE_NON_DIRECTORY_FILE
, /* create_options, */
2676 NULL
, /* smb2_create_blobs *blobs */
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",
2691 if (NT_STATUS_IS_OK(status
)) {
2692 (void)smb2cli_close(cli
->conn
,
2700 (void)cli_unlink(cli
, fname_noslash
, 0);
2704 (void)cli_unlink(cli
, fname_noslash
, 0);
2706 /* Try to create a file with the slash name. */
2707 status
= smb2cli_create(
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, */
2719 FILE_SHARE_DELETE
, /* share_access, */
2720 FILE_CREATE
, /* create_disposition, */
2721 FILE_NON_DIRECTORY_FILE
, /* create_options, */
2722 NULL
, /* smb2_create_blobs *blobs */
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",
2737 if (NT_STATUS_IS_OK(status
)) {
2738 (void)smb2cli_close(cli
->conn
,
2746 (void)cli_unlink(cli
, fname_noslash
, 0);
2750 (void)cli_unlink(cli
, fname_noslash
, 0);
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).
2764 * 6). Open with SEC_FLAG_SYSTEM_SECURITY|SEC_STD_WRITE_DAC.
2765 * 7). Write SACL. Success.
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).
2773 bool run_smb2_sacl(int dummy
)
2775 struct cli_state
*cli
= NULL
;
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
)) {
2788 status
= smbXcli_negprot(cli
->conn
,
2792 if (!NT_STATUS_IS_OK(status
)) {
2793 printf("smbXcli_negprot returned %s\n", nt_errstr(status
));
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
));
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
));
2809 (void)cli_unlink(cli
, fname
, 0);
2811 /* First create a file. */
2812 status
= cli_ntcreate(cli
,
2816 FILE_ATTRIBUTE_NORMAL
,
2824 if (!NT_STATUS_IS_OK(status
)) {
2825 printf("Create of %s failed (%s)\n",
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
,
2843 SMB2_OPLOCK_LEVEL_NONE
,
2844 SMB2_IMPERSONATION_IMPERSONATION
,
2845 SEC_FLAG_SYSTEM_SECURITY
, /* desired access */
2846 0, /* file_attributes, */
2849 FILE_SHARE_DELETE
, /* share_access, */
2850 FILE_OPEN
, /* create_disposition, */
2851 FILE_NON_DIRECTORY_FILE
, /* create_options, */
2852 NULL
, /* in_cblobs. */
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"
2862 "\"Manage auditing and security log\""
2863 "privilege setting on Windows\n");
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",
2876 * Open with SEC_FLAG_SYSTEM_SECURITY|FILE_WRITE_ATTRIBUTES.
2879 status
= cli_smb2_create_fnum(cli
,
2881 SMB2_OPLOCK_LEVEL_NONE
,
2882 SMB2_IMPERSONATION_IMPERSONATION
,
2883 SEC_FLAG_SYSTEM_SECURITY
|
2884 FILE_WRITE_ATTRIBUTES
, /* desired access */
2885 0, /* file_attributes, */
2888 FILE_SHARE_DELETE
, /* share_access, */
2889 FILE_OPEN
, /* create_disposition, */
2890 FILE_NON_DIRECTORY_FILE
, /* create_options, */
2891 NULL
, /* in_cblobs. */
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",
2905 /* Create an SD with a SACL. */
2906 sd_sacl
= security_descriptor_sacl_create(talloc_tos(),
2912 SEC_ACE_TYPE_SYSTEM_AUDIT
,
2914 SEC_ACE_FLAG_FAILED_ACCESS
,
2917 if (sd_sacl
== NULL
) {
2918 printf("Out of memory creating SACL\n");
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
,
2929 SECINFO_DACL
|SECINFO_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",
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
,
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, */
2957 FILE_SHARE_DELETE
, /* share_access, */
2958 FILE_OPEN
, /* create_disposition, */
2959 FILE_NON_DIRECTORY_FILE
, /* create_options, */
2960 NULL
, /* in_cblobs. */
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",
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
,
2981 SECINFO_DACL
|SECINFO_SACL
,
2984 if (!NT_STATUS_IS_OK(status
)) {
2985 printf("cli_set_security_descriptor SACL "
2986 "on file %s failed (%s)\n",
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
,
3006 SMB2_OPLOCK_LEVEL_NONE
,
3007 SMB2_IMPERSONATION_IMPERSONATION
,
3008 SEC_FLAG_SYSTEM_SECURITY
|
3009 FILE_READ_ATTRIBUTES
, /* desired access */
3010 0, /* file_attributes, */
3013 FILE_SHARE_DELETE
, /* share_access, */
3014 FILE_OPEN
, /* create_disposition, */
3015 FILE_NON_DIRECTORY_FILE
, /* create_options, */
3016 NULL
, /* in_cblobs. */
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",
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",
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",
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);
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);
3083 bool run_smb2_quota1(int dummy
)
3085 struct cli_state
*cli
= NULL
;
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
)) {
3096 status
= smbXcli_negprot(cli
->conn
,
3100 if (!NT_STATUS_IS_OK(status
)) {
3101 printf("smbXcli_negprot returned %s\n", nt_errstr(status
));
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
));
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
));
3117 status
= cli_smb2_create_fnum(
3120 SMB2_OPLOCK_LEVEL_NONE
,
3121 SMB2_IMPERSONATION_IMPERSONATION
,
3122 SEC_GENERIC_READ
, /* desired access */
3123 0, /* file_attributes, */
3126 FILE_SHARE_DELETE
, /* share_access, */
3127 FILE_OPEN
, /* create_disposition, */
3128 FILE_DIRECTORY_FILE
, /* create_options, */
3129 NULL
, /* in_cblobs. */
3131 NULL
, /* smb_create_returns */
3133 NULL
); /* out_cblobs */
3134 if (!NT_STATUS_IS_OK(status
)) {
3135 printf("cli_smb2_create_fnum failed: %s\n", nt_errstr(status
));
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",
3150 bool run_smb2_stream_acl(int dummy
)
3152 struct cli_state
*cli
= NULL
;
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
;
3160 printf("SMB2 stream acl\n");
3162 if (!torture_init_connection(&cli
)) {
3166 status
= smbXcli_negprot(cli
->conn
,
3170 if (!NT_STATUS_IS_OK(status
)) {
3171 printf("smbXcli_negprot returned %s\n", nt_errstr(status
));
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
));
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
));
3187 /* Ensure file doesn't exist. */
3188 (void)cli_unlink(cli
, fname
, 0);
3190 /* Create the file. */
3191 status
= cli_ntcreate(cli
,
3195 FILE_ATTRIBUTE_NORMAL
,
3203 if (!NT_STATUS_IS_OK(status
)) {
3204 printf("Create of %s failed (%s)\n",
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
,
3219 SEC_STD_READ_CONTROL
|
3221 FILE_ATTRIBUTE_NORMAL
,
3229 if (!NT_STATUS_IS_OK(status
)) {
3230 printf("Create of %s failed (%s)\n",
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
,
3248 SEC_STD_READ_CONTROL
|
3250 FILE_ATTRIBUTE_NORMAL
,
3258 if (!NT_STATUS_IS_OK(status
)) {
3259 printf("Open of %s failed (%s)\n",
3265 /* Read the security descriptor off the stream handle. */
3266 status
= cli_query_security_descriptor(cli
,
3272 if (!NT_STATUS_IS_OK(status
)) {
3273 printf("Reading DACL on stream %s got (%s)\n",
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",
3288 * Ensure it allows FILE_READ_DATA in the first ace.
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",
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
,
3306 if (!NT_STATUS_IS_OK(status
)) {
3307 printf("Setting DACL on stream %s got (%s)\n",
3313 TALLOC_FREE(sd_dacl
);
3315 /* Read again and check it changed. */
3316 status
= cli_query_security_descriptor(cli
,
3322 if (!NT_STATUS_IS_OK(status
)) {
3323 printf("Reading DACL on stream %s got (%s)\n",
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",
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",
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);
3357 static NTSTATUS
list_fn(struct file_info
*finfo
,
3361 bool *matched
= (bool *)state
;
3362 if (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
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
;
3378 const char *dname
= "ASYNC_DIR";
3380 bool matched
= false;
3382 printf("SMB2 list dir async\n");
3384 if (!torture_init_connection(&cli
)) {
3388 status
= smbXcli_negprot(cli
->conn
,
3392 if (!NT_STATUS_IS_OK(status
)) {
3393 printf("smbXcli_negprot returned %s\n", nt_errstr(status
));
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
));
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
));
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
));
3418 status
= cli_list(cli
,
3420 FILE_ATTRIBUTE_NORMAL
|FILE_ATTRIBUTE_DIRECTORY
,
3423 if (!NT_STATUS_IS_OK(status
)) {
3424 printf("cli_list %s returned %s\n", dname
, nt_errstr(status
));
3429 printf("Failed to find %s\n", dname
);
3437 (void)cli_rmdir(cli
, dname
);
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
;
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;
3457 printf("SMB2 delete on close nonempty\n");
3459 if (!torture_init_connection(&cli
)) {
3463 status
= smbXcli_negprot(cli
->conn
,
3467 if (!NT_STATUS_IS_OK(status
)) {
3468 printf("smbXcli_negprot returned %s\n", nt_errstr(status
));
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
));
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
));
3484 /* Ensure directory doesn't exist. */
3485 (void)cli_unlink(cli
,
3487 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3488 (void)cli_rmdir(cli
, dname
);
3490 /* Create target directory. */
3491 status
= cli_ntcreate(cli
,
3494 DELETE_ACCESS
|FILE_READ_DATA
,
3495 FILE_ATTRIBUTE_DIRECTORY
,
3500 FILE_DIRECTORY_FILE
,
3504 if (!NT_STATUS_IS_OK(status
)) {
3505 printf("cli_ntcreate for directory %s returned %s\n",
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 "
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
,
3532 FILE_ATTRIBUTE_NORMAL
,
3541 if (!NT_STATUS_IS_OK(status
)) {
3542 printf("cli_ntcreate for file %s returned %s\n",
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",
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
,
3572 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3573 (void)cli_rmdir(cli
, dname
);
3577 static NTSTATUS
check_empty_fn(struct file_info
*finfo
,
3581 unsigned int *pcount
= (unsigned int *)private_data
;
3583 if (ISDOT(finfo
->name
) || ISDOTDOT(finfo
->name
)) {
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
;
3605 const char *dname
= "delete_veto_yes";
3606 const char *list_dname
= "delete_veto_yes\\*";
3607 uint16_t fnum
= (uint16_t)-1;
3609 unsigned int list_count
= 0;
3611 printf("SMB2 delete on close nonwrite - delete veto yes\n");
3613 if (!torture_init_connection(&cli
)) {
3617 status
= smbXcli_negprot(cli
->conn
,
3621 if (!NT_STATUS_IS_OK(status
)) {
3622 printf("smbXcli_negprot returned %s\n", nt_errstr(status
));
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
));
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
));
3638 /* Ensure target directory is seen as empty. */
3639 status
= cli_list(cli
,
3641 FILE_ATTRIBUTE_DIRECTORY
|
3642 FILE_ATTRIBUTE_HIDDEN
|
3643 FILE_ATTRIBUTE_SYSTEM
,
3646 if (!NT_STATUS_IS_OK(status
)) {
3647 printf("cli_list of %s returned %s\n",
3652 if (list_count
!= 2) {
3653 printf("cli_list of %s returned a count of %u\n",
3659 /* Open target directory. */
3660 status
= cli_ntcreate(cli
,
3663 DELETE_ACCESS
|FILE_READ_DATA
,
3664 FILE_ATTRIBUTE_DIRECTORY
,
3669 FILE_DIRECTORY_FILE
,
3673 if (!NT_STATUS_IS_OK(status
)) {
3674 printf("cli_ntcreate for directory %s returned %s\n",
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",
3694 if (fnum
!= (uint16_t)-1) {
3695 (void)cli_nt_delete_on_close(cli
, fnum
, 0);
3696 (void)cli_close(cli
, fnum
);
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
;
3716 const char *dname
= "delete_veto_no";
3717 const char *list_dname
= "delete_veto_no\\*";
3718 uint16_t fnum
= (uint16_t)-1;
3720 unsigned int list_count
= 0;
3722 printf("SMB2 delete on close nonwrite - delete veto yes\n");
3724 if (!torture_init_connection(&cli
)) {
3728 status
= smbXcli_negprot(cli
->conn
,
3732 if (!NT_STATUS_IS_OK(status
)) {
3733 printf("smbXcli_negprot returned %s\n", nt_errstr(status
));
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
));
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
));
3749 /* Ensure target directory is seen as empty. */
3750 status
= cli_list(cli
,
3752 FILE_ATTRIBUTE_DIRECTORY
|
3753 FILE_ATTRIBUTE_HIDDEN
|
3754 FILE_ATTRIBUTE_SYSTEM
,
3757 if (!NT_STATUS_IS_OK(status
)) {
3758 printf("cli_list of %s returned %s\n",
3763 if (list_count
!= 2) {
3764 printf("cli_list of %s returned a count of %u\n",
3770 /* Open target directory. */
3771 status
= cli_ntcreate(cli
,
3774 DELETE_ACCESS
|FILE_READ_DATA
,
3775 FILE_ATTRIBUTE_DIRECTORY
,
3780 FILE_DIRECTORY_FILE
,
3784 if (!NT_STATUS_IS_OK(status
)) {
3785 printf("cli_ntcreate for directory %s returned %s\n",
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",
3800 if (!NT_STATUS_EQUAL(status
, NT_STATUS_DIRECTORY_NOT_EMPTY
)) {
3801 printf("cli_cli_nt_delete_on_close set for directory "
3803 "(should have returned "
3804 "NT_STATUS_DIRECTORY_NOT_EMPTY)\n",
3814 if (fnum
!= (uint16_t)-1) {
3815 (void)cli_nt_delete_on_close(cli
, fnum
, 0);
3816 (void)cli_close(cli
, fnum
);
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
,
3829 uint64_t fid_persistent
= 0;
3830 uint64_t fid_volatile
= 0;
3831 DATA_BLOB outbuf
= data_blob_null
;
3835 status
= smb2cli_create(cli
->conn
,
3840 SMB2_OPLOCK_LEVEL_NONE
, /* oplock_level, */
3841 SMB2_IMPERSONATION_IMPERSONATION
, /* impersonation_level, */
3842 SEC_STD_SYNCHRONIZE
|
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 */
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
)) {
3863 status
= smb2cli_query_info(cli
->conn
,
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 */
3878 if (NT_STATUS_IS_OK(status
)) {
3879 *ino_ret
= PULL_LE_U64(outbuf
.data
, 0x40);
3882 (void)smb2cli_close(cli
->conn
,
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;
3903 status
= get_smb2_inode(cli
,
3906 if (!NT_STATUS_IS_OK(status
)) {
3907 printf("%s: Failed to get ino "
3908 "number for %s, (%s)\n",
3914 if (test_ino
!= ino_tomatch
) {
3915 printf("%s: Inode missmatch, ino_tomatch (%s) "
3916 "ino=%"PRIu64
" test (%s) "
3929 * Delete an SMB2 file on a DFS share.
3931 static NTSTATUS
smb2_dfs_delete(struct cli_state
*cli
,
3932 const char *pathname
)
3935 uint64_t fid_persistent
= 0;
3936 uint64_t fid_volatile
= 0;
3943 status
= smb2cli_create(cli
->conn
,
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 */
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
)) {
3968 * Set delete on close.
3970 PUSH_LE_U8(&data
[0], 0, 1);
3971 inbuf
.data
= &data
[0];
3974 status
= smb2cli_set_info(cli
->conn
,
3978 SMB2_0_INFO_FILE
, /* info_type. */
3979 SMB_FILE_DISPOSITION_INFORMATION
- 1000, /* info_class */
3981 0, /* additional_info. */
3984 if (!NT_STATUS_IS_OK(status
)) {
3987 status
= smb2cli_close(cli
->conn
,
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
,
4008 smb_ucs2_t
*converted_str
= NULL
;
4009 size_t converted_size_bytes
= 0;
4011 uint8_t info_class
= 0;
4014 ok
= push_ucs2_talloc(talloc_tos(),
4017 &converted_size_bytes
);
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;
4054 info_class
= SMB_FILE_LINK_INFORMATION
- 1000;
4057 status
= smb2cli_set_info(cli
->conn
,
4061 SMB2_0_INFO_FILE
, /* info_type. */
4062 info_class
, /* info_class */
4064 0, /* additional_info. */
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
,
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
,
4091 false); /* do_rename */
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
,
4112 const char *test_str
= "/[]:|<>+=;,*?";
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
++) {
4123 ino_matched
= smb2_inode_matches(cli
,
4124 dfs_root_share_name
,
4132 /* Test explicit invalid characters. */
4133 for (p
= test_str
; *p
!= '\0'; 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
,
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",
4154 ino_matched
= smb2_inode_matches(cli
,
4155 dfs_root_share_name
,
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
;
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;
4191 printf("Starting SMB2-DFS-PATHS\n");
4193 if (!torture_init_connection(&cli
)) {
4197 status
= smbXcli_negprot(cli
->conn
,
4201 if (!NT_STATUS_IS_OK(status
)) {
4202 printf("smbXcli_negprot returned %s\n", nt_errstr(status
));
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
));
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
));
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
));
4225 dfs_supported
= smbXcli_tcon_is_dfs_share(cli
->smb2
.tcon
);
4226 if (!dfs_supported
) {
4227 printf("Share %s does not support DFS\n",
4232 * Create the "official" DFS share root name.
4233 * No SMB2 paths can start with '\\'.
4235 dfs_root_share_name
= talloc_asprintf(talloc_tos(),
4237 smbXcli_conn_remote_name(cli
->conn
),
4239 if (dfs_root_share_name
== NULL
) {
4240 printf("Out of memory\n");
4244 /* Get the share root inode number. */
4245 status
= get_smb2_inode(cli
,
4246 dfs_root_share_name
,
4248 if (!NT_STATUS_IS_OK(status
)) {
4249 printf("%s:%d Failed to get ino number for share root %s, (%s)\n",
4252 dfs_root_share_name
,
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
,
4266 smbXcli_conn_remote_name(cli
->conn
));
4268 printf("%s:%d Failed to match ino number for %s\n",
4271 smbXcli_conn_remote_name(cli
->conn
));
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
,
4283 if (NT_STATUS_IS_OK(status
)) {
4285 * Windows 2008 - open succeeded. Proceed to
4288 ino_matched
= smb2_inode_matches(cli
,
4289 dfs_root_share_name
,
4293 printf("%s:%d Failed to match ino number for %s\n",
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
4306 printf("%s:%d Unexpected error (%s) getting ino number for %s\n",
4313 /* A "BAD" server name should open and match the share root. */
4314 ino_matched
= smb2_inode_matches(cli
,
4315 dfs_root_share_name
,
4319 printf("%s:%d Failed to match ino number for %s\n",
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
,
4334 printf("%s:%d Failed to match ino number for %s\n",
4341 * Trying to open "BAD\\BAD\\BAD" should get
4342 * NT_STATUS_OBJECT_NAME_NOT_FOUND.
4344 status
= get_smb2_inode(cli
,
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",
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",
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",
4368 "BAD\\BAD\\BAD\\BAD",
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
,
4381 printf("%s:%d Failed to match ino number for %s\n",
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
,
4401 /* Now create a file called "file". */
4402 status
= smb2cli_create(cli
->conn
,
4407 SMB2_OPLOCK_LEVEL_NONE
, /* oplock_level, */
4408 SMB2_IMPERSONATION_IMPERSONATION
, /* impersonation_level, */
4409 SEC_STD_SYNCHRONIZE
|
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 */
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",
4434 * Trying to open "BAD\\BAD\\file" should now get
4437 status
= get_smb2_inode(cli
,
4440 if (!NT_STATUS_IS_OK(status
)) {
4441 printf("%s:%d Open of %s should succeed "
4451 * Now show that renames use relative,
4452 * not full DFS paths.
4455 /* Full DFS path should fail. */
4456 status
= smb2_dfs_rename(cli
,
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",
4466 "ANY\\NAME\\renamed_file",
4470 /* Relative DFS path should succeed. */
4471 status
= smb2_dfs_rename(cli
,
4475 if (!NT_STATUS_IS_OK(status
)) {
4476 printf("%s:%d: Rename of %s -> %s should succeed. "
4487 * Trying to open "BAD\\BAD\\renamed_file" should now get
4490 status
= get_smb2_inode(cli
,
4491 "BAD\\BAD\\renamed_file",
4493 if (!NT_STATUS_IS_OK(status
)) {
4494 printf("%s:%d: Open of %s should succeed "
4498 "BAD\\BAD\\renamed_file",
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
,
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",
4518 "ANY\\NAME\\renamed_file",
4523 /* Relative DFS path should succeed. */
4524 status
= smb2_dfs_hlink(cli
,
4528 if (!NT_STATUS_IS_OK(status
)) {
4529 printf("%s:%d: Hlink of %s -> %s should succeed. "
4533 "ANY\\NAME\\renamed_file",
4540 * Trying to open "BAD\\BAD\\hlink" should now get
4543 status
= get_smb2_inode(cli
,
4546 if (!NT_STATUS_IS_OK(status
)) {
4547 printf("%s:%d Open of %s should succeed "
4560 if (fid_persistent
!= 0 || fid_volatile
!= 0) {
4561 smb2cli_close(cli
->conn
,
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");
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
4585 bool run_smb2_non_dfs_share(int dummy
)
4587 struct cli_state
*cli
= NULL
;
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
)) {
4601 status
= smbXcli_negprot(cli
->conn
,
4605 if (!NT_STATUS_IS_OK(status
)) {
4606 printf("smbXcli_negprot returned %s\n", nt_errstr(status
));
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
));
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
));
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
));
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",
4636 * Force the share to be DFS, as far as the client
4639 smb2cli_tcon_set_values(cli
->smb2
.tcon
,
4641 smb2cli_tcon_current_id(cli
->smb2
.tcon
),
4643 smb2cli_tcon_flags(cli
->smb2
.tcon
),
4644 smb2cli_tcon_capabilities(cli
->smb2
.tcon
) |
4648 /* Come up with a "valid" SMB2 DFS name. */
4649 dfs_filename
= talloc_asprintf(talloc_tos(),
4651 smbXcli_conn_remote_name(cli
->conn
),
4653 if (dfs_filename
== NULL
) {
4654 printf("Out of memory\n");
4658 /* Now try create dfs_filename. */
4659 status
= smb2cli_create(cli
->conn
,
4664 SMB2_OPLOCK_LEVEL_NONE
, /* oplock_level, */
4665 SMB2_IMPERSONATION_IMPERSONATION
, /* impersonation_level, */
4666 SEC_STD_SYNCHRONIZE
|
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 */
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",
4697 * Prove we can still use non-DFS pathnames, even though
4698 * we are setting the FLAGS2_DFS_PATHNAMES in the SMB2
4701 status
= smb2cli_create(cli
->conn
,
4706 SMB2_OPLOCK_LEVEL_NONE
, /* oplock_level, */
4707 SMB2_IMPERSONATION_IMPERSONATION
, /* impersonation_level, */
4708 SEC_STD_SYNCHRONIZE
|
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 */
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",
4736 (void)smb2_dfs_delete(cli
, dfs_filename
);
4737 (void)smb2_dfs_delete(cli
, "file");
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
;
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
)) {
4766 status
= smbXcli_negprot(cli
->conn
,
4770 if (!NT_STATUS_IS_OK(status
)) {
4771 printf("smbXcli_negprot returned %s\n", nt_errstr(status
));
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
));
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
));
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
));
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",
4800 /* Come up with a "valid" SMB2 DFS name. */
4801 dfs_filename
= talloc_asprintf(talloc_tos(),
4803 smbXcli_conn_remote_name(cli
->conn
),
4805 if (dfs_filename
== NULL
) {
4806 printf("Out of memory\n");
4810 /* Get the root of the share ino. */
4811 status
= get_smb2_inode(cli
,
4814 if (!NT_STATUS_IS_OK(status
)) {
4815 printf("%s:%d get_smb2_inode on %s returned %s\n",
4823 /* Create a dfs_filename. */
4824 status
= smb2cli_create(cli
->conn
,
4829 SMB2_OPLOCK_LEVEL_NONE
, /* oplock_level, */
4830 SMB2_IMPERSONATION_IMPERSONATION
, /* impersonation_level, */
4831 SEC_STD_SYNCHRONIZE
|
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 */
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",
4855 /* Close the handle we just opened. */
4856 smb2cli_close(cli
->conn
,
4868 * Force the share to be non-DFS, as far as the client
4871 smb2cli_tcon_set_values(cli
->smb2
.tcon
,
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
,
4890 SMB2_OPLOCK_LEVEL_NONE
, /* oplock_level, */
4891 SMB2_IMPERSONATION_IMPERSONATION
, /* impersonation_level, */
4892 SEC_STD_SYNCHRONIZE
|
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 */
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",
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
,
4925 printf("%s:%d Failed to match ino number for %s\n",
4936 if (fid_volatile
!= 0) {
4937 smb2cli_close(cli
->conn
,
4945 (void)smb2_dfs_delete(cli
, "file");
4946 (void)smb2_dfs_delete(cli
, dfs_filename
);