2 Unix SMB/CIFS implementation.
4 Copyright (C) Volker Lendecke 2011
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "system/network.h"
22 #include "../lib/util/tevent_ntstatus.h"
23 #include "../libcli/smb/smb_common.h"
24 #include "../libcli/smb/smbXcli_base.h"
26 struct smb2cli_raw_tcon_state
{
27 struct smbXcli_session
*session
;
28 struct smbXcli_tcon
*tcon
;
33 static void smb2cli_raw_tcon_done(struct tevent_req
*subreq
);
35 struct tevent_req
*smb2cli_raw_tcon_send(TALLOC_CTX
*mem_ctx
,
36 struct tevent_context
*ev
,
37 struct smbXcli_conn
*conn
,
38 uint32_t additional_flags
,
40 uint32_t timeout_msec
,
41 struct smbXcli_session
*session
,
42 struct smbXcli_tcon
*tcon
,
46 struct tevent_req
*req
= NULL
;
47 struct smb2cli_raw_tcon_state
*state
= NULL
;
48 struct tevent_req
*subreq
= NULL
;
49 uint8_t *fixed
= NULL
;
53 req
= tevent_req_create(mem_ctx
, &state
,
54 struct smb2cli_raw_tcon_state
);
58 state
->session
= session
;
61 if (!convert_string_talloc(state
, CH_UNIX
, CH_UTF16
,
65 return tevent_req_post(req
, ev
);
68 if (strlen(unc
) == 0) {
75 if (smbXcli_conn_protocol(conn
) >= PROTOCOL_SMB3_11
) {
76 SSVAL(fixed
, 2, tcon_flags
);
78 SSVAL(fixed
, 2, 0); /* Reserved */
80 SSVAL(fixed
, 4, SMB2_HDR_BODY
+ 8);
81 SSVAL(fixed
, 6, dyn_len
);
85 dyn_len
= sizeof(state
->dyn_pad
);
88 subreq
= smb2cli_req_send(state
, ev
, conn
, SMB2_OP_TCON
,
89 additional_flags
, clear_flags
,
93 state
->fixed
, sizeof(state
->fixed
),
96 if (tevent_req_nomem(subreq
, req
)) {
97 return tevent_req_post(req
, ev
);
99 tevent_req_set_callback(subreq
, smb2cli_raw_tcon_done
, req
);
104 static void smb2cli_raw_tcon_done(struct tevent_req
*subreq
)
106 struct tevent_req
*req
= tevent_req_callback_data(
107 subreq
, struct tevent_req
);
108 struct smb2cli_raw_tcon_state
*state
= tevent_req_data(
109 req
, struct smb2cli_raw_tcon_state
);
115 uint32_t share_flags
;
116 uint32_t share_capabilities
;
117 uint32_t maximal_access
;
118 static const struct smb2cli_req_expected_response expected
[] = {
120 .status
= NT_STATUS_OK
,
125 status
= smb2cli_req_recv(subreq
, state
, &iov
,
126 expected
, ARRAY_SIZE(expected
));
128 if (!NT_STATUS_IS_OK(status
)) {
129 tevent_req_nterror(req
, status
);
133 tcon_id
= IVAL(iov
[0].iov_base
, SMB2_HDR_TID
);
135 body
= (uint8_t *)iov
[1].iov_base
;
136 share_type
= CVAL(body
, 0x02);
137 share_flags
= IVAL(body
, 0x04);
138 share_capabilities
= IVAL(body
, 0x08);
139 maximal_access
= IVAL(body
, 0x0C);
141 smb2cli_tcon_set_values(state
->tcon
,
149 tevent_req_done(req
);
152 NTSTATUS
smb2cli_raw_tcon_recv(struct tevent_req
*req
)
154 return tevent_req_simple_recv_ntstatus(req
);
157 NTSTATUS
smb2cli_raw_tcon(struct smbXcli_conn
*conn
,
158 uint32_t additional_flags
,
159 uint32_t clear_flags
,
160 uint32_t timeout_msec
,
161 struct smbXcli_session
*session
,
162 struct smbXcli_tcon
*tcon
,
166 TALLOC_CTX
*frame
= talloc_stackframe();
167 struct tevent_context
*ev
;
168 struct tevent_req
*req
;
169 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
171 if (smbXcli_conn_has_async_calls(conn
)) {
173 * Can't use sync call while an async call is in flight
175 status
= NT_STATUS_INVALID_PARAMETER
;
178 ev
= samba_tevent_context_init(frame
);
182 req
= smb2cli_raw_tcon_send(frame
, ev
, conn
,
183 additional_flags
, clear_flags
,
184 timeout_msec
, session
, tcon
,
189 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
192 status
= smb2cli_raw_tcon_recv(req
);
198 struct smb2cli_tcon_state
{
199 struct tevent_context
*ev
;
200 struct smbXcli_conn
*conn
;
201 uint32_t timeout_msec
;
202 struct smbXcli_session
*session
;
203 struct smbXcli_tcon
*tcon
;
208 static void smb2cli_tcon_done(struct tevent_req
*subreq
);
210 struct tevent_req
*smb2cli_tcon_send(TALLOC_CTX
*mem_ctx
,
211 struct tevent_context
*ev
,
212 struct smbXcli_conn
*conn
,
213 uint32_t timeout_msec
,
214 struct smbXcli_session
*session
,
215 struct smbXcli_tcon
*tcon
,
219 struct tevent_req
*req
, *subreq
;
220 struct smb2cli_tcon_state
*state
;
221 uint32_t additional_flags
= 0;
222 uint32_t clear_flags
= 0;
224 req
= tevent_req_create(mem_ctx
, &state
, struct smb2cli_tcon_state
);
230 state
->timeout_msec
= timeout_msec
;
231 state
->session
= session
;
234 if (smbXcli_session_is_authenticated(state
->session
)) {
235 additional_flags
|= SMB2_HDR_FLAG_SIGNED
;
238 subreq
= smb2cli_raw_tcon_send(state
,
248 if (tevent_req_nomem(subreq
, req
)) {
249 return tevent_req_post(req
, ev
);
251 tevent_req_set_callback(subreq
, smb2cli_tcon_done
, req
);
256 static void smb2cli_tcon_validate(struct tevent_req
*subreq
);
258 static void smb2cli_tcon_done(struct tevent_req
*subreq
)
260 struct tevent_req
*req
= tevent_req_callback_data(
261 subreq
, struct tevent_req
);
262 struct smb2cli_tcon_state
*state
= tevent_req_data(
263 req
, struct smb2cli_tcon_state
);
266 status
= smb2cli_raw_tcon_recv(subreq
);
268 if (tevent_req_nterror(req
, status
)) {
272 if (!smbXcli_session_is_authenticated(state
->session
)) {
273 tevent_req_done(req
);
277 if (smbXcli_conn_protocol(state
->conn
) >= PROTOCOL_SMB3_11
) {
278 tevent_req_done(req
);
282 subreq
= smb2cli_validate_negotiate_info_send(state
, state
->ev
,
287 if (tevent_req_nomem(subreq
, req
)) {
290 tevent_req_set_callback(subreq
, smb2cli_tcon_validate
, req
);
293 static void smb2cli_tcon_validate(struct tevent_req
*subreq
)
295 struct tevent_req
*req
= tevent_req_callback_data(
296 subreq
, struct tevent_req
);
297 struct smb2cli_tcon_state
*state
= tevent_req_data(
298 req
, struct smb2cli_tcon_state
);
301 status
= smb2cli_validate_negotiate_info_recv(subreq
);
303 if (!NT_STATUS_IS_OK(status
)) {
304 smb2cli_tcon_set_values(state
->tcon
, NULL
,
305 UINT32_MAX
, 0, 0, 0, 0);
306 tevent_req_nterror(req
, status
);
310 tevent_req_done(req
);
313 NTSTATUS
smb2cli_tcon_recv(struct tevent_req
*req
)
315 return tevent_req_simple_recv_ntstatus(req
);
318 NTSTATUS
smb2cli_tcon(struct smbXcli_conn
*conn
,
319 uint32_t timeout_msec
,
320 struct smbXcli_session
*session
,
321 struct smbXcli_tcon
*tcon
,
325 TALLOC_CTX
*frame
= talloc_stackframe();
326 struct tevent_context
*ev
;
327 struct tevent_req
*req
;
328 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
330 if (smbXcli_conn_has_async_calls(conn
)) {
332 * Can't use sync call while an async call is in flight
334 status
= NT_STATUS_INVALID_PARAMETER
;
337 ev
= samba_tevent_context_init(frame
);
341 req
= smb2cli_tcon_send(frame
, ev
, conn
,
342 timeout_msec
, session
, tcon
,
347 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
350 status
= smb2cli_tcon_recv(req
);
356 struct smb2cli_tdis_state
{
357 struct smbXcli_tcon
*tcon
;
361 static void smb2cli_tdis_done(struct tevent_req
*subreq
);
363 struct tevent_req
*smb2cli_tdis_send(TALLOC_CTX
*mem_ctx
,
364 struct tevent_context
*ev
,
365 struct smbXcli_conn
*conn
,
366 uint32_t timeout_msec
,
367 struct smbXcli_session
*session
,
368 struct smbXcli_tcon
*tcon
)
370 struct tevent_req
*req
, *subreq
;
371 struct smb2cli_tdis_state
*state
;
373 req
= tevent_req_create(mem_ctx
, &state
,
374 struct smb2cli_tdis_state
);
380 SSVAL(state
->fixed
, 0, 4);
382 subreq
= smb2cli_req_send(state
, ev
, conn
, SMB2_OP_TDIS
,
386 state
->fixed
, sizeof(state
->fixed
),
388 0); /* max_dyn_len */
389 if (tevent_req_nomem(subreq
, req
)) {
390 return tevent_req_post(req
, ev
);
392 tevent_req_set_callback(subreq
, smb2cli_tdis_done
, req
);
396 static void smb2cli_tdis_done(struct tevent_req
*subreq
)
398 struct tevent_req
*req
=
399 tevent_req_callback_data(subreq
,
401 struct smb2cli_tdis_state
*state
=
403 struct smb2cli_tdis_state
);
405 static const struct smb2cli_req_expected_response expected
[] = {
407 .status
= NT_STATUS_OK
,
412 status
= smb2cli_req_recv(subreq
, NULL
, NULL
,
413 expected
, ARRAY_SIZE(expected
));
415 if (tevent_req_nterror(req
, status
)) {
418 smb2cli_tcon_set_values(state
->tcon
, NULL
,
419 UINT32_MAX
, 0, 0, 0, 0);
420 tevent_req_done(req
);
423 NTSTATUS
smb2cli_tdis_recv(struct tevent_req
*req
)
425 return tevent_req_simple_recv_ntstatus(req
);
428 NTSTATUS
smb2cli_tdis(struct smbXcli_conn
*conn
,
429 uint32_t timeout_msec
,
430 struct smbXcli_session
*session
,
431 struct smbXcli_tcon
*tcon
)
433 TALLOC_CTX
*frame
= talloc_stackframe();
434 struct tevent_context
*ev
;
435 struct tevent_req
*req
;
436 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
438 if (smbXcli_conn_has_async_calls(conn
)) {
440 * Can't use sync call while an async call is in flight
442 status
= NT_STATUS_INVALID_PARAMETER
;
445 ev
= samba_tevent_context_init(frame
);
449 req
= smb2cli_tdis_send(frame
, ev
, conn
,
450 timeout_msec
, session
, tcon
);
454 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
457 status
= smb2cli_tdis_recv(req
);