s3:libsmb: allow store_cldap_reply() to work with a ipv6 response
[Samba.git] / source3 / libsmb / cliconnect.c
blob7e5c199b2d2a63039305aaf094448c0082d63031
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
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.
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.
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/>.
23 #include "includes.h"
24 #include "libsmb/libsmb.h"
25 #include "libsmb/namequery.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "smb_krb5.h"
28 #include "auth/credentials/credentials.h"
29 #include "auth/gensec/gensec.h"
30 #include "auth/ntlmssp/ntlmssp.h"
31 #include "auth_generic.h"
32 #include "libads/kerberos_proto.h"
33 #include "krb5_env.h"
34 #include "../lib/util/tevent_ntstatus.h"
35 #include "async_smb.h"
36 #include "libsmb/nmblib.h"
37 #include "librpc/ndr/libndr.h"
38 #include "../libcli/smb/smbXcli_base.h"
39 #include "../libcli/smb/smb_seal.h"
40 #include "lib/param/param.h"
41 #include "../libcli/smb/smb2_negotiate_context.h"
43 #define STAR_SMBSERVER "*SMBSERVER"
45 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
46 const char *principal);
48 struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
49 const char *username,
50 const char *domain,
51 const char *realm,
52 const char *password,
53 bool use_kerberos,
54 bool fallback_after_kerberos,
55 bool use_ccache,
56 bool password_is_nt_hash)
58 struct loadparm_context *lp_ctx = NULL;
59 struct cli_credentials *creds = NULL;
60 const char *principal = NULL;
61 char *tmp = NULL;
62 char *p = NULL;
63 bool ok;
65 creds = cli_credentials_init(mem_ctx);
66 if (creds == NULL) {
67 return NULL;
70 lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
71 if (lp_ctx == NULL) {
72 goto fail;
74 ok = cli_credentials_set_conf(creds, lp_ctx);
75 if (!ok) {
76 goto fail;
79 if (username == NULL) {
80 username = "";
83 if (strlen(username) == 0) {
84 if (password != NULL && strlen(password) == 0) {
86 * some callers pass "" as no password
88 * gensec only handles NULL as no password.
90 password = NULL;
92 if (password == NULL) {
93 cli_credentials_set_anonymous(creds);
94 return creds;
98 tmp = talloc_strdup(creds, username);
99 if (tmp == NULL) {
100 goto fail;
102 username = tmp;
104 /* allow for workgroups as part of the username */
105 if ((p = strchr_m(tmp, '\\')) ||
106 (p = strchr_m(tmp, '/')) ||
107 (p = strchr_m(tmp, *lp_winbind_separator()))) {
108 *p = 0;
109 username = p + 1;
110 domain = tmp;
113 principal = username;
114 username = cli_session_setup_get_account(creds, principal);
115 if (username == NULL) {
116 goto fail;
118 ok = strequal(username, principal);
119 if (ok) {
121 * Ok still the same, so it's not a principal
123 principal = NULL;
126 if (use_kerberos && fallback_after_kerberos) {
128 * Keep what we learned from the
129 * "client use kerberos" option.
131 enum credentials_use_kerberos current_krb5 =
132 cli_credentials_get_kerberos_state(creds);
133 cli_credentials_set_kerberos_state(creds,
134 current_krb5,
135 CRED_SPECIFIED);
136 } else if (use_kerberos) {
137 cli_credentials_set_kerberos_state(creds,
138 CRED_USE_KERBEROS_REQUIRED,
139 CRED_SPECIFIED);
140 } else {
141 cli_credentials_set_kerberos_state(creds,
142 CRED_USE_KERBEROS_DISABLED,
143 CRED_SPECIFIED);
146 if (use_ccache) {
147 uint32_t features;
149 features = cli_credentials_get_gensec_features(creds);
150 features |= GENSEC_FEATURE_NTLM_CCACHE;
151 cli_credentials_set_gensec_features(creds,
152 features,
153 CRED_SPECIFIED);
155 if (password != NULL && strlen(password) == 0) {
157 * some callers pass "" as no password
159 * GENSEC_FEATURE_NTLM_CCACHE only handles
160 * NULL as no password.
162 password = NULL;
166 ok = cli_credentials_set_username(creds,
167 username,
168 CRED_SPECIFIED);
169 if (!ok) {
170 goto fail;
173 if (domain != NULL) {
174 ok = cli_credentials_set_domain(creds,
175 domain,
176 CRED_SPECIFIED);
177 if (!ok) {
178 goto fail;
182 if (principal != NULL) {
183 ok = cli_credentials_set_principal(creds,
184 principal,
185 CRED_SPECIFIED);
186 if (!ok) {
187 goto fail;
191 if (realm != NULL) {
192 ok = cli_credentials_set_realm(creds,
193 realm,
194 CRED_SPECIFIED);
195 if (!ok) {
196 goto fail;
200 if (password != NULL && strlen(password) > 0) {
201 if (password_is_nt_hash) {
202 struct samr_Password nt_hash;
203 size_t converted;
205 converted = strhex_to_str((char *)nt_hash.hash,
206 sizeof(nt_hash.hash),
207 password,
208 strlen(password));
209 if (converted != sizeof(nt_hash.hash)) {
210 goto fail;
213 ok = cli_credentials_set_nt_hash(creds,
214 &nt_hash,
215 CRED_SPECIFIED);
216 if (!ok) {
217 goto fail;
219 } else {
220 ok = cli_credentials_set_password(creds,
221 password,
222 CRED_SPECIFIED);
223 if (!ok) {
224 goto fail;
229 return creds;
230 fail:
231 TALLOC_FREE(creds);
232 return NULL;
235 NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
236 struct cli_credentials *creds)
238 TALLOC_CTX *frame = talloc_stackframe();
239 const char *user_principal = NULL;
240 const char *user_account = NULL;
241 const char *user_domain = NULL;
242 const char *pass = NULL;
243 char *canon_principal = NULL;
244 char *canon_realm = NULL;
245 const char *target_hostname = NULL;
246 enum credentials_use_kerberos krb5_state;
247 bool try_kerberos = false;
248 bool need_kinit = false;
249 bool auth_requested = true;
250 int ret;
251 bool ok;
253 target_hostname = smbXcli_conn_remote_name(cli->conn);
255 auth_requested = cli_credentials_authentication_requested(creds);
256 if (auth_requested) {
257 errno = 0;
258 user_principal = cli_credentials_get_principal(creds, frame);
259 if (errno != 0) {
260 TALLOC_FREE(frame);
261 return NT_STATUS_NO_MEMORY;
264 user_account = cli_credentials_get_username(creds);
265 user_domain = cli_credentials_get_domain(creds);
266 pass = cli_credentials_get_password(creds);
268 krb5_state = cli_credentials_get_kerberos_state(creds);
270 if (krb5_state != CRED_USE_KERBEROS_DISABLED) {
271 try_kerberos = true;
274 if (user_principal == NULL) {
275 try_kerberos = false;
278 if (target_hostname == NULL) {
279 try_kerberos = false;
280 } else if (is_ipaddress(target_hostname)) {
281 try_kerberos = false;
282 } else if (strequal(target_hostname, "localhost")) {
283 try_kerberos = false;
284 } else if (strequal(target_hostname, STAR_SMBSERVER)) {
285 try_kerberos = false;
286 } else if (!auth_requested) {
287 try_kerberos = false;
290 if (krb5_state == CRED_USE_KERBEROS_REQUIRED && !try_kerberos) {
291 DEBUG(0, ("Kerberos auth with '%s' (%s\\%s) to access "
292 "'%s' not possible\n",
293 user_principal, user_domain, user_account,
294 target_hostname));
295 TALLOC_FREE(frame);
296 return NT_STATUS_ACCESS_DENIED;
299 if (pass == NULL || strlen(pass) == 0) {
300 need_kinit = false;
301 } else if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
302 need_kinit = try_kerberos;
303 } else {
304 need_kinit = try_kerberos;
307 if (!need_kinit) {
308 TALLOC_FREE(frame);
309 return NT_STATUS_OK;
312 DBG_INFO("Doing kinit for %s to access %s\n",
313 user_principal, target_hostname);
316 * TODO: This should be done within the gensec layer
317 * only if required!
319 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
320 ret = kerberos_kinit_password_ext(user_principal,
321 pass,
325 NULL,
326 false,
327 false,
329 frame,
330 &canon_principal,
331 &canon_realm,
332 NULL);
333 if (ret != 0) {
334 int dbglvl = DBGLVL_NOTICE;
336 if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
337 dbglvl = DBGLVL_ERR;
340 DEBUG(dbglvl, ("Kinit for %s to access %s failed: %s\n",
341 user_principal, target_hostname,
342 error_message(ret)));
343 if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
344 TALLOC_FREE(frame);
345 return krb5_to_nt_status(ret);
349 * Ignore the error and hope that NTLM will work
351 TALLOC_FREE(frame);
352 return NT_STATUS_OK;
355 ok = cli_credentials_set_principal(creds,
356 canon_principal,
357 CRED_SPECIFIED);
358 if (!ok) {
359 TALLOC_FREE(frame);
360 return NT_STATUS_NO_MEMORY;
363 ok = cli_credentials_set_realm(creds,
364 canon_realm,
365 CRED_SPECIFIED);
366 if (!ok) {
367 TALLOC_FREE(frame);
368 return NT_STATUS_NO_MEMORY;
371 DBG_DEBUG("Successfully authenticated as %s (%s) to access %s using "
372 "Kerberos\n",
373 user_principal,
374 canon_principal,
375 target_hostname);
377 TALLOC_FREE(frame);
378 return NT_STATUS_OK;
381 static NTSTATUS cli_state_update_after_sesssetup(struct cli_state *cli,
382 const char *native_os,
383 const char *native_lm,
384 const char *primary_domain)
386 #define _VALID_STR(p) ((p) != NULL && (p)[0] != '\0')
388 if (!_VALID_STR(cli->server_os) && _VALID_STR(native_os)) {
389 cli->server_os = talloc_strdup(cli, native_os);
390 if (cli->server_os == NULL) {
391 return NT_STATUS_NO_MEMORY;
395 if (!_VALID_STR(cli->server_type) && _VALID_STR(native_lm)) {
396 cli->server_type = talloc_strdup(cli, native_lm);
397 if (cli->server_type == NULL) {
398 return NT_STATUS_NO_MEMORY;
402 if (!_VALID_STR(cli->server_domain) && _VALID_STR(primary_domain)) {
403 cli->server_domain = talloc_strdup(cli, primary_domain);
404 if (cli->server_domain == NULL) {
405 return NT_STATUS_NO_MEMORY;
409 #undef _VALID_STRING
410 return NT_STATUS_OK;
413 /********************************************************
414 Utility function to ensure we always return at least
415 a valid char * pointer to an empty string for the
416 cli->server_os, cli->server_type and cli->server_domain
417 strings.
418 *******************************************************/
420 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
421 const uint8_t *hdr,
422 char **dest,
423 uint8_t *src,
424 size_t srclen,
425 ssize_t *destlen)
427 *destlen = pull_string_talloc(mem_ctx,
428 (const char *)hdr,
429 SVAL(hdr, HDR_FLG2),
430 dest,
431 (char *)src,
432 srclen,
433 STR_TERMINATE);
434 if (*destlen == -1) {
435 return NT_STATUS_NO_MEMORY;
438 if (*dest == NULL) {
439 *dest = talloc_strdup(mem_ctx, "");
440 if (*dest == NULL) {
441 return NT_STATUS_NO_MEMORY;
444 return NT_STATUS_OK;
447 /****************************************************************************
448 Work out suitable capabilities to offer the server.
449 ****************************************************************************/
451 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
452 uint32_t sesssetup_capabilities)
454 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
457 * We only send capabilities based on the mask for:
458 * - client only flags
459 * - flags used in both directions
461 * We do not echo the server only flags, except some legacy flags.
463 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
464 * CAP_LARGE_WRITEX in order to allow us to do large reads
465 * against old Samba releases (<= 3.6.x).
467 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
470 * Session Setup specific flags CAP_DYNAMIC_REAUTH
471 * and CAP_EXTENDED_SECURITY are passed by the caller.
472 * We need that in order to do guest logins even if
473 * CAP_EXTENDED_SECURITY is negotiated.
475 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
476 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
477 client_capabilities |= sesssetup_capabilities;
479 return client_capabilities;
482 /****************************************************************************
483 Do a NT1 guest session setup.
484 ****************************************************************************/
486 struct cli_session_setup_guest_state {
487 struct cli_state *cli;
488 uint16_t vwv[13];
489 struct iovec bytes;
492 static void cli_session_setup_guest_done(struct tevent_req *subreq);
494 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
495 struct tevent_context *ev,
496 struct cli_state *cli,
497 struct tevent_req **psmbreq)
499 struct tevent_req *req, *subreq;
500 struct cli_session_setup_guest_state *state;
501 uint16_t *vwv;
502 uint8_t *bytes;
504 req = tevent_req_create(mem_ctx, &state,
505 struct cli_session_setup_guest_state);
506 if (req == NULL) {
507 return NULL;
509 state->cli = cli;
510 vwv = state->vwv;
512 SCVAL(vwv+0, 0, 0xFF);
513 SCVAL(vwv+0, 1, 0);
514 SSVAL(vwv+1, 0, 0);
515 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
516 SSVAL(vwv+3, 0, 2);
517 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
518 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
519 SSVAL(vwv+7, 0, 0);
520 SSVAL(vwv+8, 0, 0);
521 SSVAL(vwv+9, 0, 0);
522 SSVAL(vwv+10, 0, 0);
523 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
525 bytes = talloc_array(state, uint8_t, 0);
527 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
528 NULL);
529 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
530 NULL);
531 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
532 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
534 if (bytes == NULL) {
535 TALLOC_FREE(req);
536 return NULL;
539 state->bytes.iov_base = (void *)bytes;
540 state->bytes.iov_len = talloc_get_size(bytes);
542 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
543 vwv, 1, &state->bytes);
544 if (subreq == NULL) {
545 TALLOC_FREE(req);
546 return NULL;
548 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
549 *psmbreq = subreq;
550 return req;
553 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
554 struct tevent_context *ev,
555 struct cli_state *cli)
557 struct tevent_req *req, *subreq;
558 NTSTATUS status;
560 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
561 if (req == NULL) {
562 return NULL;
565 status = smb1cli_req_chain_submit(&subreq, 1);
566 if (!NT_STATUS_IS_OK(status)) {
567 tevent_req_nterror(req, status);
568 return tevent_req_post(req, ev);
570 return req;
573 static void cli_session_setup_guest_done(struct tevent_req *subreq)
575 struct tevent_req *req = tevent_req_callback_data(
576 subreq, struct tevent_req);
577 struct cli_session_setup_guest_state *state = tevent_req_data(
578 req, struct cli_session_setup_guest_state);
579 struct cli_state *cli = state->cli;
580 uint32_t num_bytes;
581 uint8_t *in;
582 uint8_t *inhdr;
583 uint8_t *bytes;
584 uint8_t *p;
585 NTSTATUS status;
586 ssize_t ret;
587 uint8_t wct;
588 uint16_t *vwv;
590 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
591 &num_bytes, &bytes);
592 TALLOC_FREE(subreq);
593 if (!NT_STATUS_IS_OK(status)) {
594 tevent_req_nterror(req, status);
595 return;
598 inhdr = in + NBT_HDR_SIZE;
599 p = bytes;
601 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
602 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
604 status = smb_bytes_talloc_string(cli,
605 inhdr,
606 &cli->server_os,
608 bytes+num_bytes-p,
609 &ret);
611 if (!NT_STATUS_IS_OK(status)) {
612 tevent_req_nterror(req, status);
613 return;
615 p += ret;
617 status = smb_bytes_talloc_string(cli,
618 inhdr,
619 &cli->server_type,
621 bytes+num_bytes-p,
622 &ret);
624 if (!NT_STATUS_IS_OK(status)) {
625 tevent_req_nterror(req, status);
626 return;
628 p += ret;
630 status = smb_bytes_talloc_string(cli,
631 inhdr,
632 &cli->server_domain,
634 bytes+num_bytes-p,
635 &ret);
637 if (!NT_STATUS_IS_OK(status)) {
638 tevent_req_nterror(req, status);
639 return;
642 tevent_req_done(req);
645 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
647 return tevent_req_simple_recv_ntstatus(req);
650 /* The following is calculated from :
651 * (smb_size-4) = 35
652 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
653 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
654 * end of packet.
657 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
659 struct cli_sesssetup_blob_state {
660 struct tevent_context *ev;
661 struct cli_state *cli;
662 DATA_BLOB blob;
663 uint16_t max_blob_size;
665 DATA_BLOB this_blob;
666 struct iovec *recv_iov;
668 NTSTATUS status;
669 const uint8_t *inbuf;
670 DATA_BLOB ret_blob;
672 char *out_native_os;
673 char *out_native_lm;
676 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
677 struct tevent_req **psubreq);
678 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
680 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
681 struct tevent_context *ev,
682 struct cli_state *cli,
683 DATA_BLOB blob)
685 struct tevent_req *req, *subreq;
686 struct cli_sesssetup_blob_state *state;
687 uint32_t usable_space;
689 req = tevent_req_create(mem_ctx, &state,
690 struct cli_sesssetup_blob_state);
691 if (req == NULL) {
692 return NULL;
694 state->ev = ev;
695 state->blob = blob;
696 state->cli = cli;
698 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
699 usable_space = UINT16_MAX;
700 } else {
701 usable_space = cli_state_available_size(cli,
702 BASE_SESSSETUP_BLOB_PACKET_SIZE);
705 if (usable_space == 0) {
706 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
707 "(not possible to send %u bytes)\n",
708 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
709 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
710 return tevent_req_post(req, ev);
712 state->max_blob_size = MIN(usable_space, 0xFFFF);
714 if (!cli_sesssetup_blob_next(state, &subreq)) {
715 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
716 return tevent_req_post(req, ev);
718 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
719 return req;
722 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
723 struct tevent_req **psubreq)
725 struct tevent_req *subreq;
726 uint16_t thistime;
728 thistime = MIN(state->blob.length, state->max_blob_size);
730 state->this_blob.data = state->blob.data;
731 state->this_blob.length = thistime;
733 state->blob.data += thistime;
734 state->blob.length -= thistime;
736 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
737 subreq = smb2cli_session_setup_send(state, state->ev,
738 state->cli->conn,
739 state->cli->timeout,
740 state->cli->smb2.session,
741 0, /* in_flags */
742 SMB2_CAP_DFS, /* in_capabilities */
743 0, /* in_channel */
744 0, /* in_previous_session_id */
745 &state->this_blob);
746 if (subreq == NULL) {
747 return false;
749 } else {
750 uint16_t in_buf_size = 0;
751 uint16_t in_mpx_max = 0;
752 uint16_t in_vc_num = 0;
753 uint32_t in_sess_key = 0;
754 uint32_t in_capabilities = 0;
755 const char *in_native_os = NULL;
756 const char *in_native_lm = NULL;
758 in_buf_size = CLI_BUFFER_SIZE;
759 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
760 in_vc_num = cli_state_get_vc_num(state->cli);
761 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
762 in_capabilities = cli_session_setup_capabilities(state->cli,
763 CAP_EXTENDED_SECURITY);
764 in_native_os = "Unix";
765 in_native_lm = "Samba";
768 * For now we keep the same values as before,
769 * we may remove these in a separate commit later.
771 in_mpx_max = 2;
772 in_vc_num = 1;
773 in_sess_key = 0;
775 subreq = smb1cli_session_setup_ext_send(state, state->ev,
776 state->cli->conn,
777 state->cli->timeout,
778 state->cli->smb1.pid,
779 state->cli->smb1.session,
780 in_buf_size,
781 in_mpx_max,
782 in_vc_num,
783 in_sess_key,
784 state->this_blob,
785 in_capabilities,
786 in_native_os,
787 in_native_lm);
788 if (subreq == NULL) {
789 return false;
792 *psubreq = subreq;
793 return true;
796 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
798 struct tevent_req *req = tevent_req_callback_data(
799 subreq, struct tevent_req);
800 struct cli_sesssetup_blob_state *state = tevent_req_data(
801 req, struct cli_sesssetup_blob_state);
802 NTSTATUS status;
804 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
805 status = smb2cli_session_setup_recv(subreq, state,
806 &state->recv_iov,
807 &state->ret_blob);
808 } else {
809 status = smb1cli_session_setup_ext_recv(subreq, state,
810 &state->recv_iov,
811 &state->inbuf,
812 &state->ret_blob,
813 &state->out_native_os,
814 &state->out_native_lm);
816 TALLOC_FREE(subreq);
817 if (!NT_STATUS_IS_OK(status)
818 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
819 tevent_req_nterror(req, status);
820 return;
823 state->status = status;
825 status = cli_state_update_after_sesssetup(state->cli,
826 state->out_native_os,
827 state->out_native_lm,
828 NULL);
829 if (tevent_req_nterror(req, status)) {
830 return;
833 if (state->blob.length != 0) {
835 * More to send
837 if (!cli_sesssetup_blob_next(state, &subreq)) {
838 tevent_req_oom(req);
839 return;
841 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
842 return;
844 tevent_req_done(req);
847 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
848 TALLOC_CTX *mem_ctx,
849 DATA_BLOB *pblob,
850 const uint8_t **pinbuf,
851 struct iovec **precv_iov)
853 struct cli_sesssetup_blob_state *state = tevent_req_data(
854 req, struct cli_sesssetup_blob_state);
855 NTSTATUS status;
856 struct iovec *recv_iov;
858 if (tevent_req_is_nterror(req, &status)) {
859 TALLOC_FREE(state->cli->smb2.session);
860 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
861 tevent_req_received(req);
862 return status;
865 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
866 if (pblob != NULL) {
867 *pblob = state->ret_blob;
869 if (pinbuf != NULL) {
870 *pinbuf = state->inbuf;
872 if (precv_iov != NULL) {
873 *precv_iov = recv_iov;
875 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
876 status = state->status;
877 tevent_req_received(req);
878 return status;
881 /****************************************************************************
882 Do a spnego/NTLMSSP encrypted session setup.
883 ****************************************************************************/
885 struct cli_session_setup_gensec_state {
886 struct tevent_context *ev;
887 struct cli_state *cli;
888 struct auth_generic_state *auth_generic;
889 bool is_anonymous;
890 DATA_BLOB blob_in;
891 const uint8_t *inbuf;
892 struct iovec *recv_iov;
893 DATA_BLOB blob_out;
894 bool local_ready;
895 bool remote_ready;
896 DATA_BLOB session_key;
899 static int cli_session_setup_gensec_state_destructor(
900 struct cli_session_setup_gensec_state *state)
902 TALLOC_FREE(state->auth_generic);
903 data_blob_clear_free(&state->session_key);
904 return 0;
907 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
908 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
909 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
910 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
911 static void cli_session_setup_gensec_ready(struct tevent_req *req);
913 static struct tevent_req *cli_session_setup_gensec_send(
914 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
915 struct cli_credentials *creds,
916 const char *target_service,
917 const char *target_hostname)
919 struct tevent_req *req;
920 struct cli_session_setup_gensec_state *state;
921 NTSTATUS status;
922 const DATA_BLOB *b = NULL;
924 req = tevent_req_create(mem_ctx, &state,
925 struct cli_session_setup_gensec_state);
926 if (req == NULL) {
927 return NULL;
929 state->ev = ev;
930 state->cli = cli;
932 talloc_set_destructor(
933 state, cli_session_setup_gensec_state_destructor);
935 status = auth_generic_client_prepare(state, &state->auth_generic);
936 if (tevent_req_nterror(req, status)) {
937 return tevent_req_post(req, ev);
940 status = auth_generic_set_creds(state->auth_generic, creds);
941 if (tevent_req_nterror(req, status)) {
942 return tevent_req_post(req, ev);
945 gensec_want_feature(state->auth_generic->gensec_security,
946 GENSEC_FEATURE_SESSION_KEY);
948 if (target_service != NULL) {
949 status = gensec_set_target_service(
950 state->auth_generic->gensec_security,
951 target_service);
952 if (tevent_req_nterror(req, status)) {
953 return tevent_req_post(req, ev);
957 if (target_hostname != NULL) {
958 status = gensec_set_target_hostname(
959 state->auth_generic->gensec_security,
960 target_hostname);
961 if (tevent_req_nterror(req, status)) {
962 return tevent_req_post(req, ev);
966 b = smbXcli_conn_server_gss_blob(cli->conn);
967 if (b != NULL) {
968 state->blob_in = *b;
971 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
973 status = auth_generic_client_start(state->auth_generic,
974 GENSEC_OID_SPNEGO);
975 if (tevent_req_nterror(req, status)) {
976 return tevent_req_post(req, ev);
979 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
980 state->cli->smb2.session = smbXcli_session_create(cli,
981 cli->conn);
982 if (tevent_req_nomem(state->cli->smb2.session, req)) {
983 return tevent_req_post(req, ev);
987 cli_session_setup_gensec_local_next(req);
988 if (!tevent_req_is_in_progress(req)) {
989 return tevent_req_post(req, ev);
992 return req;
995 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
997 struct cli_session_setup_gensec_state *state =
998 tevent_req_data(req,
999 struct cli_session_setup_gensec_state);
1000 struct tevent_req *subreq = NULL;
1002 if (state->local_ready) {
1003 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1004 return;
1007 subreq = gensec_update_send(state, state->ev,
1008 state->auth_generic->gensec_security,
1009 state->blob_in);
1010 if (tevent_req_nomem(subreq, req)) {
1011 return;
1013 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1016 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1018 struct tevent_req *req =
1019 tevent_req_callback_data(subreq,
1020 struct tevent_req);
1021 struct cli_session_setup_gensec_state *state =
1022 tevent_req_data(req,
1023 struct cli_session_setup_gensec_state);
1024 NTSTATUS status;
1026 status = gensec_update_recv(subreq, state, &state->blob_out);
1027 TALLOC_FREE(subreq);
1028 state->blob_in = data_blob_null;
1029 if (!NT_STATUS_IS_OK(status) &&
1030 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1032 tevent_req_nterror(req, status);
1033 return;
1036 if (NT_STATUS_IS_OK(status)) {
1037 state->local_ready = true;
1040 if (state->local_ready && state->remote_ready) {
1041 cli_session_setup_gensec_ready(req);
1042 return;
1045 cli_session_setup_gensec_remote_next(req);
1048 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1050 struct cli_session_setup_gensec_state *state =
1051 tevent_req_data(req,
1052 struct cli_session_setup_gensec_state);
1053 struct tevent_req *subreq = NULL;
1055 if (state->remote_ready) {
1056 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1057 return;
1060 subreq = cli_sesssetup_blob_send(state, state->ev,
1061 state->cli, state->blob_out);
1062 if (tevent_req_nomem(subreq, req)) {
1063 return;
1065 tevent_req_set_callback(subreq,
1066 cli_session_setup_gensec_remote_done,
1067 req);
1070 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1072 struct tevent_req *req =
1073 tevent_req_callback_data(subreq,
1074 struct tevent_req);
1075 struct cli_session_setup_gensec_state *state =
1076 tevent_req_data(req,
1077 struct cli_session_setup_gensec_state);
1078 NTSTATUS status;
1080 state->inbuf = NULL;
1081 TALLOC_FREE(state->recv_iov);
1083 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1084 &state->inbuf, &state->recv_iov);
1085 TALLOC_FREE(subreq);
1086 data_blob_free(&state->blob_out);
1087 if (!NT_STATUS_IS_OK(status) &&
1088 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1090 tevent_req_nterror(req, status);
1091 return;
1094 if (NT_STATUS_IS_OK(status)) {
1095 struct smbXcli_session *session = NULL;
1096 bool is_guest = false;
1098 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1099 session = state->cli->smb2.session;
1100 } else {
1101 session = state->cli->smb1.session;
1104 is_guest = smbXcli_session_is_guest(session);
1105 if (is_guest) {
1107 * We can't finish the gensec handshake, we don't
1108 * have a negotiated session key.
1110 * So just pretend we are completely done,
1111 * we need to continue as anonymous from this point,
1112 * as we can't get a session key.
1114 * Note that smbXcli_session_is_guest()
1115 * always returns false if we require signing.
1117 state->blob_in = data_blob_null;
1118 state->local_ready = true;
1119 state->is_anonymous = true;
1122 state->remote_ready = true;
1125 if (state->local_ready && state->remote_ready) {
1126 cli_session_setup_gensec_ready(req);
1127 return;
1130 cli_session_setup_gensec_local_next(req);
1133 static void cli_session_dump_keys(TALLOC_CTX *mem_ctx,
1134 struct smbXcli_session *session,
1135 DATA_BLOB session_key)
1137 NTSTATUS status;
1138 DATA_BLOB sig = data_blob_null;
1139 DATA_BLOB app = data_blob_null;
1140 DATA_BLOB enc = data_blob_null;
1141 DATA_BLOB dec = data_blob_null;
1142 uint64_t sid = smb2cli_session_current_id(session);
1144 status = smb2cli_session_signing_key(session, mem_ctx, &sig);
1145 if (!NT_STATUS_IS_OK(status)) {
1146 goto out;
1148 status = smbXcli_session_application_key(session, mem_ctx, &app);
1149 if (!NT_STATUS_IS_OK(status)) {
1150 goto out;
1152 status = smb2cli_session_encryption_key(session, mem_ctx, &enc);
1153 if (!NT_STATUS_IS_OK(status)) {
1154 goto out;
1156 status = smb2cli_session_decryption_key(session, mem_ctx, &dec);
1157 if (!NT_STATUS_IS_OK(status)) {
1158 goto out;
1161 DEBUG(0, ("debug encryption: dumping generated session keys\n"));
1162 DEBUGADD(0, ("Session Id "));
1163 dump_data(0, (uint8_t*)&sid, sizeof(sid));
1164 DEBUGADD(0, ("Session Key "));
1165 dump_data(0, session_key.data, session_key.length);
1166 DEBUGADD(0, ("Signing Key "));
1167 dump_data(0, sig.data, sig.length);
1168 DEBUGADD(0, ("App Key "));
1169 dump_data(0, app.data, app.length);
1171 /* In client code, ServerIn is the encryption key */
1173 DEBUGADD(0, ("ServerIn Key "));
1174 dump_data(0, enc.data, enc.length);
1175 DEBUGADD(0, ("ServerOut Key "));
1176 dump_data(0, dec.data, dec.length);
1178 out:
1179 data_blob_clear_free(&sig);
1180 data_blob_clear_free(&app);
1181 data_blob_clear_free(&enc);
1182 data_blob_clear_free(&dec);
1185 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1187 struct cli_session_setup_gensec_state *state =
1188 tevent_req_data(req,
1189 struct cli_session_setup_gensec_state);
1190 const char *server_domain = NULL;
1191 NTSTATUS status;
1193 if (state->blob_in.length != 0) {
1194 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1195 return;
1198 if (state->blob_out.length != 0) {
1199 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1200 return;
1204 * gensec_ntlmssp_server_domain() returns NULL
1205 * if NTLMSSP is not used.
1207 * We can remove this later
1208 * and leave the server domain empty for SMB2 and above
1209 * in future releases.
1211 server_domain = gensec_ntlmssp_server_domain(
1212 state->auth_generic->gensec_security);
1214 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1215 TALLOC_FREE(state->cli->server_domain);
1216 state->cli->server_domain = talloc_strdup(state->cli,
1217 server_domain);
1218 if (state->cli->server_domain == NULL) {
1219 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1220 return;
1224 if (state->is_anonymous) {
1226 * Windows server does not set the
1227 * SMB2_SESSION_FLAG_IS_NULL flag.
1229 * This fix makes sure we do not try
1230 * to verify a signature on the final
1231 * session setup response.
1233 tevent_req_done(req);
1234 return;
1237 status = gensec_session_key(state->auth_generic->gensec_security,
1238 state, &state->session_key);
1239 if (tevent_req_nterror(req, status)) {
1240 return;
1243 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1244 struct smbXcli_session *session = state->cli->smb2.session;
1246 status = smb2cli_session_set_session_key(session,
1247 state->session_key,
1248 state->recv_iov);
1249 if (tevent_req_nterror(req, status)) {
1250 return;
1252 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB3_00
1253 && lp_debug_encryption())
1255 cli_session_dump_keys(state, session, state->session_key);
1257 } else {
1258 struct smbXcli_session *session = state->cli->smb1.session;
1259 bool active;
1261 status = smb1cli_session_set_session_key(session,
1262 state->session_key);
1263 if (tevent_req_nterror(req, status)) {
1264 return;
1267 active = smb1cli_conn_activate_signing(state->cli->conn,
1268 state->session_key,
1269 data_blob_null);
1270 if (active) {
1271 bool ok;
1273 ok = smb1cli_conn_check_signing(state->cli->conn,
1274 state->inbuf, 1);
1275 if (!ok) {
1276 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1277 return;
1282 tevent_req_done(req);
1285 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1287 struct cli_session_setup_gensec_state *state =
1288 tevent_req_data(req,
1289 struct cli_session_setup_gensec_state);
1290 NTSTATUS status;
1292 if (tevent_req_is_nterror(req, &status)) {
1293 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1294 return status;
1296 return NT_STATUS_OK;
1299 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1300 const char *principal)
1302 char *account, *p;
1304 account = talloc_strdup(mem_ctx, principal);
1305 if (account == NULL) {
1306 return NULL;
1308 p = strchr_m(account, '@');
1309 if (p != NULL) {
1310 *p = '\0';
1312 return account;
1315 /****************************************************************************
1316 Do a spnego encrypted session setup.
1318 user_domain: The shortname of the domain the user/machine is a member of.
1319 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1320 ****************************************************************************/
1322 struct cli_session_setup_spnego_state {
1323 ADS_STATUS result;
1326 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1328 static struct tevent_req *cli_session_setup_spnego_send(
1329 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1330 struct cli_credentials *creds)
1332 struct tevent_req *req, *subreq;
1333 struct cli_session_setup_spnego_state *state;
1334 const char *target_service = NULL;
1335 const char *target_hostname = NULL;
1336 NTSTATUS status;
1338 req = tevent_req_create(mem_ctx, &state,
1339 struct cli_session_setup_spnego_state);
1340 if (req == NULL) {
1341 return NULL;
1344 target_service = "cifs";
1345 target_hostname = smbXcli_conn_remote_name(cli->conn);
1347 status = cli_session_creds_prepare_krb5(cli, creds);
1348 if (tevent_req_nterror(req, status)) {
1349 return tevent_req_post(req, ev);
1352 DBG_INFO("Connect to %s as %s using SPNEGO\n",
1353 target_hostname,
1354 cli_credentials_get_principal(creds, talloc_tos()));
1356 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1357 target_service, target_hostname);
1358 if (tevent_req_nomem(subreq, req)) {
1359 return tevent_req_post(req, ev);
1361 tevent_req_set_callback(
1362 subreq, cli_session_setup_spnego_done, req);
1363 return req;
1366 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1368 struct tevent_req *req = tevent_req_callback_data(
1369 subreq, struct tevent_req);
1370 NTSTATUS status;
1372 status = cli_session_setup_gensec_recv(subreq);
1373 TALLOC_FREE(subreq);
1374 if (tevent_req_nterror(req, status)) {
1375 return;
1378 tevent_req_done(req);
1381 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1383 struct cli_session_setup_spnego_state *state = tevent_req_data(
1384 req, struct cli_session_setup_spnego_state);
1385 NTSTATUS status;
1387 if (tevent_req_is_nterror(req, &status)) {
1388 state->result = ADS_ERROR_NT(status);
1391 return state->result;
1394 struct cli_session_setup_creds_state {
1395 struct cli_state *cli;
1396 DATA_BLOB apassword_blob;
1397 DATA_BLOB upassword_blob;
1398 DATA_BLOB lm_session_key;
1399 DATA_BLOB session_key;
1400 char *out_native_os;
1401 char *out_native_lm;
1402 char *out_primary_domain;
1405 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1406 enum tevent_req_state req_state)
1408 struct cli_session_setup_creds_state *state = tevent_req_data(
1409 req, struct cli_session_setup_creds_state);
1411 if (req_state != TEVENT_REQ_RECEIVED) {
1412 return;
1416 * We only call data_blob_clear() as
1417 * some of the blobs point to the same memory.
1419 * We let the talloc hierarchy free the memory.
1421 data_blob_clear(&state->apassword_blob);
1422 data_blob_clear(&state->upassword_blob);
1423 data_blob_clear(&state->lm_session_key);
1424 data_blob_clear(&state->session_key);
1425 ZERO_STRUCTP(state);
1428 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1429 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1430 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1432 /****************************************************************************
1433 Send a session setup. The username and workgroup is in UNIX character
1434 format and must be converted to DOS codepage format before sending. If the
1435 password is in plaintext, the same should be done.
1436 ****************************************************************************/
1438 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1439 struct tevent_context *ev,
1440 struct cli_state *cli,
1441 struct cli_credentials *creds)
1443 struct tevent_req *req, *subreq;
1444 struct cli_session_setup_creds_state *state;
1445 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1446 bool use_spnego = false;
1447 int flags = 0;
1448 const char *username = "";
1449 const char *domain = "";
1450 DATA_BLOB target_info = data_blob_null;
1451 DATA_BLOB challenge = data_blob_null;
1452 uint16_t in_buf_size = 0;
1453 uint16_t in_mpx_max = 0;
1454 uint16_t in_vc_num = 0;
1455 uint32_t in_sess_key = 0;
1456 const char *in_native_os = NULL;
1457 const char *in_native_lm = NULL;
1458 enum credentials_use_kerberos krb5_state =
1459 cli_credentials_get_kerberos_state(creds);
1460 NTSTATUS status;
1462 req = tevent_req_create(mem_ctx, &state,
1463 struct cli_session_setup_creds_state);
1464 if (req == NULL) {
1465 return NULL;
1467 state->cli = cli;
1469 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1472 * Now work out what sort of session setup we are going to
1473 * do. I have split this into separate functions to make the flow a bit
1474 * easier to understand (tridge).
1476 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1477 use_spnego = false;
1478 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1479 use_spnego = true;
1480 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1482 * if the server supports extended security then use SPNEGO
1483 * even for anonymous connections.
1485 use_spnego = true;
1486 } else {
1487 use_spnego = false;
1490 if (use_spnego) {
1491 subreq = cli_session_setup_spnego_send(
1492 state, ev, cli, creds);
1493 if (tevent_req_nomem(subreq, req)) {
1494 return tevent_req_post(req, ev);
1496 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1497 req);
1498 return req;
1501 if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
1502 DBG_WARNING("Kerberos authentication requested, but "
1503 "the server does not support SPNEGO authentication\n");
1504 tevent_req_nterror(req, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT);
1505 return tevent_req_post(req, ev);
1508 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1510 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1511 * this step against older servers.
1513 tevent_req_done(req);
1514 return tevent_req_post(req, ev);
1517 if (cli_credentials_is_anonymous(creds)) {
1519 * Do an anonymous session setup
1521 goto non_spnego_creds_done;
1524 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1526 * Do an anonymous session setup,
1527 * the password is passed via the tree connect.
1529 goto non_spnego_creds_done;
1532 cli_credentials_get_ntlm_username_domain(creds, state,
1533 &username,
1534 &domain);
1535 if (tevent_req_nomem(username, req)) {
1536 return tevent_req_post(req, ev);
1538 if (tevent_req_nomem(domain, req)) {
1539 return tevent_req_post(req, ev);
1542 DBG_INFO("Connect to %s as %s using NTLM\n", domain, username);
1544 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1545 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1546 uint8_t *bytes = NULL;
1547 size_t bytes_len = 0;
1548 const char *pw = cli_credentials_get_password(creds);
1549 size_t pw_len = 0;
1551 if (pw == NULL) {
1552 pw = "";
1554 pw_len = strlen(pw) + 1;
1556 if (!lp_client_plaintext_auth()) {
1557 DEBUG(1, ("Server requested PLAINTEXT password but "
1558 "'client plaintext auth = no'\n"));
1559 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1560 return tevent_req_post(req, ev);
1563 bytes = talloc_array(state, uint8_t, 0);
1564 bytes = trans2_bytes_push_str(bytes, use_unicode,
1565 pw, pw_len, &bytes_len);
1566 if (tevent_req_nomem(bytes, req)) {
1567 return tevent_req_post(req, ev);
1570 if (use_unicode) {
1572 * CAP_UNICODE, can only be negotiated by NT1.
1574 state->upassword_blob = data_blob_const(bytes,
1575 bytes_len);
1576 } else {
1577 state->apassword_blob = data_blob_const(bytes,
1578 bytes_len);
1581 goto non_spnego_creds_done;
1584 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1586 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1587 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1589 * Don't send an NTLMv2 response without NTLMSSP if we
1590 * want to use spnego support.
1592 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1593 " but 'client use spnego = yes'"
1594 " and 'client ntlmv2 auth = yes' is set\n"));
1595 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1596 return tevent_req_post(req, ev);
1599 if (lp_client_ntlmv2_auth()) {
1600 flags |= CLI_CRED_NTLMv2_AUTH;
1603 * note that the 'domain' here is a best
1604 * guess - we don't know the server's domain
1605 * at this point. Windows clients also don't
1606 * use hostname...
1608 target_info = NTLMv2_generate_names_blob(state,
1609 NULL,
1610 domain);
1611 if (tevent_req_nomem(target_info.data, req)) {
1612 return tevent_req_post(req, ev);
1614 } else {
1615 flags |= CLI_CRED_NTLM_AUTH;
1616 if (lp_client_lanman_auth()) {
1617 flags |= CLI_CRED_LANMAN_AUTH;
1620 } else {
1621 if (!lp_client_lanman_auth()) {
1622 DEBUG(1, ("Server requested user level LM password but "
1623 "'client lanman auth = no' is set.\n"));
1624 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1625 return tevent_req_post(req, ev);
1628 flags |= CLI_CRED_LANMAN_AUTH;
1631 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1632 challenge, NULL,
1633 target_info,
1634 &state->apassword_blob,
1635 &state->upassword_blob,
1636 &state->lm_session_key,
1637 &state->session_key);
1638 if (tevent_req_nterror(req, status)) {
1639 return tevent_req_post(req, ev);
1642 non_spnego_creds_done:
1644 in_buf_size = CLI_BUFFER_SIZE;
1645 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1646 in_vc_num = cli_state_get_vc_num(cli);
1647 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1648 in_native_os = "Unix";
1649 in_native_lm = "Samba";
1651 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1652 uint32_t in_capabilities = 0;
1654 in_capabilities = cli_session_setup_capabilities(cli, 0);
1657 * For now we keep the same values as before,
1658 * we may remove these in a separate commit later.
1660 in_mpx_max = 2;
1662 subreq = smb1cli_session_setup_nt1_send(state, ev,
1663 cli->conn,
1664 cli->timeout,
1665 cli->smb1.pid,
1666 cli->smb1.session,
1667 in_buf_size,
1668 in_mpx_max,
1669 in_vc_num,
1670 in_sess_key,
1671 username,
1672 domain,
1673 state->apassword_blob,
1674 state->upassword_blob,
1675 in_capabilities,
1676 in_native_os,
1677 in_native_lm);
1678 if (tevent_req_nomem(subreq, req)) {
1679 return tevent_req_post(req, ev);
1681 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1682 req);
1683 return req;
1687 * For now we keep the same values as before,
1688 * we may remove these in a separate commit later.
1690 in_mpx_max = 2;
1691 in_vc_num = 1;
1693 subreq = smb1cli_session_setup_lm21_send(state, ev,
1694 cli->conn,
1695 cli->timeout,
1696 cli->smb1.pid,
1697 cli->smb1.session,
1698 in_buf_size,
1699 in_mpx_max,
1700 in_vc_num,
1701 in_sess_key,
1702 username,
1703 domain,
1704 state->apassword_blob,
1705 in_native_os,
1706 in_native_lm);
1707 if (tevent_req_nomem(subreq, req)) {
1708 return tevent_req_post(req, ev);
1710 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1711 req);
1712 return req;
1715 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1717 struct tevent_req *req = tevent_req_callback_data(
1718 subreq, struct tevent_req);
1719 ADS_STATUS status;
1721 status = cli_session_setup_spnego_recv(subreq);
1722 TALLOC_FREE(subreq);
1723 if (!ADS_ERR_OK(status)) {
1724 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1725 tevent_req_nterror(req, ads_ntstatus(status));
1726 return;
1728 tevent_req_done(req);
1731 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1733 struct tevent_req *req = tevent_req_callback_data(
1734 subreq, struct tevent_req);
1735 struct cli_session_setup_creds_state *state = tevent_req_data(
1736 req, struct cli_session_setup_creds_state);
1737 struct cli_state *cli = state->cli;
1738 NTSTATUS status;
1739 struct iovec *recv_iov = NULL;
1740 const uint8_t *inbuf = NULL;
1741 bool ok;
1743 status = smb1cli_session_setup_nt1_recv(subreq, state,
1744 &recv_iov,
1745 &inbuf,
1746 &state->out_native_os,
1747 &state->out_native_lm,
1748 &state->out_primary_domain);
1749 TALLOC_FREE(subreq);
1750 if (tevent_req_nterror(req, status)) {
1751 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1752 return;
1755 status = cli_state_update_after_sesssetup(state->cli,
1756 state->out_native_os,
1757 state->out_native_lm,
1758 state->out_primary_domain);
1759 if (tevent_req_nterror(req, status)) {
1760 return;
1763 ok = smb1cli_conn_activate_signing(cli->conn,
1764 state->session_key,
1765 state->upassword_blob);
1766 if (ok) {
1767 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1768 if (!ok) {
1769 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1770 return;
1774 if (state->session_key.data) {
1775 struct smbXcli_session *session = cli->smb1.session;
1777 status = smb1cli_session_set_session_key(session,
1778 state->session_key);
1779 if (tevent_req_nterror(req, status)) {
1780 return;
1784 tevent_req_done(req);
1787 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1789 struct tevent_req *req = tevent_req_callback_data(
1790 subreq, struct tevent_req);
1791 struct cli_session_setup_creds_state *state = tevent_req_data(
1792 req, struct cli_session_setup_creds_state);
1793 NTSTATUS status;
1795 status = smb1cli_session_setup_lm21_recv(subreq, state,
1796 &state->out_native_os,
1797 &state->out_native_lm);
1798 TALLOC_FREE(subreq);
1799 if (tevent_req_nterror(req, status)) {
1800 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1801 return;
1804 status = cli_state_update_after_sesssetup(state->cli,
1805 state->out_native_os,
1806 state->out_native_lm,
1807 NULL);
1808 if (tevent_req_nterror(req, status)) {
1809 return;
1812 tevent_req_done(req);
1815 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1817 return tevent_req_simple_recv_ntstatus(req);
1820 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1821 struct cli_credentials *creds)
1823 struct tevent_context *ev;
1824 struct tevent_req *req;
1825 NTSTATUS status = NT_STATUS_NO_MEMORY;
1827 if (smbXcli_conn_has_async_calls(cli->conn)) {
1828 return NT_STATUS_INVALID_PARAMETER;
1830 ev = samba_tevent_context_init(talloc_tos());
1831 if (ev == NULL) {
1832 goto fail;
1834 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1835 if (req == NULL) {
1836 goto fail;
1838 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1839 goto fail;
1841 status = cli_session_setup_creds_recv(req);
1842 fail:
1843 TALLOC_FREE(ev);
1844 return status;
1847 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1849 NTSTATUS status;
1850 struct cli_credentials *creds = NULL;
1852 creds = cli_credentials_init_anon(cli);
1853 if (creds == NULL) {
1854 return NT_STATUS_NO_MEMORY;
1857 status = cli_session_setup_creds(cli, creds);
1858 TALLOC_FREE(creds);
1859 if (!NT_STATUS_IS_OK(status)) {
1860 return status;
1863 return NT_STATUS_OK;
1866 /****************************************************************************
1867 Send a uloggoff.
1868 *****************************************************************************/
1870 struct cli_ulogoff_state {
1871 struct cli_state *cli;
1872 uint16_t vwv[3];
1875 static void cli_ulogoff_done(struct tevent_req *subreq);
1877 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1878 struct tevent_context *ev,
1879 struct cli_state *cli)
1881 struct tevent_req *req, *subreq;
1882 struct cli_ulogoff_state *state;
1884 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1885 if (req == NULL) {
1886 return NULL;
1888 state->cli = cli;
1890 SCVAL(state->vwv+0, 0, 0xFF);
1891 SCVAL(state->vwv+1, 0, 0);
1892 SSVAL(state->vwv+2, 0, 0);
1894 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1895 0, NULL);
1896 if (tevent_req_nomem(subreq, req)) {
1897 return tevent_req_post(req, ev);
1899 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1900 return req;
1903 static void cli_ulogoff_done(struct tevent_req *subreq)
1905 struct tevent_req *req = tevent_req_callback_data(
1906 subreq, struct tevent_req);
1907 struct cli_ulogoff_state *state = tevent_req_data(
1908 req, struct cli_ulogoff_state);
1909 NTSTATUS status;
1911 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1912 if (tevent_req_nterror(req, status)) {
1913 return;
1915 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1916 tevent_req_done(req);
1919 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1921 return tevent_req_simple_recv_ntstatus(req);
1924 NTSTATUS cli_ulogoff(struct cli_state *cli)
1926 struct tevent_context *ev;
1927 struct tevent_req *req;
1928 NTSTATUS status = NT_STATUS_NO_MEMORY;
1930 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1931 status = smb2cli_logoff(cli->conn,
1932 cli->timeout,
1933 cli->smb2.session);
1934 if (!NT_STATUS_IS_OK(status)) {
1935 return status;
1937 smb2cli_session_set_id_and_flags(cli->smb2.session,
1938 UINT64_MAX, 0);
1939 return NT_STATUS_OK;
1942 if (smbXcli_conn_has_async_calls(cli->conn)) {
1943 return NT_STATUS_INVALID_PARAMETER;
1945 ev = samba_tevent_context_init(talloc_tos());
1946 if (ev == NULL) {
1947 goto fail;
1949 req = cli_ulogoff_send(ev, ev, cli);
1950 if (req == NULL) {
1951 goto fail;
1953 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1954 goto fail;
1956 status = cli_ulogoff_recv(req);
1957 fail:
1958 TALLOC_FREE(ev);
1959 return status;
1962 /****************************************************************************
1963 Send a tconX.
1964 ****************************************************************************/
1966 struct cli_tcon_andx_state {
1967 struct cli_state *cli;
1968 uint16_t vwv[4];
1969 struct iovec bytes;
1972 static void cli_tcon_andx_done(struct tevent_req *subreq);
1974 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1975 struct tevent_context *ev,
1976 struct cli_state *cli,
1977 const char *share, const char *dev,
1978 const char *pass, int passlen,
1979 struct tevent_req **psmbreq)
1981 struct tevent_req *req, *subreq;
1982 struct cli_tcon_andx_state *state;
1983 uint8_t p24[24];
1984 uint16_t *vwv;
1985 char *tmp = NULL;
1986 uint8_t *bytes;
1987 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1988 uint16_t tcon_flags = 0;
1990 *psmbreq = NULL;
1992 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1993 if (req == NULL) {
1994 return NULL;
1996 state->cli = cli;
1997 vwv = state->vwv;
1999 TALLOC_FREE(cli->smb1.tcon);
2000 cli->smb1.tcon = smbXcli_tcon_create(cli);
2001 if (tevent_req_nomem(cli->smb1.tcon, req)) {
2002 return tevent_req_post(req, ev);
2004 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
2006 cli->share = talloc_strdup(cli, share);
2007 if (!cli->share) {
2008 return NULL;
2011 /* in user level security don't send a password now */
2012 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2013 passlen = 1;
2014 pass = "";
2015 } else if (pass == NULL) {
2016 DEBUG(1, ("Server not using user level security and no "
2017 "password supplied.\n"));
2018 goto access_denied;
2021 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2022 *pass && passlen != 24) {
2023 if (!lp_client_lanman_auth()) {
2024 DEBUG(1, ("Server requested LANMAN password "
2025 "(share-level security) but "
2026 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2027 goto access_denied;
2031 * Non-encrypted passwords - convert to DOS codepage before
2032 * encryption.
2034 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2035 passlen = 24;
2036 pass = (const char *)p24;
2037 } else {
2038 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2039 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2040 == 0) {
2041 uint8_t *tmp_pass;
2043 if (!lp_client_plaintext_auth() && (*pass)) {
2044 DEBUG(1, ("Server requested PLAINTEXT "
2045 "password but "
2046 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2047 goto access_denied;
2051 * Non-encrypted passwords - convert to DOS codepage
2052 * before using.
2054 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2055 if (tevent_req_nomem(tmp_pass, req)) {
2056 return tevent_req_post(req, ev);
2058 tmp_pass = trans2_bytes_push_str(tmp_pass,
2059 false, /* always DOS */
2060 pass,
2061 passlen,
2062 NULL);
2063 if (tevent_req_nomem(tmp_pass, req)) {
2064 return tevent_req_post(req, ev);
2066 pass = (const char *)tmp_pass;
2067 passlen = talloc_get_size(tmp_pass);
2071 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2072 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2074 SCVAL(vwv+0, 0, 0xFF);
2075 SCVAL(vwv+0, 1, 0);
2076 SSVAL(vwv+1, 0, 0);
2077 SSVAL(vwv+2, 0, tcon_flags);
2078 SSVAL(vwv+3, 0, passlen);
2080 if (passlen && pass) {
2081 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2082 } else {
2083 bytes = talloc_array(state, uint8_t, 0);
2087 * Add the sharename
2089 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2090 smbXcli_conn_remote_name(cli->conn), share);
2091 if (tmp == NULL) {
2092 TALLOC_FREE(req);
2093 return NULL;
2095 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2096 NULL);
2097 TALLOC_FREE(tmp);
2100 * Add the devicetype
2102 tmp = talloc_strdup_upper(talloc_tos(), dev);
2103 if (tmp == NULL) {
2104 TALLOC_FREE(req);
2105 return NULL;
2107 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2108 TALLOC_FREE(tmp);
2110 if (bytes == NULL) {
2111 TALLOC_FREE(req);
2112 return NULL;
2115 state->bytes.iov_base = (void *)bytes;
2116 state->bytes.iov_len = talloc_get_size(bytes);
2118 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2119 1, &state->bytes);
2120 if (subreq == NULL) {
2121 TALLOC_FREE(req);
2122 return NULL;
2124 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2125 *psmbreq = subreq;
2126 return req;
2128 access_denied:
2129 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2130 return tevent_req_post(req, ev);
2133 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2134 struct tevent_context *ev,
2135 struct cli_state *cli,
2136 const char *share, const char *dev,
2137 const char *pass, int passlen)
2139 struct tevent_req *req, *subreq;
2140 NTSTATUS status;
2142 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2143 &subreq);
2144 if (req == NULL) {
2145 return NULL;
2147 if (subreq == NULL) {
2148 return req;
2150 status = smb1cli_req_chain_submit(&subreq, 1);
2151 if (tevent_req_nterror(req, status)) {
2152 return tevent_req_post(req, ev);
2154 return req;
2157 static void cli_tcon_andx_done(struct tevent_req *subreq)
2159 struct tevent_req *req = tevent_req_callback_data(
2160 subreq, struct tevent_req);
2161 struct cli_tcon_andx_state *state = tevent_req_data(
2162 req, struct cli_tcon_andx_state);
2163 struct cli_state *cli = state->cli;
2164 uint8_t *in;
2165 uint8_t *inhdr;
2166 uint8_t wct;
2167 uint16_t *vwv;
2168 uint32_t num_bytes;
2169 uint8_t *bytes;
2170 NTSTATUS status;
2171 uint16_t optional_support = 0;
2173 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2174 &num_bytes, &bytes);
2175 TALLOC_FREE(subreq);
2176 if (tevent_req_nterror(req, status)) {
2177 return;
2180 inhdr = in + NBT_HDR_SIZE;
2182 if (num_bytes) {
2183 if (pull_string_talloc(cli,
2184 (const char *)inhdr,
2185 SVAL(inhdr, HDR_FLG2),
2186 &cli->dev,
2187 bytes,
2188 num_bytes,
2189 STR_TERMINATE|STR_ASCII) == -1) {
2190 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2191 return;
2193 } else {
2194 cli->dev = talloc_strdup(cli, "");
2195 if (cli->dev == NULL) {
2196 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2197 return;
2201 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2202 /* almost certainly win95 - enable bug fixes */
2203 cli->win95 = True;
2207 * Make sure that we have the optional support 16-bit field. WCT > 2.
2208 * Avoids issues when connecting to Win9x boxes sharing files
2211 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2212 optional_support = SVAL(vwv+2, 0);
2215 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2216 smb1cli_session_protect_session_key(cli->smb1.session);
2219 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2220 SVAL(inhdr, HDR_TID),
2221 optional_support,
2222 0, /* maximal_access */
2223 0, /* guest_maximal_access */
2224 NULL, /* service */
2225 NULL); /* fs_type */
2227 tevent_req_done(req);
2230 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2232 return tevent_req_simple_recv_ntstatus(req);
2235 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2236 const char *dev, const char *pass, int passlen)
2238 TALLOC_CTX *frame = talloc_stackframe();
2239 struct tevent_context *ev;
2240 struct tevent_req *req;
2241 NTSTATUS status = NT_STATUS_NO_MEMORY;
2243 if (smbXcli_conn_has_async_calls(cli->conn)) {
2245 * Can't use sync call while an async call is in flight
2247 status = NT_STATUS_INVALID_PARAMETER;
2248 goto fail;
2251 ev = samba_tevent_context_init(frame);
2252 if (ev == NULL) {
2253 goto fail;
2256 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2257 if (req == NULL) {
2258 goto fail;
2261 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2262 goto fail;
2265 status = cli_tcon_andx_recv(req);
2266 fail:
2267 TALLOC_FREE(frame);
2268 return status;
2271 struct cli_tree_connect_state {
2272 struct cli_state *cli;
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);
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);
2285 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)
2289 struct tevent_req *req, *subreq;
2290 struct cli_tree_connect_state *state;
2291 int passlen;
2293 if (pass == NULL) {
2294 pass = "";
2296 passlen = strlen(pass) + 1;
2298 req = tevent_req_create(mem_ctx, &state,
2299 struct cli_tree_connect_state);
2300 if (req == NULL) {
2301 return NULL;
2303 state->cli = cli;
2305 cli->share = talloc_strdup(cli, share);
2306 if (tevent_req_nomem(cli->share, req)) {
2307 return tevent_req_post(req, ev);
2310 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2311 char *unc;
2313 TALLOC_FREE(cli->smb2.tcon);
2314 cli->smb2.tcon = smbXcli_tcon_create(cli);
2315 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2316 return tevent_req_post(req, ev);
2319 unc = talloc_asprintf(state, "\\\\%s\\%s",
2320 smbXcli_conn_remote_name(cli->conn),
2321 share);
2322 if (tevent_req_nomem(unc, req)) {
2323 return tevent_req_post(req, ev);
2326 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2327 cli->smb2.session, cli->smb2.tcon,
2328 0, /* flags */
2329 unc);
2330 if (tevent_req_nomem(subreq, req)) {
2331 return tevent_req_post(req, ev);
2333 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2334 req);
2335 return req;
2338 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2339 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2340 pass, passlen);
2341 if (tevent_req_nomem(subreq, req)) {
2342 return tevent_req_post(req, ev);
2344 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2345 req);
2346 return req;
2349 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2350 if (tevent_req_nomem(subreq, req)) {
2351 return tevent_req_post(req, ev);
2353 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2355 return req;
2358 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2360 NTSTATUS status = smb2cli_tcon_recv(subreq);
2361 tevent_req_simple_finish_ntstatus(subreq, status);
2364 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2366 NTSTATUS status = cli_tcon_andx_recv(subreq);
2367 tevent_req_simple_finish_ntstatus(subreq, status);
2370 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2372 struct tevent_req *req = tevent_req_callback_data(
2373 subreq, struct tevent_req);
2374 struct cli_tree_connect_state *state = tevent_req_data(
2375 req, struct cli_tree_connect_state);
2376 NTSTATUS status;
2377 uint16_t max_xmit = 0;
2378 uint16_t tid = 0;
2380 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2381 if (tevent_req_nterror(req, status)) {
2382 return;
2385 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 */
2393 tevent_req_done(req);
2396 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2398 return tevent_req_simple_recv_ntstatus(req);
2401 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2402 const char *dev, const char *pass)
2404 struct tevent_context *ev;
2405 struct tevent_req *req;
2406 NTSTATUS status = NT_STATUS_NO_MEMORY;
2408 if (smbXcli_conn_has_async_calls(cli->conn)) {
2409 return NT_STATUS_INVALID_PARAMETER;
2411 ev = samba_tevent_context_init(talloc_tos());
2412 if (ev == NULL) {
2413 goto fail;
2415 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2416 if (req == NULL) {
2417 goto fail;
2419 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2420 goto fail;
2422 status = cli_tree_connect_recv(req);
2423 fail:
2424 TALLOC_FREE(ev);
2425 return status;
2428 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2429 const char *share, const char *dev,
2430 struct cli_credentials *creds)
2432 bool need_pass = false;
2433 const char *pw = NULL;
2436 * We should work out if the protocol
2437 * will make use of a password for share level
2438 * authentication before we may cause
2439 * the password prompt to be called.
2441 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2442 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2444 /* in user level security don't send a password now */
2445 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
2446 need_pass = true;
2450 if (need_pass && creds != NULL) {
2451 pw = cli_credentials_get_password(creds);
2454 return cli_tree_connect(cli, share, dev, pw);
2457 /****************************************************************************
2458 Send a tree disconnect.
2459 ****************************************************************************/
2461 struct cli_tdis_state {
2462 struct cli_state *cli;
2465 static void cli_tdis_done(struct tevent_req *subreq);
2467 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2468 struct tevent_context *ev,
2469 struct cli_state *cli)
2471 struct tevent_req *req, *subreq;
2472 struct cli_tdis_state *state;
2474 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2475 if (req == NULL) {
2476 return NULL;
2478 state->cli = cli;
2480 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2481 if (tevent_req_nomem(subreq, req)) {
2482 return tevent_req_post(req, ev);
2484 tevent_req_set_callback(subreq, cli_tdis_done, req);
2485 return req;
2488 static void cli_tdis_done(struct tevent_req *subreq)
2490 struct tevent_req *req = tevent_req_callback_data(
2491 subreq, struct tevent_req);
2492 struct cli_tdis_state *state = tevent_req_data(
2493 req, struct cli_tdis_state);
2494 NTSTATUS status;
2496 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2497 TALLOC_FREE(subreq);
2498 if (tevent_req_nterror(req, status)) {
2499 return;
2501 TALLOC_FREE(state->cli->smb1.tcon);
2502 tevent_req_done(req);
2505 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2507 return tevent_req_simple_recv_ntstatus(req);
2510 NTSTATUS cli_tdis(struct cli_state *cli)
2512 struct tevent_context *ev;
2513 struct tevent_req *req;
2514 NTSTATUS status = NT_STATUS_NO_MEMORY;
2516 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2517 status = smb2cli_tdis(cli->conn,
2518 cli->timeout,
2519 cli->smb2.session,
2520 cli->smb2.tcon);
2521 if (NT_STATUS_IS_OK(status)) {
2522 TALLOC_FREE(cli->smb2.tcon);
2524 return status;
2527 if (smbXcli_conn_has_async_calls(cli->conn)) {
2528 return NT_STATUS_INVALID_PARAMETER;
2530 ev = samba_tevent_context_init(talloc_tos());
2531 if (ev == NULL) {
2532 goto fail;
2534 req = cli_tdis_send(ev, ev, cli);
2535 if (req == NULL) {
2536 goto fail;
2538 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2539 goto fail;
2541 status = cli_tdis_recv(req);
2542 fail:
2543 TALLOC_FREE(ev);
2544 return status;
2547 struct cli_connect_sock_state {
2548 const char **called_names;
2549 const char **calling_names;
2550 int *called_types;
2551 int fd;
2552 uint16_t port;
2555 static void cli_connect_sock_done(struct tevent_req *subreq);
2558 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2559 * nonzero address.
2562 static struct tevent_req *cli_connect_sock_send(
2563 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2564 const char *host, int name_type, const struct sockaddr_storage *pss,
2565 const char *myname, uint16_t port)
2567 struct tevent_req *req, *subreq;
2568 struct cli_connect_sock_state *state;
2569 struct sockaddr_storage *addrs = NULL;
2570 unsigned i;
2571 unsigned num_addrs = 0;
2572 NTSTATUS status;
2574 req = tevent_req_create(mem_ctx, &state,
2575 struct cli_connect_sock_state);
2576 if (req == NULL) {
2577 return NULL;
2580 if ((pss == NULL) || is_zero_addr(pss)) {
2583 * Here we cheat. resolve_name_list is not async at all. So
2584 * this call will only be really async if the name lookup has
2585 * been done externally.
2588 status = resolve_name_list(state, host, name_type,
2589 &addrs, &num_addrs);
2590 if (tevent_req_nterror(req, status)) {
2591 return tevent_req_post(req, ev);
2593 } else {
2594 addrs = talloc_array(state, struct sockaddr_storage, 1);
2595 if (tevent_req_nomem(addrs, req)) {
2596 return tevent_req_post(req, ev);
2598 addrs[0] = *pss;
2599 num_addrs = 1;
2602 state->called_names = talloc_array(state, const char *, num_addrs);
2603 if (tevent_req_nomem(state->called_names, req)) {
2604 return tevent_req_post(req, ev);
2606 state->called_types = talloc_array(state, int, num_addrs);
2607 if (tevent_req_nomem(state->called_types, req)) {
2608 return tevent_req_post(req, ev);
2610 state->calling_names = talloc_array(state, const char *, num_addrs);
2611 if (tevent_req_nomem(state->calling_names, req)) {
2612 return tevent_req_post(req, ev);
2614 for (i=0; i<num_addrs; i++) {
2615 state->called_names[i] = host;
2616 state->called_types[i] = name_type;
2617 state->calling_names[i] = myname;
2620 subreq = smbsock_any_connect_send(
2621 state, ev, addrs, state->called_names, state->called_types,
2622 state->calling_names, NULL, num_addrs, port);
2623 if (tevent_req_nomem(subreq, req)) {
2624 return tevent_req_post(req, ev);
2626 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2627 return req;
2630 static void cli_connect_sock_done(struct tevent_req *subreq)
2632 struct tevent_req *req = tevent_req_callback_data(
2633 subreq, struct tevent_req);
2634 struct cli_connect_sock_state *state = tevent_req_data(
2635 req, struct cli_connect_sock_state);
2636 NTSTATUS status;
2638 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2639 &state->port);
2640 TALLOC_FREE(subreq);
2641 if (tevent_req_nterror(req, status)) {
2642 return;
2644 set_socket_options(state->fd, lp_socket_options());
2645 tevent_req_done(req);
2648 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2649 int *pfd, uint16_t *pport)
2651 struct cli_connect_sock_state *state = tevent_req_data(
2652 req, struct cli_connect_sock_state);
2653 NTSTATUS status;
2655 if (tevent_req_is_nterror(req, &status)) {
2656 return status;
2658 *pfd = state->fd;
2659 *pport = state->port;
2660 return NT_STATUS_OK;
2663 struct cli_connect_nb_state {
2664 const char *desthost;
2665 enum smb_signing_setting signing_state;
2666 int flags;
2667 struct cli_state *cli;
2670 static void cli_connect_nb_done(struct tevent_req *subreq);
2672 static struct tevent_req *cli_connect_nb_send(
2673 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2674 const char *host, const struct sockaddr_storage *dest_ss,
2675 uint16_t port, int name_type, const char *myname,
2676 enum smb_signing_setting signing_state, int flags)
2678 struct tevent_req *req, *subreq;
2679 struct cli_connect_nb_state *state;
2681 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2682 if (req == NULL) {
2683 return NULL;
2685 state->signing_state = signing_state;
2686 state->flags = flags;
2688 if (host != NULL) {
2689 char *p = strchr(host, '#');
2691 if (p != NULL) {
2692 name_type = strtol(p+1, NULL, 16);
2693 host = talloc_strndup(state, host, p - host);
2694 if (tevent_req_nomem(host, req)) {
2695 return tevent_req_post(req, ev);
2699 state->desthost = host;
2700 } else if (dest_ss != NULL) {
2701 state->desthost = print_canonical_sockaddr(state, dest_ss);
2702 if (tevent_req_nomem(state->desthost, req)) {
2703 return tevent_req_post(req, ev);
2705 } else {
2706 /* No host or dest_ss given. Error out. */
2707 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2708 return tevent_req_post(req, ev);
2711 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2712 myname, port);
2713 if (tevent_req_nomem(subreq, req)) {
2714 return tevent_req_post(req, ev);
2716 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2717 return req;
2720 static void cli_connect_nb_done(struct tevent_req *subreq)
2722 struct tevent_req *req = tevent_req_callback_data(
2723 subreq, struct tevent_req);
2724 struct cli_connect_nb_state *state = tevent_req_data(
2725 req, struct cli_connect_nb_state);
2726 NTSTATUS status;
2727 int fd = 0;
2728 uint16_t port;
2730 status = cli_connect_sock_recv(subreq, &fd, &port);
2731 TALLOC_FREE(subreq);
2732 if (tevent_req_nterror(req, status)) {
2733 return;
2736 state->cli = cli_state_create(state, fd, state->desthost,
2737 state->signing_state, state->flags);
2738 if (tevent_req_nomem(state->cli, req)) {
2739 close(fd);
2740 return;
2742 tevent_req_done(req);
2745 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2746 TALLOC_CTX *mem_ctx,
2747 struct cli_state **pcli)
2749 struct cli_connect_nb_state *state = tevent_req_data(
2750 req, struct cli_connect_nb_state);
2751 NTSTATUS status;
2753 if (tevent_req_is_nterror(req, &status)) {
2754 return status;
2756 *pcli = talloc_move(mem_ctx, &state->cli);
2757 return NT_STATUS_OK;
2760 NTSTATUS cli_connect_nb(TALLOC_CTX *mem_ctx,
2761 const char *host,
2762 const struct sockaddr_storage *dest_ss,
2763 uint16_t port,
2764 int name_type,
2765 const char *myname,
2766 enum smb_signing_setting signing_state,
2767 int flags,
2768 struct cli_state **pcli)
2770 struct tevent_context *ev;
2771 struct tevent_req *req;
2772 NTSTATUS status = NT_STATUS_NO_MEMORY;
2774 ev = samba_tevent_context_init(mem_ctx);
2775 if (ev == NULL) {
2776 goto fail;
2778 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2779 myname, signing_state, flags);
2780 if (req == NULL) {
2781 goto fail;
2783 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2784 goto fail;
2786 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2787 goto fail;
2789 status = cli_connect_nb_recv(req, mem_ctx, pcli);
2790 fail:
2791 TALLOC_FREE(ev);
2792 return status;
2795 struct cli_start_connection_state {
2796 struct tevent_context *ev;
2797 struct cli_state *cli;
2798 int min_protocol;
2799 int max_protocol;
2800 struct smb2_negotiate_contexts *negotiate_contexts;
2803 static void cli_start_connection_connected(struct tevent_req *subreq);
2804 static void cli_start_connection_done(struct tevent_req *subreq);
2807 establishes a connection to after the negprot.
2808 @param output_cli A fully initialised cli structure, non-null only on success
2809 @param dest_host The netbios name of the remote host
2810 @param dest_ss (optional) The destination IP, NULL for name based lookup
2811 @param port (optional) The destination port (0 for default)
2814 static struct tevent_req *cli_start_connection_send(
2815 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2816 const char *my_name, const char *dest_host,
2817 const struct sockaddr_storage *dest_ss, int port,
2818 enum smb_signing_setting signing_state, int flags,
2819 struct smb2_negotiate_contexts *negotiate_contexts)
2821 struct tevent_req *req, *subreq;
2822 struct cli_start_connection_state *state;
2824 req = tevent_req_create(mem_ctx, &state,
2825 struct cli_start_connection_state);
2826 if (req == NULL) {
2827 return NULL;
2829 state->ev = ev;
2831 if (flags & CLI_FULL_CONNECTION_IPC) {
2832 state->min_protocol = lp_client_ipc_min_protocol();
2833 state->max_protocol = lp_client_ipc_max_protocol();
2834 } else {
2835 state->min_protocol = lp_client_min_protocol();
2836 state->max_protocol = lp_client_max_protocol();
2839 if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
2840 state->max_protocol = MIN(state->max_protocol,
2841 PROTOCOL_NT1);
2842 state->min_protocol = MIN(state->min_protocol,
2843 state->max_protocol);
2846 if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
2847 state->min_protocol = MAX(state->min_protocol,
2848 PROTOCOL_SMB2_02);
2849 state->max_protocol = MAX(state->max_protocol,
2850 state->min_protocol);
2853 state->negotiate_contexts = talloc_zero(
2854 state, struct smb2_negotiate_contexts);
2855 if (tevent_req_nomem(state->negotiate_contexts, req)) {
2856 return tevent_req_post(req, ev);
2859 if (flags & CLI_FULL_CONNECTION_REQUEST_POSIX) {
2860 NTSTATUS status;
2862 status = smb2_negotiate_context_add(
2863 state->negotiate_contexts,
2864 state->negotiate_contexts,
2865 SMB2_POSIX_EXTENSIONS_AVAILABLE,
2866 (const uint8_t *)SMB2_CREATE_TAG_POSIX,
2867 strlen(SMB2_CREATE_TAG_POSIX));
2868 if (tevent_req_nterror(req, status)) {
2869 return tevent_req_post(req, ev);
2873 if (negotiate_contexts != NULL) {
2874 uint16_t i;
2876 for (i=0; i<negotiate_contexts->num_contexts; i++) {
2877 struct smb2_negotiate_context *ctx =
2878 &negotiate_contexts->contexts[i];
2879 NTSTATUS status;
2881 status = smb2_negotiate_context_add(
2882 state->negotiate_contexts,
2883 state->negotiate_contexts,
2884 ctx->type,
2885 ctx->data.data,
2886 ctx->data.length);
2887 if (tevent_req_nterror(req, status)) {
2888 return tevent_req_post(req, ev);
2893 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2894 0x20, my_name, signing_state, flags);
2895 if (tevent_req_nomem(subreq, req)) {
2896 return tevent_req_post(req, ev);
2898 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2899 return req;
2902 static void cli_start_connection_connected(struct tevent_req *subreq)
2904 struct tevent_req *req = tevent_req_callback_data(
2905 subreq, struct tevent_req);
2906 struct cli_start_connection_state *state = tevent_req_data(
2907 req, struct cli_start_connection_state);
2908 NTSTATUS status;
2910 status = cli_connect_nb_recv(subreq, state, &state->cli);
2911 TALLOC_FREE(subreq);
2912 if (tevent_req_nterror(req, status)) {
2913 return;
2916 subreq = smbXcli_negprot_send(
2917 state,
2918 state->ev,
2919 state->cli->conn,
2920 state->cli->timeout,
2921 state->min_protocol,
2922 state->max_protocol,
2923 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK,
2924 state->negotiate_contexts);
2925 if (tevent_req_nomem(subreq, req)) {
2926 return;
2928 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2931 static void cli_start_connection_done(struct tevent_req *subreq)
2933 struct tevent_req *req = tevent_req_callback_data(
2934 subreq, struct tevent_req);
2935 struct cli_start_connection_state *state = tevent_req_data(
2936 req, struct cli_start_connection_state);
2937 NTSTATUS status;
2939 status = smbXcli_negprot_recv(subreq, NULL, NULL);
2940 TALLOC_FREE(subreq);
2941 if (tevent_req_nterror(req, status)) {
2942 return;
2945 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2946 /* Ensure we ask for some initial credits. */
2947 smb2cli_conn_set_max_credits(state->cli->conn,
2948 DEFAULT_SMB2_MAX_CREDITS);
2951 tevent_req_done(req);
2954 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2955 TALLOC_CTX *mem_ctx,
2956 struct cli_state **output_cli)
2958 struct cli_start_connection_state *state = tevent_req_data(
2959 req, struct cli_start_connection_state);
2960 NTSTATUS status;
2962 if (tevent_req_is_nterror(req, &status)) {
2963 return status;
2965 *output_cli = talloc_move(mem_ctx, &state->cli);
2967 return NT_STATUS_OK;
2970 NTSTATUS cli_start_connection(TALLOC_CTX *mem_ctx,
2971 struct cli_state **output_cli,
2972 const char *my_name,
2973 const char *dest_host,
2974 const struct sockaddr_storage *dest_ss, int port,
2975 enum smb_signing_setting signing_state, int flags)
2977 struct tevent_context *ev;
2978 struct tevent_req *req;
2979 NTSTATUS status = NT_STATUS_NO_MEMORY;
2981 ev = samba_tevent_context_init(mem_ctx);
2982 if (ev == NULL) {
2983 goto fail;
2985 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2986 port, signing_state, flags, NULL);
2987 if (req == NULL) {
2988 goto fail;
2990 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2991 goto fail;
2993 status = cli_start_connection_recv(req, mem_ctx, output_cli);
2994 fail:
2995 TALLOC_FREE(ev);
2996 return status;
2999 struct cli_smb1_setup_encryption_blob_state {
3000 uint16_t setup[1];
3001 uint8_t param[4];
3002 NTSTATUS status;
3003 DATA_BLOB out;
3004 uint16_t enc_ctx_id;
3007 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
3009 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
3010 struct tevent_context *ev,
3011 struct cli_state *cli,
3012 const DATA_BLOB in)
3014 struct tevent_req *req = NULL;
3015 struct cli_smb1_setup_encryption_blob_state *state = NULL;
3016 struct tevent_req *subreq = NULL;
3018 req = tevent_req_create(mem_ctx, &state,
3019 struct cli_smb1_setup_encryption_blob_state);
3020 if (req == NULL) {
3021 return NULL;
3024 if (in.length > CLI_BUFFER_SIZE) {
3025 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3026 return tevent_req_post(req, ev);
3029 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
3030 SSVAL(state->param, 0, 0);
3031 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
3033 subreq = smb1cli_trans_send(state, ev, cli->conn,
3034 SMBtrans2,
3035 0, 0, /* _flags */
3036 0, 0, /* _flags2 */
3037 cli->timeout,
3038 cli->smb1.pid,
3039 cli->smb1.tcon,
3040 cli->smb1.session,
3041 NULL, /* pipe_name */
3042 0, /* fid */
3043 0, /* function */
3044 0, /* flags */
3045 state->setup, 1, 0,
3046 state->param, 4, 2,
3047 in.data, in.length, CLI_BUFFER_SIZE);
3048 if (tevent_req_nomem(subreq, req)) {
3049 return tevent_req_post(req, ev);
3051 tevent_req_set_callback(subreq,
3052 cli_smb1_setup_encryption_blob_done,
3053 req);
3055 return req;
3058 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
3060 struct tevent_req *req =
3061 tevent_req_callback_data(subreq,
3062 struct tevent_req);
3063 struct cli_smb1_setup_encryption_blob_state *state =
3064 tevent_req_data(req,
3065 struct cli_smb1_setup_encryption_blob_state);
3066 uint8_t *rparam=NULL, *rdata=NULL;
3067 uint32_t num_rparam, num_rdata;
3068 NTSTATUS status;
3070 status = smb1cli_trans_recv(subreq, state,
3071 NULL, /* recv_flags */
3072 NULL, 0, NULL, /* rsetup */
3073 &rparam, 0, &num_rparam,
3074 &rdata, 0, &num_rdata);
3075 TALLOC_FREE(subreq);
3076 state->status = status;
3077 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
3078 status = NT_STATUS_OK;
3080 if (tevent_req_nterror(req, status)) {
3081 return;
3084 if (num_rparam == 2) {
3085 state->enc_ctx_id = SVAL(rparam, 0);
3087 TALLOC_FREE(rparam);
3089 state->out = data_blob_const(rdata, num_rdata);
3091 tevent_req_done(req);
3094 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
3095 TALLOC_CTX *mem_ctx,
3096 DATA_BLOB *out,
3097 uint16_t *enc_ctx_id)
3099 struct cli_smb1_setup_encryption_blob_state *state =
3100 tevent_req_data(req,
3101 struct cli_smb1_setup_encryption_blob_state);
3102 NTSTATUS status;
3104 if (tevent_req_is_nterror(req, &status)) {
3105 tevent_req_received(req);
3106 return status;
3109 status = state->status;
3111 *out = state->out;
3112 talloc_steal(mem_ctx, out->data);
3114 *enc_ctx_id = state->enc_ctx_id;
3116 tevent_req_received(req);
3117 return status;
3120 struct cli_smb1_setup_encryption_state {
3121 struct tevent_context *ev;
3122 struct cli_state *cli;
3123 struct smb_trans_enc_state *es;
3124 DATA_BLOB blob_in;
3125 DATA_BLOB blob_out;
3126 bool local_ready;
3127 bool remote_ready;
3130 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
3131 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
3132 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
3133 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
3134 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
3136 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
3137 struct tevent_context *ev,
3138 struct cli_state *cli,
3139 struct cli_credentials *creds)
3141 struct tevent_req *req = NULL;
3142 struct cli_smb1_setup_encryption_state *state = NULL;
3143 struct auth_generic_state *ags = NULL;
3144 const DATA_BLOB *b = NULL;
3145 bool auth_requested = false;
3146 const char *target_service = NULL;
3147 const char *target_hostname = NULL;
3148 NTSTATUS status;
3150 req = tevent_req_create(mem_ctx, &state,
3151 struct cli_smb1_setup_encryption_state);
3152 if (req == NULL) {
3153 return NULL;
3155 state->ev = ev;
3156 state->cli = cli;
3158 auth_requested = cli_credentials_authentication_requested(creds);
3159 if (!auth_requested) {
3160 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3161 return tevent_req_post(req, ev);
3164 target_service = "cifs";
3165 target_hostname = smbXcli_conn_remote_name(cli->conn);
3167 status = cli_session_creds_prepare_krb5(cli, creds);
3168 if (tevent_req_nterror(req, status)) {
3169 return tevent_req_post(req, ev);
3172 state->es = talloc_zero(state, struct smb_trans_enc_state);
3173 if (tevent_req_nomem(state->es, req)) {
3174 return tevent_req_post(req, ev);
3177 status = auth_generic_client_prepare(state->es, &ags);
3178 if (tevent_req_nterror(req, status)) {
3179 return tevent_req_post(req, ev);
3182 gensec_want_feature(ags->gensec_security,
3183 GENSEC_FEATURE_SIGN);
3184 gensec_want_feature(ags->gensec_security,
3185 GENSEC_FEATURE_SEAL);
3187 status = auth_generic_set_creds(ags, creds);
3188 if (tevent_req_nterror(req, status)) {
3189 return tevent_req_post(req, ev);
3192 if (target_service != NULL) {
3193 status = gensec_set_target_service(ags->gensec_security,
3194 target_service);
3195 if (tevent_req_nterror(req, status)) {
3196 return tevent_req_post(req, ev);
3200 if (target_hostname != NULL) {
3201 status = gensec_set_target_hostname(ags->gensec_security,
3202 target_hostname);
3203 if (tevent_req_nterror(req, status)) {
3204 return tevent_req_post(req, ev);
3208 gensec_set_max_update_size(ags->gensec_security,
3209 CLI_BUFFER_SIZE);
3211 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3212 if (b != NULL) {
3213 state->blob_in = *b;
3216 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3217 if (tevent_req_nterror(req, status)) {
3218 return tevent_req_post(req, ev);
3222 * We only need the gensec_security part from here.
3224 state->es->gensec_security = talloc_move(state->es,
3225 &ags->gensec_security);
3226 TALLOC_FREE(ags);
3228 cli_smb1_setup_encryption_local_next(req);
3229 if (!tevent_req_is_in_progress(req)) {
3230 return tevent_req_post(req, ev);
3233 return req;
3236 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3238 struct cli_smb1_setup_encryption_state *state =
3239 tevent_req_data(req,
3240 struct cli_smb1_setup_encryption_state);
3241 struct tevent_req *subreq = NULL;
3243 if (state->local_ready) {
3244 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3245 return;
3248 subreq = gensec_update_send(state, state->ev,
3249 state->es->gensec_security,
3250 state->blob_in);
3251 if (tevent_req_nomem(subreq, req)) {
3252 return;
3254 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3257 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3259 struct tevent_req *req =
3260 tevent_req_callback_data(subreq,
3261 struct tevent_req);
3262 struct cli_smb1_setup_encryption_state *state =
3263 tevent_req_data(req,
3264 struct cli_smb1_setup_encryption_state);
3265 NTSTATUS status;
3267 status = gensec_update_recv(subreq, state, &state->blob_out);
3268 TALLOC_FREE(subreq);
3269 state->blob_in = data_blob_null;
3270 if (!NT_STATUS_IS_OK(status) &&
3271 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3273 tevent_req_nterror(req, status);
3274 return;
3277 if (NT_STATUS_IS_OK(status)) {
3278 state->local_ready = true;
3282 * We always get NT_STATUS_OK from the server even if it is not ready.
3283 * So guess the server is ready when we are ready and already sent
3284 * our last blob to the server.
3286 if (state->local_ready && state->blob_out.length == 0) {
3287 state->remote_ready = true;
3290 if (state->local_ready && state->remote_ready) {
3291 cli_smb1_setup_encryption_ready(req);
3292 return;
3295 cli_smb1_setup_encryption_remote_next(req);
3298 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3300 struct cli_smb1_setup_encryption_state *state =
3301 tevent_req_data(req,
3302 struct cli_smb1_setup_encryption_state);
3303 struct tevent_req *subreq = NULL;
3305 if (state->remote_ready) {
3306 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3307 return;
3310 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3311 state->cli, state->blob_out);
3312 if (tevent_req_nomem(subreq, req)) {
3313 return;
3315 tevent_req_set_callback(subreq,
3316 cli_smb1_setup_encryption_remote_done,
3317 req);
3320 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3322 struct tevent_req *req =
3323 tevent_req_callback_data(subreq,
3324 struct tevent_req);
3325 struct cli_smb1_setup_encryption_state *state =
3326 tevent_req_data(req,
3327 struct cli_smb1_setup_encryption_state);
3328 NTSTATUS status;
3330 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3331 &state->blob_in,
3332 &state->es->enc_ctx_num);
3333 TALLOC_FREE(subreq);
3334 data_blob_free(&state->blob_out);
3335 if (!NT_STATUS_IS_OK(status) &&
3336 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3338 tevent_req_nterror(req, status);
3339 return;
3343 * We always get NT_STATUS_OK even if the server is not ready.
3344 * So guess the server is ready when we are ready and sent
3345 * our last blob to the server.
3347 if (state->local_ready) {
3348 state->remote_ready = true;
3351 if (state->local_ready && state->remote_ready) {
3352 cli_smb1_setup_encryption_ready(req);
3353 return;
3356 cli_smb1_setup_encryption_local_next(req);
3359 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3361 struct cli_smb1_setup_encryption_state *state =
3362 tevent_req_data(req,
3363 struct cli_smb1_setup_encryption_state);
3364 struct smb_trans_enc_state *es = NULL;
3366 if (state->blob_in.length != 0) {
3367 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3368 return;
3371 if (state->blob_out.length != 0) {
3372 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3373 return;
3376 es = talloc_move(state->cli->conn, &state->es);
3377 es->enc_on = true;
3378 smb1cli_conn_set_encryption(state->cli->conn, es);
3379 es = NULL;
3381 tevent_req_done(req);
3384 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3386 return tevent_req_simple_recv_ntstatus(req);
3389 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3390 struct cli_credentials *creds)
3392 struct tevent_context *ev = NULL;
3393 struct tevent_req *req = NULL;
3394 NTSTATUS status = NT_STATUS_NO_MEMORY;
3396 ev = samba_tevent_context_init(talloc_tos());
3397 if (ev == NULL) {
3398 goto fail;
3400 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3401 if (req == NULL) {
3402 goto fail;
3404 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3405 goto fail;
3407 status = cli_smb1_setup_encryption_recv(req);
3408 fail:
3409 TALLOC_FREE(ev);
3410 return status;
3414 establishes a connection right up to doing tconX, password specified.
3415 @param output_cli A fully initialised cli structure, non-null only on success
3416 @param dest_host The netbios name of the remote host
3417 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3418 @param port (optional) The destination port (0 for default)
3419 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3420 @param service_type The 'type' of service.
3421 @param creds The used user credentials
3424 struct cli_full_connection_creds_state {
3425 struct tevent_context *ev;
3426 const char *service;
3427 const char *service_type;
3428 struct cli_credentials *creds;
3429 int flags;
3430 struct cli_state *cli;
3433 static int cli_full_connection_creds_state_destructor(
3434 struct cli_full_connection_creds_state *s)
3436 if (s->cli != NULL) {
3437 cli_shutdown(s->cli);
3438 s->cli = NULL;
3440 return 0;
3443 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3444 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3445 static void cli_full_connection_creds_enc_start(struct tevent_req *req);
3446 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq);
3447 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq);
3448 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq);
3449 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req);
3450 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq);
3451 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3452 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3454 struct tevent_req *cli_full_connection_creds_send(
3455 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3456 const char *my_name, const char *dest_host,
3457 const struct sockaddr_storage *dest_ss, int port,
3458 const char *service, const char *service_type,
3459 struct cli_credentials *creds,
3460 int flags,
3461 struct smb2_negotiate_contexts *negotiate_contexts)
3463 struct tevent_req *req, *subreq;
3464 struct cli_full_connection_creds_state *state;
3465 enum smb_signing_setting signing_state;
3466 enum smb_encryption_setting encryption_state =
3467 cli_credentials_get_smb_encryption(creds);
3469 req = tevent_req_create(mem_ctx, &state,
3470 struct cli_full_connection_creds_state);
3471 if (req == NULL) {
3472 return NULL;
3474 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3476 state->ev = ev;
3477 state->service = service;
3478 state->service_type = service_type;
3479 state->creds = creds;
3480 state->flags = flags;
3482 if (flags & CLI_FULL_CONNECTION_IPC) {
3483 signing_state = cli_credentials_get_smb_ipc_signing(creds);
3484 } else {
3485 signing_state = cli_credentials_get_smb_signing(creds);
3488 if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
3489 if (flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK) {
3490 encryption_state = SMB_ENCRYPTION_DESIRED;
3494 if (encryption_state >= SMB_ENCRYPTION_DESIRED) {
3495 signing_state = SMB_SIGNING_REQUIRED;
3498 subreq = cli_start_connection_send(
3499 state, ev, my_name, dest_host, dest_ss, port,
3500 signing_state, flags,
3501 negotiate_contexts);
3502 if (tevent_req_nomem(subreq, req)) {
3503 return tevent_req_post(req, ev);
3505 tevent_req_set_callback(subreq,
3506 cli_full_connection_creds_conn_done,
3507 req);
3508 return req;
3511 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3513 struct tevent_req *req = tevent_req_callback_data(
3514 subreq, struct tevent_req);
3515 struct cli_full_connection_creds_state *state = tevent_req_data(
3516 req, struct cli_full_connection_creds_state);
3517 NTSTATUS status;
3519 status = cli_start_connection_recv(subreq, state, &state->cli);
3520 TALLOC_FREE(subreq);
3521 if (tevent_req_nterror(req, status)) {
3522 return;
3525 subreq = cli_session_setup_creds_send(
3526 state, state->ev, state->cli, state->creds);
3527 if (tevent_req_nomem(subreq, req)) {
3528 return;
3530 tevent_req_set_callback(subreq,
3531 cli_full_connection_creds_sess_done,
3532 req);
3535 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3537 struct tevent_req *req = tevent_req_callback_data(
3538 subreq, struct tevent_req);
3539 struct cli_full_connection_creds_state *state = tevent_req_data(
3540 req, struct cli_full_connection_creds_state);
3541 NTSTATUS status;
3543 status = cli_session_setup_creds_recv(subreq);
3544 TALLOC_FREE(subreq);
3546 if (!NT_STATUS_IS_OK(status) &&
3547 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3549 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3551 state->creds = cli_credentials_init_anon(state);
3552 if (tevent_req_nomem(state->creds, req)) {
3553 return;
3556 subreq = cli_session_setup_creds_send(
3557 state, state->ev, state->cli, state->creds);
3558 if (tevent_req_nomem(subreq, req)) {
3559 return;
3561 tevent_req_set_callback(subreq,
3562 cli_full_connection_creds_sess_done,
3563 req);
3564 return;
3567 if (tevent_req_nterror(req, status)) {
3568 return;
3571 cli_full_connection_creds_enc_start(req);
3574 static void cli_full_connection_creds_enc_start(struct tevent_req *req)
3576 struct cli_full_connection_creds_state *state = tevent_req_data(
3577 req, struct cli_full_connection_creds_state);
3578 enum smb_encryption_setting encryption_state =
3579 cli_credentials_get_smb_encryption(state->creds);
3580 struct tevent_req *subreq = NULL;
3581 NTSTATUS status;
3583 if (encryption_state < SMB_ENCRYPTION_DESIRED) {
3584 cli_full_connection_creds_tcon_start(req);
3585 return;
3588 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3589 status = smb2cli_session_encryption_on(state->cli->smb2.session);
3590 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
3591 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3592 cli_full_connection_creds_tcon_start(req);
3593 return;
3595 d_printf("Encryption required and "
3596 "server doesn't support "
3597 "SMB3 encryption - failing connect\n");
3598 tevent_req_nterror(req, status);
3599 return;
3600 } else if (!NT_STATUS_IS_OK(status)) {
3601 d_printf("Encryption required and "
3602 "setup failed with error %s.\n",
3603 nt_errstr(status));
3604 tevent_req_nterror(req, status);
3605 return;
3608 cli_full_connection_creds_tcon_start(req);
3609 return;
3612 if (!SERVER_HAS_UNIX_CIFS(state->cli)) {
3613 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3614 cli_full_connection_creds_tcon_start(req);
3615 return;
3618 status = NT_STATUS_NOT_SUPPORTED;
3619 d_printf("Encryption required and "
3620 "server doesn't support "
3621 "SMB1 Unix Extensions - failing connect\n");
3622 tevent_req_nterror(req, status);
3623 return;
3627 * We do a tcon on IPC$ just to setup the encryption,
3628 * the real tcon will be encrypted then.
3630 subreq = cli_tree_connect_send(state, state->ev, state->cli,
3631 "IPC$", "IPC", NULL);
3632 if (tevent_req_nomem(subreq, req)) {
3633 return;
3635 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_tcon, req);
3638 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq)
3640 struct tevent_req *req = tevent_req_callback_data(
3641 subreq, struct tevent_req);
3642 struct cli_full_connection_creds_state *state = tevent_req_data(
3643 req, struct cli_full_connection_creds_state);
3644 NTSTATUS status;
3646 status = cli_tree_connect_recv(subreq);
3647 TALLOC_FREE(subreq);
3648 if (tevent_req_nterror(req, status)) {
3649 return;
3652 subreq = cli_unix_extensions_version_send(state, state->ev, state->cli);
3653 if (tevent_req_nomem(subreq, req)) {
3654 return;
3656 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_ver, req);
3659 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq)
3661 struct tevent_req *req = tevent_req_callback_data(
3662 subreq, struct tevent_req);
3663 struct cli_full_connection_creds_state *state = tevent_req_data(
3664 req, struct cli_full_connection_creds_state);
3665 enum smb_encryption_setting encryption_state =
3666 cli_credentials_get_smb_encryption(state->creds);
3667 uint16_t major, minor;
3668 uint32_t caplow, caphigh;
3669 NTSTATUS status;
3671 status = cli_unix_extensions_version_recv(subreq,
3672 &major, &minor,
3673 &caplow,
3674 &caphigh);
3675 TALLOC_FREE(subreq);
3676 if (!NT_STATUS_IS_OK(status)) {
3677 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3678 /* disconnect ipc$ followed by the real tree connect */
3679 cli_full_connection_creds_enc_tdis(req);
3680 return;
3682 DEBUG(10, ("%s: cli_unix_extensions_version "
3683 "returned %s\n", __func__, nt_errstr(status)));
3684 tevent_req_nterror(req, NT_STATUS_UNKNOWN_REVISION);
3685 return;
3688 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
3689 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3690 /* disconnect ipc$ followed by the real tree connect */
3691 cli_full_connection_creds_enc_tdis(req);
3692 return;
3694 DEBUG(10, ("%s: CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP "
3695 "not supported\n", __func__));
3696 tevent_req_nterror(req, NT_STATUS_UNSUPPORTED_COMPRESSION);
3697 return;
3700 subreq = cli_smb1_setup_encryption_send(state, state->ev,
3701 state->cli,
3702 state->creds);
3703 if (tevent_req_nomem(subreq, req)) {
3704 return;
3706 tevent_req_set_callback(subreq,
3707 cli_full_connection_creds_enc_done,
3708 req);
3711 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq)
3713 struct tevent_req *req = tevent_req_callback_data(
3714 subreq, struct tevent_req);
3715 NTSTATUS status;
3717 status = cli_smb1_setup_encryption_recv(subreq);
3718 TALLOC_FREE(subreq);
3719 if (tevent_req_nterror(req, status)) {
3720 return;
3723 /* disconnect ipc$ followed by the real tree connect */
3724 cli_full_connection_creds_enc_tdis(req);
3727 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req)
3729 struct cli_full_connection_creds_state *state = tevent_req_data(
3730 req, struct cli_full_connection_creds_state);
3731 struct tevent_req *subreq = NULL;
3733 subreq = cli_tdis_send(state, state->ev, state->cli);
3734 if (tevent_req_nomem(subreq, req)) {
3735 return;
3737 tevent_req_set_callback(subreq,
3738 cli_full_connection_creds_enc_finished,
3739 req);
3742 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq)
3744 struct tevent_req *req = tevent_req_callback_data(
3745 subreq, struct tevent_req);
3746 NTSTATUS status;
3748 status = cli_tdis_recv(subreq);
3749 TALLOC_FREE(subreq);
3750 if (tevent_req_nterror(req, status)) {
3751 return;
3754 cli_full_connection_creds_tcon_start(req);
3757 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3759 struct cli_full_connection_creds_state *state = tevent_req_data(
3760 req, struct cli_full_connection_creds_state);
3761 struct tevent_req *subreq = NULL;
3762 const char *password = NULL;
3764 if (state->service == NULL) {
3765 tevent_req_done(req);
3766 return;
3769 password = cli_credentials_get_password(state->creds);
3771 subreq = cli_tree_connect_send(state, state->ev,
3772 state->cli,
3773 state->service,
3774 state->service_type,
3775 password);
3776 if (tevent_req_nomem(subreq, req)) {
3777 return;
3779 tevent_req_set_callback(subreq,
3780 cli_full_connection_creds_tcon_done,
3781 req);
3784 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3786 struct tevent_req *req = tevent_req_callback_data(
3787 subreq, struct tevent_req);
3788 NTSTATUS status;
3790 status = cli_tree_connect_recv(subreq);
3791 TALLOC_FREE(subreq);
3792 if (tevent_req_nterror(req, status)) {
3793 return;
3796 tevent_req_done(req);
3799 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3800 TALLOC_CTX *mem_ctx,
3801 struct cli_state **output_cli)
3803 struct cli_full_connection_creds_state *state = tevent_req_data(
3804 req, struct cli_full_connection_creds_state);
3805 NTSTATUS status;
3807 if (tevent_req_is_nterror(req, &status)) {
3808 return status;
3810 *output_cli = talloc_move(mem_ctx, &state->cli);
3811 talloc_set_destructor(state, NULL);
3812 return NT_STATUS_OK;
3815 NTSTATUS cli_full_connection_creds(TALLOC_CTX *mem_ctx,
3816 struct cli_state **output_cli,
3817 const char *my_name,
3818 const char *dest_host,
3819 const struct sockaddr_storage *dest_ss, int port,
3820 const char *service, const char *service_type,
3821 struct cli_credentials *creds,
3822 int flags)
3824 struct tevent_context *ev;
3825 struct tevent_req *req;
3826 NTSTATUS status = NT_STATUS_NO_MEMORY;
3828 ev = samba_tevent_context_init(mem_ctx);
3829 if (ev == NULL) {
3830 goto fail;
3832 req = cli_full_connection_creds_send(
3833 ev, ev, my_name, dest_host, dest_ss, port, service,
3834 service_type, creds, flags,
3835 NULL);
3836 if (req == NULL) {
3837 goto fail;
3839 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3840 goto fail;
3842 status = cli_full_connection_creds_recv(req, mem_ctx, output_cli);
3843 fail:
3844 TALLOC_FREE(ev);
3845 return status;
3848 /****************************************************************************
3849 Send an old style tcon.
3850 ****************************************************************************/
3851 struct cli_raw_tcon_state {
3852 uint16_t *ret_vwv;
3855 static void cli_raw_tcon_done(struct tevent_req *subreq);
3857 static struct tevent_req *cli_raw_tcon_send(
3858 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3859 const char *service, const char *pass, const char *dev)
3861 struct tevent_req *req, *subreq;
3862 struct cli_raw_tcon_state *state;
3863 uint8_t *bytes;
3865 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3866 if (req == NULL) {
3867 return NULL;
3870 if (!lp_client_plaintext_auth() && (*pass)) {
3871 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3872 " or 'client ntlmv2 auth = yes'\n"));
3873 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3874 return tevent_req_post(req, ev);
3877 TALLOC_FREE(cli->smb1.tcon);
3878 cli->smb1.tcon = smbXcli_tcon_create(cli);
3879 if (tevent_req_nomem(cli->smb1.tcon, req)) {
3880 return tevent_req_post(req, ev);
3882 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
3884 bytes = talloc_array(state, uint8_t, 0);
3885 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3886 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3887 service, strlen(service)+1, NULL);
3888 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3889 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3890 pass, strlen(pass)+1, NULL);
3891 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3892 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3893 dev, strlen(dev)+1, NULL);
3895 if (tevent_req_nomem(bytes, req)) {
3896 return tevent_req_post(req, ev);
3899 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3900 talloc_get_size(bytes), bytes);
3901 if (tevent_req_nomem(subreq, req)) {
3902 return tevent_req_post(req, ev);
3904 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3905 return req;
3908 static void cli_raw_tcon_done(struct tevent_req *subreq)
3910 struct tevent_req *req = tevent_req_callback_data(
3911 subreq, struct tevent_req);
3912 struct cli_raw_tcon_state *state = tevent_req_data(
3913 req, struct cli_raw_tcon_state);
3914 NTSTATUS status;
3916 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3917 NULL, NULL);
3918 TALLOC_FREE(subreq);
3919 if (tevent_req_nterror(req, status)) {
3920 return;
3922 tevent_req_done(req);
3925 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3926 uint16_t *max_xmit, uint16_t *tid)
3928 struct cli_raw_tcon_state *state = tevent_req_data(
3929 req, struct cli_raw_tcon_state);
3930 NTSTATUS status;
3932 if (tevent_req_is_nterror(req, &status)) {
3933 return status;
3935 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3936 *tid = SVAL(state->ret_vwv + 1, 0);
3937 return NT_STATUS_OK;
3940 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3941 const char *service, const char *pass, const char *dev,
3942 uint16_t *max_xmit, uint16_t *tid)
3944 struct tevent_context *ev;
3945 struct tevent_req *req;
3946 NTSTATUS status = NT_STATUS_NO_MEMORY;
3948 ev = samba_tevent_context_init(talloc_tos());
3949 if (ev == NULL) {
3950 goto fail;
3952 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3953 if (req == NULL) {
3954 goto fail;
3956 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3957 goto fail;
3959 status = cli_raw_tcon_recv(req, max_xmit, tid);
3960 fail:
3961 TALLOC_FREE(ev);
3962 return status;
3965 /* Return a cli_state pointing at the IPC$ share for the given server */
3967 static struct cli_state *get_ipc_connect(TALLOC_CTX *mem_ctx,
3968 char *server,
3969 struct sockaddr_storage *server_ss,
3970 struct cli_credentials *creds)
3972 struct cli_state *cli;
3973 NTSTATUS nt_status;
3974 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3976 flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
3977 flags |= CLI_FULL_CONNECTION_IPC;
3979 nt_status = cli_full_connection_creds(mem_ctx,
3980 &cli,
3981 NULL,
3982 server,
3983 server_ss,
3985 "IPC$",
3986 "IPC",
3987 creds,
3988 flags);
3990 if (NT_STATUS_IS_OK(nt_status)) {
3991 return cli;
3993 if (is_ipaddress(server)) {
3994 /* windows 9* needs a correct NMB name for connections */
3995 fstring remote_name;
3997 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3998 cli = get_ipc_connect(mem_ctx, remote_name, server_ss, creds);
3999 if (cli)
4000 return cli;
4003 return NULL;
4007 * Given the IP address of a master browser on the network, return its
4008 * workgroup and connect to it.
4010 * This function is provided to allow additional processing beyond what
4011 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
4012 * browsers and obtain each master browsers' list of domains (in case the
4013 * first master browser is recently on the network and has not yet
4014 * synchronized with other master browsers and therefore does not yet have the
4015 * entire network browse list)
4018 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
4019 struct sockaddr_storage *mb_ip,
4020 struct cli_credentials *creds,
4021 char **pp_workgroup_out)
4023 char addr[INET6_ADDRSTRLEN];
4024 fstring name;
4025 struct cli_state *cli;
4026 struct sockaddr_storage server_ss;
4028 *pp_workgroup_out = NULL;
4030 print_sockaddr(addr, sizeof(addr), mb_ip);
4031 DEBUG(99, ("Looking up name of master browser %s\n",
4032 addr));
4035 * Do a name status query to find out the name of the master browser.
4036 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
4037 * master browser will not respond to a wildcard query (or, at least,
4038 * an NT4 server acting as the domain master browser will not).
4040 * We might be able to use ONLY the query on MSBROWSE, but that's not
4041 * yet been tested with all Windows versions, so until it is, leave
4042 * the original wildcard query as the first choice and fall back to
4043 * MSBROWSE if the wildcard query fails.
4045 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
4046 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
4048 DEBUG(99, ("Could not retrieve name status for %s\n",
4049 addr));
4050 return NULL;
4053 if (!find_master_ip(name, &server_ss)) {
4054 DEBUG(99, ("Could not find master ip for %s\n", name));
4055 return NULL;
4058 *pp_workgroup_out = talloc_strdup(ctx, name);
4060 DEBUG(4, ("found master browser %s, %s\n", name, addr));
4062 print_sockaddr(addr, sizeof(addr), &server_ss);
4063 cli = get_ipc_connect(ctx, addr, &server_ss, creds);
4065 return cli;