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(
3955 : cli->conn,
3956 110 : cli->timeout,
3957 : cli->smb2.session,
3958 : cli->smb2.tcon,
3959 : SMB2_0_INFO_FILE,
3960 : FSCC_FILE_ALL_INFORMATION, /* in_file_info_class */
3961 : 1024, /* in_max_output_length */
3962 : NULL, /* in_input_buffer */
3963 : 0, /* in_additional_info */
3964 : 0, /* in_flags */
3965 : fid_persistent,
3966 : fid_volatile,
3967 : talloc_tos(),
3968 : &outbuf);
3969 :
3970 110 : if (NT_STATUS_IS_OK(status)) {
3971 110 : *ino_ret = PULL_LE_U64(outbuf.data, 0x40);
3972 : }
3973 :
3974 110 : (void)smb2cli_close(cli->conn,
3975 110 : cli->timeout,
3976 : cli->smb2.session,
3977 : cli->smb2.tcon,
3978 : 0,
3979 : fid_persistent,
3980 : fid_volatile);
3981 110 : return status;
3982 : }
3983 :
3984 : /*
3985 : * Check an inode matches a given SMB2 path.
3986 : */
3987 98 : static bool smb2_inode_matches(struct cli_state *cli,
3988 : const char *match_pathname,
3989 : uint64_t ino_tomatch,
3990 : const char *test_pathname)
3991 : {
3992 98 : uint64_t test_ino = 0;
3993 0 : NTSTATUS status;
3994 :
3995 98 : status = get_smb2_inode(cli,
3996 : test_pathname,
3997 : &test_ino);
3998 98 : if (!NT_STATUS_IS_OK(status)) {
3999 0 : printf("%s: Failed to get ino "
4000 : "number for %s, (%s)\n",
4001 : __func__,
4002 : test_pathname,
4003 : nt_errstr(status));
4004 0 : return false;
4005 : }
4006 98 : if (test_ino != ino_tomatch) {
4007 0 : printf("%s: Inode mismatch, ino_tomatch (%s) "
4008 : "ino=%"PRIu64" test (%s) "
4009 : "ino=%"PRIu64"\n",
4010 : __func__,
4011 : match_pathname,
4012 : ino_tomatch,
4013 : test_pathname,
4014 : test_ino);
4015 0 : return false;
4016 : }
4017 98 : return true;
4018 : }
4019 :
4020 : /*
4021 : * Delete an SMB2 file on a DFS share.
4022 : */
4023 18 : static NTSTATUS smb2_dfs_delete(struct cli_state *cli,
4024 : const char *pathname)
4025 : {
4026 0 : NTSTATUS status;
4027 18 : uint64_t fid_persistent = 0;
4028 18 : uint64_t fid_volatile = 0;
4029 0 : uint8_t data[1];
4030 0 : DATA_BLOB inbuf;
4031 :
4032 : /*
4033 : * Open the file.
4034 : */
4035 18 : status = smb2cli_create(cli->conn,
4036 18 : cli->timeout,
4037 : cli->smb2.session,
4038 : cli->smb2.tcon,
4039 : pathname,
4040 : SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4041 : SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4042 : SEC_STD_SYNCHRONIZE|
4043 : SEC_STD_DELETE, /* desired_access, */
4044 : FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4045 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4046 : FILE_OPEN, /* create_disposition, */
4047 : 0, /* create_options, */
4048 : NULL, /* smb2_create_blobs *blobs */
4049 : &fid_persistent,
4050 : &fid_volatile,
4051 : NULL, /* struct smb_create_returns * */
4052 : talloc_tos(), /* mem_ctx. */
4053 : NULL, /* struct smb2_create_blobs * */
4054 : NULL); /* struct symlink_reparse_struct */
4055 18 : if (!NT_STATUS_IS_OK(status)) {
4056 8 : return status;
4057 : }
4058 :
4059 : /*
4060 : * Set delete on close.
4061 : */
4062 10 : PUSH_LE_U8(&data[0], 0, 1);
4063 10 : inbuf.data = &data[0];
4064 10 : inbuf.length = 1;
4065 :
4066 10 : status = smb2cli_set_info(cli->conn,
4067 10 : cli->timeout,
4068 : cli->smb2.session,
4069 : cli->smb2.tcon,
4070 : SMB2_0_INFO_FILE, /* info_type. */
4071 : SMB_FILE_DISPOSITION_INFORMATION - 1000, /* info_class */
4072 : &inbuf,
4073 : 0, /* additional_info. */
4074 : fid_persistent,
4075 : fid_volatile);
4076 10 : if (!NT_STATUS_IS_OK(status)) {
4077 0 : return status;
4078 : }
4079 10 : status = smb2cli_close(cli->conn,
4080 10 : cli->timeout,
4081 : cli->smb2.session,
4082 : cli->smb2.tcon,
4083 : 0,
4084 : fid_persistent,
4085 : fid_volatile);
4086 10 : return status;
4087 : }
4088 :
4089 : /*
4090 : * Rename or hardlink an SMB2 file on a DFS share.
4091 : */
4092 8 : static NTSTATUS smb2_dfs_setinfo_name(struct cli_state *cli,
4093 : uint64_t fid_persistent,
4094 : uint64_t fid_volatile,
4095 : const char *newname,
4096 : bool do_rename)
4097 : {
4098 0 : NTSTATUS status;
4099 0 : DATA_BLOB inbuf;
4100 8 : smb_ucs2_t *converted_str = NULL;
4101 8 : size_t converted_size_bytes = 0;
4102 0 : size_t inbuf_size;
4103 8 : uint8_t info_class = 0;
4104 0 : bool ok;
4105 :
4106 8 : ok = push_ucs2_talloc(talloc_tos(),
4107 : &converted_str,
4108 : newname,
4109 : &converted_size_bytes);
4110 8 : if (!ok) {
4111 0 : return NT_STATUS_INVALID_PARAMETER;
4112 : }
4113 : /*
4114 : * W2K8 insists the dest name is not null terminated. Remove
4115 : * the last 2 zero bytes and reduce the name length.
4116 : */
4117 8 : if (converted_size_bytes < 2) {
4118 0 : return NT_STATUS_INVALID_PARAMETER;
4119 : }
4120 8 : converted_size_bytes -= 2;
4121 8 : inbuf_size = 20 + converted_size_bytes;
4122 8 : if (inbuf_size < 20) {
4123 : /* Integer wrap check. */
4124 0 : return NT_STATUS_INVALID_PARAMETER;
4125 : }
4126 :
4127 : /*
4128 : * The Windows 10 SMB2 server has a minimum length
4129 : * for a SMB2_FILE_RENAME_INFORMATION buffer of
4130 : * 24 bytes. It returns NT_STATUS_INFO_LENGTH_MISMATCH
4131 : * if the length is less.
4132 : */
4133 8 : inbuf_size = MAX(inbuf_size, 24);
4134 8 : inbuf = data_blob_talloc_zero(talloc_tos(), inbuf_size);
4135 8 : if (inbuf.data == NULL) {
4136 0 : return NT_STATUS_NO_MEMORY;
4137 : }
4138 8 : PUSH_LE_U32(inbuf.data, 16, converted_size_bytes);
4139 8 : memcpy(inbuf.data + 20, converted_str, converted_size_bytes);
4140 8 : TALLOC_FREE(converted_str);
4141 :
4142 8 : if (do_rename == true) {
4143 4 : info_class = SMB_FILE_RENAME_INFORMATION - 1000;
4144 : } else {
4145 : /* Hardlink. */
4146 4 : info_class = SMB_FILE_LINK_INFORMATION - 1000;
4147 : }
4148 :
4149 8 : status = smb2cli_set_info(cli->conn,
4150 8 : cli->timeout,
4151 : cli->smb2.session,
4152 : cli->smb2.tcon,
4153 : SMB2_0_INFO_FILE, /* info_type. */
4154 : info_class, /* info_class */
4155 : &inbuf,
4156 : 0, /* additional_info. */
4157 : fid_persistent,
4158 : fid_volatile);
4159 8 : return status;
4160 : }
4161 :
4162 4 : static NTSTATUS smb2_dfs_rename(struct cli_state *cli,
4163 : uint64_t fid_persistent,
4164 : uint64_t fid_volatile,
4165 : const char *newname)
4166 : {
4167 4 : return smb2_dfs_setinfo_name(cli,
4168 : fid_persistent,
4169 : fid_volatile,
4170 : newname,
4171 : true); /* do_rename */
4172 : }
4173 :
4174 4 : static NTSTATUS smb2_dfs_hlink(struct cli_state *cli,
4175 : uint64_t fid_persistent,
4176 : uint64_t fid_volatile,
4177 : const char *newname)
4178 : {
4179 4 : return smb2_dfs_setinfo_name(cli,
4180 : fid_persistent,
4181 : fid_volatile,
4182 : newname,
4183 : false); /* do_rename */
4184 : }
4185 :
4186 : /*
4187 : * According to:
4188 :
4189 : * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/dc9978d7-6299-4c5a-a22d-a039cdc716ea
4190 : *
4191 : * (Characters " \ / [ ] : | < > + = ; , * ?,
4192 : * and control characters in range 0x00 through
4193 : * 0x1F, inclusive, are illegal in a share name)
4194 : *
4195 : * But Windows server only checks in DFS sharenames ':'. All other
4196 : * share names are allowed.
4197 : */
4198 :
4199 2 : static bool test_smb2_dfs_sharenames(struct cli_state *cli,
4200 : const char *dfs_root_share_name,
4201 : uint64_t root_ino)
4202 : {
4203 0 : char test_path[9];
4204 2 : const char *test_str = "/[]:|<>+=;,*?";
4205 0 : const char *p;
4206 0 : unsigned int i;
4207 2 : bool ino_matched = false;
4208 :
4209 : /* Setup template pathname. */
4210 2 : memcpy(test_path, "SERVER\\X", 9);
4211 :
4212 : /* Test invalid control characters. */
4213 64 : for (i = 1; i < 0x20; i++) {
4214 62 : test_path[7] = i;
4215 62 : ino_matched = smb2_inode_matches(cli,
4216 : dfs_root_share_name,
4217 : root_ino,
4218 : test_path);
4219 62 : if (!ino_matched) {
4220 0 : return false;
4221 : }
4222 : }
4223 :
4224 : /* Test explicit invalid characters. */
4225 28 : for (p = test_str; *p != '\0'; p++) {
4226 26 : test_path[7] = *p;
4227 26 : if (*p == ':') {
4228 : /*
4229 : * Only ':' is treated as an INVALID sharename
4230 : * for a DFS SERVER\\SHARE path.
4231 : */
4232 2 : uint64_t test_ino = 0;
4233 2 : NTSTATUS status = get_smb2_inode(cli,
4234 : test_path,
4235 : &test_ino);
4236 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_INVALID)) {
4237 0 : printf("%s:%d Open of %s should get "
4238 : "NT_STATUS_OBJECT_NAME_INVALID, got %s\n",
4239 : __FILE__,
4240 : __LINE__,
4241 : test_path,
4242 : nt_errstr(status));
4243 0 : return false;
4244 : }
4245 : } else {
4246 24 : ino_matched = smb2_inode_matches(cli,
4247 : dfs_root_share_name,
4248 : root_ino,
4249 : test_path);
4250 24 : if (!ino_matched) {
4251 0 : return false;
4252 : }
4253 : }
4254 : }
4255 2 : return true;
4256 : }
4257 :
4258 : /*
4259 : * "Raw" test of SMB2 paths to a DFS share.
4260 : * We must use the lower level smb2cli_XXXX() interfaces,
4261 : * not the cli_XXX() ones here as the ultimate goal is to fix our
4262 : * cli_XXX() interfaces to work transparently over DFS.
4263 : *
4264 : * So here, we're testing the server code, not the client code.
4265 : *
4266 : * Passes cleanly against Windows.
4267 : */
4268 :
4269 2 : bool run_smb2_dfs_paths(int dummy)
4270 : {
4271 2 : struct cli_state *cli = NULL;
4272 0 : NTSTATUS status;
4273 2 : bool dfs_supported = false;
4274 2 : char *dfs_root_share_name = NULL;
4275 2 : uint64_t root_ino = 0;
4276 2 : uint64_t test_ino = 0;
4277 2 : bool ino_matched = false;
4278 2 : uint64_t fid_persistent = 0;
4279 2 : uint64_t fid_volatile = 0;
4280 2 : bool retval = false;
4281 2 : bool ok = false;
4282 :
4283 2 : printf("Starting SMB2-DFS-PATHS\n");
4284 :
4285 2 : if (!torture_init_connection(&cli)) {
4286 0 : return false;
4287 : }
4288 :
4289 2 : status = smbXcli_negprot(cli->conn,
4290 2 : cli->timeout,
4291 : PROTOCOL_SMB2_02,
4292 : PROTOCOL_SMB3_11,
4293 : NULL,
4294 : NULL,
4295 : NULL);
4296 2 : if (!NT_STATUS_IS_OK(status)) {
4297 0 : printf("smbXcli_negprot returned %s\n", nt_errstr(status));
4298 0 : return false;
4299 : }
4300 :
4301 2 : status = cli_session_setup_creds(cli, torture_creds);
4302 2 : if (!NT_STATUS_IS_OK(status)) {
4303 0 : printf("cli_session_setup returned %s\n", nt_errstr(status));
4304 0 : return false;
4305 : }
4306 :
4307 2 : status = cli_tree_connect(cli, share, "?????", NULL);
4308 2 : if (!NT_STATUS_IS_OK(status)) {
4309 0 : printf("cli_tree_connect returned %s\n", nt_errstr(status));
4310 0 : return false;
4311 : }
4312 :
4313 : /* Ensure this is a DFS share. */
4314 2 : dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
4315 2 : if (!dfs_supported) {
4316 0 : printf("Server %s does not support DFS\n",
4317 0 : smbXcli_conn_remote_name(cli->conn));
4318 0 : return false;
4319 : }
4320 2 : dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb2.tcon);
4321 2 : if (!dfs_supported) {
4322 0 : printf("Share %s does not support DFS\n",
4323 0 : cli->share);
4324 0 : return false;
4325 : }
4326 : /*
4327 : * Create the "official" DFS share root name.
4328 : * No SMB2 paths can start with '\\'.
4329 : */
4330 2 : dfs_root_share_name = talloc_asprintf(talloc_tos(),
4331 : "%s\\%s",
4332 2 : smbXcli_conn_remote_name(cli->conn),
4333 2 : cli->share);
4334 2 : if (dfs_root_share_name == NULL) {
4335 0 : printf("Out of memory\n");
4336 0 : return false;
4337 : }
4338 :
4339 : /* Get the share root inode number. */
4340 2 : status = get_smb2_inode(cli,
4341 : dfs_root_share_name,
4342 : &root_ino);
4343 2 : if (!NT_STATUS_IS_OK(status)) {
4344 0 : printf("%s:%d Failed to get ino number for share root %s, (%s)\n",
4345 : __FILE__,
4346 : __LINE__,
4347 : dfs_root_share_name,
4348 : nt_errstr(status));
4349 0 : return false;
4350 : }
4351 :
4352 : /*
4353 : * Test the Windows algorithm for parsing DFS names.
4354 : */
4355 : /*
4356 : * A single "SERVER" element should open and match the share root.
4357 : */
4358 2 : ino_matched = smb2_inode_matches(cli,
4359 : dfs_root_share_name,
4360 : root_ino,
4361 2 : smbXcli_conn_remote_name(cli->conn));
4362 2 : if (!ino_matched) {
4363 0 : printf("%s:%d Failed to match ino number for %s\n",
4364 : __FILE__,
4365 : __LINE__,
4366 0 : smbXcli_conn_remote_name(cli->conn));
4367 0 : return false;
4368 : }
4369 :
4370 : /*
4371 : * An "" DFS empty server name should open and match the share root on
4372 : * Windows 2008. Windows 2022 returns NT_STATUS_INVALID_PARAMETER
4373 : * for a DFS empty server name.
4374 : */
4375 2 : status = get_smb2_inode(cli,
4376 : "",
4377 : &test_ino);
4378 2 : if (NT_STATUS_IS_OK(status)) {
4379 : /*
4380 : * Windows 2008 - open succeeded. Proceed to
4381 : * check ino number.
4382 : */
4383 0 : ino_matched = smb2_inode_matches(cli,
4384 : dfs_root_share_name,
4385 : root_ino,
4386 : "");
4387 0 : if (!ino_matched) {
4388 0 : printf("%s:%d Failed to match ino number for %s\n",
4389 : __FILE__,
4390 : __LINE__,
4391 : "");
4392 0 : return false;
4393 : }
4394 : }
4395 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4396 : /*
4397 : * For Windows 2022 we expect to fail with
4398 : * NT_STATUS_INVALID_PARAMETER. Anything else is
4399 : * unexpected.
4400 : */
4401 0 : printf("%s:%d Unexpected error (%s) getting ino number for %s\n",
4402 : __FILE__,
4403 : __LINE__,
4404 : nt_errstr(status),
4405 : "");
4406 0 : return false;
4407 : }
4408 : /* A "BAD" server name should open and match the share root. */
4409 2 : ino_matched = smb2_inode_matches(cli,
4410 : dfs_root_share_name,
4411 : root_ino,
4412 : "BAD");
4413 2 : if (!ino_matched) {
4414 0 : printf("%s:%d Failed to match ino number for %s\n",
4415 : __FILE__,
4416 : __LINE__,
4417 : "BAD");
4418 0 : return false;
4419 : }
4420 : /*
4421 : * A "BAD\\BAD" server and share name should open
4422 : * and match the share root.
4423 : */
4424 2 : ino_matched = smb2_inode_matches(cli,
4425 : dfs_root_share_name,
4426 : root_ino,
4427 : "BAD\\BAD");
4428 2 : if (!ino_matched) {
4429 0 : printf("%s:%d Failed to match ino number for %s\n",
4430 : __FILE__,
4431 : __LINE__,
4432 : "BAD\\BAD");
4433 0 : return false;
4434 : }
4435 : /*
4436 : * Trying to open "BAD\\BAD\\BAD" should get
4437 : * NT_STATUS_OBJECT_NAME_NOT_FOUND.
4438 : */
4439 2 : status = get_smb2_inode(cli,
4440 : "BAD\\BAD\\BAD",
4441 : &test_ino);
4442 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4443 0 : printf("%s:%d Open of %s should get "
4444 : "STATUS_OBJECT_NAME_NOT_FOUND, got %s\n",
4445 : __FILE__,
4446 : __LINE__,
4447 : "BAD\\BAD\\BAD",
4448 : nt_errstr(status));
4449 0 : return false;
4450 : }
4451 : /*
4452 : * Trying to open "BAD\\BAD\\BAD\\BAD" should get
4453 : * NT_STATUS_OBJECT_PATH_NOT_FOUND.
4454 : */
4455 2 : status = get_smb2_inode(cli,
4456 : "BAD\\BAD\\BAD\\BAD",
4457 : &test_ino);
4458 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4459 0 : printf("%s:%d Open of %s should get "
4460 : "STATUS_OBJECT_NAME_NOT_FOUND, got %s\n",
4461 : __FILE__,
4462 : __LINE__,
4463 : "BAD\\BAD\\BAD\\BAD",
4464 : nt_errstr(status));
4465 0 : return false;
4466 : }
4467 : /*
4468 : * Test for invalid pathname characters in the servername.
4469 : * They are ignored, and it still opens the share root.
4470 : */
4471 2 : ino_matched = smb2_inode_matches(cli,
4472 : dfs_root_share_name,
4473 : root_ino,
4474 : "::::");
4475 2 : if (!ino_matched) {
4476 0 : printf("%s:%d Failed to match ino number for %s\n",
4477 : __FILE__,
4478 : __LINE__,
4479 : "::::");
4480 0 : return false;
4481 : }
4482 :
4483 : /*
4484 : * Test for invalid pathname characters in the sharename.
4485 : * Invalid sharename characters should still be flagged as
4486 : * NT_STATUS_OBJECT_NAME_INVALID. It turns out only ':'
4487 : * is considered an invalid sharename character.
4488 : */
4489 2 : ok = test_smb2_dfs_sharenames(cli,
4490 : dfs_root_share_name,
4491 : root_ino);
4492 2 : if (!ok) {
4493 0 : return false;
4494 : }
4495 :
4496 : /* Now create a file called "file". */
4497 2 : status = smb2cli_create(cli->conn,
4498 2 : cli->timeout,
4499 2 : cli->smb2.session,
4500 2 : cli->smb2.tcon,
4501 : "BAD\\BAD\\file",
4502 : SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4503 : SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4504 : SEC_STD_SYNCHRONIZE|
4505 : SEC_STD_DELETE |
4506 : SEC_FILE_READ_DATA|
4507 : SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4508 : FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4509 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4510 : FILE_CREATE, /* create_disposition, */
4511 : 0, /* create_options, */
4512 : NULL, /* smb2_create_blobs *blobs */
4513 : &fid_persistent,
4514 : &fid_volatile,
4515 : NULL, /* struct smb_create_returns * */
4516 : talloc_tos(), /* mem_ctx. */
4517 : NULL, /* struct smb2_create_blobs * */
4518 : NULL); /* struct symlink_reparse_struct */
4519 2 : if (!NT_STATUS_IS_OK(status)) {
4520 0 : printf("%s:%d smb2cli_create on %s returned %s\n",
4521 : __FILE__,
4522 : __LINE__,
4523 : "BAD\\BAD\\file",
4524 : nt_errstr(status));
4525 0 : return false;
4526 : }
4527 :
4528 : /*
4529 : * Trying to open "BAD\\BAD\\file" should now get
4530 : * a valid inode.
4531 : */
4532 2 : status = get_smb2_inode(cli,
4533 : "BAD\\BAD\\file",
4534 : &test_ino);
4535 2 : if (!NT_STATUS_IS_OK(status)) {
4536 0 : printf("%s:%d Open of %s should succeed "
4537 : "got %s\n",
4538 : __FILE__,
4539 : __LINE__,
4540 : "BAD\\BAD\\file",
4541 : nt_errstr(status));
4542 0 : goto err;
4543 : }
4544 :
4545 : /*
4546 : * Now show that renames use relative,
4547 : * not full DFS paths.
4548 : */
4549 :
4550 : /* Full DFS path should fail. */
4551 2 : status = smb2_dfs_rename(cli,
4552 : fid_persistent,
4553 : fid_volatile,
4554 : "ANY\\NAME\\renamed_file");
4555 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4556 0 : printf("%s:%d Rename of %s -> %s should fail "
4557 : "with NT_STATUS_OBJECT_PATH_NOT_FOUND. Got %s\n",
4558 : __FILE__,
4559 : __LINE__,
4560 : "BAD\\BAD\\file",
4561 : "ANY\\NAME\\renamed_file",
4562 : nt_errstr(status));
4563 0 : goto err;
4564 : }
4565 : /* Relative DFS path should succeed. */
4566 2 : status = smb2_dfs_rename(cli,
4567 : fid_persistent,
4568 : fid_volatile,
4569 : "renamed_file");
4570 2 : if (!NT_STATUS_IS_OK(status)) {
4571 0 : printf("%s:%d: Rename of %s -> %s should succeed. "
4572 : "Got %s\n",
4573 : __FILE__,
4574 : __LINE__,
4575 : "BAD\\BAD\\file",
4576 : "renamed_file",
4577 : nt_errstr(status));
4578 0 : goto err;
4579 : }
4580 :
4581 : /*
4582 : * Trying to open "BAD\\BAD\\renamed_file" should now get
4583 : * a valid inode.
4584 : */
4585 2 : status = get_smb2_inode(cli,
4586 : "BAD\\BAD\\renamed_file",
4587 : &test_ino);
4588 2 : if (!NT_STATUS_IS_OK(status)) {
4589 0 : printf("%s:%d: Open of %s should succeed "
4590 : "got %s\n",
4591 : __FILE__,
4592 : __LINE__,
4593 : "BAD\\BAD\\renamed_file",
4594 : nt_errstr(status));
4595 0 : goto err;
4596 : }
4597 :
4598 : /*
4599 : * Now show that hard links use relative,
4600 : * not full DFS paths.
4601 : */
4602 :
4603 : /* Full DFS path should fail. */
4604 2 : status = smb2_dfs_hlink(cli,
4605 : fid_persistent,
4606 : fid_volatile,
4607 : "ANY\\NAME\\hlink");
4608 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4609 0 : printf("%s:%d Hlink of %s -> %s should fail "
4610 : "with NT_STATUS_OBJECT_PATH_NOT_FOUND. Got %s\n",
4611 : __FILE__,
4612 : __LINE__,
4613 : "ANY\\NAME\\renamed_file",
4614 : "ANY\\NAME\\hlink",
4615 : nt_errstr(status));
4616 0 : goto err;
4617 : }
4618 : /* Relative DFS path should succeed. */
4619 2 : status = smb2_dfs_hlink(cli,
4620 : fid_persistent,
4621 : fid_volatile,
4622 : "hlink");
4623 2 : if (!NT_STATUS_IS_OK(status)) {
4624 0 : printf("%s:%d: Hlink of %s -> %s should succeed. "
4625 : "Got %s\n",
4626 : __FILE__,
4627 : __LINE__,
4628 : "ANY\\NAME\\renamed_file",
4629 : "hlink",
4630 : nt_errstr(status));
4631 0 : goto err;
4632 : }
4633 :
4634 : /*
4635 : * Trying to open "BAD\\BAD\\hlink" should now get
4636 : * a valid inode.
4637 : */
4638 2 : status = get_smb2_inode(cli,
4639 : "BAD\\BAD\\hlink",
4640 : &test_ino);
4641 2 : if (!NT_STATUS_IS_OK(status)) {
4642 0 : printf("%s:%d Open of %s should succeed "
4643 : "got %s\n",
4644 : __FILE__,
4645 : __LINE__,
4646 : "BAD\\BAD\\hlink",
4647 : nt_errstr(status));
4648 0 : goto err;
4649 : }
4650 :
4651 2 : retval = true;
4652 :
4653 2 : err:
4654 :
4655 2 : if (fid_persistent != 0 || fid_volatile != 0) {
4656 2 : smb2cli_close(cli->conn,
4657 2 : cli->timeout,
4658 2 : cli->smb2.session,
4659 2 : cli->smb2.tcon,
4660 : 0, /* flags */
4661 : fid_persistent,
4662 : fid_volatile);
4663 : }
4664 : /* Delete anything we made. */
4665 2 : (void)smb2_dfs_delete(cli, "BAD\\BAD\\BAD");
4666 2 : (void)smb2_dfs_delete(cli, "BAD\\BAD\\file");
4667 2 : (void)smb2_dfs_delete(cli, "BAD\\BAD\\renamed_file");
4668 2 : (void)smb2_dfs_delete(cli, "BAD\\BAD\\hlink");
4669 2 : return retval;
4670 : }
4671 :
4672 : /*
4673 : * Add a test that sends DFS paths and sets the
4674 : * SMB2 flag FLAGS2_DFS_PATHNAMES, but to a non-DFS
4675 : * share. Windows passes this (it just treats the
4676 : * pathnames as non-DFS and ignores the FLAGS2_DFS_PATHNAMES
4677 : * bit).
4678 : */
4679 :
4680 2 : bool run_smb2_non_dfs_share(int dummy)
4681 : {
4682 2 : struct cli_state *cli = NULL;
4683 0 : NTSTATUS status;
4684 2 : bool dfs_supported = false;
4685 2 : uint64_t fid_persistent = 0;
4686 2 : uint64_t fid_volatile = 0;
4687 2 : bool retval = false;
4688 2 : char *dfs_filename = NULL;
4689 :
4690 2 : printf("Starting SMB2-DFS-NON-DFS-SHARE\n");
4691 :
4692 2 : if (!torture_init_connection(&cli)) {
4693 0 : return false;
4694 : }
4695 :
4696 2 : status = smbXcli_negprot(cli->conn,
4697 2 : cli->timeout,
4698 : PROTOCOL_SMB2_02,
4699 : PROTOCOL_SMB3_11,
4700 : NULL,
4701 : NULL,
4702 : NULL);
4703 2 : if (!NT_STATUS_IS_OK(status)) {
4704 0 : printf("smbXcli_negprot returned %s\n", nt_errstr(status));
4705 0 : return false;
4706 : }
4707 :
4708 2 : status = cli_session_setup_creds(cli, torture_creds);
4709 2 : if (!NT_STATUS_IS_OK(status)) {
4710 0 : printf("cli_session_setup returned %s\n", nt_errstr(status));
4711 0 : return false;
4712 : }
4713 :
4714 2 : status = cli_tree_connect(cli, share, "?????", NULL);
4715 2 : if (!NT_STATUS_IS_OK(status)) {
4716 0 : printf("cli_tree_connect returned %s\n", nt_errstr(status));
4717 0 : return false;
4718 : }
4719 :
4720 2 : dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
4721 2 : if (!dfs_supported) {
4722 0 : printf("Server %s does not support DFS\n",
4723 0 : smbXcli_conn_remote_name(cli->conn));
4724 0 : return false;
4725 : }
4726 : /* Ensure this is *NOT* a DFS share. */
4727 2 : dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb2.tcon);
4728 2 : if (dfs_supported) {
4729 0 : printf("Share %s is a DFS share.\n",
4730 0 : cli->share);
4731 0 : return false;
4732 : }
4733 : /*
4734 : * Force the share to be DFS, as far as the client
4735 : * is concerned.
4736 : */
4737 6 : smb2cli_tcon_set_values(cli->smb2.tcon,
4738 2 : cli->smb2.session,
4739 2 : smb2cli_tcon_current_id(cli->smb2.tcon),
4740 : 0,
4741 2 : smb2cli_tcon_flags(cli->smb2.tcon),
4742 2 : smb2cli_tcon_capabilities(cli->smb2.tcon) |
4743 : SMB2_SHARE_CAP_DFS,
4744 : 0);
4745 :
4746 : /* Come up with a "valid" SMB2 DFS name. */
4747 2 : dfs_filename = talloc_asprintf(talloc_tos(),
4748 : "%s\\%s\\file",
4749 2 : smbXcli_conn_remote_name(cli->conn),
4750 2 : cli->share);
4751 2 : if (dfs_filename == NULL) {
4752 0 : printf("Out of memory\n");
4753 0 : return false;
4754 : }
4755 :
4756 : /* Now try create dfs_filename. */
4757 2 : status = smb2cli_create(cli->conn,
4758 2 : cli->timeout,
4759 2 : cli->smb2.session,
4760 2 : cli->smb2.tcon,
4761 : dfs_filename,
4762 : SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4763 : SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4764 : SEC_STD_SYNCHRONIZE|
4765 : SEC_STD_DELETE |
4766 : SEC_FILE_READ_DATA|
4767 : SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4768 : FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4769 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4770 : FILE_CREATE, /* create_disposition, */
4771 : 0, /* create_options, */
4772 : NULL, /* smb2_create_blobs *blobs */
4773 : &fid_persistent,
4774 : &fid_volatile,
4775 : NULL, /* struct smb_create_returns * */
4776 : talloc_tos(), /* mem_ctx. */
4777 : NULL, /* struct smb2_create_blobs */
4778 : NULL); /* struct symlink_reparse_struct */
4779 : /*
4780 : * Should fail with NT_STATUS_OBJECT_PATH_NOT_FOUND, as
4781 : * even though we set the FLAGS2_DFS_PATHNAMES the server
4782 : * knows this isn't a DFS share and so treats BAD\\BAD as
4783 : * part of the filename.
4784 : */
4785 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4786 0 : printf("%s:%d create of %s should fail "
4787 : "with NT_STATUS_OBJECT_PATH_NOT_FOUND. Got %s\n",
4788 : __FILE__,
4789 : __LINE__,
4790 : dfs_filename,
4791 : nt_errstr(status));
4792 0 : goto err;
4793 : }
4794 : /*
4795 : * Prove we can still use non-DFS pathnames, even though
4796 : * we are setting the FLAGS2_DFS_PATHNAMES in the SMB2
4797 : * request.
4798 : */
4799 2 : status = smb2cli_create(cli->conn,
4800 2 : cli->timeout,
4801 2 : cli->smb2.session,
4802 2 : cli->smb2.tcon,
4803 : "file",
4804 : SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4805 : SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4806 : SEC_STD_SYNCHRONIZE|
4807 : SEC_STD_DELETE |
4808 : SEC_FILE_READ_DATA|
4809 : SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4810 : FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4811 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4812 : FILE_CREATE, /* create_disposition, */
4813 : 0, /* create_options, */
4814 : NULL, /* smb2_create_blobs *blobs */
4815 : &fid_persistent,
4816 : &fid_volatile,
4817 : NULL, /* struct smb_create_returns * */
4818 : talloc_tos(), /* mem_ctx. */
4819 : NULL, /* struct smb2_create_blobs * */
4820 : NULL); /* struct symlink_reparse_struct */
4821 2 : if (!NT_STATUS_IS_OK(status)) {
4822 0 : printf("%s:%d smb2cli_create on %s returned %s\n",
4823 : __FILE__,
4824 : __LINE__,
4825 : "file",
4826 : nt_errstr(status));
4827 0 : return false;
4828 : }
4829 :
4830 2 : retval = true;
4831 :
4832 2 : err:
4833 :
4834 2 : (void)smb2_dfs_delete(cli, dfs_filename);
4835 2 : (void)smb2_dfs_delete(cli, "file");
4836 2 : return retval;
4837 : }
4838 :
4839 : /*
4840 : * Add a test that sends a non-DFS path and does not set the
4841 : * SMB2 flag FLAGS2_DFS_PATHNAMES to a DFS
4842 : * share. Windows passes this (it just treats the
4843 : * pathnames as non-DFS).
4844 : */
4845 :
4846 2 : bool run_smb2_dfs_share_non_dfs_path(int dummy)
4847 : {
4848 2 : struct cli_state *cli = NULL;
4849 0 : NTSTATUS status;
4850 2 : bool dfs_supported = false;
4851 2 : uint64_t fid_persistent = 0;
4852 2 : uint64_t fid_volatile = 0;
4853 2 : bool retval = false;
4854 2 : char *dfs_filename = NULL;
4855 2 : uint64_t root_ino = (uint64_t)-1;
4856 2 : bool ino_matched = false;
4857 :
4858 2 : printf("Starting SMB2-DFS-SHARE-NON-DFS-PATH\n");
4859 :
4860 2 : if (!torture_init_connection(&cli)) {
4861 0 : return false;
4862 : }
4863 :
4864 2 : status = smbXcli_negprot(cli->conn,
4865 2 : cli->timeout,
4866 : PROTOCOL_SMB2_02,
4867 : PROTOCOL_SMB3_11,
4868 : NULL,
4869 : NULL,
4870 : NULL);
4871 2 : if (!NT_STATUS_IS_OK(status)) {
4872 0 : printf("smbXcli_negprot returned %s\n", nt_errstr(status));
4873 0 : return false;
4874 : }
4875 :
4876 2 : status = cli_session_setup_creds(cli, torture_creds);
4877 2 : if (!NT_STATUS_IS_OK(status)) {
4878 0 : printf("cli_session_setup returned %s\n", nt_errstr(status));
4879 0 : return false;
4880 : }
4881 :
4882 2 : status = cli_tree_connect(cli, share, "?????", NULL);
4883 2 : if (!NT_STATUS_IS_OK(status)) {
4884 0 : printf("cli_tree_connect returned %s\n", nt_errstr(status));
4885 0 : return false;
4886 : }
4887 :
4888 2 : dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
4889 2 : if (!dfs_supported) {
4890 0 : printf("Server %s does not support DFS\n",
4891 0 : smbXcli_conn_remote_name(cli->conn));
4892 0 : return false;
4893 : }
4894 : /* Ensure this is a DFS share. */
4895 2 : dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb2.tcon);
4896 2 : if (!dfs_supported) {
4897 0 : printf("Share %s is not a DFS share.\n",
4898 0 : cli->share);
4899 0 : return false;
4900 : }
4901 : /* Come up with a "valid" SMB2 DFS name. */
4902 2 : dfs_filename = talloc_asprintf(talloc_tos(),
4903 : "%s\\%s\\file",
4904 2 : smbXcli_conn_remote_name(cli->conn),
4905 2 : cli->share);
4906 2 : if (dfs_filename == NULL) {
4907 0 : printf("Out of memory\n");
4908 0 : return false;
4909 : }
4910 :
4911 : /* Get the root of the share ino. */
4912 2 : status = get_smb2_inode(cli,
4913 : "SERVER\\SHARE",
4914 : &root_ino);
4915 2 : if (!NT_STATUS_IS_OK(status)) {
4916 0 : printf("%s:%d get_smb2_inode on %s returned %s\n",
4917 : __FILE__,
4918 : __LINE__,
4919 : "SERVER\\SHARE",
4920 : nt_errstr(status));
4921 0 : goto err;
4922 : }
4923 :
4924 : /* Create a dfs_filename. */
4925 2 : status = smb2cli_create(cli->conn,
4926 2 : cli->timeout,
4927 2 : cli->smb2.session,
4928 2 : cli->smb2.tcon,
4929 : dfs_filename,
4930 : SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4931 : SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4932 : SEC_STD_SYNCHRONIZE|
4933 : SEC_STD_DELETE |
4934 : SEC_FILE_READ_DATA|
4935 : SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4936 : FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4937 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4938 : FILE_CREATE, /* create_disposition, */
4939 : 0, /* create_options, */
4940 : NULL, /* smb2_create_blobs *blobs */
4941 : &fid_persistent,
4942 : &fid_volatile,
4943 : NULL, /* struct smb_create_returns * */
4944 : talloc_tos(), /* mem_ctx. */
4945 : NULL, /* struct smb2_create_blobs * */
4946 : NULL); /* psymlink */
4947 2 : if (!NT_STATUS_IS_OK(status)) {
4948 0 : printf("%s:%d smb2cli_create on %s returned %s\n",
4949 : __FILE__,
4950 : __LINE__,
4951 : dfs_filename,
4952 : nt_errstr(status));
4953 0 : goto err;
4954 : }
4955 :
4956 : /* Close the handle we just opened. */
4957 2 : smb2cli_close(cli->conn,
4958 2 : cli->timeout,
4959 2 : cli->smb2.session,
4960 2 : cli->smb2.tcon,
4961 : 0, /* flags */
4962 : fid_persistent,
4963 : fid_volatile);
4964 :
4965 2 : fid_persistent = 0;
4966 2 : fid_volatile = 0;
4967 :
4968 : /*
4969 : * Force the share to be non-DFS, as far as the client
4970 : * is concerned.
4971 : */
4972 6 : smb2cli_tcon_set_values(cli->smb2.tcon,
4973 2 : cli->smb2.session,
4974 2 : smb2cli_tcon_current_id(cli->smb2.tcon),
4975 : 0,
4976 2 : smb2cli_tcon_flags(cli->smb2.tcon),
4977 2 : smb2cli_tcon_capabilities(cli->smb2.tcon) &
4978 : ~SMB2_SHARE_CAP_DFS,
4979 : 0);
4980 :
4981 : /*
4982 : * Prove we can still use non-DFS pathnames on a DFS
4983 : * share so long as we don't set the FLAGS2_DFS_PATHNAMES
4984 : * in the SMB2 request.
4985 : */
4986 2 : status = smb2cli_create(cli->conn,
4987 2 : cli->timeout,
4988 2 : cli->smb2.session,
4989 2 : cli->smb2.tcon,
4990 : "file",
4991 : SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
4992 : SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
4993 : SEC_STD_SYNCHRONIZE|
4994 : SEC_STD_DELETE |
4995 : SEC_FILE_READ_DATA|
4996 : SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
4997 : FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
4998 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
4999 : FILE_OPEN, /* create_disposition, */
5000 : 0, /* create_options, */
5001 : NULL, /* smb2_create_blobs *blobs */
5002 : &fid_persistent,
5003 : &fid_volatile,
5004 : NULL, /* struct smb_create_returns * */
5005 : talloc_tos(), /* mem_ctx. */
5006 : NULL, /* struct smb2_create_blobs * */
5007 : NULL); /* psymlink */
5008 2 : if (!NT_STATUS_IS_OK(status)) {
5009 0 : printf("%s:%d smb2cli_create on %s returned %s\n",
5010 : __FILE__,
5011 : __LINE__,
5012 : "file",
5013 : nt_errstr(status));
5014 0 : goto err;
5015 : }
5016 :
5017 : /*
5018 : * Show that now we're using non-DFS pathnames
5019 : * on a DFS share, "" opens the root of the share.
5020 : */
5021 2 : ino_matched = smb2_inode_matches(cli,
5022 : "SERVER\\SHARE",
5023 : root_ino,
5024 : "");
5025 2 : if (!ino_matched) {
5026 0 : printf("%s:%d Failed to match ino number for %s\n",
5027 : __FILE__,
5028 : __LINE__,
5029 : "");
5030 0 : goto err;
5031 : }
5032 :
5033 2 : retval = true;
5034 :
5035 2 : err:
5036 :
5037 2 : if (fid_volatile != 0) {
5038 2 : smb2cli_close(cli->conn,
5039 2 : cli->timeout,
5040 2 : cli->smb2.session,
5041 2 : cli->smb2.tcon,
5042 : 0, /* flags */
5043 : fid_persistent,
5044 : fid_volatile);
5045 : }
5046 2 : (void)smb2_dfs_delete(cli, "file");
5047 2 : (void)smb2_dfs_delete(cli, dfs_filename);
5048 2 : return retval;
5049 : }
5050 :
5051 : /*
5052 : * "Raw" test of an SMB2 filename with one or more leading
5053 : * backslash characters to a DFS share.
5054 : *
5055 : * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15277
5056 : *
5057 : * Once the server passes SMB2-DFS-PATHS we can
5058 : * fold this test into that one.
5059 : *
5060 : * Passes cleanly against Windows.
5061 : */
5062 :
5063 2 : bool run_smb2_dfs_filename_leading_backslash(int dummy)
5064 : {
5065 2 : struct cli_state *cli = NULL;
5066 0 : NTSTATUS status;
5067 2 : bool dfs_supported = false;
5068 2 : char *dfs_filename_slash = NULL;
5069 2 : char *dfs_filename_slash_multi = NULL;
5070 2 : uint64_t file_ino = 0;
5071 2 : bool ino_matched = false;
5072 2 : uint64_t fid_persistent = 0;
5073 2 : uint64_t fid_volatile = 0;
5074 2 : bool retval = false;
5075 :
5076 2 : printf("Starting SMB2-DFS-FILENAME-LEADING-BACKSLASH\n");
5077 :
5078 2 : if (!torture_init_connection(&cli)) {
5079 0 : return false;
5080 : }
5081 :
5082 2 : status = smbXcli_negprot(cli->conn,
5083 2 : cli->timeout,
5084 : PROTOCOL_SMB2_02,
5085 : PROTOCOL_SMB3_11,
5086 : NULL,
5087 : NULL,
5088 : NULL);
5089 2 : if (!NT_STATUS_IS_OK(status)) {
5090 0 : printf("smbXcli_negprot returned %s\n", nt_errstr(status));
5091 0 : return false;
5092 : }
5093 :
5094 2 : status = cli_session_setup_creds(cli, torture_creds);
5095 2 : if (!NT_STATUS_IS_OK(status)) {
5096 0 : printf("cli_session_setup returned %s\n", nt_errstr(status));
5097 0 : return false;
5098 : }
5099 :
5100 2 : status = cli_tree_connect(cli, share, "?????", NULL);
5101 2 : if (!NT_STATUS_IS_OK(status)) {
5102 0 : printf("cli_tree_connect returned %s\n", nt_errstr(status));
5103 0 : return false;
5104 : }
5105 :
5106 : /* Ensure this is a DFS share. */
5107 2 : dfs_supported = smbXcli_conn_dfs_supported(cli->conn);
5108 2 : if (!dfs_supported) {
5109 0 : printf("Server %s does not support DFS\n",
5110 0 : smbXcli_conn_remote_name(cli->conn));
5111 0 : return false;
5112 : }
5113 2 : dfs_supported = smbXcli_tcon_is_dfs_share(cli->smb2.tcon);
5114 2 : if (!dfs_supported) {
5115 0 : printf("Share %s does not support DFS\n",
5116 0 : cli->share);
5117 0 : return false;
5118 : }
5119 :
5120 : /*
5121 : * Create the filename with one leading backslash.
5122 : */
5123 2 : dfs_filename_slash = talloc_asprintf(talloc_tos(),
5124 : "\\%s\\%s\\file",
5125 2 : smbXcli_conn_remote_name(cli->conn),
5126 2 : cli->share);
5127 2 : if (dfs_filename_slash == NULL) {
5128 0 : printf("Out of memory\n");
5129 0 : return false;
5130 : }
5131 :
5132 : /*
5133 : * Create the filename with many leading backslashes.
5134 : */
5135 2 : dfs_filename_slash_multi = talloc_asprintf(talloc_tos(),
5136 : "\\\\\\\\%s\\%s\\file",
5137 2 : smbXcli_conn_remote_name(cli->conn),
5138 2 : cli->share);
5139 2 : if (dfs_filename_slash_multi == NULL) {
5140 0 : printf("Out of memory\n");
5141 0 : return false;
5142 : }
5143 :
5144 : /*
5145 : * Trying to open "\\server\\share\\file" should get
5146 : * NT_STATUS_OBJECT_NAME_NOT_FOUND.
5147 : */
5148 2 : status = get_smb2_inode(cli,
5149 : dfs_filename_slash,
5150 : &file_ino);
5151 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5152 0 : printf("%s:%d Open of %s should get "
5153 : "STATUS_OBJECT_NAME_NOT_FOUND, got %s\n",
5154 : __FILE__,
5155 : __LINE__,
5156 : dfs_filename_slash,
5157 : nt_errstr(status));
5158 0 : return false;
5159 : }
5160 :
5161 : /* Now create a file called "\\server\\share\\file". */
5162 2 : status = smb2cli_create(cli->conn,
5163 2 : cli->timeout,
5164 2 : cli->smb2.session,
5165 2 : cli->smb2.tcon,
5166 : dfs_filename_slash,
5167 : SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
5168 : SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
5169 : SEC_STD_SYNCHRONIZE|
5170 : SEC_STD_DELETE |
5171 : SEC_FILE_READ_DATA|
5172 : SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
5173 : FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
5174 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
5175 : FILE_CREATE, /* create_disposition, */
5176 : 0, /* create_options, */
5177 : NULL, /* smb2_create_blobs *blobs */
5178 : &fid_persistent,
5179 : &fid_volatile,
5180 : NULL, /* struct smb_create_returns * */
5181 : talloc_tos(), /* mem_ctx. */
5182 : NULL, /* struct smb2_create_blobs * */
5183 : NULL); /* struct symlink_reparse_struct */
5184 2 : if (!NT_STATUS_IS_OK(status)) {
5185 0 : printf("%s:%d smb2cli_create on %s returned %s\n",
5186 : __FILE__,
5187 : __LINE__,
5188 : dfs_filename_slash,
5189 : nt_errstr(status));
5190 0 : return false;
5191 : }
5192 :
5193 : /*
5194 : * Trying to open "\\server\\share\\file" should now get
5195 : * a valid inode.
5196 : */
5197 2 : status = get_smb2_inode(cli,
5198 : dfs_filename_slash,
5199 : &file_ino);
5200 2 : if (!NT_STATUS_IS_OK(status)) {
5201 0 : printf("%s:%d Open of %s should succeed "
5202 : "got %s\n",
5203 : __FILE__,
5204 : __LINE__,
5205 : dfs_filename_slash,
5206 : nt_errstr(status));
5207 0 : goto err;
5208 : }
5209 :
5210 : /*
5211 : * Trying to open "\\\\\\server\\share\\file" should now get
5212 : * a valid inode that matches. MacOSX-style of DFS name test.
5213 : */
5214 2 : ino_matched = smb2_inode_matches(cli,
5215 : dfs_filename_slash,
5216 : file_ino,
5217 : dfs_filename_slash_multi);
5218 2 : if (!ino_matched) {
5219 0 : printf("%s:%d Failed to match ino number for %s\n",
5220 : __FILE__,
5221 : __LINE__,
5222 : dfs_filename_slash_multi);
5223 0 : goto err;
5224 : }
5225 :
5226 2 : retval = true;
5227 :
5228 2 : err:
5229 :
5230 2 : if (fid_persistent != 0 || fid_volatile != 0) {
5231 2 : smb2cli_close(cli->conn,
5232 2 : cli->timeout,
5233 2 : cli->smb2.session,
5234 2 : cli->smb2.tcon,
5235 : 0, /* flags */
5236 : fid_persistent,
5237 : fid_volatile);
5238 : }
5239 : /* Delete anything we made. */
5240 2 : (void)smb2_dfs_delete(cli, dfs_filename_slash);
5241 2 : return retval;
5242 : }
5243 :
5244 : /*
5245 : * Ensure a named pipe async read followed by a disconnect
5246 : * doesn't crash the server (server crash checked for in
5247 : * containing test script:
5248 : * source3/script/tests/test_smbtorture_nocrash_s3.sh)
5249 : * BUG: https://bugzilla.samba.org/show_bug.cgi?id=15423
5250 : */
5251 :
5252 2 : bool run_smb2_pipe_read_async_disconnect(int dummy)
5253 : {
5254 2 : struct cli_state *cli = NULL;
5255 0 : NTSTATUS status;
5256 2 : uint64_t fid_persistent = 0;
5257 2 : uint64_t fid_volatile = 0;
5258 0 : struct tevent_context *ev;
5259 0 : struct tevent_req *req;
5260 2 : bool retval = false;
5261 :
5262 2 : printf("Starting SMB2-PIPE-READ-ASYNC-DISCONNECT\n");
5263 :
5264 2 : if (!torture_init_connection(&cli)) {
5265 0 : return false;
5266 : }
5267 :
5268 2 : status = smbXcli_negprot(cli->conn,
5269 2 : cli->timeout,
5270 : PROTOCOL_SMB2_02,
5271 : PROTOCOL_SMB3_11,
5272 : NULL,
5273 : NULL,
5274 : NULL);
5275 2 : if (!NT_STATUS_IS_OK(status)) {
5276 0 : printf("smbXcli_negprot returned %s\n", nt_errstr(status));
5277 0 : return false;
5278 : }
5279 :
5280 2 : status = cli_session_setup_creds(cli, torture_creds);
5281 2 : if (!NT_STATUS_IS_OK(status)) {
5282 0 : printf("cli_session_setup returned %s\n", nt_errstr(status));
5283 0 : return false;
5284 : }
5285 :
5286 2 : status = cli_tree_connect_creds(cli, "IPC$", "IPC", torture_creds);
5287 2 : if (!NT_STATUS_IS_OK(status)) {
5288 0 : printf("cli_tree_connect to IPC$ returned %s\n",
5289 : nt_errstr(status));
5290 0 : return false;
5291 : }
5292 :
5293 : /* Open the SAMR pipe. */
5294 2 : status = smb2cli_create(cli->conn,
5295 2 : cli->timeout,
5296 2 : cli->smb2.session,
5297 2 : cli->smb2.tcon,
5298 : "SAMR",
5299 : SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
5300 : SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
5301 : SEC_STD_SYNCHRONIZE|
5302 : SEC_FILE_READ_DATA|
5303 : SEC_FILE_WRITE_DATA, /* desired_access, */
5304 : FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
5305 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
5306 : FILE_OPEN, /* create_disposition, */
5307 : 0, /* create_options, */
5308 : NULL, /* smb2_create_blobs *blobs */
5309 : &fid_persistent,
5310 : &fid_volatile,
5311 : NULL, /* struct smb_create_returns * */
5312 : talloc_tos(), /* mem_ctx. */
5313 : NULL, /* struct smb2_create_blobs * */
5314 : NULL); /* psymlink */
5315 2 : if (!NT_STATUS_IS_OK(status)) {
5316 0 : printf("%s:%d smb2cli_create on SAMR returned %s\n",
5317 : __FILE__,
5318 : __LINE__,
5319 : nt_errstr(status));
5320 0 : goto err;
5321 : }
5322 :
5323 2 : ev = samba_tevent_context_init(talloc_tos());
5324 2 : if (ev == NULL) {
5325 0 : goto err;
5326 : }
5327 :
5328 : /* Start an async read. */
5329 2 : req = smb2cli_read_send(talloc_tos(),
5330 : ev,
5331 2 : cli->conn,
5332 2 : cli->timeout,
5333 2 : cli->smb2.session,
5334 2 : cli->smb2.tcon,
5335 : 16*1024,
5336 : 0, /* offset */
5337 : fid_persistent,
5338 : fid_volatile,
5339 : 0, /* minimum_count */
5340 : 0); /* remaining_bytes */
5341 2 : if (req == NULL) {
5342 0 : goto err;
5343 : }
5344 :
5345 : /* Force disconnect. */
5346 2 : smbXcli_conn_disconnect(cli->conn, NT_STATUS_LOCAL_DISCONNECT);
5347 2 : fid_volatile = 0;
5348 2 : retval = true;
5349 :
5350 2 : err:
5351 :
5352 2 : if (fid_volatile != 0) {
5353 0 : smb2cli_close(cli->conn,
5354 0 : cli->timeout,
5355 0 : cli->smb2.session,
5356 0 : cli->smb2.tcon,
5357 : 0, /* flags */
5358 : fid_persistent,
5359 : fid_volatile);
5360 : }
5361 2 : return retval;
5362 : }
5363 :
5364 2 : bool run_smb2_invalid_pipename(int dummy)
5365 : {
5366 2 : struct cli_state *cli = NULL;
5367 0 : NTSTATUS status;
5368 2 : uint64_t fid_persistent = 0;
5369 2 : uint64_t fid_volatile = 0;
5370 2 : const char *unknown_pipe = "badpipe";
5371 2 : const char *invalid_pipe = "../../../../../../../../../badpipe";
5372 :
5373 2 : printf("Starting SMB2-INVALID-PIPENAME\n");
5374 :
5375 2 : if (!torture_init_connection(&cli)) {
5376 0 : return false;
5377 : }
5378 :
5379 2 : status = smbXcli_negprot(cli->conn,
5380 2 : cli->timeout,
5381 : PROTOCOL_SMB2_02,
5382 : PROTOCOL_SMB3_11,
5383 : NULL,
5384 : NULL,
5385 : NULL);
5386 2 : if (!NT_STATUS_IS_OK(status)) {
5387 0 : printf("smbXcli_negprot returned %s\n", nt_errstr(status));
5388 0 : return false;
5389 : }
5390 :
5391 2 : status = cli_session_setup_creds(cli, torture_creds);
5392 2 : if (!NT_STATUS_IS_OK(status)) {
5393 0 : printf("cli_session_setup returned %s\n", nt_errstr(status));
5394 0 : return false;
5395 : }
5396 :
5397 2 : status = cli_tree_connect(cli, "IPC$", "?????", NULL);
5398 2 : if (!NT_STATUS_IS_OK(status)) {
5399 0 : printf("cli_tree_connect returned %s\n", nt_errstr(status));
5400 0 : return false;
5401 : }
5402 :
5403 : /* Try and connect to an unknown pipename. */
5404 2 : status = smb2cli_create(cli->conn,
5405 2 : cli->timeout,
5406 2 : cli->smb2.session,
5407 2 : cli->smb2.tcon,
5408 : unknown_pipe,
5409 : SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
5410 : SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
5411 : SEC_STD_SYNCHRONIZE|
5412 : SEC_FILE_READ_DATA|
5413 : SEC_FILE_WRITE_DATA|
5414 : SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
5415 : FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
5416 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
5417 : FILE_CREATE, /* create_disposition, */
5418 : 0, /* create_options, */
5419 : NULL, /* smb2_create_blobs *blobs */
5420 : &fid_persistent,
5421 : &fid_volatile,
5422 : NULL, /* struct smb_create_returns * */
5423 : talloc_tos(), /* mem_ctx. */
5424 : NULL, /* struct smb2_create_blobs * */
5425 : NULL); /* struct symlink_reparse_struct */
5426 : /* We should get NT_STATUS_OBJECT_NAME_NOT_FOUND */
5427 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5428 0 : printf("%s:%d smb2cli_create on name %s returned %s\n",
5429 : __FILE__,
5430 : __LINE__,
5431 : unknown_pipe,
5432 : nt_errstr(status));
5433 0 : return false;
5434 : }
5435 :
5436 : /* Try and connect to an invalid pipename containing unix separators. */
5437 2 : status = smb2cli_create(cli->conn,
5438 2 : cli->timeout,
5439 2 : cli->smb2.session,
5440 2 : cli->smb2.tcon,
5441 : invalid_pipe,
5442 : SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
5443 : SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
5444 : SEC_STD_SYNCHRONIZE|
5445 : SEC_FILE_READ_DATA|
5446 : SEC_FILE_WRITE_DATA|
5447 : SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
5448 : FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
5449 : FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
5450 : FILE_CREATE, /* create_disposition, */
5451 : 0, /* create_options, */
5452 : NULL, /* smb2_create_blobs *blobs */
5453 : &fid_persistent,
5454 : &fid_volatile,
5455 : NULL, /* struct smb_create_returns * */
5456 : talloc_tos(), /* mem_ctx. */
5457 : NULL, /* struct smb2_create_blobs * */
5458 : NULL); /* struct symlink_reparse_struct */
5459 : /*
5460 : * We should still get NT_STATUS_OBJECT_NAME_NOT_FOUND
5461 : * (tested against Windows 2022).
5462 : */
5463 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5464 0 : printf("%s:%d smb2cli_create on name %s returned %s\n",
5465 : __FILE__,
5466 : __LINE__,
5467 : invalid_pipe,
5468 : nt_errstr(status));
5469 0 : return false;
5470 : }
5471 2 : return true;
5472 : }
|