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