Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : SMB client generic functions
4 : Copyright (C) Andrew Tridgell 1994-1998
5 : Copyright (C) Jeremy Allison 2007.
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "libsmb/libsmb.h"
23 : #include "../lib/util/tevent_ntstatus.h"
24 : #include "../libcli/smb/smb_signing.h"
25 : #include "../libcli/smb/smb_seal.h"
26 : #include "async_smb.h"
27 : #include "../libcli/smb/smbXcli_base.h"
28 : #include "../libcli/smb/smb2_negotiate_context.h"
29 : #include "../librpc/ndr/libndr.h"
30 : #include "../include/client.h"
31 :
32 : /****************************************************************************
33 : Change the timeout (in milliseconds).
34 : ****************************************************************************/
35 :
36 9933 : unsigned int cli_set_timeout(struct cli_state *cli, unsigned int timeout)
37 : {
38 9933 : unsigned int old_timeout = cli->timeout;
39 9933 : cli->timeout = timeout;
40 9933 : return old_timeout;
41 : }
42 :
43 : /****************************************************************************
44 : Set the 'backup_intent' flag.
45 : ****************************************************************************/
46 :
47 20 : bool cli_set_backup_intent(struct cli_state *cli, bool flag)
48 : {
49 20 : bool old_state = cli->backup_intent;
50 20 : cli->backup_intent = flag;
51 20 : return old_state;
52 : }
53 :
54 : /****************************************************************************
55 : Initialise a client structure. Always returns a talloc'ed struct.
56 : Set the signing state (used from the command line).
57 : ****************************************************************************/
58 :
59 : struct GUID cli_state_client_guid;
60 :
61 14964 : struct cli_state *cli_state_create(TALLOC_CTX *mem_ctx,
62 : int fd,
63 : const char *remote_name,
64 : int signing_state, int flags)
65 : {
66 14964 : struct cli_state *cli = NULL;
67 14964 : bool use_spnego = lp_client_use_spnego();
68 14964 : bool force_dos_errors = false;
69 14964 : bool force_ascii = false;
70 14964 : bool use_level_II_oplocks = false;
71 14964 : uint32_t smb1_capabilities = 0;
72 14964 : uint32_t smb2_capabilities = 0;
73 13947 : struct smb311_capabilities smb3_capabilities =
74 1017 : smb311_capabilities_parse("client",
75 14964 : lp_client_smb3_signing_algorithms(),
76 14964 : lp_client_smb3_encryption_algorithms());
77 : struct GUID client_guid;
78 :
79 14964 : if (!GUID_all_zero(&cli_state_client_guid)) {
80 0 : client_guid = cli_state_client_guid;
81 : } else {
82 14964 : client_guid = GUID_random();
83 : }
84 :
85 : /* Check the effective uid - make sure we are not setuid */
86 14964 : if (is_setuid_root()) {
87 0 : DEBUG(0,("libsmb based programs must *NOT* be setuid root.\n"));
88 0 : return NULL;
89 : }
90 :
91 14964 : cli = talloc_zero(mem_ctx, struct cli_state);
92 14964 : if (!cli) {
93 0 : return NULL;
94 : }
95 :
96 14964 : cli->server_domain = talloc_strdup(cli, "");
97 14964 : if (!cli->server_domain) {
98 0 : goto error;
99 : }
100 14964 : cli->server_os = talloc_strdup(cli, "");
101 14964 : if (!cli->server_os) {
102 0 : goto error;
103 : }
104 14964 : cli->server_type = talloc_strdup(cli, "");
105 14964 : if (!cli->server_type) {
106 0 : goto error;
107 : }
108 :
109 14964 : cli->raw_status = NT_STATUS_INTERNAL_ERROR;
110 14964 : cli->map_dos_errors = true; /* remove this */
111 14964 : cli->timeout = CLIENT_TIMEOUT;
112 :
113 : /* Set the CLI_FORCE_DOSERR environment variable to test
114 : client routines using DOS errors instead of STATUS32
115 : ones. This intended only as a temporary hack. */
116 14964 : if (getenv("CLI_FORCE_DOSERR")) {
117 0 : force_dos_errors = true;
118 : }
119 14964 : if (flags & CLI_FULL_CONNECTION_FORCE_DOS_ERRORS) {
120 0 : force_dos_errors = true;
121 : }
122 :
123 14964 : if (getenv("CLI_FORCE_ASCII")) {
124 0 : force_ascii = true;
125 : }
126 14964 : if (!lp_unicode()) {
127 0 : force_ascii = true;
128 : }
129 14964 : if (flags & CLI_FULL_CONNECTION_FORCE_ASCII) {
130 0 : force_ascii = true;
131 : }
132 :
133 14964 : if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO) {
134 0 : use_spnego = false;
135 : }
136 :
137 14964 : if (flags & CLI_FULL_CONNECTION_OPLOCKS) {
138 8 : cli->use_oplocks = true;
139 : }
140 14964 : if (flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) {
141 8 : use_level_II_oplocks = true;
142 : }
143 :
144 14964 : if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
145 : /*
146 : * Ensure for IPC/RPC the default is to require
147 : * signing unless explicitly turned off by the
148 : * administrator.
149 : */
150 9 : signing_state = lp_client_ipc_signing();
151 : }
152 :
153 14964 : if (signing_state == SMB_SIGNING_DEFAULT) {
154 11619 : signing_state = lp_client_signing();
155 : }
156 :
157 14964 : smb1_capabilities = 0;
158 14964 : smb1_capabilities |= CAP_LARGE_FILES;
159 14964 : smb1_capabilities |= CAP_NT_SMBS | CAP_RPC_REMOTE_APIS;
160 14964 : smb1_capabilities |= CAP_LOCK_AND_READ | CAP_NT_FIND;
161 14964 : smb1_capabilities |= CAP_DFS | CAP_W2K_SMBS;
162 14964 : smb1_capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX;
163 14964 : smb1_capabilities |= CAP_LWIO;
164 :
165 14964 : if (!force_dos_errors) {
166 14964 : smb1_capabilities |= CAP_STATUS32;
167 : }
168 :
169 14964 : if (!force_ascii) {
170 14964 : smb1_capabilities |= CAP_UNICODE;
171 : }
172 :
173 14964 : if (use_spnego) {
174 14753 : smb1_capabilities |= CAP_EXTENDED_SECURITY;
175 : }
176 :
177 14964 : if (use_level_II_oplocks) {
178 8 : smb1_capabilities |= CAP_LEVEL_II_OPLOCKS;
179 : }
180 :
181 14964 : smb2_capabilities = SMB2_CAP_ALL;
182 :
183 14964 : cli->conn = smbXcli_conn_create(cli, fd, remote_name,
184 : signing_state,
185 : smb1_capabilities,
186 : &client_guid,
187 : smb2_capabilities,
188 : &smb3_capabilities);
189 14964 : if (cli->conn == NULL) {
190 0 : goto error;
191 : }
192 :
193 14964 : cli->smb1.pid = (uint32_t)getpid();
194 14964 : cli->smb1.vc_num = cli->smb1.pid;
195 14964 : cli->smb1.session = smbXcli_session_create(cli, cli->conn);
196 14964 : if (cli->smb1.session == NULL) {
197 0 : goto error;
198 : }
199 :
200 14964 : cli->initialised = 1;
201 14964 : return cli;
202 :
203 : /* Clean up after malloc() error */
204 :
205 0 : error:
206 :
207 0 : TALLOC_FREE(cli);
208 0 : return NULL;
209 : }
210 :
211 : /****************************************************************************
212 : Close all pipes open on this session.
213 : ****************************************************************************/
214 :
215 11936 : static void cli_nt_pipes_close(struct cli_state *cli)
216 : {
217 23414 : while (cli->pipe_list != NULL) {
218 : /*
219 : * No TALLOC_FREE here!
220 : */
221 521 : talloc_free(cli->pipe_list);
222 : }
223 11936 : }
224 :
225 : /****************************************************************************
226 : Shutdown a client structure.
227 : ****************************************************************************/
228 :
229 11936 : static void _cli_shutdown(struct cli_state *cli)
230 : {
231 11936 : cli_nt_pipes_close(cli);
232 :
233 : /*
234 : * tell our peer to free his resources. Without this, when an
235 : * application attempts to do a graceful shutdown and calls
236 : * smbc_free_context() to clean up all connections, some connections
237 : * can remain active on the peer end, until some (long) timeout period
238 : * later. This tree disconnect forces the peer to clean up, since the
239 : * connection will be going away.
240 : */
241 11936 : if (cli_state_has_tcon(cli)) {
242 10816 : cli_tdis(cli);
243 : }
244 :
245 11936 : smbXcli_conn_disconnect(cli->conn, NT_STATUS_OK);
246 :
247 11936 : TALLOC_FREE(cli);
248 11936 : }
249 :
250 11936 : void cli_shutdown(struct cli_state *cli)
251 : {
252 : struct cli_state *cli_head;
253 11936 : if (cli == NULL) {
254 0 : return;
255 : }
256 11950 : DLIST_HEAD(cli, cli_head);
257 11936 : if (cli_head == cli) {
258 : /*
259 : * head of a DFS list, shutdown all subsidiary DFS
260 : * connections.
261 : */
262 : struct cli_state *p, *next;
263 :
264 11746 : for (p = cli_head->next; p; p = next) {
265 0 : next = p->next;
266 0 : DLIST_REMOVE(cli_head, p);
267 0 : _cli_shutdown(p);
268 : }
269 : } else {
270 190 : DLIST_REMOVE(cli_head, cli);
271 : }
272 :
273 11936 : _cli_shutdown(cli);
274 : }
275 :
276 5981 : uint16_t cli_state_get_vc_num(struct cli_state *cli)
277 : {
278 5981 : return cli->smb1.vc_num;
279 : }
280 :
281 : /****************************************************************************
282 : Set the PID to use for smb messages. Return the old pid.
283 : ****************************************************************************/
284 :
285 89 : uint32_t cli_setpid(struct cli_state *cli, uint32_t pid)
286 : {
287 89 : uint32_t ret = cli->smb1.pid;
288 89 : cli->smb1.pid = pid;
289 89 : return ret;
290 : }
291 :
292 4650 : uint32_t cli_getpid(struct cli_state *cli)
293 : {
294 4650 : return cli->smb1.pid;
295 : }
296 :
297 0 : bool cli_state_is_encryption_on(struct cli_state *cli)
298 : {
299 0 : if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
300 0 : return smb1cli_conn_encryption_on(cli->conn);
301 : }
302 :
303 0 : if (cli->smb2.tcon == NULL) {
304 0 : return false;
305 : }
306 :
307 0 : return smb2cli_tcon_is_encryption_on(cli->smb2.tcon);
308 : }
309 :
310 28598 : bool cli_state_has_tcon(struct cli_state *cli)
311 : {
312 : uint32_t tid;
313 28598 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
314 22986 : if (cli->smb2.tcon == NULL) {
315 6537 : return false;
316 : }
317 16449 : tid = cli_state_get_tid(cli);
318 16449 : if (tid == UINT32_MAX) {
319 0 : return false;
320 : }
321 : } else {
322 5612 : if (cli->smb1.tcon == NULL) {
323 3100 : return false;
324 : }
325 2512 : tid = cli_state_get_tid(cli);
326 2512 : if (tid == UINT16_MAX) {
327 11 : return false;
328 : }
329 : }
330 18950 : return true;
331 : }
332 :
333 18990 : uint32_t cli_state_get_tid(struct cli_state *cli)
334 : {
335 18990 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
336 16449 : return smb2cli_tcon_current_id(cli->smb2.tcon);
337 : } else {
338 2541 : return (uint32_t)smb1cli_tcon_current_id(cli->smb1.tcon);
339 : }
340 : }
341 :
342 54 : uint32_t cli_state_set_tid(struct cli_state *cli, uint32_t tid)
343 : {
344 : uint32_t ret;
345 54 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
346 0 : ret = smb2cli_tcon_current_id(cli->smb2.tcon);
347 0 : smb2cli_tcon_set_id(cli->smb2.tcon, tid);
348 : } else {
349 54 : ret = smb1cli_tcon_current_id(cli->smb1.tcon);
350 54 : smb1cli_tcon_set_id(cli->smb1.tcon, tid);
351 : }
352 54 : return ret;
353 : }
354 :
355 8156 : struct smbXcli_tcon *cli_state_save_tcon(struct cli_state *cli)
356 : {
357 : /*
358 : * Note. This used to make a deep copy of either
359 : * cli->smb2.tcon or cli->smb1.tcon, but this leaves
360 : * the original pointer in place which will then get
361 : * TALLOC_FREE()'d when the new connection is made on
362 : * this cli_state.
363 : *
364 : * As there may be pipes open on the old connection with
365 : * talloc'ed state allocated using the tcon pointer as a
366 : * parent we can't deep copy and then free this as that
367 : * closes the open pipes.
368 : *
369 : * This call is used to temporarily swap out a tcon pointer
370 : * to allow a new tcon on the same cli_state.
371 : *
372 : * Just return the raw pointer and set the old value to NULL.
373 : * We know we MUST be calling cli_state_restore_tcon() below
374 : * to restore before closing the session.
375 : *
376 : * See BUG: https://bugzilla.samba.org/show_bug.cgi?id=13992
377 : */
378 8156 : struct smbXcli_tcon *tcon_ret = NULL;
379 :
380 8156 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
381 8031 : tcon_ret = cli->smb2.tcon;
382 8031 : cli->smb2.tcon = NULL; /* *Not* TALLOC_FREE(). */
383 : } else {
384 125 : tcon_ret = cli->smb1.tcon;
385 125 : cli->smb1.tcon = NULL; /* *Not* TALLOC_FREE(). */
386 : }
387 8156 : return tcon_ret;
388 : }
389 :
390 16684 : void cli_state_restore_tcon(struct cli_state *cli, struct smbXcli_tcon *tcon)
391 : {
392 16684 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
393 14236 : TALLOC_FREE(cli->smb2.tcon);
394 14236 : cli->smb2.tcon = tcon;
395 : } else {
396 2448 : TALLOC_FREE(cli->smb1.tcon);
397 2448 : cli->smb1.tcon = tcon;
398 : }
399 16684 : }
400 :
401 34 : uint16_t cli_state_get_uid(struct cli_state *cli)
402 : {
403 34 : return smb1cli_session_current_id(cli->smb1.session);
404 : }
405 :
406 806 : uint16_t cli_state_set_uid(struct cli_state *cli, uint16_t uid)
407 : {
408 806 : uint16_t ret = smb1cli_session_current_id(cli->smb1.session);
409 806 : smb1cli_session_set_id(cli->smb1.session, uid);
410 806 : return ret;
411 : }
412 :
413 : /****************************************************************************
414 : Set the case sensitivity flag on the packets. Returns old state.
415 : ****************************************************************************/
416 :
417 0 : bool cli_set_case_sensitive(struct cli_state *cli, bool case_sensitive)
418 : {
419 : bool ret;
420 : uint32_t fs_attrs;
421 : struct smbXcli_tcon *tcon;
422 :
423 0 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
424 0 : tcon = cli->smb2.tcon;
425 : } else {
426 0 : tcon = cli->smb1.tcon;
427 : }
428 :
429 0 : fs_attrs = smbXcli_tcon_get_fs_attributes(tcon);
430 0 : if (fs_attrs & FILE_CASE_SENSITIVE_SEARCH) {
431 0 : ret = true;
432 : } else {
433 0 : ret = false;
434 : }
435 0 : if (case_sensitive) {
436 0 : fs_attrs |= FILE_CASE_SENSITIVE_SEARCH;
437 : } else {
438 0 : fs_attrs &= ~FILE_CASE_SENSITIVE_SEARCH;
439 : }
440 0 : smbXcli_tcon_set_fs_attributes(tcon, fs_attrs);
441 :
442 0 : return ret;
443 : }
444 :
445 20354 : uint32_t cli_state_available_size(struct cli_state *cli, uint32_t ofs)
446 : {
447 20354 : uint32_t ret = smb1cli_conn_max_xmit(cli->conn);
448 :
449 20354 : if (ofs >= ret) {
450 0 : return 0;
451 : }
452 :
453 20354 : ret -= ofs;
454 :
455 20354 : return ret;
456 : }
457 :
458 12 : time_t cli_state_server_time(struct cli_state *cli)
459 : {
460 : NTTIME nt;
461 : time_t t;
462 :
463 12 : nt = smbXcli_conn_server_system_time(cli->conn);
464 12 : t = nt_time_to_unix(nt);
465 :
466 12 : return t;
467 : }
468 :
469 : struct cli_echo_state {
470 : bool is_smb2;
471 : };
472 :
473 : static void cli_echo_done(struct tevent_req *subreq);
474 :
475 105 : struct tevent_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
476 : struct cli_state *cli, uint16_t num_echos,
477 : DATA_BLOB data)
478 : {
479 : struct tevent_req *req, *subreq;
480 : struct cli_echo_state *state;
481 :
482 105 : req = tevent_req_create(mem_ctx, &state, struct cli_echo_state);
483 105 : if (req == NULL) {
484 0 : return NULL;
485 : }
486 :
487 105 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
488 92 : state->is_smb2 = true;
489 92 : subreq = smb2cli_echo_send(state, ev,
490 : cli->conn,
491 92 : cli->timeout);
492 : } else {
493 26 : subreq = smb1cli_echo_send(state, ev,
494 : cli->conn,
495 13 : cli->timeout,
496 : num_echos,
497 : data);
498 : }
499 105 : if (tevent_req_nomem(subreq, req)) {
500 0 : return tevent_req_post(req, ev);
501 : }
502 105 : tevent_req_set_callback(subreq, cli_echo_done, req);
503 :
504 105 : return req;
505 : }
506 :
507 105 : static void cli_echo_done(struct tevent_req *subreq)
508 : {
509 105 : struct tevent_req *req = tevent_req_callback_data(
510 : subreq, struct tevent_req);
511 105 : struct cli_echo_state *state = tevent_req_data(
512 : req, struct cli_echo_state);
513 : NTSTATUS status;
514 :
515 105 : if (state->is_smb2) {
516 92 : status = smb2cli_echo_recv(subreq);
517 : } else {
518 13 : status = smb1cli_echo_recv(subreq);
519 : }
520 105 : TALLOC_FREE(subreq);
521 105 : if (!NT_STATUS_IS_OK(status)) {
522 2 : tevent_req_nterror(req, status);
523 2 : return;
524 : }
525 :
526 103 : tevent_req_done(req);
527 : }
528 :
529 : /**
530 : * Get the result out from an echo request
531 : * @param[in] req The async_req from cli_echo_send
532 : * @retval Did the server reply correctly?
533 : */
534 :
535 105 : NTSTATUS cli_echo_recv(struct tevent_req *req)
536 : {
537 105 : return tevent_req_simple_recv_ntstatus(req);
538 : }
539 :
540 : /**
541 : * @brief Send/Receive SMBEcho requests
542 : * @param[in] mem_ctx The memory context to put the async_req on
543 : * @param[in] ev The event context that will call us back
544 : * @param[in] cli The connection to send the echo to
545 : * @param[in] num_echos How many times do we want to get the reply?
546 : * @param[in] data The data we want to get back
547 : * @retval Did the server reply correctly?
548 : */
549 :
550 52 : NTSTATUS cli_echo(struct cli_state *cli, uint16_t num_echos, DATA_BLOB data)
551 : {
552 52 : TALLOC_CTX *frame = talloc_stackframe();
553 : struct tevent_context *ev;
554 : struct tevent_req *req;
555 52 : NTSTATUS status = NT_STATUS_OK;
556 :
557 52 : if (smbXcli_conn_has_async_calls(cli->conn)) {
558 : /*
559 : * Can't use sync call while an async call is in flight
560 : */
561 0 : status = NT_STATUS_INVALID_PARAMETER;
562 0 : goto fail;
563 : }
564 :
565 52 : ev = samba_tevent_context_init(frame);
566 52 : if (ev == NULL) {
567 0 : status = NT_STATUS_NO_MEMORY;
568 0 : goto fail;
569 : }
570 :
571 52 : req = cli_echo_send(frame, ev, cli, num_echos, data);
572 52 : if (req == NULL) {
573 0 : status = NT_STATUS_NO_MEMORY;
574 0 : goto fail;
575 : }
576 :
577 52 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
578 0 : goto fail;
579 : }
580 :
581 52 : status = cli_echo_recv(req);
582 52 : fail:
583 52 : TALLOC_FREE(frame);
584 52 : return status;
585 : }
586 :
587 327804 : NTSTATUS cli_smb(TALLOC_CTX *mem_ctx, struct cli_state *cli,
588 : uint8_t smb_command, uint8_t additional_flags,
589 : uint8_t wct, uint16_t *vwv,
590 : uint32_t num_bytes, const uint8_t *bytes,
591 : struct tevent_req **result_parent,
592 : uint8_t min_wct, uint8_t *pwct, uint16_t **pvwv,
593 : uint32_t *pnum_bytes, uint8_t **pbytes)
594 : {
595 : struct tevent_context *ev;
596 327804 : struct tevent_req *req = NULL;
597 327804 : NTSTATUS status = NT_STATUS_NO_MEMORY;
598 :
599 327804 : if (smbXcli_conn_has_async_calls(cli->conn)) {
600 0 : return NT_STATUS_INVALID_PARAMETER;
601 : }
602 327804 : ev = samba_tevent_context_init(mem_ctx);
603 327804 : if (ev == NULL) {
604 0 : goto fail;
605 : }
606 327804 : req = cli_smb_send(mem_ctx, ev, cli, smb_command, additional_flags, 0,
607 : wct, vwv, num_bytes, bytes);
608 327804 : if (req == NULL) {
609 0 : goto fail;
610 : }
611 327804 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
612 0 : goto fail;
613 : }
614 327804 : status = cli_smb_recv(req, NULL, NULL, min_wct, pwct, pvwv,
615 : pnum_bytes, pbytes);
616 327804 : fail:
617 327804 : TALLOC_FREE(ev);
618 327804 : if (NT_STATUS_IS_OK(status) && (result_parent != NULL)) {
619 109 : *result_parent = req;
620 : }
621 327804 : return status;
622 : }
|