Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : client connect/disconnect routines
4 : Copyright (C) Andrew Tridgell 1994-1998
5 : Copyright (C) Andrew Bartlett 2001-2003
6 : Copyright (C) Volker Lendecke 2011
7 : Copyright (C) Jeremy Allison 2011
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "libsmb/libsmb.h"
25 : #include "libsmb/namequery.h"
26 : #include "../libcli/auth/libcli_auth.h"
27 : #include "auth/credentials/credentials.h"
28 : #include "auth/gensec/gensec.h"
29 : #include "auth/ntlmssp/ntlmssp.h"
30 : #include "auth_generic.h"
31 : #include "../lib/util/tevent_ntstatus.h"
32 : #include "async_smb.h"
33 : #include "libsmb/nmblib.h"
34 : #include "librpc/ndr/libndr.h"
35 : #include "../libcli/smb/smbXcli_base.h"
36 : #include "../libcli/smb/smb_seal.h"
37 : #include "lib/param/param.h"
38 : #include "../libcli/smb/smb2_negotiate_context.h"
39 :
40 : static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
41 : const char *principal);
42 :
43 671 : struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
44 : const char *username,
45 : const char *domain,
46 : const char *realm,
47 : const char *password,
48 : bool use_kerberos,
49 : bool fallback_after_kerberos,
50 : bool use_ccache,
51 : bool password_is_nt_hash)
52 : {
53 671 : struct loadparm_context *lp_ctx = NULL;
54 671 : struct cli_credentials *creds = NULL;
55 671 : const char *principal = NULL;
56 671 : char *tmp = NULL;
57 671 : char *p = NULL;
58 45 : bool ok;
59 :
60 671 : creds = cli_credentials_init(mem_ctx);
61 671 : if (creds == NULL) {
62 0 : return NULL;
63 : }
64 :
65 671 : lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
66 671 : if (lp_ctx == NULL) {
67 0 : goto fail;
68 : }
69 671 : ok = cli_credentials_set_conf(creds, lp_ctx);
70 671 : if (!ok) {
71 0 : goto fail;
72 : }
73 :
74 671 : if (username == NULL) {
75 0 : username = "";
76 : }
77 :
78 671 : if (strlen(username) == 0) {
79 53 : if (password != NULL && strlen(password) == 0) {
80 : /*
81 : * some callers pass "" as no password
82 : *
83 : * gensec only handles NULL as no password.
84 : */
85 8 : password = NULL;
86 : }
87 8 : if (password == NULL) {
88 53 : cli_credentials_set_anonymous(creds);
89 53 : return creds;
90 : }
91 : }
92 :
93 618 : tmp = talloc_strdup(creds, username);
94 618 : if (tmp == NULL) {
95 0 : goto fail;
96 : }
97 618 : username = tmp;
98 :
99 : /* allow for workgroups as part of the username */
100 1236 : if ((p = strchr_m(tmp, '\\')) ||
101 1234 : (p = strchr_m(tmp, '/')) ||
102 616 : (p = strchr_m(tmp, *lp_winbind_separator()))) {
103 2 : *p = 0;
104 2 : username = p + 1;
105 2 : domain = tmp;
106 : }
107 :
108 618 : principal = username;
109 618 : username = cli_session_setup_get_account(creds, principal);
110 618 : if (username == NULL) {
111 0 : goto fail;
112 : }
113 618 : ok = strequal(username, principal);
114 618 : if (ok) {
115 : /*
116 : * Ok still the same, so it's not a principal
117 : */
118 612 : principal = NULL;
119 : }
120 :
121 672 : if (use_kerberos && fallback_after_kerberos) {
122 : /*
123 : * Keep what we learned from the
124 : * "client use kerberos" option.
125 : */
126 0 : enum credentials_use_kerberos current_krb5 =
127 54 : cli_credentials_get_kerberos_state(creds);
128 54 : cli_credentials_set_kerberos_state(creds,
129 : current_krb5,
130 : CRED_SPECIFIED);
131 564 : } else if (use_kerberos) {
132 4 : cli_credentials_set_kerberos_state(creds,
133 : CRED_USE_KERBEROS_REQUIRED,
134 : CRED_SPECIFIED);
135 : } else {
136 560 : cli_credentials_set_kerberos_state(creds,
137 : CRED_USE_KERBEROS_DISABLED,
138 : CRED_SPECIFIED);
139 : }
140 :
141 618 : if (use_ccache) {
142 0 : uint32_t features;
143 :
144 49 : features = cli_credentials_get_gensec_features(creds);
145 49 : features |= GENSEC_FEATURE_NTLM_CCACHE;
146 49 : cli_credentials_set_gensec_features(creds,
147 : features,
148 : CRED_SPECIFIED);
149 :
150 49 : if (password != NULL && strlen(password) == 0) {
151 : /*
152 : * some callers pass "" as no password
153 : *
154 : * GENSEC_FEATURE_NTLM_CCACHE only handles
155 : * NULL as no password.
156 : */
157 0 : password = NULL;
158 : }
159 : }
160 :
161 618 : ok = cli_credentials_set_username(creds,
162 : username,
163 : CRED_SPECIFIED);
164 618 : if (!ok) {
165 0 : goto fail;
166 : }
167 :
168 618 : if (domain != NULL) {
169 618 : ok = cli_credentials_set_domain(creds,
170 : domain,
171 : CRED_SPECIFIED);
172 618 : if (!ok) {
173 0 : goto fail;
174 : }
175 : }
176 :
177 618 : if (principal != NULL) {
178 6 : ok = cli_credentials_set_principal(creds,
179 : principal,
180 : CRED_SPECIFIED);
181 6 : if (!ok) {
182 0 : goto fail;
183 : }
184 : }
185 :
186 618 : if (realm != NULL) {
187 0 : ok = cli_credentials_set_realm(creds,
188 : realm,
189 : CRED_SPECIFIED);
190 0 : if (!ok) {
191 0 : goto fail;
192 : }
193 : }
194 :
195 618 : if (password != NULL && strlen(password) > 0) {
196 616 : if (password_is_nt_hash) {
197 0 : struct samr_Password nt_hash;
198 0 : size_t converted;
199 :
200 0 : converted = strhex_to_str((char *)nt_hash.hash,
201 : sizeof(nt_hash.hash),
202 : password,
203 : strlen(password));
204 0 : if (converted != sizeof(nt_hash.hash)) {
205 0 : goto fail;
206 : }
207 :
208 0 : ok = cli_credentials_set_nt_hash(creds,
209 : &nt_hash,
210 : CRED_SPECIFIED);
211 0 : if (!ok) {
212 0 : goto fail;
213 : }
214 : } else {
215 616 : ok = cli_credentials_set_password(creds,
216 : password,
217 : CRED_SPECIFIED);
218 616 : if (!ok) {
219 0 : goto fail;
220 : }
221 : }
222 2 : } else if (use_kerberos && !fallback_after_kerberos) {
223 2 : const char *error_string = NULL;
224 0 : int rc;
225 :
226 2 : rc = cli_credentials_set_ccache(creds,
227 : lp_ctx,
228 : NULL,
229 : CRED_SPECIFIED,
230 : &error_string);
231 2 : if (rc != 0) {
232 0 : fprintf(stderr,
233 : "Warning reading default "
234 : "krb5 credentials cache: %s\n",
235 : error_string);
236 : }
237 : }
238 :
239 618 : return creds;
240 0 : fail:
241 0 : TALLOC_FREE(creds);
242 0 : return NULL;
243 : }
244 :
245 33257 : static NTSTATUS cli_state_update_after_sesssetup(struct cli_state *cli,
246 : const char *native_os,
247 : const char *native_lm,
248 : const char *primary_domain)
249 : {
250 : #define _VALID_STR(p) ((p) != NULL && (p)[0] != '\0')
251 :
252 33257 : if (!_VALID_STR(cli->server_os) && _VALID_STR(native_os)) {
253 3857 : cli->server_os = talloc_strdup(cli, native_os);
254 3857 : if (cli->server_os == NULL) {
255 0 : return NT_STATUS_NO_MEMORY;
256 : }
257 : }
258 :
259 33257 : if (!_VALID_STR(cli->server_type) && _VALID_STR(native_lm)) {
260 3857 : cli->server_type = talloc_strdup(cli, native_lm);
261 3857 : if (cli->server_type == NULL) {
262 0 : return NT_STATUS_NO_MEMORY;
263 : }
264 : }
265 :
266 33257 : if (!_VALID_STR(cli->server_domain) && _VALID_STR(primary_domain)) {
267 61 : cli->server_domain = talloc_strdup(cli, primary_domain);
268 61 : if (cli->server_domain == NULL) {
269 0 : return NT_STATUS_NO_MEMORY;
270 : }
271 : }
272 :
273 : #undef _VALID_STRING
274 33257 : return NT_STATUS_OK;
275 : }
276 :
277 : /********************************************************
278 : Utility function to ensure we always return at least
279 : a valid char * pointer to an empty string for the
280 : cli->server_os, cli->server_type and cli->server_domain
281 : strings.
282 : *******************************************************/
283 :
284 15 : static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
285 : const uint8_t *hdr,
286 : char **dest,
287 : uint8_t *src,
288 : size_t srclen,
289 : ssize_t *destlen)
290 : {
291 30 : *destlen = pull_string_talloc(mem_ctx,
292 : (const char *)hdr,
293 15 : SVAL(hdr, HDR_FLG2),
294 : dest,
295 : (char *)src,
296 : srclen,
297 : STR_TERMINATE);
298 15 : if (*destlen == -1) {
299 0 : return NT_STATUS_NO_MEMORY;
300 : }
301 :
302 15 : if (*dest == NULL) {
303 0 : *dest = talloc_strdup(mem_ctx, "");
304 0 : if (*dest == NULL) {
305 0 : return NT_STATUS_NO_MEMORY;
306 : }
307 : }
308 15 : return NT_STATUS_OK;
309 : }
310 :
311 : /****************************************************************************
312 : Work out suitable capabilities to offer the server.
313 : ****************************************************************************/
314 :
315 7712 : static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
316 : uint32_t sesssetup_capabilities)
317 : {
318 7712 : uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
319 :
320 : /*
321 : * We only send capabilities based on the mask for:
322 : * - client only flags
323 : * - flags used in both directions
324 : *
325 : * We do not echo the server only flags, except some legacy flags.
326 : *
327 : * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
328 : * CAP_LARGE_WRITEX in order to allow us to do large reads
329 : * against old Samba releases (<= 3.6.x).
330 : */
331 7712 : client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
332 :
333 : /*
334 : * Session Setup specific flags CAP_DYNAMIC_REAUTH
335 : * and CAP_EXTENDED_SECURITY are passed by the caller.
336 : * We need that in order to do guest logins even if
337 : * CAP_EXTENDED_SECURITY is negotiated.
338 : */
339 7712 : client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
340 7712 : sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
341 7712 : client_capabilities |= sesssetup_capabilities;
342 :
343 7712 : return client_capabilities;
344 : }
345 :
346 : /****************************************************************************
347 : Do a NT1 guest session setup.
348 : ****************************************************************************/
349 :
350 : struct cli_session_setup_guest_state {
351 : struct cli_state *cli;
352 : uint16_t vwv[13];
353 : struct iovec bytes;
354 : };
355 :
356 : static void cli_session_setup_guest_done(struct tevent_req *subreq);
357 :
358 5 : struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
359 : struct tevent_context *ev,
360 : struct cli_state *cli,
361 : struct tevent_req **psmbreq)
362 : {
363 0 : struct tevent_req *req, *subreq;
364 0 : struct cli_session_setup_guest_state *state;
365 0 : uint16_t *vwv;
366 0 : uint8_t *bytes;
367 :
368 5 : req = tevent_req_create(mem_ctx, &state,
369 : struct cli_session_setup_guest_state);
370 5 : if (req == NULL) {
371 0 : return NULL;
372 : }
373 5 : state->cli = cli;
374 5 : vwv = state->vwv;
375 :
376 5 : SCVAL(vwv+0, 0, 0xFF);
377 5 : SCVAL(vwv+0, 1, 0);
378 5 : SSVAL(vwv+1, 0, 0);
379 5 : SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
380 5 : SSVAL(vwv+3, 0, 2);
381 5 : SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
382 5 : SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
383 5 : SSVAL(vwv+7, 0, 0);
384 5 : SSVAL(vwv+8, 0, 0);
385 5 : SSVAL(vwv+9, 0, 0);
386 5 : SSVAL(vwv+10, 0, 0);
387 5 : SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
388 :
389 5 : bytes = talloc_array(state, uint8_t, 0);
390 :
391 5 : bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
392 : NULL);
393 5 : bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
394 : NULL);
395 5 : bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
396 5 : bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
397 :
398 5 : if (bytes == NULL) {
399 0 : TALLOC_FREE(req);
400 0 : return NULL;
401 : }
402 :
403 5 : state->bytes.iov_base = (void *)bytes;
404 5 : state->bytes.iov_len = talloc_get_size(bytes);
405 :
406 5 : subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
407 5 : vwv, 1, &state->bytes);
408 5 : if (subreq == NULL) {
409 0 : TALLOC_FREE(req);
410 0 : return NULL;
411 : }
412 5 : tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
413 5 : *psmbreq = subreq;
414 5 : return req;
415 : }
416 :
417 0 : struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
418 : struct tevent_context *ev,
419 : struct cli_state *cli)
420 : {
421 0 : struct tevent_req *req, *subreq;
422 0 : NTSTATUS status;
423 :
424 0 : req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
425 0 : if (req == NULL) {
426 0 : return NULL;
427 : }
428 :
429 0 : status = smb1cli_req_chain_submit(&subreq, 1);
430 0 : if (!NT_STATUS_IS_OK(status)) {
431 0 : tevent_req_nterror(req, status);
432 0 : return tevent_req_post(req, ev);
433 : }
434 0 : return req;
435 : }
436 :
437 5 : static void cli_session_setup_guest_done(struct tevent_req *subreq)
438 : {
439 5 : struct tevent_req *req = tevent_req_callback_data(
440 : subreq, struct tevent_req);
441 5 : struct cli_session_setup_guest_state *state = tevent_req_data(
442 : req, struct cli_session_setup_guest_state);
443 5 : struct cli_state *cli = state->cli;
444 0 : uint32_t num_bytes;
445 0 : uint8_t *in;
446 0 : uint8_t *inhdr;
447 0 : uint8_t *bytes;
448 0 : uint8_t *p;
449 0 : NTSTATUS status;
450 0 : ssize_t ret;
451 0 : uint8_t wct;
452 0 : uint16_t *vwv;
453 :
454 5 : status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
455 : &num_bytes, &bytes);
456 5 : TALLOC_FREE(subreq);
457 5 : if (!NT_STATUS_IS_OK(status)) {
458 0 : tevent_req_nterror(req, status);
459 0 : return;
460 : }
461 :
462 5 : inhdr = in + NBT_HDR_SIZE;
463 5 : p = bytes;
464 :
465 5 : cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
466 5 : smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
467 :
468 5 : status = smb_bytes_talloc_string(cli,
469 : inhdr,
470 : &cli->server_os,
471 : p,
472 5 : bytes+num_bytes-p,
473 : &ret);
474 :
475 5 : if (!NT_STATUS_IS_OK(status)) {
476 0 : tevent_req_nterror(req, status);
477 0 : return;
478 : }
479 5 : p += ret;
480 :
481 5 : status = smb_bytes_talloc_string(cli,
482 : inhdr,
483 : &cli->server_type,
484 : p,
485 5 : bytes+num_bytes-p,
486 : &ret);
487 :
488 5 : if (!NT_STATUS_IS_OK(status)) {
489 0 : tevent_req_nterror(req, status);
490 0 : return;
491 : }
492 5 : p += ret;
493 :
494 5 : status = smb_bytes_talloc_string(cli,
495 : inhdr,
496 : &cli->server_domain,
497 : p,
498 5 : bytes+num_bytes-p,
499 : &ret);
500 :
501 5 : if (!NT_STATUS_IS_OK(status)) {
502 0 : tevent_req_nterror(req, status);
503 0 : return;
504 : }
505 :
506 5 : tevent_req_done(req);
507 : }
508 :
509 5 : NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
510 : {
511 5 : return tevent_req_simple_recv_ntstatus(req);
512 : }
513 :
514 : /* The following is calculated from :
515 : * (smb_size-4) = 35
516 : * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
517 : * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
518 : * end of packet.
519 : */
520 :
521 : #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
522 :
523 : struct cli_sesssetup_blob_state {
524 : struct tevent_context *ev;
525 : struct cli_state *cli;
526 : DATA_BLOB blob;
527 : uint16_t max_blob_size;
528 :
529 : DATA_BLOB this_blob;
530 : struct iovec *recv_iov;
531 :
532 : NTSTATUS status;
533 : const uint8_t *inbuf;
534 : DATA_BLOB ret_blob;
535 :
536 : char *out_native_os;
537 : char *out_native_lm;
538 : };
539 :
540 : static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
541 : struct tevent_req **psubreq);
542 : static void cli_sesssetup_blob_done(struct tevent_req *subreq);
543 :
544 33529 : static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
545 : struct tevent_context *ev,
546 : struct cli_state *cli,
547 : DATA_BLOB blob)
548 : {
549 0 : struct tevent_req *req, *subreq;
550 0 : struct cli_sesssetup_blob_state *state;
551 0 : uint32_t usable_space;
552 :
553 33529 : req = tevent_req_create(mem_ctx, &state,
554 : struct cli_sesssetup_blob_state);
555 33529 : if (req == NULL) {
556 0 : return NULL;
557 : }
558 33529 : state->ev = ev;
559 33529 : state->blob = blob;
560 33529 : state->cli = cli;
561 :
562 33529 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
563 25902 : usable_space = UINT16_MAX;
564 : } else {
565 7627 : usable_space = cli_state_available_size(cli,
566 : BASE_SESSSETUP_BLOB_PACKET_SIZE);
567 : }
568 :
569 33529 : if (usable_space == 0) {
570 0 : DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
571 : "(not possible to send %u bytes)\n",
572 : BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
573 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
574 0 : return tevent_req_post(req, ev);
575 : }
576 33529 : state->max_blob_size = MIN(usable_space, 0xFFFF);
577 :
578 33529 : if (!cli_sesssetup_blob_next(state, &subreq)) {
579 0 : tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
580 0 : return tevent_req_post(req, ev);
581 : }
582 33529 : tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
583 33529 : return req;
584 : }
585 :
586 33529 : static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
587 : struct tevent_req **psubreq)
588 : {
589 0 : struct tevent_req *subreq;
590 0 : uint16_t thistime;
591 :
592 33529 : thistime = MIN(state->blob.length, state->max_blob_size);
593 :
594 33529 : state->this_blob.data = state->blob.data;
595 33529 : state->this_blob.length = thistime;
596 :
597 33529 : state->blob.data += thistime;
598 33529 : state->blob.length -= thistime;
599 :
600 33529 : if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
601 25902 : subreq = smb2cli_session_setup_send(state, state->ev,
602 25902 : state->cli->conn,
603 25902 : state->cli->timeout,
604 25902 : state->cli->smb2.session,
605 : 0, /* in_flags */
606 : SMB2_CAP_DFS, /* in_capabilities */
607 : 0, /* in_channel */
608 : 0, /* in_previous_session_id */
609 25902 : &state->this_blob);
610 25902 : if (subreq == NULL) {
611 0 : return false;
612 : }
613 : } else {
614 7627 : uint16_t in_buf_size = 0;
615 7627 : uint16_t in_mpx_max = 0;
616 7627 : uint16_t in_vc_num = 0;
617 7627 : uint32_t in_sess_key = 0;
618 7627 : uint32_t in_capabilities = 0;
619 7627 : const char *in_native_os = NULL;
620 7627 : const char *in_native_lm = NULL;
621 :
622 7627 : in_buf_size = CLI_BUFFER_SIZE;
623 7627 : in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
624 7627 : in_vc_num = cli_state_get_vc_num(state->cli);
625 7627 : in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
626 7627 : in_capabilities = cli_session_setup_capabilities(state->cli,
627 : CAP_EXTENDED_SECURITY);
628 7627 : in_native_os = "Unix";
629 7627 : in_native_lm = "Samba";
630 :
631 : /*
632 : * For now we keep the same values as before,
633 : * we may remove these in a separate commit later.
634 : */
635 7627 : in_mpx_max = 2;
636 7627 : in_vc_num = 1;
637 7627 : in_sess_key = 0;
638 :
639 7627 : subreq = smb1cli_session_setup_ext_send(state, state->ev,
640 7627 : state->cli->conn,
641 7627 : state->cli->timeout,
642 7627 : state->cli->smb1.pid,
643 7627 : state->cli->smb1.session,
644 : in_buf_size,
645 : in_mpx_max,
646 : in_vc_num,
647 : in_sess_key,
648 : state->this_blob,
649 : in_capabilities,
650 : in_native_os,
651 : in_native_lm);
652 7627 : if (subreq == NULL) {
653 0 : return false;
654 : }
655 : }
656 33529 : *psubreq = subreq;
657 33529 : return true;
658 : }
659 :
660 33529 : static void cli_sesssetup_blob_done(struct tevent_req *subreq)
661 : {
662 33529 : struct tevent_req *req = tevent_req_callback_data(
663 : subreq, struct tevent_req);
664 33529 : struct cli_sesssetup_blob_state *state = tevent_req_data(
665 : req, struct cli_sesssetup_blob_state);
666 0 : NTSTATUS status;
667 :
668 33529 : if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
669 25902 : status = smb2cli_session_setup_recv(subreq, state,
670 : &state->recv_iov,
671 : &state->ret_blob);
672 : } else {
673 7627 : status = smb1cli_session_setup_ext_recv(subreq, state,
674 : &state->recv_iov,
675 : &state->inbuf,
676 : &state->ret_blob,
677 : &state->out_native_os,
678 : &state->out_native_lm);
679 : }
680 33529 : TALLOC_FREE(subreq);
681 33529 : if (!NT_STATUS_IS_OK(status)
682 15947 : && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
683 357 : tevent_req_nterror(req, status);
684 357 : return;
685 : }
686 :
687 33172 : state->status = status;
688 :
689 33172 : status = cli_state_update_after_sesssetup(state->cli,
690 33172 : state->out_native_os,
691 33172 : state->out_native_lm,
692 : NULL);
693 33172 : if (tevent_req_nterror(req, status)) {
694 0 : return;
695 : }
696 :
697 33172 : if (state->blob.length != 0) {
698 : /*
699 : * More to send
700 : */
701 0 : if (!cli_sesssetup_blob_next(state, &subreq)) {
702 0 : tevent_req_oom(req);
703 0 : return;
704 : }
705 0 : tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
706 0 : return;
707 : }
708 33172 : tevent_req_done(req);
709 : }
710 :
711 33529 : static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
712 : TALLOC_CTX *mem_ctx,
713 : DATA_BLOB *pblob,
714 : const uint8_t **pinbuf,
715 : struct iovec **precv_iov)
716 : {
717 33529 : struct cli_sesssetup_blob_state *state = tevent_req_data(
718 : req, struct cli_sesssetup_blob_state);
719 0 : NTSTATUS status;
720 0 : struct iovec *recv_iov;
721 :
722 33529 : if (tevent_req_is_nterror(req, &status)) {
723 357 : TALLOC_FREE(state->cli->smb2.session);
724 357 : cli_state_set_uid(state->cli, UID_FIELD_INVALID);
725 357 : tevent_req_received(req);
726 357 : return status;
727 : }
728 :
729 33172 : recv_iov = talloc_move(mem_ctx, &state->recv_iov);
730 33172 : if (pblob != NULL) {
731 33172 : *pblob = state->ret_blob;
732 : }
733 33172 : if (pinbuf != NULL) {
734 33172 : *pinbuf = state->inbuf;
735 : }
736 33172 : if (precv_iov != NULL) {
737 33172 : *precv_iov = recv_iov;
738 : }
739 : /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
740 33172 : status = state->status;
741 33172 : tevent_req_received(req);
742 33172 : return status;
743 : }
744 :
745 : /****************************************************************************
746 : Do a spnego/NTLMSSP encrypted session setup.
747 : ****************************************************************************/
748 :
749 : struct cli_session_setup_gensec_state {
750 : struct tevent_context *ev;
751 : struct cli_state *cli;
752 : struct auth_generic_state *auth_generic;
753 : bool is_anonymous;
754 : DATA_BLOB blob_in;
755 : const uint8_t *inbuf;
756 : struct iovec *recv_iov;
757 : DATA_BLOB blob_out;
758 : bool local_ready;
759 : bool remote_ready;
760 : DATA_BLOB session_key;
761 : };
762 :
763 17961 : static int cli_session_setup_gensec_state_destructor(
764 : struct cli_session_setup_gensec_state *state)
765 : {
766 17961 : TALLOC_FREE(state->auth_generic);
767 17961 : data_blob_clear_free(&state->session_key);
768 17961 : return 0;
769 : }
770 :
771 : static void cli_session_setup_gensec_local_next(struct tevent_req *req);
772 : static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
773 : static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
774 : static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
775 : static void cli_session_setup_gensec_ready(struct tevent_req *req);
776 :
777 17961 : static struct tevent_req *cli_session_setup_gensec_send(
778 : TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
779 : struct cli_credentials *creds,
780 : const char *target_service,
781 : const char *target_hostname)
782 : {
783 0 : struct tevent_req *req;
784 0 : struct cli_session_setup_gensec_state *state;
785 0 : NTSTATUS status;
786 17961 : const DATA_BLOB *b = NULL;
787 :
788 17961 : req = tevent_req_create(mem_ctx, &state,
789 : struct cli_session_setup_gensec_state);
790 17961 : if (req == NULL) {
791 0 : return NULL;
792 : }
793 17961 : state->ev = ev;
794 17961 : state->cli = cli;
795 :
796 17961 : talloc_set_destructor(
797 : state, cli_session_setup_gensec_state_destructor);
798 :
799 17961 : status = auth_generic_client_prepare(state, &state->auth_generic);
800 17961 : if (tevent_req_nterror(req, status)) {
801 0 : return tevent_req_post(req, ev);
802 : }
803 :
804 17961 : status = auth_generic_set_creds(state->auth_generic, creds);
805 17961 : if (tevent_req_nterror(req, status)) {
806 0 : return tevent_req_post(req, ev);
807 : }
808 :
809 17961 : gensec_want_feature(state->auth_generic->gensec_security,
810 : GENSEC_FEATURE_SESSION_KEY);
811 :
812 17961 : if (target_service != NULL) {
813 17961 : status = gensec_set_target_service(
814 17961 : state->auth_generic->gensec_security,
815 : target_service);
816 17961 : if (tevent_req_nterror(req, status)) {
817 0 : return tevent_req_post(req, ev);
818 : }
819 : }
820 :
821 17961 : if (target_hostname != NULL) {
822 17961 : status = gensec_set_target_hostname(
823 17961 : state->auth_generic->gensec_security,
824 : target_hostname);
825 17961 : if (tevent_req_nterror(req, status)) {
826 0 : return tevent_req_post(req, ev);
827 : }
828 : }
829 :
830 17961 : b = smbXcli_conn_server_gss_blob(cli->conn);
831 17961 : if (b != NULL) {
832 17961 : state->blob_in = *b;
833 : }
834 :
835 17961 : state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
836 :
837 17961 : status = auth_generic_client_start(state->auth_generic,
838 : GENSEC_OID_SPNEGO);
839 17961 : if (tevent_req_nterror(req, status)) {
840 0 : return tevent_req_post(req, ev);
841 : }
842 :
843 17961 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
844 14135 : state->cli->smb2.session = smbXcli_session_create(cli,
845 : cli->conn);
846 14135 : if (tevent_req_nomem(state->cli->smb2.session, req)) {
847 0 : return tevent_req_post(req, ev);
848 : }
849 : }
850 :
851 17961 : cli_session_setup_gensec_local_next(req);
852 17961 : if (!tevent_req_is_in_progress(req)) {
853 0 : return tevent_req_post(req, ev);
854 : }
855 :
856 17961 : return req;
857 : }
858 :
859 51111 : static void cli_session_setup_gensec_local_next(struct tevent_req *req)
860 : {
861 0 : struct cli_session_setup_gensec_state *state =
862 51111 : tevent_req_data(req,
863 : struct cli_session_setup_gensec_state);
864 51111 : struct tevent_req *subreq = NULL;
865 :
866 51111 : if (state->local_ready) {
867 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
868 0 : return;
869 : }
870 :
871 51111 : subreq = gensec_update_send(state, state->ev,
872 51111 : state->auth_generic->gensec_security,
873 : state->blob_in);
874 51111 : if (tevent_req_nomem(subreq, req)) {
875 0 : return;
876 : }
877 51111 : tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
878 : }
879 :
880 51111 : static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
881 : {
882 0 : struct tevent_req *req =
883 51111 : tevent_req_callback_data(subreq,
884 : struct tevent_req);
885 0 : struct cli_session_setup_gensec_state *state =
886 51111 : tevent_req_data(req,
887 : struct cli_session_setup_gensec_state);
888 0 : NTSTATUS status;
889 :
890 51111 : status = gensec_update_recv(subreq, state, &state->blob_out);
891 51111 : TALLOC_FREE(subreq);
892 51111 : state->blob_in = data_blob_null;
893 51111 : if (!NT_STATUS_IS_OK(status) &&
894 33553 : !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
895 : {
896 24 : tevent_req_nterror(req, status);
897 24 : return;
898 : }
899 :
900 51087 : if (NT_STATUS_IS_OK(status)) {
901 17558 : state->local_ready = true;
902 : }
903 :
904 51087 : if (state->local_ready && state->remote_ready) {
905 17558 : cli_session_setup_gensec_ready(req);
906 17558 : return;
907 : }
908 :
909 33529 : cli_session_setup_gensec_remote_next(req);
910 : }
911 :
912 33529 : static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
913 : {
914 0 : struct cli_session_setup_gensec_state *state =
915 33529 : tevent_req_data(req,
916 : struct cli_session_setup_gensec_state);
917 33529 : struct tevent_req *subreq = NULL;
918 :
919 33529 : if (state->remote_ready) {
920 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
921 0 : return;
922 : }
923 :
924 33529 : subreq = cli_sesssetup_blob_send(state, state->ev,
925 : state->cli, state->blob_out);
926 33529 : if (tevent_req_nomem(subreq, req)) {
927 0 : return;
928 : }
929 33529 : tevent_req_set_callback(subreq,
930 : cli_session_setup_gensec_remote_done,
931 : req);
932 : }
933 :
934 33529 : static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
935 : {
936 0 : struct tevent_req *req =
937 33529 : tevent_req_callback_data(subreq,
938 : struct tevent_req);
939 0 : struct cli_session_setup_gensec_state *state =
940 33529 : tevent_req_data(req,
941 : struct cli_session_setup_gensec_state);
942 0 : NTSTATUS status;
943 :
944 33529 : state->inbuf = NULL;
945 33529 : TALLOC_FREE(state->recv_iov);
946 :
947 33529 : status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
948 : &state->inbuf, &state->recv_iov);
949 33529 : TALLOC_FREE(subreq);
950 33529 : data_blob_free(&state->blob_out);
951 33529 : if (!NT_STATUS_IS_OK(status) &&
952 15947 : !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
953 : {
954 357 : tevent_req_nterror(req, status);
955 357 : return;
956 : }
957 :
958 33172 : if (NT_STATUS_IS_OK(status)) {
959 17582 : struct smbXcli_session *session = NULL;
960 17582 : bool is_guest = false;
961 :
962 17582 : if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
963 13801 : session = state->cli->smb2.session;
964 : } else {
965 3781 : session = state->cli->smb1.session;
966 : }
967 :
968 17582 : is_guest = smbXcli_session_is_guest(session);
969 17582 : if (is_guest) {
970 : /*
971 : * We can't finish the gensec handshake, we don't
972 : * have a negotiated session key.
973 : *
974 : * So just pretend we are completely done,
975 : * we need to continue as anonymous from this point,
976 : * as we can't get a session key.
977 : *
978 : * Note that smbXcli_session_is_guest()
979 : * always returns false if we require signing.
980 : */
981 22 : state->blob_in = data_blob_null;
982 22 : state->local_ready = true;
983 22 : state->is_anonymous = true;
984 : }
985 :
986 17582 : state->remote_ready = true;
987 : }
988 :
989 33172 : if (state->local_ready && state->remote_ready) {
990 22 : cli_session_setup_gensec_ready(req);
991 22 : return;
992 : }
993 :
994 33150 : cli_session_setup_gensec_local_next(req);
995 : }
996 :
997 0 : static void cli_session_dump_keys(TALLOC_CTX *mem_ctx,
998 : struct smbXcli_session *session,
999 : DATA_BLOB session_key)
1000 : {
1001 0 : NTSTATUS status;
1002 0 : DATA_BLOB sig = data_blob_null;
1003 0 : DATA_BLOB app = data_blob_null;
1004 0 : DATA_BLOB enc = data_blob_null;
1005 0 : DATA_BLOB dec = data_blob_null;
1006 0 : uint64_t sid = smb2cli_session_current_id(session);
1007 :
1008 0 : status = smb2cli_session_signing_key(session, mem_ctx, &sig);
1009 0 : if (!NT_STATUS_IS_OK(status)) {
1010 0 : goto out;
1011 : }
1012 0 : status = smbXcli_session_application_key(session, mem_ctx, &app);
1013 0 : if (!NT_STATUS_IS_OK(status)) {
1014 0 : goto out;
1015 : }
1016 0 : status = smb2cli_session_encryption_key(session, mem_ctx, &enc);
1017 0 : if (!NT_STATUS_IS_OK(status)) {
1018 0 : goto out;
1019 : }
1020 0 : status = smb2cli_session_decryption_key(session, mem_ctx, &dec);
1021 0 : if (!NT_STATUS_IS_OK(status)) {
1022 0 : goto out;
1023 : }
1024 :
1025 0 : DEBUG(0, ("debug encryption: dumping generated session keys\n"));
1026 0 : DEBUGADD(0, ("Session Id "));
1027 0 : dump_data(0, (uint8_t*)&sid, sizeof(sid));
1028 0 : DEBUGADD(0, ("Session Key "));
1029 0 : dump_data(0, session_key.data, session_key.length);
1030 0 : DEBUGADD(0, ("Signing Key "));
1031 0 : dump_data(0, sig.data, sig.length);
1032 0 : DEBUGADD(0, ("App Key "));
1033 0 : dump_data(0, app.data, app.length);
1034 :
1035 : /* In client code, ServerIn is the encryption key */
1036 :
1037 0 : DEBUGADD(0, ("ServerIn Key "));
1038 0 : dump_data(0, enc.data, enc.length);
1039 0 : DEBUGADD(0, ("ServerOut Key "));
1040 0 : dump_data(0, dec.data, dec.length);
1041 :
1042 0 : out:
1043 0 : data_blob_clear_free(&sig);
1044 0 : data_blob_clear_free(&app);
1045 0 : data_blob_clear_free(&enc);
1046 0 : data_blob_clear_free(&dec);
1047 0 : }
1048 :
1049 17580 : static void cli_session_setup_gensec_ready(struct tevent_req *req)
1050 : {
1051 0 : struct cli_session_setup_gensec_state *state =
1052 17580 : tevent_req_data(req,
1053 : struct cli_session_setup_gensec_state);
1054 17580 : const char *server_domain = NULL;
1055 0 : NTSTATUS status;
1056 :
1057 17580 : if (state->blob_in.length != 0) {
1058 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1059 0 : return;
1060 : }
1061 :
1062 17580 : if (state->blob_out.length != 0) {
1063 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1064 0 : return;
1065 : }
1066 :
1067 : /*
1068 : * gensec_ntlmssp_server_domain() returns NULL
1069 : * if NTLMSSP is not used.
1070 : *
1071 : * We can remove this later
1072 : * and leave the server domain empty for SMB2 and above
1073 : * in future releases.
1074 : */
1075 17580 : server_domain = gensec_ntlmssp_server_domain(
1076 17580 : state->auth_generic->gensec_security);
1077 :
1078 17580 : if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1079 15220 : TALLOC_FREE(state->cli->server_domain);
1080 15220 : state->cli->server_domain = talloc_strdup(state->cli,
1081 : server_domain);
1082 15220 : if (state->cli->server_domain == NULL) {
1083 0 : tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1084 0 : return;
1085 : }
1086 : }
1087 :
1088 17580 : if (state->is_anonymous) {
1089 : /*
1090 : * Windows server does not set the
1091 : * SMB2_SESSION_FLAG_IS_NULL flag.
1092 : *
1093 : * This fix makes sure we do not try
1094 : * to verify a signature on the final
1095 : * session setup response.
1096 : */
1097 503 : tevent_req_done(req);
1098 503 : return;
1099 : }
1100 :
1101 17077 : status = gensec_session_key(state->auth_generic->gensec_security,
1102 : state, &state->session_key);
1103 17077 : if (tevent_req_nterror(req, status)) {
1104 0 : return;
1105 : }
1106 :
1107 17077 : if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1108 13336 : struct smbXcli_session *session = state->cli->smb2.session;
1109 :
1110 13336 : status = smb2cli_session_set_session_key(session,
1111 : state->session_key,
1112 13336 : state->recv_iov);
1113 13336 : if (tevent_req_nterror(req, status)) {
1114 0 : return;
1115 : }
1116 13336 : if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB3_00
1117 11963 : && lp_debug_encryption())
1118 : {
1119 0 : cli_session_dump_keys(state, session, state->session_key);
1120 : }
1121 : } else {
1122 3741 : struct smbXcli_session *session = state->cli->smb1.session;
1123 0 : bool active;
1124 :
1125 3741 : status = smb1cli_session_set_session_key(session,
1126 : state->session_key);
1127 3741 : if (tevent_req_nterror(req, status)) {
1128 0 : return;
1129 : }
1130 :
1131 3741 : active = smb1cli_conn_activate_signing(state->cli->conn,
1132 : state->session_key,
1133 : data_blob_null);
1134 3741 : if (active) {
1135 0 : bool ok;
1136 :
1137 326 : ok = smb1cli_conn_check_signing(state->cli->conn,
1138 : state->inbuf, 1);
1139 326 : if (!ok) {
1140 0 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1141 0 : return;
1142 : }
1143 : }
1144 : }
1145 :
1146 17077 : tevent_req_done(req);
1147 : }
1148 :
1149 17961 : static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1150 : {
1151 0 : struct cli_session_setup_gensec_state *state =
1152 17961 : tevent_req_data(req,
1153 : struct cli_session_setup_gensec_state);
1154 0 : NTSTATUS status;
1155 :
1156 17961 : if (tevent_req_is_nterror(req, &status)) {
1157 381 : cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1158 381 : return status;
1159 : }
1160 17580 : return NT_STATUS_OK;
1161 : }
1162 :
1163 618 : static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1164 : const char *principal)
1165 : {
1166 0 : char *account, *p;
1167 :
1168 618 : account = talloc_strdup(mem_ctx, principal);
1169 618 : if (account == NULL) {
1170 0 : return NULL;
1171 : }
1172 618 : p = strchr_m(account, '@');
1173 618 : if (p != NULL) {
1174 6 : *p = '\0';
1175 : }
1176 618 : return account;
1177 : }
1178 :
1179 : /****************************************************************************
1180 : Do a spnego encrypted session setup.
1181 :
1182 : user_domain: The shortname of the domain the user/machine is a member of.
1183 : dest_realm: The realm we're connecting to, if NULL we use our default realm.
1184 : ****************************************************************************/
1185 :
1186 : struct cli_session_setup_spnego_state {
1187 : ADS_STATUS result;
1188 : };
1189 :
1190 : static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1191 :
1192 17961 : static struct tevent_req *cli_session_setup_spnego_send(
1193 : TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1194 : struct cli_credentials *creds)
1195 : {
1196 0 : struct tevent_req *req, *subreq;
1197 0 : struct cli_session_setup_spnego_state *state;
1198 17961 : const char *target_service = NULL;
1199 17961 : const char *target_hostname = NULL;
1200 :
1201 17961 : req = tevent_req_create(mem_ctx, &state,
1202 : struct cli_session_setup_spnego_state);
1203 17961 : if (req == NULL) {
1204 0 : return NULL;
1205 : }
1206 :
1207 17961 : target_service = "cifs";
1208 17961 : target_hostname = smbXcli_conn_remote_name(cli->conn);
1209 :
1210 17961 : DBG_INFO("Connect to %s as %s using SPNEGO\n",
1211 : target_hostname,
1212 : cli_credentials_get_principal(creds, talloc_tos()));
1213 :
1214 17961 : subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1215 : target_service, target_hostname);
1216 17961 : if (tevent_req_nomem(subreq, req)) {
1217 0 : return tevent_req_post(req, ev);
1218 : }
1219 17961 : tevent_req_set_callback(
1220 : subreq, cli_session_setup_spnego_done, req);
1221 17961 : return req;
1222 : }
1223 :
1224 17961 : static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1225 : {
1226 17961 : struct tevent_req *req = tevent_req_callback_data(
1227 : subreq, struct tevent_req);
1228 0 : NTSTATUS status;
1229 :
1230 17961 : status = cli_session_setup_gensec_recv(subreq);
1231 17961 : TALLOC_FREE(subreq);
1232 17961 : if (tevent_req_nterror(req, status)) {
1233 381 : return;
1234 : }
1235 :
1236 17580 : tevent_req_done(req);
1237 : }
1238 :
1239 17961 : static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1240 : {
1241 17961 : struct cli_session_setup_spnego_state *state = tevent_req_data(
1242 : req, struct cli_session_setup_spnego_state);
1243 0 : NTSTATUS status;
1244 :
1245 17961 : if (tevent_req_is_nterror(req, &status)) {
1246 381 : state->result = ADS_ERROR_NT(status);
1247 : }
1248 :
1249 17961 : return state->result;
1250 : }
1251 :
1252 : struct cli_session_setup_creds_state {
1253 : struct cli_state *cli;
1254 : DATA_BLOB apassword_blob;
1255 : DATA_BLOB upassword_blob;
1256 : DATA_BLOB lm_session_key;
1257 : DATA_BLOB session_key;
1258 : char *out_native_os;
1259 : char *out_native_lm;
1260 : char *out_primary_domain;
1261 : };
1262 :
1263 36100 : static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1264 : enum tevent_req_state req_state)
1265 : {
1266 36100 : struct cli_session_setup_creds_state *state = tevent_req_data(
1267 : req, struct cli_session_setup_creds_state);
1268 :
1269 36100 : if (req_state != TEVENT_REQ_RECEIVED) {
1270 18050 : return;
1271 : }
1272 :
1273 : /*
1274 : * We only call data_blob_clear() as
1275 : * some of the blobs point to the same memory.
1276 : *
1277 : * We let the talloc hierarchy free the memory.
1278 : */
1279 18050 : data_blob_clear(&state->apassword_blob);
1280 18050 : data_blob_clear(&state->upassword_blob);
1281 18050 : data_blob_clear(&state->lm_session_key);
1282 18050 : data_blob_clear(&state->session_key);
1283 18050 : ZERO_STRUCTP(state);
1284 : }
1285 :
1286 : static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1287 : static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1288 : static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1289 :
1290 : /****************************************************************************
1291 : Send a session setup. The username and workgroup is in UNIX character
1292 : format and must be converted to DOS codepage format before sending. If the
1293 : password is in plaintext, the same should be done.
1294 : ****************************************************************************/
1295 :
1296 18050 : struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1297 : struct tevent_context *ev,
1298 : struct cli_state *cli,
1299 : struct cli_credentials *creds)
1300 : {
1301 0 : struct tevent_req *req, *subreq;
1302 0 : struct cli_session_setup_creds_state *state;
1303 18050 : uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1304 18050 : bool use_spnego = false;
1305 18050 : int flags = 0;
1306 18050 : const char *username = "";
1307 18050 : const char *domain = "";
1308 18050 : DATA_BLOB target_info = data_blob_null;
1309 18050 : DATA_BLOB challenge = data_blob_null;
1310 18050 : uint16_t in_buf_size = 0;
1311 18050 : uint16_t in_mpx_max = 0;
1312 18050 : uint16_t in_vc_num = 0;
1313 18050 : uint32_t in_sess_key = 0;
1314 18050 : const char *in_native_os = NULL;
1315 18050 : const char *in_native_lm = NULL;
1316 0 : enum credentials_use_kerberos krb5_state =
1317 18050 : cli_credentials_get_kerberos_state(creds);
1318 0 : NTSTATUS status;
1319 :
1320 18050 : req = tevent_req_create(mem_ctx, &state,
1321 : struct cli_session_setup_creds_state);
1322 18050 : if (req == NULL) {
1323 0 : return NULL;
1324 : }
1325 18050 : state->cli = cli;
1326 :
1327 18050 : tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1328 :
1329 : /*
1330 : * Now work out what sort of session setup we are going to
1331 : * do. I have split this into separate functions to make the flow a bit
1332 : * easier to understand (tridge).
1333 : */
1334 18050 : if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1335 24 : use_spnego = false;
1336 18026 : } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1337 14135 : use_spnego = true;
1338 3891 : } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1339 : /*
1340 : * if the server supports extended security then use SPNEGO
1341 : * even for anonymous connections.
1342 : */
1343 3826 : use_spnego = true;
1344 : } else {
1345 65 : use_spnego = false;
1346 : }
1347 :
1348 18050 : if (use_spnego) {
1349 17961 : subreq = cli_session_setup_spnego_send(
1350 : state, ev, cli, creds);
1351 17961 : if (tevent_req_nomem(subreq, req)) {
1352 0 : return tevent_req_post(req, ev);
1353 : }
1354 17961 : tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1355 : req);
1356 17961 : return req;
1357 : }
1358 :
1359 89 : if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
1360 0 : DBG_WARNING("Kerberos authentication requested, but "
1361 : "the server does not support SPNEGO authentication\n");
1362 0 : tevent_req_nterror(req, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT);
1363 0 : return tevent_req_post(req, ev);
1364 : }
1365 :
1366 89 : if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1367 : /*
1368 : * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1369 : * this step against older servers.
1370 : */
1371 0 : tevent_req_done(req);
1372 0 : return tevent_req_post(req, ev);
1373 : }
1374 :
1375 89 : if (cli_credentials_is_anonymous(creds)) {
1376 : /*
1377 : * Do an anonymous session setup
1378 : */
1379 33 : goto non_spnego_creds_done;
1380 : }
1381 :
1382 56 : if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1383 : /*
1384 : * Do an anonymous session setup,
1385 : * the password is passed via the tree connect.
1386 : */
1387 0 : goto non_spnego_creds_done;
1388 : }
1389 :
1390 56 : cli_credentials_get_ntlm_username_domain(creds, state,
1391 : &username,
1392 : &domain);
1393 56 : if (tevent_req_nomem(username, req)) {
1394 0 : return tevent_req_post(req, ev);
1395 : }
1396 56 : if (tevent_req_nomem(domain, req)) {
1397 0 : return tevent_req_post(req, ev);
1398 : }
1399 :
1400 56 : DBG_INFO("Connect to %s as %s using NTLM\n", domain, username);
1401 :
1402 56 : if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1403 0 : bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1404 0 : uint8_t *bytes = NULL;
1405 0 : size_t bytes_len = 0;
1406 0 : const char *pw = cli_credentials_get_password(creds);
1407 0 : size_t pw_len = 0;
1408 :
1409 0 : if (pw == NULL) {
1410 0 : pw = "";
1411 : }
1412 0 : pw_len = strlen(pw) + 1;
1413 :
1414 0 : if (!lp_client_plaintext_auth()) {
1415 0 : DEBUG(1, ("Server requested PLAINTEXT password but "
1416 : "'client plaintext auth = no'\n"));
1417 0 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1418 0 : return tevent_req_post(req, ev);
1419 : }
1420 :
1421 0 : bytes = talloc_array(state, uint8_t, 0);
1422 0 : bytes = trans2_bytes_push_str(bytes, use_unicode,
1423 : pw, pw_len, &bytes_len);
1424 0 : if (tevent_req_nomem(bytes, req)) {
1425 0 : return tevent_req_post(req, ev);
1426 : }
1427 :
1428 0 : if (use_unicode) {
1429 : /*
1430 : * CAP_UNICODE, can only be negotiated by NT1.
1431 : */
1432 0 : state->upassword_blob = data_blob_const(bytes,
1433 : bytes_len);
1434 : } else {
1435 0 : state->apassword_blob = data_blob_const(bytes,
1436 : bytes_len);
1437 : }
1438 :
1439 0 : goto non_spnego_creds_done;
1440 : }
1441 :
1442 56 : challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1443 :
1444 56 : if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1445 42 : if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1446 : /*
1447 : * Don't send an NTLMv2 response without NTLMSSP if we
1448 : * want to use spnego support.
1449 : */
1450 0 : DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1451 : " but 'client use spnego = yes'"
1452 : " and 'client ntlmv2 auth = yes' is set\n"));
1453 0 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1454 0 : return tevent_req_post(req, ev);
1455 : }
1456 :
1457 42 : if (lp_client_ntlmv2_auth()) {
1458 0 : flags |= CLI_CRED_NTLMv2_AUTH;
1459 :
1460 : /*
1461 : * note that the 'domain' here is a best
1462 : * guess - we don't know the server's domain
1463 : * at this point. Windows clients also don't
1464 : * use hostname...
1465 : */
1466 0 : target_info = NTLMv2_generate_names_blob(state,
1467 : NULL,
1468 : domain);
1469 0 : if (tevent_req_nomem(target_info.data, req)) {
1470 0 : return tevent_req_post(req, ev);
1471 : }
1472 : } else {
1473 42 : flags |= CLI_CRED_NTLM_AUTH;
1474 42 : if (lp_client_lanman_auth()) {
1475 36 : flags |= CLI_CRED_LANMAN_AUTH;
1476 : }
1477 : }
1478 : } else {
1479 14 : if (!lp_client_lanman_auth()) {
1480 0 : DEBUG(1, ("Server requested user level LM password but "
1481 : "'client lanman auth = no' is set.\n"));
1482 0 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1483 0 : return tevent_req_post(req, ev);
1484 : }
1485 :
1486 14 : flags |= CLI_CRED_LANMAN_AUTH;
1487 : }
1488 :
1489 56 : status = cli_credentials_get_ntlm_response(creds, state, &flags,
1490 : challenge, NULL,
1491 : target_info,
1492 56 : &state->apassword_blob,
1493 56 : &state->upassword_blob,
1494 56 : &state->lm_session_key,
1495 56 : &state->session_key);
1496 56 : if (tevent_req_nterror(req, status)) {
1497 0 : return tevent_req_post(req, ev);
1498 : }
1499 :
1500 56 : non_spnego_creds_done:
1501 :
1502 89 : in_buf_size = CLI_BUFFER_SIZE;
1503 89 : in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1504 89 : in_vc_num = cli_state_get_vc_num(cli);
1505 89 : in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1506 89 : in_native_os = "Unix";
1507 89 : in_native_lm = "Samba";
1508 :
1509 89 : if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1510 65 : uint32_t in_capabilities = 0;
1511 :
1512 65 : in_capabilities = cli_session_setup_capabilities(cli, 0);
1513 :
1514 : /*
1515 : * For now we keep the same values as before,
1516 : * we may remove these in a separate commit later.
1517 : */
1518 65 : in_mpx_max = 2;
1519 :
1520 65 : subreq = smb1cli_session_setup_nt1_send(state, ev,
1521 : cli->conn,
1522 65 : cli->timeout,
1523 : cli->smb1.pid,
1524 : cli->smb1.session,
1525 : in_buf_size,
1526 : in_mpx_max,
1527 : in_vc_num,
1528 : in_sess_key,
1529 : username,
1530 : domain,
1531 65 : state->apassword_blob,
1532 65 : state->upassword_blob,
1533 : in_capabilities,
1534 : in_native_os,
1535 : in_native_lm);
1536 65 : if (tevent_req_nomem(subreq, req)) {
1537 0 : return tevent_req_post(req, ev);
1538 : }
1539 65 : tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1540 : req);
1541 65 : return req;
1542 : }
1543 :
1544 : /*
1545 : * For now we keep the same values as before,
1546 : * we may remove these in a separate commit later.
1547 : */
1548 24 : in_mpx_max = 2;
1549 24 : in_vc_num = 1;
1550 :
1551 24 : subreq = smb1cli_session_setup_lm21_send(state, ev,
1552 : cli->conn,
1553 24 : cli->timeout,
1554 : cli->smb1.pid,
1555 : cli->smb1.session,
1556 : in_buf_size,
1557 : in_mpx_max,
1558 : in_vc_num,
1559 : in_sess_key,
1560 : username,
1561 : domain,
1562 24 : state->apassword_blob,
1563 : in_native_os,
1564 : in_native_lm);
1565 24 : if (tevent_req_nomem(subreq, req)) {
1566 0 : return tevent_req_post(req, ev);
1567 : }
1568 24 : tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1569 : req);
1570 24 : return req;
1571 : }
1572 :
1573 17961 : static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1574 : {
1575 17961 : struct tevent_req *req = tevent_req_callback_data(
1576 : subreq, struct tevent_req);
1577 0 : ADS_STATUS status;
1578 :
1579 17961 : status = cli_session_setup_spnego_recv(subreq);
1580 17961 : TALLOC_FREE(subreq);
1581 17961 : if (!ADS_ERR_OK(status)) {
1582 381 : DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1583 381 : tevent_req_nterror(req, ads_ntstatus(status));
1584 381 : return;
1585 : }
1586 17580 : tevent_req_done(req);
1587 : }
1588 :
1589 65 : static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1590 : {
1591 65 : struct tevent_req *req = tevent_req_callback_data(
1592 : subreq, struct tevent_req);
1593 65 : struct cli_session_setup_creds_state *state = tevent_req_data(
1594 : req, struct cli_session_setup_creds_state);
1595 65 : struct cli_state *cli = state->cli;
1596 0 : NTSTATUS status;
1597 65 : struct iovec *recv_iov = NULL;
1598 65 : const uint8_t *inbuf = NULL;
1599 0 : bool ok;
1600 :
1601 65 : status = smb1cli_session_setup_nt1_recv(subreq, state,
1602 : &recv_iov,
1603 : &inbuf,
1604 : &state->out_native_os,
1605 : &state->out_native_lm,
1606 : &state->out_primary_domain);
1607 65 : TALLOC_FREE(subreq);
1608 65 : if (tevent_req_nterror(req, status)) {
1609 4 : DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1610 5 : return;
1611 : }
1612 :
1613 61 : status = cli_state_update_after_sesssetup(state->cli,
1614 61 : state->out_native_os,
1615 61 : state->out_native_lm,
1616 61 : state->out_primary_domain);
1617 61 : if (tevent_req_nterror(req, status)) {
1618 0 : return;
1619 : }
1620 :
1621 61 : ok = smb1cli_conn_activate_signing(cli->conn,
1622 : state->session_key,
1623 : state->upassword_blob);
1624 61 : if (ok) {
1625 5 : ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1626 5 : if (!ok) {
1627 1 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1628 1 : return;
1629 : }
1630 : }
1631 :
1632 60 : if (state->session_key.data) {
1633 37 : struct smbXcli_session *session = cli->smb1.session;
1634 :
1635 37 : status = smb1cli_session_set_session_key(session,
1636 : state->session_key);
1637 37 : if (tevent_req_nterror(req, status)) {
1638 0 : return;
1639 : }
1640 : }
1641 :
1642 60 : tevent_req_done(req);
1643 : }
1644 :
1645 24 : static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1646 : {
1647 24 : struct tevent_req *req = tevent_req_callback_data(
1648 : subreq, struct tevent_req);
1649 24 : struct cli_session_setup_creds_state *state = tevent_req_data(
1650 : req, struct cli_session_setup_creds_state);
1651 0 : NTSTATUS status;
1652 :
1653 24 : status = smb1cli_session_setup_lm21_recv(subreq, state,
1654 : &state->out_native_os,
1655 : &state->out_native_lm);
1656 24 : TALLOC_FREE(subreq);
1657 24 : if (tevent_req_nterror(req, status)) {
1658 0 : DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1659 0 : return;
1660 : }
1661 :
1662 24 : status = cli_state_update_after_sesssetup(state->cli,
1663 24 : state->out_native_os,
1664 24 : state->out_native_lm,
1665 : NULL);
1666 24 : if (tevent_req_nterror(req, status)) {
1667 0 : return;
1668 : }
1669 :
1670 24 : tevent_req_done(req);
1671 : }
1672 :
1673 18050 : NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1674 : {
1675 18050 : return tevent_req_simple_recv_ntstatus(req);
1676 : }
1677 :
1678 12280 : NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1679 : struct cli_credentials *creds)
1680 : {
1681 0 : struct tevent_context *ev;
1682 0 : struct tevent_req *req;
1683 12280 : NTSTATUS status = NT_STATUS_NO_MEMORY;
1684 :
1685 12280 : if (smbXcli_conn_has_async_calls(cli->conn)) {
1686 0 : return NT_STATUS_INVALID_PARAMETER;
1687 : }
1688 12280 : ev = samba_tevent_context_init(talloc_tos());
1689 12280 : if (ev == NULL) {
1690 0 : goto fail;
1691 : }
1692 12280 : req = cli_session_setup_creds_send(ev, ev, cli, creds);
1693 12280 : if (req == NULL) {
1694 0 : goto fail;
1695 : }
1696 12280 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1697 0 : goto fail;
1698 : }
1699 12280 : status = cli_session_setup_creds_recv(req);
1700 12280 : fail:
1701 12280 : TALLOC_FREE(ev);
1702 12280 : return status;
1703 : }
1704 :
1705 50 : NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1706 : {
1707 0 : NTSTATUS status;
1708 50 : struct cli_credentials *creds = NULL;
1709 :
1710 50 : creds = cli_credentials_init_anon(cli);
1711 50 : if (creds == NULL) {
1712 0 : return NT_STATUS_NO_MEMORY;
1713 : }
1714 :
1715 50 : status = cli_session_setup_creds(cli, creds);
1716 50 : TALLOC_FREE(creds);
1717 50 : if (!NT_STATUS_IS_OK(status)) {
1718 0 : return status;
1719 : }
1720 :
1721 50 : return NT_STATUS_OK;
1722 : }
1723 :
1724 : /****************************************************************************
1725 : Send a uloggoff.
1726 : *****************************************************************************/
1727 :
1728 : struct cli_ulogoff_state {
1729 : struct cli_state *cli;
1730 : uint16_t vwv[3];
1731 : };
1732 :
1733 : static void cli_ulogoff_done(struct tevent_req *subreq);
1734 :
1735 4 : static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1736 : struct tevent_context *ev,
1737 : struct cli_state *cli)
1738 : {
1739 0 : struct tevent_req *req, *subreq;
1740 0 : struct cli_ulogoff_state *state;
1741 :
1742 4 : req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1743 4 : if (req == NULL) {
1744 0 : return NULL;
1745 : }
1746 4 : state->cli = cli;
1747 :
1748 4 : SCVAL(state->vwv+0, 0, 0xFF);
1749 4 : SCVAL(state->vwv+1, 0, 0);
1750 4 : SSVAL(state->vwv+2, 0, 0);
1751 :
1752 4 : subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1753 : 0, NULL);
1754 4 : if (tevent_req_nomem(subreq, req)) {
1755 0 : return tevent_req_post(req, ev);
1756 : }
1757 4 : tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1758 4 : return req;
1759 : }
1760 :
1761 4 : static void cli_ulogoff_done(struct tevent_req *subreq)
1762 : {
1763 4 : struct tevent_req *req = tevent_req_callback_data(
1764 : subreq, struct tevent_req);
1765 4 : struct cli_ulogoff_state *state = tevent_req_data(
1766 : req, struct cli_ulogoff_state);
1767 0 : NTSTATUS status;
1768 :
1769 4 : status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1770 4 : if (tevent_req_nterror(req, status)) {
1771 0 : return;
1772 : }
1773 4 : cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1774 4 : tevent_req_done(req);
1775 : }
1776 :
1777 4 : static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1778 : {
1779 4 : return tevent_req_simple_recv_ntstatus(req);
1780 : }
1781 :
1782 4 : NTSTATUS cli_ulogoff(struct cli_state *cli)
1783 : {
1784 0 : struct tevent_context *ev;
1785 0 : struct tevent_req *req;
1786 4 : NTSTATUS status = NT_STATUS_NO_MEMORY;
1787 :
1788 4 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1789 0 : status = smb2cli_logoff(cli->conn,
1790 0 : cli->timeout,
1791 : cli->smb2.session);
1792 0 : if (!NT_STATUS_IS_OK(status)) {
1793 0 : return status;
1794 : }
1795 0 : smb2cli_session_set_id_and_flags(cli->smb2.session,
1796 : UINT64_MAX, 0);
1797 0 : return NT_STATUS_OK;
1798 : }
1799 :
1800 4 : if (smbXcli_conn_has_async_calls(cli->conn)) {
1801 0 : return NT_STATUS_INVALID_PARAMETER;
1802 : }
1803 4 : ev = samba_tevent_context_init(talloc_tos());
1804 4 : if (ev == NULL) {
1805 0 : goto fail;
1806 : }
1807 4 : req = cli_ulogoff_send(ev, ev, cli);
1808 4 : if (req == NULL) {
1809 0 : goto fail;
1810 : }
1811 4 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1812 0 : goto fail;
1813 : }
1814 4 : status = cli_ulogoff_recv(req);
1815 4 : fail:
1816 4 : TALLOC_FREE(ev);
1817 4 : return status;
1818 : }
1819 :
1820 : /****************************************************************************
1821 : Send a tconX.
1822 : ****************************************************************************/
1823 :
1824 : struct cli_tcon_andx_state {
1825 : struct cli_state *cli;
1826 : uint16_t vwv[4];
1827 : struct iovec bytes;
1828 : };
1829 :
1830 : static void cli_tcon_andx_done(struct tevent_req *subreq);
1831 :
1832 7303 : struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1833 : struct tevent_context *ev,
1834 : struct cli_state *cli,
1835 : const char *share, const char *dev,
1836 : const char *pass, int passlen,
1837 : struct tevent_req **psmbreq)
1838 : {
1839 0 : struct tevent_req *req, *subreq;
1840 0 : struct cli_tcon_andx_state *state;
1841 0 : uint8_t p24[24];
1842 0 : uint16_t *vwv;
1843 7303 : char *tmp = NULL;
1844 0 : uint8_t *bytes;
1845 7303 : uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1846 7303 : uint16_t tcon_flags = 0;
1847 :
1848 7303 : *psmbreq = NULL;
1849 :
1850 7303 : req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1851 7303 : if (req == NULL) {
1852 0 : return NULL;
1853 : }
1854 7303 : state->cli = cli;
1855 7303 : vwv = state->vwv;
1856 :
1857 7303 : TALLOC_FREE(cli->smb1.tcon);
1858 7303 : cli->smb1.tcon = smbXcli_tcon_create(cli);
1859 7303 : if (tevent_req_nomem(cli->smb1.tcon, req)) {
1860 0 : return tevent_req_post(req, ev);
1861 : }
1862 7303 : smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
1863 :
1864 7303 : cli->share = talloc_strdup(cli, share);
1865 7303 : if (!cli->share) {
1866 0 : return NULL;
1867 : }
1868 :
1869 : /* in user level security don't send a password now */
1870 7303 : if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1871 7303 : passlen = 1;
1872 7303 : pass = "";
1873 0 : } else if (pass == NULL) {
1874 0 : DEBUG(1, ("Server not using user level security and no "
1875 : "password supplied.\n"));
1876 0 : goto access_denied;
1877 : }
1878 :
1879 7303 : if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1880 7303 : *pass && passlen != 24) {
1881 0 : if (!lp_client_lanman_auth()) {
1882 0 : DEBUG(1, ("Server requested LANMAN password "
1883 : "(share-level security) but "
1884 : "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1885 0 : goto access_denied;
1886 : }
1887 :
1888 : /*
1889 : * Non-encrypted passwords - convert to DOS codepage before
1890 : * encryption.
1891 : */
1892 0 : SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1893 0 : passlen = 24;
1894 0 : pass = (const char *)p24;
1895 : } else {
1896 7303 : if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1897 : |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1898 : == 0) {
1899 0 : uint8_t *tmp_pass;
1900 :
1901 0 : if (!lp_client_plaintext_auth() && (*pass)) {
1902 0 : DEBUG(1, ("Server requested PLAINTEXT "
1903 : "password but "
1904 : "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
1905 0 : goto access_denied;
1906 : }
1907 :
1908 : /*
1909 : * Non-encrypted passwords - convert to DOS codepage
1910 : * before using.
1911 : */
1912 0 : tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
1913 0 : if (tevent_req_nomem(tmp_pass, req)) {
1914 0 : return tevent_req_post(req, ev);
1915 : }
1916 0 : tmp_pass = trans2_bytes_push_str(tmp_pass,
1917 : false, /* always DOS */
1918 : pass,
1919 : passlen,
1920 : NULL);
1921 0 : if (tevent_req_nomem(tmp_pass, req)) {
1922 0 : return tevent_req_post(req, ev);
1923 : }
1924 0 : pass = (const char *)tmp_pass;
1925 0 : passlen = talloc_get_size(tmp_pass);
1926 : }
1927 : }
1928 :
1929 7303 : tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
1930 7303 : tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
1931 :
1932 7303 : SCVAL(vwv+0, 0, 0xFF);
1933 7303 : SCVAL(vwv+0, 1, 0);
1934 7303 : SSVAL(vwv+1, 0, 0);
1935 7303 : SSVAL(vwv+2, 0, tcon_flags);
1936 7303 : SSVAL(vwv+3, 0, passlen);
1937 :
1938 7303 : if (passlen && pass) {
1939 7303 : bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
1940 : } else {
1941 0 : bytes = talloc_array(state, uint8_t, 0);
1942 : }
1943 :
1944 : /*
1945 : * Add the sharename
1946 : */
1947 7303 : tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1948 : smbXcli_conn_remote_name(cli->conn), share);
1949 7303 : if (tmp == NULL) {
1950 0 : TALLOC_FREE(req);
1951 0 : return NULL;
1952 : }
1953 7303 : bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
1954 : NULL);
1955 7303 : TALLOC_FREE(tmp);
1956 :
1957 : /*
1958 : * Add the devicetype
1959 : */
1960 7303 : tmp = talloc_strdup_upper(talloc_tos(), dev);
1961 7303 : if (tmp == NULL) {
1962 0 : TALLOC_FREE(req);
1963 0 : return NULL;
1964 : }
1965 7303 : bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1966 7303 : TALLOC_FREE(tmp);
1967 :
1968 7303 : if (bytes == NULL) {
1969 0 : TALLOC_FREE(req);
1970 0 : return NULL;
1971 : }
1972 :
1973 7303 : state->bytes.iov_base = (void *)bytes;
1974 7303 : state->bytes.iov_len = talloc_get_size(bytes);
1975 :
1976 7303 : subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
1977 7303 : 1, &state->bytes);
1978 7303 : if (subreq == NULL) {
1979 0 : TALLOC_FREE(req);
1980 0 : return NULL;
1981 : }
1982 7303 : tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1983 7303 : *psmbreq = subreq;
1984 7303 : return req;
1985 :
1986 0 : access_denied:
1987 0 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1988 0 : return tevent_req_post(req, ev);
1989 : }
1990 :
1991 7298 : struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1992 : struct tevent_context *ev,
1993 : struct cli_state *cli,
1994 : const char *share, const char *dev,
1995 : const char *pass, int passlen)
1996 : {
1997 0 : struct tevent_req *req, *subreq;
1998 0 : NTSTATUS status;
1999 :
2000 7298 : req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2001 : &subreq);
2002 7298 : if (req == NULL) {
2003 0 : return NULL;
2004 : }
2005 7298 : if (subreq == NULL) {
2006 0 : return req;
2007 : }
2008 7298 : status = smb1cli_req_chain_submit(&subreq, 1);
2009 7298 : if (tevent_req_nterror(req, status)) {
2010 0 : return tevent_req_post(req, ev);
2011 : }
2012 7298 : return req;
2013 : }
2014 :
2015 7303 : static void cli_tcon_andx_done(struct tevent_req *subreq)
2016 : {
2017 7303 : struct tevent_req *req = tevent_req_callback_data(
2018 : subreq, struct tevent_req);
2019 7303 : struct cli_tcon_andx_state *state = tevent_req_data(
2020 : req, struct cli_tcon_andx_state);
2021 7303 : struct cli_state *cli = state->cli;
2022 0 : uint8_t *in;
2023 0 : uint8_t *inhdr;
2024 0 : uint8_t wct;
2025 0 : uint16_t *vwv;
2026 0 : uint32_t num_bytes;
2027 0 : uint8_t *bytes;
2028 0 : NTSTATUS status;
2029 7303 : uint16_t optional_support = 0;
2030 :
2031 7303 : status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2032 : &num_bytes, &bytes);
2033 7303 : TALLOC_FREE(subreq);
2034 7303 : if (tevent_req_nterror(req, status)) {
2035 36 : return;
2036 : }
2037 :
2038 7267 : inhdr = in + NBT_HDR_SIZE;
2039 :
2040 7267 : if (num_bytes) {
2041 7267 : if (pull_string_talloc(cli,
2042 : (const char *)inhdr,
2043 7267 : SVAL(inhdr, HDR_FLG2),
2044 : &cli->dev,
2045 : bytes,
2046 : num_bytes,
2047 : STR_TERMINATE|STR_ASCII) == -1) {
2048 0 : tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2049 0 : return;
2050 : }
2051 : } else {
2052 0 : cli->dev = talloc_strdup(cli, "");
2053 0 : if (cli->dev == NULL) {
2054 0 : tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2055 0 : return;
2056 : }
2057 : }
2058 :
2059 7267 : if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2060 : /* almost certainly win95 - enable bug fixes */
2061 0 : cli->win95 = True;
2062 : }
2063 :
2064 : /*
2065 : * Make sure that we have the optional support 16-bit field. WCT > 2.
2066 : * Avoids issues when connecting to Win9x boxes sharing files
2067 : */
2068 :
2069 7267 : if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2070 7243 : optional_support = SVAL(vwv+2, 0);
2071 : }
2072 :
2073 7267 : if (optional_support & SMB_EXTENDED_SIGNATURES) {
2074 3708 : smb1cli_session_protect_session_key(cli->smb1.session);
2075 : }
2076 :
2077 7267 : smb1cli_tcon_set_values(state->cli->smb1.tcon,
2078 7267 : SVAL(inhdr, HDR_TID),
2079 : optional_support,
2080 : 0, /* maximal_access */
2081 : 0, /* guest_maximal_access */
2082 : NULL, /* service */
2083 : NULL); /* fs_type */
2084 :
2085 7267 : tevent_req_done(req);
2086 : }
2087 :
2088 7303 : NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2089 : {
2090 7303 : return tevent_req_simple_recv_ntstatus(req);
2091 : }
2092 :
2093 0 : NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2094 : const char *dev, const char *pass, int passlen)
2095 : {
2096 0 : TALLOC_CTX *frame = talloc_stackframe();
2097 0 : struct tevent_context *ev;
2098 0 : struct tevent_req *req;
2099 0 : NTSTATUS status = NT_STATUS_NO_MEMORY;
2100 :
2101 0 : if (smbXcli_conn_has_async_calls(cli->conn)) {
2102 : /*
2103 : * Can't use sync call while an async call is in flight
2104 : */
2105 0 : status = NT_STATUS_INVALID_PARAMETER;
2106 0 : goto fail;
2107 : }
2108 :
2109 0 : ev = samba_tevent_context_init(frame);
2110 0 : if (ev == NULL) {
2111 0 : goto fail;
2112 : }
2113 :
2114 0 : req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2115 0 : if (req == NULL) {
2116 0 : goto fail;
2117 : }
2118 :
2119 0 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2120 0 : goto fail;
2121 : }
2122 :
2123 0 : status = cli_tcon_andx_recv(req);
2124 0 : fail:
2125 0 : TALLOC_FREE(frame);
2126 0 : return status;
2127 : }
2128 :
2129 : struct cli_tree_connect_state {
2130 : struct cli_state *cli;
2131 : };
2132 :
2133 : static struct tevent_req *cli_raw_tcon_send(
2134 : TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2135 : const char *service, const char *pass, const char *dev);
2136 : static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2137 : uint16_t *max_xmit, uint16_t *tid);
2138 :
2139 : static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2140 : static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2141 : static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2142 :
2143 38069 : static struct tevent_req *cli_tree_connect_send(
2144 : TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2145 : const char *share, const char *dev, const char *pass)
2146 : {
2147 0 : struct tevent_req *req, *subreq;
2148 0 : struct cli_tree_connect_state *state;
2149 0 : int passlen;
2150 :
2151 38069 : if (pass == NULL) {
2152 32483 : pass = "";
2153 : }
2154 38069 : passlen = strlen(pass) + 1;
2155 :
2156 38069 : req = tevent_req_create(mem_ctx, &state,
2157 : struct cli_tree_connect_state);
2158 38069 : if (req == NULL) {
2159 0 : return NULL;
2160 : }
2161 38069 : state->cli = cli;
2162 :
2163 38069 : cli->share = talloc_strdup(cli, share);
2164 38069 : if (tevent_req_nomem(cli->share, req)) {
2165 0 : return tevent_req_post(req, ev);
2166 : }
2167 :
2168 38069 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2169 0 : char *unc;
2170 :
2171 30771 : TALLOC_FREE(cli->smb2.tcon);
2172 30771 : cli->smb2.tcon = smbXcli_tcon_create(cli);
2173 30771 : if (tevent_req_nomem(cli->smb2.tcon, req)) {
2174 0 : return tevent_req_post(req, ev);
2175 : }
2176 :
2177 30771 : unc = talloc_asprintf(state, "\\\\%s\\%s",
2178 : smbXcli_conn_remote_name(cli->conn),
2179 : share);
2180 30771 : if (tevent_req_nomem(unc, req)) {
2181 0 : return tevent_req_post(req, ev);
2182 : }
2183 :
2184 30771 : subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2185 : cli->smb2.session, cli->smb2.tcon,
2186 : 0, /* flags */
2187 : unc);
2188 30771 : if (tevent_req_nomem(subreq, req)) {
2189 0 : return tevent_req_post(req, ev);
2190 : }
2191 30771 : tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2192 : req);
2193 30771 : return req;
2194 : }
2195 :
2196 7298 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2197 7298 : subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2198 : pass, passlen);
2199 7298 : if (tevent_req_nomem(subreq, req)) {
2200 0 : return tevent_req_post(req, ev);
2201 : }
2202 7298 : tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2203 : req);
2204 7298 : return req;
2205 : }
2206 :
2207 0 : subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2208 0 : if (tevent_req_nomem(subreq, req)) {
2209 0 : return tevent_req_post(req, ev);
2210 : }
2211 0 : tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2212 :
2213 0 : return req;
2214 : }
2215 :
2216 30771 : static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2217 : {
2218 30771 : NTSTATUS status = smb2cli_tcon_recv(subreq);
2219 30771 : tevent_req_simple_finish_ntstatus(subreq, status);
2220 30771 : }
2221 :
2222 7298 : static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2223 : {
2224 7298 : NTSTATUS status = cli_tcon_andx_recv(subreq);
2225 7298 : tevent_req_simple_finish_ntstatus(subreq, status);
2226 7298 : }
2227 :
2228 0 : static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2229 : {
2230 0 : struct tevent_req *req = tevent_req_callback_data(
2231 : subreq, struct tevent_req);
2232 0 : struct cli_tree_connect_state *state = tevent_req_data(
2233 : req, struct cli_tree_connect_state);
2234 0 : NTSTATUS status;
2235 0 : uint16_t max_xmit = 0;
2236 0 : uint16_t tid = 0;
2237 :
2238 0 : status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2239 0 : if (tevent_req_nterror(req, status)) {
2240 0 : return;
2241 : }
2242 :
2243 0 : smb1cli_tcon_set_values(state->cli->smb1.tcon,
2244 : tid,
2245 : 0, /* optional_support */
2246 : 0, /* maximal_access */
2247 : 0, /* guest_maximal_access */
2248 : NULL, /* service */
2249 : NULL); /* fs_type */
2250 :
2251 0 : tevent_req_done(req);
2252 : }
2253 :
2254 38069 : static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2255 : {
2256 38069 : return tevent_req_simple_recv_ntstatus(req);
2257 : }
2258 :
2259 32362 : NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2260 : const char *dev, const char *pass)
2261 : {
2262 0 : struct tevent_context *ev;
2263 0 : struct tevent_req *req;
2264 32362 : NTSTATUS status = NT_STATUS_NO_MEMORY;
2265 :
2266 32362 : if (smbXcli_conn_has_async_calls(cli->conn)) {
2267 0 : return NT_STATUS_INVALID_PARAMETER;
2268 : }
2269 32362 : ev = samba_tevent_context_init(talloc_tos());
2270 32362 : if (ev == NULL) {
2271 0 : goto fail;
2272 : }
2273 32362 : req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2274 32362 : if (req == NULL) {
2275 0 : goto fail;
2276 : }
2277 32362 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2278 0 : goto fail;
2279 : }
2280 32362 : status = cli_tree_connect_recv(req);
2281 32362 : fail:
2282 32362 : TALLOC_FREE(ev);
2283 32362 : return status;
2284 : }
2285 :
2286 12022 : NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2287 : const char *share, const char *dev,
2288 : struct cli_credentials *creds)
2289 : {
2290 12022 : bool need_pass = false;
2291 12022 : const char *pw = NULL;
2292 :
2293 : /*
2294 : * We should work out if the protocol
2295 : * will make use of a password for share level
2296 : * authentication before we may cause
2297 : * the password prompt to be called.
2298 : */
2299 12022 : if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2300 3445 : uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2301 :
2302 : /* in user level security don't send a password now */
2303 3445 : if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
2304 0 : need_pass = true;
2305 : }
2306 : }
2307 :
2308 12022 : if (need_pass && creds != NULL) {
2309 0 : pw = cli_credentials_get_password(creds);
2310 : }
2311 :
2312 12022 : return cli_tree_connect(cli, share, dev, pw);
2313 : }
2314 :
2315 : /****************************************************************************
2316 : Send a tree disconnect.
2317 : ****************************************************************************/
2318 :
2319 : struct cli_tdis_state {
2320 : struct cli_state *cli;
2321 : };
2322 :
2323 : static void cli_tdis_done(struct tevent_req *subreq);
2324 :
2325 7003 : static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2326 : struct tevent_context *ev,
2327 : struct cli_state *cli)
2328 : {
2329 0 : struct tevent_req *req, *subreq;
2330 0 : struct cli_tdis_state *state;
2331 :
2332 7003 : req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2333 7003 : if (req == NULL) {
2334 0 : return NULL;
2335 : }
2336 7003 : state->cli = cli;
2337 :
2338 7003 : subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2339 7003 : if (tevent_req_nomem(subreq, req)) {
2340 0 : return tevent_req_post(req, ev);
2341 : }
2342 7003 : tevent_req_set_callback(subreq, cli_tdis_done, req);
2343 7003 : return req;
2344 : }
2345 :
2346 7003 : static void cli_tdis_done(struct tevent_req *subreq)
2347 : {
2348 7003 : struct tevent_req *req = tevent_req_callback_data(
2349 : subreq, struct tevent_req);
2350 7003 : struct cli_tdis_state *state = tevent_req_data(
2351 : req, struct cli_tdis_state);
2352 0 : NTSTATUS status;
2353 :
2354 7003 : status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2355 7003 : TALLOC_FREE(subreq);
2356 7003 : if (tevent_req_nterror(req, status)) {
2357 18 : return;
2358 : }
2359 6985 : TALLOC_FREE(state->cli->smb1.tcon);
2360 6985 : tevent_req_done(req);
2361 : }
2362 :
2363 7003 : static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2364 : {
2365 7003 : return tevent_req_simple_recv_ntstatus(req);
2366 : }
2367 :
2368 34303 : NTSTATUS cli_tdis(struct cli_state *cli)
2369 : {
2370 0 : struct tevent_context *ev;
2371 0 : struct tevent_req *req;
2372 34303 : NTSTATUS status = NT_STATUS_NO_MEMORY;
2373 :
2374 34303 : if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2375 27302 : status = smb2cli_tdis(cli->conn,
2376 27302 : cli->timeout,
2377 : cli->smb2.session,
2378 : cli->smb2.tcon);
2379 27302 : if (NT_STATUS_IS_OK(status)) {
2380 27201 : TALLOC_FREE(cli->smb2.tcon);
2381 : }
2382 27302 : return status;
2383 : }
2384 :
2385 7001 : if (smbXcli_conn_has_async_calls(cli->conn)) {
2386 0 : return NT_STATUS_INVALID_PARAMETER;
2387 : }
2388 7001 : ev = samba_tevent_context_init(talloc_tos());
2389 7001 : if (ev == NULL) {
2390 0 : goto fail;
2391 : }
2392 7001 : req = cli_tdis_send(ev, ev, cli);
2393 7001 : if (req == NULL) {
2394 0 : goto fail;
2395 : }
2396 7001 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2397 0 : goto fail;
2398 : }
2399 7001 : status = cli_tdis_recv(req);
2400 7001 : fail:
2401 7001 : TALLOC_FREE(ev);
2402 7001 : return status;
2403 : }
2404 :
2405 : struct cli_connect_sock_state {
2406 : const char **called_names;
2407 : const char **calling_names;
2408 : int *called_types;
2409 : int fd;
2410 : uint16_t port;
2411 : };
2412 :
2413 : static void cli_connect_sock_done(struct tevent_req *subreq);
2414 :
2415 : /*
2416 : * Async only if we don't have to look up the name, i.e. "pss" is set with a
2417 : * nonzero address.
2418 : */
2419 :
2420 18455 : static struct tevent_req *cli_connect_sock_send(
2421 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2422 : const char *host, int name_type, const struct sockaddr_storage *pss,
2423 : const char *myname, uint16_t port)
2424 : {
2425 0 : struct tevent_req *req, *subreq;
2426 0 : struct cli_connect_sock_state *state;
2427 18455 : struct sockaddr_storage *addrs = NULL;
2428 0 : unsigned i;
2429 18455 : unsigned num_addrs = 0;
2430 0 : NTSTATUS status;
2431 :
2432 18455 : req = tevent_req_create(mem_ctx, &state,
2433 : struct cli_connect_sock_state);
2434 18455 : if (req == NULL) {
2435 0 : return NULL;
2436 : }
2437 :
2438 18455 : if ((pss == NULL) || is_zero_addr(pss)) {
2439 :
2440 : /*
2441 : * Here we cheat. resolve_name_list is not async at all. So
2442 : * this call will only be really async if the name lookup has
2443 : * been done externally.
2444 : */
2445 :
2446 10325 : status = resolve_name_list(state, host, name_type,
2447 : &addrs, &num_addrs);
2448 10325 : if (tevent_req_nterror(req, status)) {
2449 2 : return tevent_req_post(req, ev);
2450 : }
2451 : } else {
2452 8130 : addrs = talloc_array(state, struct sockaddr_storage, 1);
2453 8130 : if (tevent_req_nomem(addrs, req)) {
2454 0 : return tevent_req_post(req, ev);
2455 : }
2456 8130 : addrs[0] = *pss;
2457 8130 : num_addrs = 1;
2458 : }
2459 :
2460 18453 : state->called_names = talloc_array(state, const char *, num_addrs);
2461 18453 : if (tevent_req_nomem(state->called_names, req)) {
2462 0 : return tevent_req_post(req, ev);
2463 : }
2464 18453 : state->called_types = talloc_array(state, int, num_addrs);
2465 18453 : if (tevent_req_nomem(state->called_types, req)) {
2466 0 : return tevent_req_post(req, ev);
2467 : }
2468 18453 : state->calling_names = talloc_array(state, const char *, num_addrs);
2469 18453 : if (tevent_req_nomem(state->calling_names, req)) {
2470 0 : return tevent_req_post(req, ev);
2471 : }
2472 45504 : for (i=0; i<num_addrs; i++) {
2473 27051 : state->called_names[i] = host;
2474 27051 : state->called_types[i] = name_type;
2475 27051 : state->calling_names[i] = myname;
2476 : }
2477 :
2478 18453 : subreq = smbsock_any_connect_send(
2479 18453 : state, ev, addrs, state->called_names, state->called_types,
2480 18453 : state->calling_names, NULL, num_addrs, port);
2481 18453 : if (tevent_req_nomem(subreq, req)) {
2482 0 : return tevent_req_post(req, ev);
2483 : }
2484 18453 : tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2485 18453 : return req;
2486 : }
2487 :
2488 18453 : static void cli_connect_sock_done(struct tevent_req *subreq)
2489 : {
2490 18453 : struct tevent_req *req = tevent_req_callback_data(
2491 : subreq, struct tevent_req);
2492 18453 : struct cli_connect_sock_state *state = tevent_req_data(
2493 : req, struct cli_connect_sock_state);
2494 0 : NTSTATUS status;
2495 :
2496 18453 : status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2497 : &state->port);
2498 18453 : TALLOC_FREE(subreq);
2499 18453 : if (tevent_req_nterror(req, status)) {
2500 2 : return;
2501 : }
2502 18451 : set_socket_options(state->fd, lp_socket_options());
2503 18451 : tevent_req_done(req);
2504 : }
2505 :
2506 18455 : static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2507 : int *pfd, uint16_t *pport)
2508 : {
2509 18455 : struct cli_connect_sock_state *state = tevent_req_data(
2510 : req, struct cli_connect_sock_state);
2511 0 : NTSTATUS status;
2512 :
2513 18455 : if (tevent_req_is_nterror(req, &status)) {
2514 4 : return status;
2515 : }
2516 18451 : *pfd = state->fd;
2517 18451 : *pport = state->port;
2518 18451 : return NT_STATUS_OK;
2519 : }
2520 :
2521 : struct cli_connect_nb_state {
2522 : const char *desthost;
2523 : enum smb_signing_setting signing_state;
2524 : int flags;
2525 : struct cli_state *cli;
2526 : };
2527 :
2528 : static void cli_connect_nb_done(struct tevent_req *subreq);
2529 :
2530 18455 : static struct tevent_req *cli_connect_nb_send(
2531 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2532 : const char *host, const struct sockaddr_storage *dest_ss,
2533 : uint16_t port, int name_type, const char *myname,
2534 : enum smb_signing_setting signing_state, int flags)
2535 : {
2536 0 : struct tevent_req *req, *subreq;
2537 0 : struct cli_connect_nb_state *state;
2538 :
2539 18455 : req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2540 18455 : if (req == NULL) {
2541 0 : return NULL;
2542 : }
2543 18455 : state->signing_state = signing_state;
2544 18455 : state->flags = flags;
2545 :
2546 18455 : if (host != NULL) {
2547 18455 : char *p = strchr(host, '#');
2548 :
2549 18455 : if (p != NULL) {
2550 0 : name_type = strtol(p+1, NULL, 16);
2551 0 : host = talloc_strndup(state, host, p - host);
2552 0 : if (tevent_req_nomem(host, req)) {
2553 0 : return tevent_req_post(req, ev);
2554 : }
2555 : }
2556 :
2557 18455 : state->desthost = host;
2558 0 : } else if (dest_ss != NULL) {
2559 0 : state->desthost = print_canonical_sockaddr(state, dest_ss);
2560 0 : if (tevent_req_nomem(state->desthost, req)) {
2561 0 : return tevent_req_post(req, ev);
2562 : }
2563 : } else {
2564 : /* No host or dest_ss given. Error out. */
2565 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2566 0 : return tevent_req_post(req, ev);
2567 : }
2568 :
2569 18455 : subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2570 : myname, port);
2571 18455 : if (tevent_req_nomem(subreq, req)) {
2572 0 : return tevent_req_post(req, ev);
2573 : }
2574 18455 : tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2575 18455 : return req;
2576 : }
2577 :
2578 18455 : static void cli_connect_nb_done(struct tevent_req *subreq)
2579 : {
2580 18455 : struct tevent_req *req = tevent_req_callback_data(
2581 : subreq, struct tevent_req);
2582 18455 : struct cli_connect_nb_state *state = tevent_req_data(
2583 : req, struct cli_connect_nb_state);
2584 0 : NTSTATUS status;
2585 18455 : int fd = 0;
2586 0 : uint16_t port;
2587 :
2588 18455 : status = cli_connect_sock_recv(subreq, &fd, &port);
2589 18455 : TALLOC_FREE(subreq);
2590 18455 : if (tevent_req_nterror(req, status)) {
2591 4 : return;
2592 : }
2593 :
2594 18451 : state->cli = cli_state_create(state, fd, state->desthost,
2595 : state->signing_state, state->flags);
2596 18451 : if (tevent_req_nomem(state->cli, req)) {
2597 0 : close(fd);
2598 0 : return;
2599 : }
2600 18451 : tevent_req_done(req);
2601 : }
2602 :
2603 18455 : static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2604 : TALLOC_CTX *mem_ctx,
2605 : struct cli_state **pcli)
2606 : {
2607 18455 : struct cli_connect_nb_state *state = tevent_req_data(
2608 : req, struct cli_connect_nb_state);
2609 0 : NTSTATUS status;
2610 :
2611 18455 : if (tevent_req_is_nterror(req, &status)) {
2612 4 : return status;
2613 : }
2614 18451 : *pcli = talloc_move(mem_ctx, &state->cli);
2615 18451 : return NT_STATUS_OK;
2616 : }
2617 :
2618 12635 : NTSTATUS cli_connect_nb(TALLOC_CTX *mem_ctx,
2619 : const char *host,
2620 : const struct sockaddr_storage *dest_ss,
2621 : uint16_t port,
2622 : int name_type,
2623 : const char *myname,
2624 : enum smb_signing_setting signing_state,
2625 : int flags,
2626 : struct cli_state **pcli)
2627 : {
2628 0 : struct tevent_context *ev;
2629 0 : struct tevent_req *req;
2630 12635 : NTSTATUS status = NT_STATUS_NO_MEMORY;
2631 :
2632 12635 : ev = samba_tevent_context_init(mem_ctx);
2633 12635 : if (ev == NULL) {
2634 0 : goto fail;
2635 : }
2636 12635 : req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2637 : myname, signing_state, flags);
2638 12635 : if (req == NULL) {
2639 0 : goto fail;
2640 : }
2641 12635 : if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2642 0 : goto fail;
2643 : }
2644 12635 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2645 0 : goto fail;
2646 : }
2647 12635 : status = cli_connect_nb_recv(req, mem_ctx, pcli);
2648 12635 : fail:
2649 12635 : TALLOC_FREE(ev);
2650 12635 : return status;
2651 : }
2652 :
2653 : struct cli_start_connection_state {
2654 : struct tevent_context *ev;
2655 : struct cli_state *cli;
2656 : int min_protocol;
2657 : int max_protocol;
2658 : struct smb2_negotiate_contexts *negotiate_contexts;
2659 : };
2660 :
2661 : static void cli_start_connection_connected(struct tevent_req *subreq);
2662 : static void cli_start_connection_done(struct tevent_req *subreq);
2663 :
2664 : /**
2665 : establishes a connection to after the negprot.
2666 : @param output_cli A fully initialised cli structure, non-null only on success
2667 : @param dest_host The netbios name of the remote host
2668 : @param dest_ss (optional) The destination IP, NULL for name based lookup
2669 : @param port (optional) The destination port (0 for default)
2670 : */
2671 :
2672 5820 : static struct tevent_req *cli_start_connection_send(
2673 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2674 : const char *my_name, const char *dest_host,
2675 : const struct sockaddr_storage *dest_ss, int port,
2676 : enum smb_signing_setting signing_state, int flags,
2677 : struct smb2_negotiate_contexts *negotiate_contexts)
2678 : {
2679 0 : struct tevent_req *req, *subreq;
2680 0 : struct cli_start_connection_state *state;
2681 :
2682 5820 : req = tevent_req_create(mem_ctx, &state,
2683 : struct cli_start_connection_state);
2684 5820 : if (req == NULL) {
2685 0 : return NULL;
2686 : }
2687 5820 : state->ev = ev;
2688 :
2689 5820 : if (flags & CLI_FULL_CONNECTION_IPC) {
2690 1584 : state->min_protocol = lp_client_ipc_min_protocol();
2691 1584 : state->max_protocol = lp_client_ipc_max_protocol();
2692 : } else {
2693 4236 : state->min_protocol = lp_client_min_protocol();
2694 4236 : state->max_protocol = lp_client_max_protocol();
2695 : }
2696 :
2697 5820 : if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
2698 540 : state->max_protocol = MIN(state->max_protocol,
2699 : PROTOCOL_NT1);
2700 540 : state->min_protocol = MIN(state->min_protocol,
2701 : state->max_protocol);
2702 : }
2703 :
2704 5820 : if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
2705 4 : state->min_protocol = MAX(state->min_protocol,
2706 : PROTOCOL_SMB2_02);
2707 4 : state->max_protocol = MAX(state->max_protocol,
2708 : state->min_protocol);
2709 : }
2710 :
2711 5820 : state->negotiate_contexts = talloc_zero(
2712 : state, struct smb2_negotiate_contexts);
2713 5820 : if (tevent_req_nomem(state->negotiate_contexts, req)) {
2714 0 : return tevent_req_post(req, ev);
2715 : }
2716 :
2717 5820 : if (flags & CLI_FULL_CONNECTION_REQUEST_POSIX) {
2718 0 : NTSTATUS status;
2719 :
2720 24 : status = smb2_negotiate_context_add(
2721 24 : state->negotiate_contexts,
2722 24 : state->negotiate_contexts,
2723 : SMB2_POSIX_EXTENSIONS_AVAILABLE,
2724 : (const uint8_t *)SMB2_CREATE_TAG_POSIX,
2725 : strlen(SMB2_CREATE_TAG_POSIX));
2726 24 : if (tevent_req_nterror(req, status)) {
2727 0 : return tevent_req_post(req, ev);
2728 : }
2729 : }
2730 :
2731 5820 : if (negotiate_contexts != NULL) {
2732 : uint16_t i;
2733 :
2734 8 : for (i=0; i<negotiate_contexts->num_contexts; i++) {
2735 4 : struct smb2_negotiate_context *ctx =
2736 4 : &negotiate_contexts->contexts[i];
2737 0 : NTSTATUS status;
2738 :
2739 4 : status = smb2_negotiate_context_add(
2740 4 : state->negotiate_contexts,
2741 4 : state->negotiate_contexts,
2742 4 : ctx->type,
2743 4 : ctx->data.data,
2744 : ctx->data.length);
2745 4 : if (tevent_req_nterror(req, status)) {
2746 0 : return tevent_req_post(req, ev);
2747 : }
2748 : }
2749 : }
2750 :
2751 5820 : subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2752 : 0x20, my_name, signing_state, flags);
2753 5820 : if (tevent_req_nomem(subreq, req)) {
2754 0 : return tevent_req_post(req, ev);
2755 : }
2756 5820 : tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2757 5820 : return req;
2758 : }
2759 :
2760 5820 : static void cli_start_connection_connected(struct tevent_req *subreq)
2761 : {
2762 5820 : struct tevent_req *req = tevent_req_callback_data(
2763 : subreq, struct tevent_req);
2764 5820 : struct cli_start_connection_state *state = tevent_req_data(
2765 : req, struct cli_start_connection_state);
2766 0 : NTSTATUS status;
2767 :
2768 5820 : status = cli_connect_nb_recv(subreq, state, &state->cli);
2769 5820 : TALLOC_FREE(subreq);
2770 5820 : if (tevent_req_nterror(req, status)) {
2771 4 : return;
2772 : }
2773 :
2774 5816 : subreq = smbXcli_negprot_send(
2775 : state,
2776 : state->ev,
2777 5816 : state->cli->conn,
2778 5816 : state->cli->timeout,
2779 5816 : state->min_protocol,
2780 5816 : state->max_protocol,
2781 : WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK,
2782 : state->negotiate_contexts);
2783 5816 : if (tevent_req_nomem(subreq, req)) {
2784 0 : return;
2785 : }
2786 5816 : tevent_req_set_callback(subreq, cli_start_connection_done, req);
2787 : }
2788 :
2789 5816 : static void cli_start_connection_done(struct tevent_req *subreq)
2790 : {
2791 5816 : struct tevent_req *req = tevent_req_callback_data(
2792 : subreq, struct tevent_req);
2793 5816 : struct cli_start_connection_state *state = tevent_req_data(
2794 : req, struct cli_start_connection_state);
2795 0 : NTSTATUS status;
2796 :
2797 5816 : status = smbXcli_negprot_recv(subreq, NULL, NULL);
2798 5816 : TALLOC_FREE(subreq);
2799 5816 : if (tevent_req_nterror(req, status)) {
2800 26 : return;
2801 : }
2802 :
2803 5790 : if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2804 : /* Ensure we ask for some initial credits. */
2805 5180 : smb2cli_conn_set_max_credits(state->cli->conn,
2806 : DEFAULT_SMB2_MAX_CREDITS);
2807 : }
2808 :
2809 5790 : tevent_req_done(req);
2810 : }
2811 :
2812 5820 : static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2813 : TALLOC_CTX *mem_ctx,
2814 : struct cli_state **output_cli)
2815 : {
2816 5820 : struct cli_start_connection_state *state = tevent_req_data(
2817 : req, struct cli_start_connection_state);
2818 0 : NTSTATUS status;
2819 :
2820 5820 : if (tevent_req_is_nterror(req, &status)) {
2821 30 : return status;
2822 : }
2823 5790 : *output_cli = talloc_move(mem_ctx, &state->cli);
2824 :
2825 5790 : return NT_STATUS_OK;
2826 : }
2827 :
2828 21 : NTSTATUS cli_start_connection(TALLOC_CTX *mem_ctx,
2829 : struct cli_state **output_cli,
2830 : const char *my_name,
2831 : const char *dest_host,
2832 : const struct sockaddr_storage *dest_ss, int port,
2833 : enum smb_signing_setting signing_state, int flags)
2834 : {
2835 0 : struct tevent_context *ev;
2836 0 : struct tevent_req *req;
2837 21 : NTSTATUS status = NT_STATUS_NO_MEMORY;
2838 :
2839 21 : ev = samba_tevent_context_init(mem_ctx);
2840 21 : if (ev == NULL) {
2841 0 : goto fail;
2842 : }
2843 21 : req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2844 : port, signing_state, flags, NULL);
2845 21 : if (req == NULL) {
2846 0 : goto fail;
2847 : }
2848 21 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2849 0 : goto fail;
2850 : }
2851 21 : status = cli_start_connection_recv(req, mem_ctx, output_cli);
2852 21 : fail:
2853 21 : TALLOC_FREE(ev);
2854 21 : return status;
2855 : }
2856 :
2857 : struct cli_smb1_setup_encryption_blob_state {
2858 : uint16_t setup[1];
2859 : uint8_t param[4];
2860 : NTSTATUS status;
2861 : DATA_BLOB out;
2862 : uint16_t enc_ctx_id;
2863 : };
2864 :
2865 : static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2866 :
2867 884 : static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2868 : struct tevent_context *ev,
2869 : struct cli_state *cli,
2870 : const DATA_BLOB in)
2871 : {
2872 884 : struct tevent_req *req = NULL;
2873 884 : struct cli_smb1_setup_encryption_blob_state *state = NULL;
2874 884 : struct tevent_req *subreq = NULL;
2875 :
2876 884 : req = tevent_req_create(mem_ctx, &state,
2877 : struct cli_smb1_setup_encryption_blob_state);
2878 884 : if (req == NULL) {
2879 0 : return NULL;
2880 : }
2881 :
2882 884 : if (in.length > CLI_BUFFER_SIZE) {
2883 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2884 0 : return tevent_req_post(req, ev);
2885 : }
2886 :
2887 884 : SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
2888 884 : SSVAL(state->param, 0, 0);
2889 884 : SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
2890 :
2891 884 : subreq = smb1cli_trans_send(state, ev, cli->conn,
2892 : SMBtrans2,
2893 : 0, 0, /* _flags */
2894 : 0, 0, /* _flags2 */
2895 884 : cli->timeout,
2896 : cli->smb1.pid,
2897 : cli->smb1.tcon,
2898 : cli->smb1.session,
2899 : NULL, /* pipe_name */
2900 : 0, /* fid */
2901 : 0, /* function */
2902 : 0, /* flags */
2903 884 : state->setup, 1, 0,
2904 884 : state->param, 4, 2,
2905 884 : in.data, in.length, CLI_BUFFER_SIZE);
2906 884 : if (tevent_req_nomem(subreq, req)) {
2907 0 : return tevent_req_post(req, ev);
2908 : }
2909 884 : tevent_req_set_callback(subreq,
2910 : cli_smb1_setup_encryption_blob_done,
2911 : req);
2912 :
2913 884 : return req;
2914 : }
2915 :
2916 884 : static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
2917 : {
2918 0 : struct tevent_req *req =
2919 884 : tevent_req_callback_data(subreq,
2920 : struct tevent_req);
2921 0 : struct cli_smb1_setup_encryption_blob_state *state =
2922 884 : tevent_req_data(req,
2923 : struct cli_smb1_setup_encryption_blob_state);
2924 884 : uint8_t *rparam=NULL, *rdata=NULL;
2925 0 : uint32_t num_rparam, num_rdata;
2926 0 : NTSTATUS status;
2927 :
2928 884 : status = smb1cli_trans_recv(subreq, state,
2929 : NULL, /* recv_flags */
2930 : NULL, 0, NULL, /* rsetup */
2931 : &rparam, 0, &num_rparam,
2932 : &rdata, 0, &num_rdata);
2933 884 : TALLOC_FREE(subreq);
2934 884 : state->status = status;
2935 884 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2936 0 : status = NT_STATUS_OK;
2937 : }
2938 884 : if (tevent_req_nterror(req, status)) {
2939 0 : return;
2940 : }
2941 :
2942 884 : if (num_rparam == 2) {
2943 442 : state->enc_ctx_id = SVAL(rparam, 0);
2944 : }
2945 884 : TALLOC_FREE(rparam);
2946 :
2947 884 : state->out = data_blob_const(rdata, num_rdata);
2948 :
2949 884 : tevent_req_done(req);
2950 : }
2951 :
2952 884 : static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
2953 : TALLOC_CTX *mem_ctx,
2954 : DATA_BLOB *out,
2955 : uint16_t *enc_ctx_id)
2956 : {
2957 0 : struct cli_smb1_setup_encryption_blob_state *state =
2958 884 : tevent_req_data(req,
2959 : struct cli_smb1_setup_encryption_blob_state);
2960 0 : NTSTATUS status;
2961 :
2962 884 : if (tevent_req_is_nterror(req, &status)) {
2963 0 : tevent_req_received(req);
2964 0 : return status;
2965 : }
2966 :
2967 884 : status = state->status;
2968 :
2969 884 : *out = state->out;
2970 884 : talloc_steal(mem_ctx, out->data);
2971 :
2972 884 : *enc_ctx_id = state->enc_ctx_id;
2973 :
2974 884 : tevent_req_received(req);
2975 884 : return status;
2976 : }
2977 :
2978 : struct cli_smb1_setup_encryption_state {
2979 : struct tevent_context *ev;
2980 : struct cli_state *cli;
2981 : struct smb_trans_enc_state *es;
2982 : DATA_BLOB blob_in;
2983 : DATA_BLOB blob_out;
2984 : bool local_ready;
2985 : bool remote_ready;
2986 : };
2987 :
2988 : static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
2989 : static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
2990 : static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
2991 : static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
2992 : static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
2993 :
2994 442 : static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
2995 : struct tevent_context *ev,
2996 : struct cli_state *cli,
2997 : struct cli_credentials *creds)
2998 : {
2999 442 : struct tevent_req *req = NULL;
3000 442 : struct cli_smb1_setup_encryption_state *state = NULL;
3001 442 : struct auth_generic_state *ags = NULL;
3002 442 : const DATA_BLOB *b = NULL;
3003 442 : bool auth_requested = false;
3004 442 : const char *target_service = NULL;
3005 442 : const char *target_hostname = NULL;
3006 0 : NTSTATUS status;
3007 :
3008 442 : req = tevent_req_create(mem_ctx, &state,
3009 : struct cli_smb1_setup_encryption_state);
3010 442 : if (req == NULL) {
3011 0 : return NULL;
3012 : }
3013 442 : state->ev = ev;
3014 442 : state->cli = cli;
3015 :
3016 442 : auth_requested = cli_credentials_authentication_requested(creds);
3017 442 : if (!auth_requested) {
3018 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3019 0 : return tevent_req_post(req, ev);
3020 : }
3021 :
3022 442 : target_service = "cifs";
3023 442 : target_hostname = smbXcli_conn_remote_name(cli->conn);
3024 :
3025 442 : state->es = talloc_zero(state, struct smb_trans_enc_state);
3026 442 : if (tevent_req_nomem(state->es, req)) {
3027 0 : return tevent_req_post(req, ev);
3028 : }
3029 :
3030 442 : status = auth_generic_client_prepare(state->es, &ags);
3031 442 : if (tevent_req_nterror(req, status)) {
3032 0 : return tevent_req_post(req, ev);
3033 : }
3034 :
3035 442 : gensec_want_feature(ags->gensec_security,
3036 : GENSEC_FEATURE_SIGN);
3037 442 : gensec_want_feature(ags->gensec_security,
3038 : GENSEC_FEATURE_SEAL);
3039 :
3040 442 : status = auth_generic_set_creds(ags, creds);
3041 442 : if (tevent_req_nterror(req, status)) {
3042 0 : return tevent_req_post(req, ev);
3043 : }
3044 :
3045 442 : if (target_service != NULL) {
3046 442 : status = gensec_set_target_service(ags->gensec_security,
3047 : target_service);
3048 442 : if (tevent_req_nterror(req, status)) {
3049 0 : return tevent_req_post(req, ev);
3050 : }
3051 : }
3052 :
3053 442 : if (target_hostname != NULL) {
3054 442 : status = gensec_set_target_hostname(ags->gensec_security,
3055 : target_hostname);
3056 442 : if (tevent_req_nterror(req, status)) {
3057 0 : return tevent_req_post(req, ev);
3058 : }
3059 : }
3060 :
3061 442 : gensec_set_max_update_size(ags->gensec_security,
3062 : CLI_BUFFER_SIZE);
3063 :
3064 442 : b = smbXcli_conn_server_gss_blob(state->cli->conn);
3065 442 : if (b != NULL) {
3066 442 : state->blob_in = *b;
3067 : }
3068 :
3069 442 : status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3070 442 : if (tevent_req_nterror(req, status)) {
3071 0 : return tevent_req_post(req, ev);
3072 : }
3073 :
3074 : /*
3075 : * We only need the gensec_security part from here.
3076 : */
3077 442 : state->es->gensec_security = talloc_move(state->es,
3078 : &ags->gensec_security);
3079 442 : TALLOC_FREE(ags);
3080 :
3081 442 : cli_smb1_setup_encryption_local_next(req);
3082 442 : if (!tevent_req_is_in_progress(req)) {
3083 0 : return tevent_req_post(req, ev);
3084 : }
3085 :
3086 442 : return req;
3087 : }
3088 :
3089 1326 : static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3090 : {
3091 0 : struct cli_smb1_setup_encryption_state *state =
3092 1326 : tevent_req_data(req,
3093 : struct cli_smb1_setup_encryption_state);
3094 1326 : struct tevent_req *subreq = NULL;
3095 :
3096 1326 : if (state->local_ready) {
3097 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3098 0 : return;
3099 : }
3100 :
3101 1326 : subreq = gensec_update_send(state, state->ev,
3102 1326 : state->es->gensec_security,
3103 : state->blob_in);
3104 1326 : if (tevent_req_nomem(subreq, req)) {
3105 0 : return;
3106 : }
3107 1326 : tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3108 : }
3109 :
3110 1326 : static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3111 : {
3112 0 : struct tevent_req *req =
3113 1326 : tevent_req_callback_data(subreq,
3114 : struct tevent_req);
3115 0 : struct cli_smb1_setup_encryption_state *state =
3116 1326 : tevent_req_data(req,
3117 : struct cli_smb1_setup_encryption_state);
3118 0 : NTSTATUS status;
3119 :
3120 1326 : status = gensec_update_recv(subreq, state, &state->blob_out);
3121 1326 : TALLOC_FREE(subreq);
3122 1326 : state->blob_in = data_blob_null;
3123 1326 : if (!NT_STATUS_IS_OK(status) &&
3124 884 : !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3125 : {
3126 0 : tevent_req_nterror(req, status);
3127 0 : return;
3128 : }
3129 :
3130 1326 : if (NT_STATUS_IS_OK(status)) {
3131 442 : state->local_ready = true;
3132 : }
3133 :
3134 : /*
3135 : * We always get NT_STATUS_OK from the server even if it is not ready.
3136 : * So guess the server is ready when we are ready and already sent
3137 : * our last blob to the server.
3138 : */
3139 1326 : if (state->local_ready && state->blob_out.length == 0) {
3140 442 : state->remote_ready = true;
3141 : }
3142 :
3143 1326 : if (state->local_ready && state->remote_ready) {
3144 442 : cli_smb1_setup_encryption_ready(req);
3145 442 : return;
3146 : }
3147 :
3148 884 : cli_smb1_setup_encryption_remote_next(req);
3149 : }
3150 :
3151 884 : static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3152 : {
3153 0 : struct cli_smb1_setup_encryption_state *state =
3154 884 : tevent_req_data(req,
3155 : struct cli_smb1_setup_encryption_state);
3156 884 : struct tevent_req *subreq = NULL;
3157 :
3158 884 : if (state->remote_ready) {
3159 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3160 0 : return;
3161 : }
3162 :
3163 884 : subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3164 : state->cli, state->blob_out);
3165 884 : if (tevent_req_nomem(subreq, req)) {
3166 0 : return;
3167 : }
3168 884 : tevent_req_set_callback(subreq,
3169 : cli_smb1_setup_encryption_remote_done,
3170 : req);
3171 : }
3172 :
3173 884 : static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3174 : {
3175 0 : struct tevent_req *req =
3176 884 : tevent_req_callback_data(subreq,
3177 : struct tevent_req);
3178 0 : struct cli_smb1_setup_encryption_state *state =
3179 884 : tevent_req_data(req,
3180 : struct cli_smb1_setup_encryption_state);
3181 0 : NTSTATUS status;
3182 :
3183 884 : status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3184 : &state->blob_in,
3185 884 : &state->es->enc_ctx_num);
3186 884 : TALLOC_FREE(subreq);
3187 884 : data_blob_free(&state->blob_out);
3188 884 : if (!NT_STATUS_IS_OK(status) &&
3189 0 : !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3190 : {
3191 0 : tevent_req_nterror(req, status);
3192 0 : return;
3193 : }
3194 :
3195 : /*
3196 : * We always get NT_STATUS_OK even if the server is not ready.
3197 : * So guess the server is ready when we are ready and sent
3198 : * our last blob to the server.
3199 : */
3200 884 : if (state->local_ready) {
3201 0 : state->remote_ready = true;
3202 : }
3203 :
3204 884 : if (state->local_ready && state->remote_ready) {
3205 0 : cli_smb1_setup_encryption_ready(req);
3206 0 : return;
3207 : }
3208 :
3209 884 : cli_smb1_setup_encryption_local_next(req);
3210 : }
3211 :
3212 442 : static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3213 : {
3214 0 : struct cli_smb1_setup_encryption_state *state =
3215 442 : tevent_req_data(req,
3216 : struct cli_smb1_setup_encryption_state);
3217 442 : struct smb_trans_enc_state *es = NULL;
3218 :
3219 442 : if (state->blob_in.length != 0) {
3220 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3221 0 : return;
3222 : }
3223 :
3224 442 : if (state->blob_out.length != 0) {
3225 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3226 0 : return;
3227 : }
3228 :
3229 442 : es = talloc_move(state->cli->conn, &state->es);
3230 442 : es->enc_on = true;
3231 442 : smb1cli_conn_set_encryption(state->cli->conn, es);
3232 442 : es = NULL;
3233 :
3234 442 : tevent_req_done(req);
3235 : }
3236 :
3237 442 : static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3238 : {
3239 442 : return tevent_req_simple_recv_ntstatus(req);
3240 : }
3241 :
3242 440 : NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3243 : struct cli_credentials *creds)
3244 : {
3245 440 : struct tevent_context *ev = NULL;
3246 440 : struct tevent_req *req = NULL;
3247 440 : NTSTATUS status = NT_STATUS_NO_MEMORY;
3248 :
3249 440 : ev = samba_tevent_context_init(talloc_tos());
3250 440 : if (ev == NULL) {
3251 0 : goto fail;
3252 : }
3253 440 : req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3254 440 : if (req == NULL) {
3255 0 : goto fail;
3256 : }
3257 440 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3258 0 : goto fail;
3259 : }
3260 440 : status = cli_smb1_setup_encryption_recv(req);
3261 440 : fail:
3262 440 : TALLOC_FREE(ev);
3263 440 : return status;
3264 : }
3265 :
3266 : /**
3267 : establishes a connection right up to doing tconX, password specified.
3268 : @param output_cli A fully initialised cli structure, non-null only on success
3269 : @param dest_host The netbios name of the remote host
3270 : @param dest_ip (optional) The the destination IP, NULL for name based lookup
3271 : @param port (optional) The destination port (0 for default)
3272 : @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3273 : @param service_type The 'type' of service.
3274 : @param creds The used user credentials
3275 : */
3276 :
3277 : struct cli_full_connection_creds_state {
3278 : struct tevent_context *ev;
3279 : const char *service;
3280 : const char *service_type;
3281 : struct cli_credentials *creds;
3282 : int flags;
3283 : struct cli_state *cli;
3284 : };
3285 :
3286 89 : static int cli_full_connection_creds_state_destructor(
3287 : struct cli_full_connection_creds_state *s)
3288 : {
3289 89 : if (s->cli != NULL) {
3290 59 : cli_shutdown(s->cli);
3291 59 : s->cli = NULL;
3292 : }
3293 89 : return 0;
3294 : }
3295 :
3296 : static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3297 : static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3298 : static void cli_full_connection_creds_enc_start(struct tevent_req *req);
3299 : static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq);
3300 : static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq);
3301 : static void cli_full_connection_creds_enc_done(struct tevent_req *subreq);
3302 : static void cli_full_connection_creds_enc_tdis(struct tevent_req *req);
3303 : static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq);
3304 : static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3305 : static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3306 :
3307 5799 : struct tevent_req *cli_full_connection_creds_send(
3308 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3309 : const char *my_name, const char *dest_host,
3310 : const struct sockaddr_storage *dest_ss, int port,
3311 : const char *service, const char *service_type,
3312 : struct cli_credentials *creds,
3313 : int flags,
3314 : struct smb2_negotiate_contexts *negotiate_contexts)
3315 : {
3316 0 : struct tevent_req *req, *subreq;
3317 0 : struct cli_full_connection_creds_state *state;
3318 0 : enum smb_signing_setting signing_state;
3319 0 : enum smb_encryption_setting encryption_state =
3320 5799 : cli_credentials_get_smb_encryption(creds);
3321 :
3322 5799 : req = tevent_req_create(mem_ctx, &state,
3323 : struct cli_full_connection_creds_state);
3324 5799 : if (req == NULL) {
3325 0 : return NULL;
3326 : }
3327 5799 : talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3328 :
3329 5799 : state->ev = ev;
3330 5799 : state->service = service;
3331 5799 : state->service_type = service_type;
3332 5799 : state->creds = creds;
3333 5799 : state->flags = flags;
3334 :
3335 5799 : if (flags & CLI_FULL_CONNECTION_IPC) {
3336 1584 : signing_state = cli_credentials_get_smb_ipc_signing(creds);
3337 : } else {
3338 4215 : signing_state = cli_credentials_get_smb_signing(creds);
3339 : }
3340 :
3341 5799 : if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
3342 4 : if (flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK) {
3343 0 : encryption_state = SMB_ENCRYPTION_DESIRED;
3344 : }
3345 : }
3346 :
3347 5799 : if (encryption_state >= SMB_ENCRYPTION_DESIRED) {
3348 4 : signing_state = SMB_SIGNING_REQUIRED;
3349 : }
3350 :
3351 5799 : subreq = cli_start_connection_send(
3352 : state, ev, my_name, dest_host, dest_ss, port,
3353 : signing_state, flags,
3354 : negotiate_contexts);
3355 5799 : if (tevent_req_nomem(subreq, req)) {
3356 0 : return tevent_req_post(req, ev);
3357 : }
3358 5799 : tevent_req_set_callback(subreq,
3359 : cli_full_connection_creds_conn_done,
3360 : req);
3361 5799 : return req;
3362 : }
3363 :
3364 5799 : static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3365 : {
3366 5799 : struct tevent_req *req = tevent_req_callback_data(
3367 : subreq, struct tevent_req);
3368 5799 : struct cli_full_connection_creds_state *state = tevent_req_data(
3369 : req, struct cli_full_connection_creds_state);
3370 0 : NTSTATUS status;
3371 :
3372 5799 : status = cli_start_connection_recv(subreq, state, &state->cli);
3373 5799 : TALLOC_FREE(subreq);
3374 5799 : if (tevent_req_nterror(req, status)) {
3375 30 : return;
3376 : }
3377 :
3378 5769 : subreq = cli_session_setup_creds_send(
3379 : state, state->ev, state->cli, state->creds);
3380 5769 : if (tevent_req_nomem(subreq, req)) {
3381 0 : return;
3382 : }
3383 5769 : tevent_req_set_callback(subreq,
3384 : cli_full_connection_creds_sess_done,
3385 : req);
3386 : }
3387 :
3388 5770 : static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3389 : {
3390 5770 : struct tevent_req *req = tevent_req_callback_data(
3391 : subreq, struct tevent_req);
3392 5770 : struct cli_full_connection_creds_state *state = tevent_req_data(
3393 : req, struct cli_full_connection_creds_state);
3394 0 : NTSTATUS status;
3395 :
3396 5770 : status = cli_session_setup_creds_recv(subreq);
3397 5770 : TALLOC_FREE(subreq);
3398 :
3399 5770 : if (!NT_STATUS_IS_OK(status) &&
3400 60 : (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3401 :
3402 1 : state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3403 :
3404 1 : state->creds = cli_credentials_init_anon(state);
3405 1 : if (tevent_req_nomem(state->creds, req)) {
3406 60 : return;
3407 : }
3408 :
3409 1 : subreq = cli_session_setup_creds_send(
3410 : state, state->ev, state->cli, state->creds);
3411 1 : if (tevent_req_nomem(subreq, req)) {
3412 0 : return;
3413 : }
3414 1 : tevent_req_set_callback(subreq,
3415 : cli_full_connection_creds_sess_done,
3416 : req);
3417 1 : return;
3418 : }
3419 :
3420 5769 : if (tevent_req_nterror(req, status)) {
3421 59 : return;
3422 : }
3423 :
3424 5710 : cli_full_connection_creds_enc_start(req);
3425 : }
3426 :
3427 5710 : static void cli_full_connection_creds_enc_start(struct tevent_req *req)
3428 : {
3429 5710 : struct cli_full_connection_creds_state *state = tevent_req_data(
3430 : req, struct cli_full_connection_creds_state);
3431 0 : enum smb_encryption_setting encryption_state =
3432 5710 : cli_credentials_get_smb_encryption(state->creds);
3433 5710 : struct tevent_req *subreq = NULL;
3434 0 : NTSTATUS status;
3435 :
3436 5710 : if (encryption_state < SMB_ENCRYPTION_DESIRED) {
3437 5706 : cli_full_connection_creds_tcon_start(req);
3438 5708 : return;
3439 : }
3440 :
3441 4 : if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3442 2 : status = smb2cli_session_encryption_on(state->cli->smb2.session);
3443 2 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
3444 0 : if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3445 0 : cli_full_connection_creds_tcon_start(req);
3446 0 : return;
3447 : }
3448 0 : d_printf("Encryption required and "
3449 : "server doesn't support "
3450 : "SMB3 encryption - failing connect\n");
3451 0 : tevent_req_nterror(req, status);
3452 0 : return;
3453 2 : } else if (!NT_STATUS_IS_OK(status)) {
3454 0 : d_printf("Encryption required and "
3455 : "setup failed with error %s.\n",
3456 : nt_errstr(status));
3457 0 : tevent_req_nterror(req, status);
3458 0 : return;
3459 : }
3460 :
3461 2 : cli_full_connection_creds_tcon_start(req);
3462 2 : return;
3463 : }
3464 :
3465 2 : if (!SERVER_HAS_UNIX_CIFS(state->cli)) {
3466 0 : if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3467 0 : cli_full_connection_creds_tcon_start(req);
3468 0 : return;
3469 : }
3470 :
3471 0 : status = NT_STATUS_NOT_SUPPORTED;
3472 0 : d_printf("Encryption required and "
3473 : "server doesn't support "
3474 : "SMB1 Unix Extensions - failing connect\n");
3475 0 : tevent_req_nterror(req, status);
3476 0 : return;
3477 : }
3478 :
3479 : /*
3480 : * We do a tcon on IPC$ just to setup the encryption,
3481 : * the real tcon will be encrypted then.
3482 : */
3483 2 : subreq = cli_tree_connect_send(state, state->ev, state->cli,
3484 : "IPC$", "IPC", NULL);
3485 2 : if (tevent_req_nomem(subreq, req)) {
3486 0 : return;
3487 : }
3488 2 : tevent_req_set_callback(subreq, cli_full_connection_creds_enc_tcon, req);
3489 : }
3490 :
3491 2 : static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq)
3492 : {
3493 2 : struct tevent_req *req = tevent_req_callback_data(
3494 : subreq, struct tevent_req);
3495 2 : struct cli_full_connection_creds_state *state = tevent_req_data(
3496 : req, struct cli_full_connection_creds_state);
3497 0 : NTSTATUS status;
3498 :
3499 2 : status = cli_tree_connect_recv(subreq);
3500 2 : TALLOC_FREE(subreq);
3501 2 : if (tevent_req_nterror(req, status)) {
3502 0 : return;
3503 : }
3504 :
3505 2 : subreq = cli_unix_extensions_version_send(state, state->ev, state->cli);
3506 2 : if (tevent_req_nomem(subreq, req)) {
3507 0 : return;
3508 : }
3509 2 : tevent_req_set_callback(subreq, cli_full_connection_creds_enc_ver, req);
3510 : }
3511 :
3512 2 : static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq)
3513 : {
3514 2 : struct tevent_req *req = tevent_req_callback_data(
3515 : subreq, struct tevent_req);
3516 2 : struct cli_full_connection_creds_state *state = tevent_req_data(
3517 : req, struct cli_full_connection_creds_state);
3518 0 : enum smb_encryption_setting encryption_state =
3519 2 : cli_credentials_get_smb_encryption(state->creds);
3520 0 : uint16_t major, minor;
3521 0 : uint32_t caplow, caphigh;
3522 0 : NTSTATUS status;
3523 :
3524 2 : status = cli_unix_extensions_version_recv(subreq,
3525 : &major, &minor,
3526 : &caplow,
3527 : &caphigh);
3528 2 : TALLOC_FREE(subreq);
3529 2 : if (!NT_STATUS_IS_OK(status)) {
3530 0 : if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3531 : /* disconnect ipc$ followed by the real tree connect */
3532 0 : cli_full_connection_creds_enc_tdis(req);
3533 0 : return;
3534 : }
3535 0 : DEBUG(10, ("%s: cli_unix_extensions_version "
3536 : "returned %s\n", __func__, nt_errstr(status)));
3537 0 : tevent_req_nterror(req, NT_STATUS_UNKNOWN_REVISION);
3538 0 : return;
3539 : }
3540 :
3541 2 : if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
3542 0 : if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3543 : /* disconnect ipc$ followed by the real tree connect */
3544 0 : cli_full_connection_creds_enc_tdis(req);
3545 0 : return;
3546 : }
3547 0 : DEBUG(10, ("%s: CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP "
3548 : "not supported\n", __func__));
3549 0 : tevent_req_nterror(req, NT_STATUS_UNSUPPORTED_COMPRESSION);
3550 0 : return;
3551 : }
3552 :
3553 2 : subreq = cli_smb1_setup_encryption_send(state, state->ev,
3554 : state->cli,
3555 : state->creds);
3556 2 : if (tevent_req_nomem(subreq, req)) {
3557 0 : return;
3558 : }
3559 2 : tevent_req_set_callback(subreq,
3560 : cli_full_connection_creds_enc_done,
3561 : req);
3562 : }
3563 :
3564 2 : static void cli_full_connection_creds_enc_done(struct tevent_req *subreq)
3565 : {
3566 2 : struct tevent_req *req = tevent_req_callback_data(
3567 : subreq, struct tevent_req);
3568 0 : NTSTATUS status;
3569 :
3570 2 : status = cli_smb1_setup_encryption_recv(subreq);
3571 2 : TALLOC_FREE(subreq);
3572 2 : if (tevent_req_nterror(req, status)) {
3573 0 : return;
3574 : }
3575 :
3576 : /* disconnect ipc$ followed by the real tree connect */
3577 2 : cli_full_connection_creds_enc_tdis(req);
3578 : }
3579 :
3580 2 : static void cli_full_connection_creds_enc_tdis(struct tevent_req *req)
3581 : {
3582 2 : struct cli_full_connection_creds_state *state = tevent_req_data(
3583 : req, struct cli_full_connection_creds_state);
3584 2 : struct tevent_req *subreq = NULL;
3585 :
3586 2 : subreq = cli_tdis_send(state, state->ev, state->cli);
3587 2 : if (tevent_req_nomem(subreq, req)) {
3588 0 : return;
3589 : }
3590 2 : tevent_req_set_callback(subreq,
3591 : cli_full_connection_creds_enc_finished,
3592 : req);
3593 : }
3594 :
3595 2 : static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq)
3596 : {
3597 2 : struct tevent_req *req = tevent_req_callback_data(
3598 : subreq, struct tevent_req);
3599 0 : NTSTATUS status;
3600 :
3601 2 : status = cli_tdis_recv(subreq);
3602 2 : TALLOC_FREE(subreq);
3603 2 : if (tevent_req_nterror(req, status)) {
3604 0 : return;
3605 : }
3606 :
3607 2 : cli_full_connection_creds_tcon_start(req);
3608 : }
3609 :
3610 5710 : static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3611 : {
3612 5710 : struct cli_full_connection_creds_state *state = tevent_req_data(
3613 : req, struct cli_full_connection_creds_state);
3614 5710 : struct tevent_req *subreq = NULL;
3615 5710 : const char *password = NULL;
3616 :
3617 5710 : if (state->service == NULL) {
3618 5 : tevent_req_done(req);
3619 5 : return;
3620 : }
3621 :
3622 5705 : password = cli_credentials_get_password(state->creds);
3623 :
3624 5705 : subreq = cli_tree_connect_send(state, state->ev,
3625 : state->cli,
3626 : state->service,
3627 : state->service_type,
3628 : password);
3629 5705 : if (tevent_req_nomem(subreq, req)) {
3630 0 : return;
3631 : }
3632 5705 : tevent_req_set_callback(subreq,
3633 : cli_full_connection_creds_tcon_done,
3634 : req);
3635 : }
3636 :
3637 5705 : static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3638 : {
3639 5705 : struct tevent_req *req = tevent_req_callback_data(
3640 : subreq, struct tevent_req);
3641 0 : NTSTATUS status;
3642 :
3643 5705 : status = cli_tree_connect_recv(subreq);
3644 5705 : TALLOC_FREE(subreq);
3645 5705 : if (tevent_req_nterror(req, status)) {
3646 0 : return;
3647 : }
3648 :
3649 5705 : tevent_req_done(req);
3650 : }
3651 :
3652 5799 : NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3653 : TALLOC_CTX *mem_ctx,
3654 : struct cli_state **output_cli)
3655 : {
3656 5799 : struct cli_full_connection_creds_state *state = tevent_req_data(
3657 : req, struct cli_full_connection_creds_state);
3658 0 : NTSTATUS status;
3659 :
3660 5799 : if (tevent_req_is_nterror(req, &status)) {
3661 89 : return status;
3662 : }
3663 5710 : *output_cli = talloc_move(mem_ctx, &state->cli);
3664 5710 : talloc_set_destructor(state, NULL);
3665 5710 : return NT_STATUS_OK;
3666 : }
3667 :
3668 4347 : NTSTATUS cli_full_connection_creds(TALLOC_CTX *mem_ctx,
3669 : struct cli_state **output_cli,
3670 : const char *my_name,
3671 : const char *dest_host,
3672 : const struct sockaddr_storage *dest_ss, int port,
3673 : const char *service, const char *service_type,
3674 : struct cli_credentials *creds,
3675 : int flags)
3676 : {
3677 0 : struct tevent_context *ev;
3678 0 : struct tevent_req *req;
3679 4347 : NTSTATUS status = NT_STATUS_NO_MEMORY;
3680 :
3681 4347 : ev = samba_tevent_context_init(mem_ctx);
3682 4347 : if (ev == NULL) {
3683 0 : goto fail;
3684 : }
3685 4347 : req = cli_full_connection_creds_send(
3686 : ev, ev, my_name, dest_host, dest_ss, port, service,
3687 : service_type, creds, flags,
3688 : NULL);
3689 4347 : if (req == NULL) {
3690 0 : goto fail;
3691 : }
3692 4347 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3693 0 : goto fail;
3694 : }
3695 4347 : status = cli_full_connection_creds_recv(req, mem_ctx, output_cli);
3696 4347 : fail:
3697 4347 : TALLOC_FREE(ev);
3698 4347 : return status;
3699 : }
3700 :
3701 : /****************************************************************************
3702 : Send an old style tcon.
3703 : ****************************************************************************/
3704 : struct cli_raw_tcon_state {
3705 : uint16_t *ret_vwv;
3706 : };
3707 :
3708 : static void cli_raw_tcon_done(struct tevent_req *subreq);
3709 :
3710 7 : static struct tevent_req *cli_raw_tcon_send(
3711 : TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3712 : const char *service, const char *pass, const char *dev)
3713 : {
3714 0 : struct tevent_req *req, *subreq;
3715 0 : struct cli_raw_tcon_state *state;
3716 0 : uint8_t *bytes;
3717 :
3718 7 : req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3719 7 : if (req == NULL) {
3720 0 : return NULL;
3721 : }
3722 :
3723 7 : if (!lp_client_plaintext_auth() && (*pass)) {
3724 5 : DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3725 : " or 'client ntlmv2 auth = yes'\n"));
3726 5 : tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3727 5 : return tevent_req_post(req, ev);
3728 : }
3729 :
3730 2 : TALLOC_FREE(cli->smb1.tcon);
3731 2 : cli->smb1.tcon = smbXcli_tcon_create(cli);
3732 2 : if (tevent_req_nomem(cli->smb1.tcon, req)) {
3733 0 : return tevent_req_post(req, ev);
3734 : }
3735 2 : smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
3736 :
3737 2 : bytes = talloc_array(state, uint8_t, 0);
3738 2 : bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3739 2 : bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3740 2 : service, strlen(service)+1, NULL);
3741 2 : bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3742 2 : bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3743 2 : pass, strlen(pass)+1, NULL);
3744 2 : bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3745 2 : bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3746 2 : dev, strlen(dev)+1, NULL);
3747 :
3748 2 : if (tevent_req_nomem(bytes, req)) {
3749 0 : return tevent_req_post(req, ev);
3750 : }
3751 :
3752 2 : subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3753 2 : talloc_get_size(bytes), bytes);
3754 2 : if (tevent_req_nomem(subreq, req)) {
3755 0 : return tevent_req_post(req, ev);
3756 : }
3757 2 : tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3758 2 : return req;
3759 : }
3760 :
3761 2 : static void cli_raw_tcon_done(struct tevent_req *subreq)
3762 : {
3763 2 : struct tevent_req *req = tevent_req_callback_data(
3764 : subreq, struct tevent_req);
3765 2 : struct cli_raw_tcon_state *state = tevent_req_data(
3766 : req, struct cli_raw_tcon_state);
3767 0 : NTSTATUS status;
3768 :
3769 2 : status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3770 : NULL, NULL);
3771 2 : TALLOC_FREE(subreq);
3772 2 : if (tevent_req_nterror(req, status)) {
3773 2 : return;
3774 : }
3775 0 : tevent_req_done(req);
3776 : }
3777 :
3778 7 : static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3779 : uint16_t *max_xmit, uint16_t *tid)
3780 : {
3781 7 : struct cli_raw_tcon_state *state = tevent_req_data(
3782 : req, struct cli_raw_tcon_state);
3783 0 : NTSTATUS status;
3784 :
3785 7 : if (tevent_req_is_nterror(req, &status)) {
3786 7 : return status;
3787 : }
3788 0 : *max_xmit = SVAL(state->ret_vwv + 0, 0);
3789 0 : *tid = SVAL(state->ret_vwv + 1, 0);
3790 0 : return NT_STATUS_OK;
3791 : }
3792 :
3793 7 : NTSTATUS cli_raw_tcon(struct cli_state *cli,
3794 : const char *service, const char *pass, const char *dev,
3795 : uint16_t *max_xmit, uint16_t *tid)
3796 : {
3797 0 : struct tevent_context *ev;
3798 0 : struct tevent_req *req;
3799 7 : NTSTATUS status = NT_STATUS_NO_MEMORY;
3800 :
3801 7 : ev = samba_tevent_context_init(talloc_tos());
3802 7 : if (ev == NULL) {
3803 0 : goto fail;
3804 : }
3805 7 : req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3806 7 : if (req == NULL) {
3807 0 : goto fail;
3808 : }
3809 7 : if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3810 0 : goto fail;
3811 : }
3812 7 : status = cli_raw_tcon_recv(req, max_xmit, tid);
3813 7 : fail:
3814 7 : TALLOC_FREE(ev);
3815 7 : return status;
3816 : }
3817 :
3818 : /* Return a cli_state pointing at the IPC$ share for the given server */
3819 :
3820 23 : static struct cli_state *get_ipc_connect(TALLOC_CTX *mem_ctx,
3821 : char *server,
3822 : struct sockaddr_storage *server_ss,
3823 : struct cli_credentials *creds)
3824 : {
3825 0 : struct cli_state *cli;
3826 0 : NTSTATUS nt_status;
3827 23 : uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3828 :
3829 23 : flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
3830 23 : flags |= CLI_FULL_CONNECTION_IPC;
3831 :
3832 23 : nt_status = cli_full_connection_creds(mem_ctx,
3833 : &cli,
3834 : NULL,
3835 : server,
3836 : server_ss,
3837 : 0,
3838 : "IPC$",
3839 : "IPC",
3840 : creds,
3841 : flags);
3842 :
3843 23 : if (NT_STATUS_IS_OK(nt_status)) {
3844 1 : return cli;
3845 : }
3846 22 : if (is_ipaddress(server)) {
3847 : /* windows 9* needs a correct NMB name for connections */
3848 0 : fstring remote_name;
3849 :
3850 11 : if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3851 11 : cli = get_ipc_connect(mem_ctx, remote_name, server_ss, creds);
3852 11 : if (cli)
3853 0 : return cli;
3854 : }
3855 : }
3856 22 : return NULL;
3857 : }
3858 :
3859 : /*
3860 : * Given the IP address of a master browser on the network, return its
3861 : * workgroup and connect to it.
3862 : *
3863 : * This function is provided to allow additional processing beyond what
3864 : * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3865 : * browsers and obtain each master browsers' list of domains (in case the
3866 : * first master browser is recently on the network and has not yet
3867 : * synchronized with other master browsers and therefore does not yet have the
3868 : * entire network browse list)
3869 : */
3870 :
3871 12 : struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3872 : struct sockaddr_storage *mb_ip,
3873 : struct cli_credentials *creds,
3874 : char **pp_workgroup_out)
3875 : {
3876 0 : char addr[INET6_ADDRSTRLEN];
3877 0 : fstring name;
3878 0 : struct cli_state *cli;
3879 0 : struct sockaddr_storage server_ss;
3880 :
3881 12 : *pp_workgroup_out = NULL;
3882 :
3883 12 : print_sockaddr(addr, sizeof(addr), mb_ip);
3884 12 : DEBUG(99, ("Looking up name of master browser %s\n",
3885 : addr));
3886 :
3887 : /*
3888 : * Do a name status query to find out the name of the master browser.
3889 : * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3890 : * master browser will not respond to a wildcard query (or, at least,
3891 : * an NT4 server acting as the domain master browser will not).
3892 : *
3893 : * We might be able to use ONLY the query on MSBROWSE, but that's not
3894 : * yet been tested with all Windows versions, so until it is, leave
3895 : * the original wildcard query as the first choice and fall back to
3896 : * MSBROWSE if the wildcard query fails.
3897 : */
3898 12 : if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3899 0 : !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3900 :
3901 0 : DEBUG(99, ("Could not retrieve name status for %s\n",
3902 : addr));
3903 0 : return NULL;
3904 : }
3905 :
3906 12 : if (!find_master_ip(name, &server_ss)) {
3907 0 : DEBUG(99, ("Could not find master ip for %s\n", name));
3908 0 : return NULL;
3909 : }
3910 :
3911 12 : *pp_workgroup_out = talloc_strdup(ctx, name);
3912 :
3913 12 : DEBUG(4, ("found master browser %s, %s\n", name, addr));
3914 :
3915 12 : print_sockaddr(addr, sizeof(addr), &server_ss);
3916 12 : cli = get_ipc_connect(ctx, addr, &server_ss, creds);
3917 :
3918 12 : return cli;
3919 : }
|