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