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