third_party: Update socket_wrapper to version 1.4.2
[Samba.git] / source3 / libsmb / cliconnect.c
blobb687a22e11cf142b2bc1543d469d805c8b70ea69
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 "../libcli/auth/spnego.h"
28 #include "smb_krb5.h"
29 #include "auth/credentials/credentials.h"
30 #include "auth/gensec/gensec.h"
31 #include "auth/ntlmssp/ntlmssp.h"
32 #include "auth_generic.h"
33 #include "libads/kerberos_proto.h"
34 #include "krb5_env.h"
35 #include "../lib/util/tevent_ntstatus.h"
36 #include "async_smb.h"
37 #include "libsmb/nmblib.h"
38 #include "librpc/ndr/libndr.h"
39 #include "../libcli/smb/smbXcli_base.h"
40 #include "../libcli/smb/smb_seal.h"
41 #include "lib/param/param.h"
42 #include "../libcli/smb/smb2_negotiate_context.h"
44 #define STAR_SMBSERVER "*SMBSERVER"
46 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
47 const char *principal);
49 struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
50 const char *username,
51 const char *domain,
52 const char *realm,
53 const char *password,
54 bool use_kerberos,
55 bool fallback_after_kerberos,
56 bool use_ccache,
57 bool password_is_nt_hash)
59 struct loadparm_context *lp_ctx = NULL;
60 struct cli_credentials *creds = NULL;
61 const char *principal = NULL;
62 char *tmp = NULL;
63 char *p = NULL;
64 bool ok;
66 creds = cli_credentials_init(mem_ctx);
67 if (creds == NULL) {
68 return NULL;
71 lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
72 if (lp_ctx == NULL) {
73 goto fail;
75 ok = cli_credentials_set_conf(creds, lp_ctx);
76 if (!ok) {
77 goto fail;
80 if (username == NULL) {
81 username = "";
84 if (strlen(username) == 0) {
85 if (password != NULL && strlen(password) == 0) {
87 * some callers pass "" as no password
89 * gensec only handles NULL as no password.
91 password = NULL;
93 if (password == NULL) {
94 cli_credentials_set_anonymous(creds);
95 return creds;
99 tmp = talloc_strdup(creds, username);
100 if (tmp == NULL) {
101 goto fail;
103 username = tmp;
105 /* allow for workgroups as part of the username */
106 if ((p = strchr_m(tmp, '\\')) ||
107 (p = strchr_m(tmp, '/')) ||
108 (p = strchr_m(tmp, *lp_winbind_separator()))) {
109 *p = 0;
110 username = p + 1;
111 domain = tmp;
114 principal = username;
115 username = cli_session_setup_get_account(creds, principal);
116 if (username == NULL) {
117 goto fail;
119 ok = strequal(username, principal);
120 if (ok) {
122 * Ok still the same, so it's not a principal
124 principal = NULL;
127 if (use_kerberos && fallback_after_kerberos) {
128 cli_credentials_set_kerberos_state(creds,
129 CRED_USE_KERBEROS_DESIRED,
130 CRED_SPECIFIED);
131 } else if (use_kerberos) {
132 cli_credentials_set_kerberos_state(creds,
133 CRED_USE_KERBEROS_REQUIRED,
134 CRED_SPECIFIED);
135 } else {
136 cli_credentials_set_kerberos_state(creds,
137 CRED_USE_KERBEROS_DISABLED,
138 CRED_SPECIFIED);
141 if (use_ccache) {
142 uint32_t features;
144 features = cli_credentials_get_gensec_features(creds);
145 features |= GENSEC_FEATURE_NTLM_CCACHE;
146 cli_credentials_set_gensec_features(creds,
147 features,
148 CRED_SPECIFIED);
150 if (password != NULL && strlen(password) == 0) {
152 * some callers pass "" as no password
154 * GENSEC_FEATURE_NTLM_CCACHE only handles
155 * NULL as no password.
157 password = NULL;
161 ok = cli_credentials_set_username(creds,
162 username,
163 CRED_SPECIFIED);
164 if (!ok) {
165 goto fail;
168 if (domain != NULL) {
169 ok = cli_credentials_set_domain(creds,
170 domain,
171 CRED_SPECIFIED);
172 if (!ok) {
173 goto fail;
177 if (principal != NULL) {
178 ok = cli_credentials_set_principal(creds,
179 principal,
180 CRED_SPECIFIED);
181 if (!ok) {
182 goto fail;
186 if (realm != NULL) {
187 ok = cli_credentials_set_realm(creds,
188 realm,
189 CRED_SPECIFIED);
190 if (!ok) {
191 goto fail;
195 if (password != NULL && strlen(password) > 0) {
196 if (password_is_nt_hash) {
197 struct samr_Password nt_hash;
198 size_t converted;
200 converted = strhex_to_str((char *)nt_hash.hash,
201 sizeof(nt_hash.hash),
202 password,
203 strlen(password));
204 if (converted != sizeof(nt_hash.hash)) {
205 goto fail;
208 ok = cli_credentials_set_nt_hash(creds,
209 &nt_hash,
210 CRED_SPECIFIED);
211 if (!ok) {
212 goto fail;
214 } else {
215 ok = cli_credentials_set_password(creds,
216 password,
217 CRED_SPECIFIED);
218 if (!ok) {
219 goto fail;
224 return creds;
225 fail:
226 TALLOC_FREE(creds);
227 return NULL;
230 NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
231 struct cli_credentials *creds)
233 TALLOC_CTX *frame = talloc_stackframe();
234 const char *user_principal = NULL;
235 const char *user_account = NULL;
236 const char *user_domain = NULL;
237 const char *pass = NULL;
238 char *canon_principal = NULL;
239 char *canon_realm = NULL;
240 const char *target_hostname = NULL;
241 enum credentials_use_kerberos krb5_state;
242 bool try_kerberos = false;
243 bool need_kinit = false;
244 bool auth_requested = true;
245 int ret;
246 bool ok;
248 target_hostname = smbXcli_conn_remote_name(cli->conn);
250 auth_requested = cli_credentials_authentication_requested(creds);
251 if (auth_requested) {
252 errno = 0;
253 user_principal = cli_credentials_get_principal(creds, frame);
254 if (errno != 0) {
255 TALLOC_FREE(frame);
256 return NT_STATUS_NO_MEMORY;
259 user_account = cli_credentials_get_username(creds);
260 user_domain = cli_credentials_get_domain(creds);
261 pass = cli_credentials_get_password(creds);
263 krb5_state = cli_credentials_get_kerberos_state(creds);
265 if (krb5_state != CRED_USE_KERBEROS_DISABLED) {
266 try_kerberos = true;
269 if (user_principal == NULL) {
270 try_kerberos = false;
273 if (target_hostname == NULL) {
274 try_kerberos = false;
275 } else if (is_ipaddress(target_hostname)) {
276 try_kerberos = false;
277 } else if (strequal(target_hostname, "localhost")) {
278 try_kerberos = false;
279 } else if (strequal(target_hostname, STAR_SMBSERVER)) {
280 try_kerberos = false;
281 } else if (!auth_requested) {
282 try_kerberos = false;
285 if (krb5_state == CRED_USE_KERBEROS_REQUIRED && !try_kerberos) {
286 DEBUG(0, ("Kerberos auth with '%s' (%s\\%s) to access "
287 "'%s' not possible\n",
288 user_principal, user_domain, user_account,
289 target_hostname));
290 TALLOC_FREE(frame);
291 return NT_STATUS_ACCESS_DENIED;
294 if (pass == NULL || strlen(pass) == 0) {
295 need_kinit = false;
296 } else if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
297 need_kinit = try_kerberos;
298 } else {
299 need_kinit = try_kerberos;
302 if (!need_kinit) {
303 TALLOC_FREE(frame);
304 return NT_STATUS_OK;
307 DBG_INFO("Doing kinit for %s to access %s\n",
308 user_principal, target_hostname);
311 * TODO: This should be done within the gensec layer
312 * only if required!
314 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
315 ret = kerberos_kinit_password_ext(user_principal,
316 pass,
320 NULL,
321 false,
322 false,
324 frame,
325 &canon_principal,
326 &canon_realm,
327 NULL);
328 if (ret != 0) {
329 int dbglvl = DBGLVL_NOTICE;
331 if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
332 dbglvl = DBGLVL_ERR;
335 DEBUG(dbglvl, ("Kinit for %s to access %s failed: %s\n",
336 user_principal, target_hostname,
337 error_message(ret)));
338 if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
339 TALLOC_FREE(frame);
340 return krb5_to_nt_status(ret);
344 * Ignore the error and hope that NTLM will work
346 TALLOC_FREE(frame);
347 return NT_STATUS_OK;
350 ok = cli_credentials_set_principal(creds,
351 canon_principal,
352 CRED_SPECIFIED);
353 if (!ok) {
354 TALLOC_FREE(frame);
355 return NT_STATUS_NO_MEMORY;
358 ok = cli_credentials_set_realm(creds,
359 canon_realm,
360 CRED_SPECIFIED);
361 if (!ok) {
362 TALLOC_FREE(frame);
363 return NT_STATUS_NO_MEMORY;
366 DBG_DEBUG("Successfully authenticated as %s (%s) to access %s using "
367 "Kerberos\n",
368 user_principal,
369 canon_principal,
370 target_hostname);
372 TALLOC_FREE(frame);
373 return NT_STATUS_OK;
376 static NTSTATUS cli_state_update_after_sesssetup(struct cli_state *cli,
377 const char *native_os,
378 const char *native_lm,
379 const char *primary_domain)
381 #define _VALID_STR(p) ((p) != NULL && (p)[0] != '\0')
383 if (!_VALID_STR(cli->server_os) && _VALID_STR(native_os)) {
384 cli->server_os = talloc_strdup(cli, native_os);
385 if (cli->server_os == NULL) {
386 return NT_STATUS_NO_MEMORY;
390 if (!_VALID_STR(cli->server_type) && _VALID_STR(native_lm)) {
391 cli->server_type = talloc_strdup(cli, native_lm);
392 if (cli->server_type == NULL) {
393 return NT_STATUS_NO_MEMORY;
397 if (!_VALID_STR(cli->server_domain) && _VALID_STR(primary_domain)) {
398 cli->server_domain = talloc_strdup(cli, primary_domain);
399 if (cli->server_domain == NULL) {
400 return NT_STATUS_NO_MEMORY;
404 #undef _VALID_STRING
405 return NT_STATUS_OK;
408 /********************************************************
409 Utility function to ensure we always return at least
410 a valid char * pointer to an empty string for the
411 cli->server_os, cli->server_type and cli->server_domain
412 strings.
413 *******************************************************/
415 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
416 const uint8_t *hdr,
417 char **dest,
418 uint8_t *src,
419 size_t srclen,
420 ssize_t *destlen)
422 *destlen = pull_string_talloc(mem_ctx,
423 (const char *)hdr,
424 SVAL(hdr, HDR_FLG2),
425 dest,
426 (char *)src,
427 srclen,
428 STR_TERMINATE);
429 if (*destlen == -1) {
430 return NT_STATUS_NO_MEMORY;
433 if (*dest == NULL) {
434 *dest = talloc_strdup(mem_ctx, "");
435 if (*dest == NULL) {
436 return NT_STATUS_NO_MEMORY;
439 return NT_STATUS_OK;
442 /****************************************************************************
443 Work out suitable capabilities to offer the server.
444 ****************************************************************************/
446 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
447 uint32_t sesssetup_capabilities)
449 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
452 * We only send capabilities based on the mask for:
453 * - client only flags
454 * - flags used in both directions
456 * We do not echo the server only flags, except some legacy flags.
458 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
459 * CAP_LARGE_WRITEX in order to allow us to do large reads
460 * against old Samba releases (<= 3.6.x).
462 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
465 * Session Setup specific flags CAP_DYNAMIC_REAUTH
466 * and CAP_EXTENDED_SECURITY are passed by the caller.
467 * We need that in order to do guest logins even if
468 * CAP_EXTENDED_SECURITY is negotiated.
470 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
471 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
472 client_capabilities |= sesssetup_capabilities;
474 return client_capabilities;
477 /****************************************************************************
478 Do a NT1 guest session setup.
479 ****************************************************************************/
481 struct cli_session_setup_guest_state {
482 struct cli_state *cli;
483 uint16_t vwv[13];
484 struct iovec bytes;
487 static void cli_session_setup_guest_done(struct tevent_req *subreq);
489 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
490 struct tevent_context *ev,
491 struct cli_state *cli,
492 struct tevent_req **psmbreq)
494 struct tevent_req *req, *subreq;
495 struct cli_session_setup_guest_state *state;
496 uint16_t *vwv;
497 uint8_t *bytes;
499 req = tevent_req_create(mem_ctx, &state,
500 struct cli_session_setup_guest_state);
501 if (req == NULL) {
502 return NULL;
504 state->cli = cli;
505 vwv = state->vwv;
507 SCVAL(vwv+0, 0, 0xFF);
508 SCVAL(vwv+0, 1, 0);
509 SSVAL(vwv+1, 0, 0);
510 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
511 SSVAL(vwv+3, 0, 2);
512 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
513 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
514 SSVAL(vwv+7, 0, 0);
515 SSVAL(vwv+8, 0, 0);
516 SSVAL(vwv+9, 0, 0);
517 SSVAL(vwv+10, 0, 0);
518 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
520 bytes = talloc_array(state, uint8_t, 0);
522 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
523 NULL);
524 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
525 NULL);
526 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
527 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
529 if (bytes == NULL) {
530 TALLOC_FREE(req);
531 return NULL;
534 state->bytes.iov_base = (void *)bytes;
535 state->bytes.iov_len = talloc_get_size(bytes);
537 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
538 vwv, 1, &state->bytes);
539 if (subreq == NULL) {
540 TALLOC_FREE(req);
541 return NULL;
543 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
544 *psmbreq = subreq;
545 return req;
548 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
549 struct tevent_context *ev,
550 struct cli_state *cli)
552 struct tevent_req *req, *subreq;
553 NTSTATUS status;
555 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
556 if (req == NULL) {
557 return NULL;
560 status = smb1cli_req_chain_submit(&subreq, 1);
561 if (!NT_STATUS_IS_OK(status)) {
562 tevent_req_nterror(req, status);
563 return tevent_req_post(req, ev);
565 return req;
568 static void cli_session_setup_guest_done(struct tevent_req *subreq)
570 struct tevent_req *req = tevent_req_callback_data(
571 subreq, struct tevent_req);
572 struct cli_session_setup_guest_state *state = tevent_req_data(
573 req, struct cli_session_setup_guest_state);
574 struct cli_state *cli = state->cli;
575 uint32_t num_bytes;
576 uint8_t *in;
577 uint8_t *inhdr;
578 uint8_t *bytes;
579 uint8_t *p;
580 NTSTATUS status;
581 ssize_t ret;
582 uint8_t wct;
583 uint16_t *vwv;
585 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
586 &num_bytes, &bytes);
587 TALLOC_FREE(subreq);
588 if (!NT_STATUS_IS_OK(status)) {
589 tevent_req_nterror(req, status);
590 return;
593 inhdr = in + NBT_HDR_SIZE;
594 p = bytes;
596 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
597 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
599 status = smb_bytes_talloc_string(cli,
600 inhdr,
601 &cli->server_os,
603 bytes+num_bytes-p,
604 &ret);
606 if (!NT_STATUS_IS_OK(status)) {
607 tevent_req_nterror(req, status);
608 return;
610 p += ret;
612 status = smb_bytes_talloc_string(cli,
613 inhdr,
614 &cli->server_type,
616 bytes+num_bytes-p,
617 &ret);
619 if (!NT_STATUS_IS_OK(status)) {
620 tevent_req_nterror(req, status);
621 return;
623 p += ret;
625 status = smb_bytes_talloc_string(cli,
626 inhdr,
627 &cli->server_domain,
629 bytes+num_bytes-p,
630 &ret);
632 if (!NT_STATUS_IS_OK(status)) {
633 tevent_req_nterror(req, status);
634 return;
637 tevent_req_done(req);
640 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
642 return tevent_req_simple_recv_ntstatus(req);
645 /* The following is calculated from :
646 * (smb_size-4) = 35
647 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
648 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
649 * end of packet.
652 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
654 struct cli_sesssetup_blob_state {
655 struct tevent_context *ev;
656 struct cli_state *cli;
657 DATA_BLOB blob;
658 uint16_t max_blob_size;
660 DATA_BLOB this_blob;
661 struct iovec *recv_iov;
663 NTSTATUS status;
664 const uint8_t *inbuf;
665 DATA_BLOB ret_blob;
667 char *out_native_os;
668 char *out_native_lm;
671 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
672 struct tevent_req **psubreq);
673 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
675 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
676 struct tevent_context *ev,
677 struct cli_state *cli,
678 DATA_BLOB blob)
680 struct tevent_req *req, *subreq;
681 struct cli_sesssetup_blob_state *state;
682 uint32_t usable_space;
684 req = tevent_req_create(mem_ctx, &state,
685 struct cli_sesssetup_blob_state);
686 if (req == NULL) {
687 return NULL;
689 state->ev = ev;
690 state->blob = blob;
691 state->cli = cli;
693 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
694 usable_space = UINT16_MAX;
695 } else {
696 usable_space = cli_state_available_size(cli,
697 BASE_SESSSETUP_BLOB_PACKET_SIZE);
700 if (usable_space == 0) {
701 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
702 "(not possible to send %u bytes)\n",
703 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
704 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
705 return tevent_req_post(req, ev);
707 state->max_blob_size = MIN(usable_space, 0xFFFF);
709 if (!cli_sesssetup_blob_next(state, &subreq)) {
710 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
711 return tevent_req_post(req, ev);
713 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
714 return req;
717 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
718 struct tevent_req **psubreq)
720 struct tevent_req *subreq;
721 uint16_t thistime;
723 thistime = MIN(state->blob.length, state->max_blob_size);
725 state->this_blob.data = state->blob.data;
726 state->this_blob.length = thistime;
728 state->blob.data += thistime;
729 state->blob.length -= thistime;
731 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
732 subreq = smb2cli_session_setup_send(state, state->ev,
733 state->cli->conn,
734 state->cli->timeout,
735 state->cli->smb2.session,
736 0, /* in_flags */
737 SMB2_CAP_DFS, /* in_capabilities */
738 0, /* in_channel */
739 0, /* in_previous_session_id */
740 &state->this_blob);
741 if (subreq == NULL) {
742 return false;
744 } else {
745 uint16_t in_buf_size = 0;
746 uint16_t in_mpx_max = 0;
747 uint16_t in_vc_num = 0;
748 uint32_t in_sess_key = 0;
749 uint32_t in_capabilities = 0;
750 const char *in_native_os = NULL;
751 const char *in_native_lm = NULL;
753 in_buf_size = CLI_BUFFER_SIZE;
754 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
755 in_vc_num = cli_state_get_vc_num(state->cli);
756 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
757 in_capabilities = cli_session_setup_capabilities(state->cli,
758 CAP_EXTENDED_SECURITY);
759 in_native_os = "Unix";
760 in_native_lm = "Samba";
763 * For now we keep the same values as before,
764 * we may remove these in a separate commit later.
766 in_mpx_max = 2;
767 in_vc_num = 1;
768 in_sess_key = 0;
770 subreq = smb1cli_session_setup_ext_send(state, state->ev,
771 state->cli->conn,
772 state->cli->timeout,
773 state->cli->smb1.pid,
774 state->cli->smb1.session,
775 in_buf_size,
776 in_mpx_max,
777 in_vc_num,
778 in_sess_key,
779 state->this_blob,
780 in_capabilities,
781 in_native_os,
782 in_native_lm);
783 if (subreq == NULL) {
784 return false;
787 *psubreq = subreq;
788 return true;
791 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
793 struct tevent_req *req = tevent_req_callback_data(
794 subreq, struct tevent_req);
795 struct cli_sesssetup_blob_state *state = tevent_req_data(
796 req, struct cli_sesssetup_blob_state);
797 NTSTATUS status;
799 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
800 status = smb2cli_session_setup_recv(subreq, state,
801 &state->recv_iov,
802 &state->ret_blob);
803 } else {
804 status = smb1cli_session_setup_ext_recv(subreq, state,
805 &state->recv_iov,
806 &state->inbuf,
807 &state->ret_blob,
808 &state->out_native_os,
809 &state->out_native_lm);
811 TALLOC_FREE(subreq);
812 if (!NT_STATUS_IS_OK(status)
813 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
814 tevent_req_nterror(req, status);
815 return;
818 state->status = status;
820 status = cli_state_update_after_sesssetup(state->cli,
821 state->out_native_os,
822 state->out_native_lm,
823 NULL);
824 if (tevent_req_nterror(req, status)) {
825 return;
828 if (state->blob.length != 0) {
830 * More to send
832 if (!cli_sesssetup_blob_next(state, &subreq)) {
833 tevent_req_oom(req);
834 return;
836 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
837 return;
839 tevent_req_done(req);
842 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
843 TALLOC_CTX *mem_ctx,
844 DATA_BLOB *pblob,
845 const uint8_t **pinbuf,
846 struct iovec **precv_iov)
848 struct cli_sesssetup_blob_state *state = tevent_req_data(
849 req, struct cli_sesssetup_blob_state);
850 NTSTATUS status;
851 struct iovec *recv_iov;
853 if (tevent_req_is_nterror(req, &status)) {
854 TALLOC_FREE(state->cli->smb2.session);
855 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
856 tevent_req_received(req);
857 return status;
860 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
861 if (pblob != NULL) {
862 *pblob = state->ret_blob;
864 if (pinbuf != NULL) {
865 *pinbuf = state->inbuf;
867 if (precv_iov != NULL) {
868 *precv_iov = recv_iov;
870 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
871 status = state->status;
872 tevent_req_received(req);
873 return status;
876 /****************************************************************************
877 Do a spnego/NTLMSSP encrypted session setup.
878 ****************************************************************************/
880 struct cli_session_setup_gensec_state {
881 struct tevent_context *ev;
882 struct cli_state *cli;
883 struct auth_generic_state *auth_generic;
884 bool is_anonymous;
885 DATA_BLOB blob_in;
886 const uint8_t *inbuf;
887 struct iovec *recv_iov;
888 DATA_BLOB blob_out;
889 bool local_ready;
890 bool remote_ready;
891 DATA_BLOB session_key;
894 static int cli_session_setup_gensec_state_destructor(
895 struct cli_session_setup_gensec_state *state)
897 TALLOC_FREE(state->auth_generic);
898 data_blob_clear_free(&state->session_key);
899 return 0;
902 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
903 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
904 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
905 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
906 static void cli_session_setup_gensec_ready(struct tevent_req *req);
908 static struct tevent_req *cli_session_setup_gensec_send(
909 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
910 struct cli_credentials *creds,
911 const char *target_service,
912 const char *target_hostname)
914 struct tevent_req *req;
915 struct cli_session_setup_gensec_state *state;
916 NTSTATUS status;
917 const DATA_BLOB *b = NULL;
919 req = tevent_req_create(mem_ctx, &state,
920 struct cli_session_setup_gensec_state);
921 if (req == NULL) {
922 return NULL;
924 state->ev = ev;
925 state->cli = cli;
927 talloc_set_destructor(
928 state, cli_session_setup_gensec_state_destructor);
930 status = auth_generic_client_prepare(state, &state->auth_generic);
931 if (tevent_req_nterror(req, status)) {
932 return tevent_req_post(req, ev);
935 status = auth_generic_set_creds(state->auth_generic, creds);
936 if (tevent_req_nterror(req, status)) {
937 return tevent_req_post(req, ev);
940 gensec_want_feature(state->auth_generic->gensec_security,
941 GENSEC_FEATURE_SESSION_KEY);
943 if (target_service != NULL) {
944 status = gensec_set_target_service(
945 state->auth_generic->gensec_security,
946 target_service);
947 if (tevent_req_nterror(req, status)) {
948 return tevent_req_post(req, ev);
952 if (target_hostname != NULL) {
953 status = gensec_set_target_hostname(
954 state->auth_generic->gensec_security,
955 target_hostname);
956 if (tevent_req_nterror(req, status)) {
957 return tevent_req_post(req, ev);
961 b = smbXcli_conn_server_gss_blob(cli->conn);
962 if (b != NULL) {
963 state->blob_in = *b;
966 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
968 status = auth_generic_client_start(state->auth_generic,
969 GENSEC_OID_SPNEGO);
970 if (tevent_req_nterror(req, status)) {
971 return tevent_req_post(req, ev);
974 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
975 state->cli->smb2.session = smbXcli_session_create(cli,
976 cli->conn);
977 if (tevent_req_nomem(state->cli->smb2.session, req)) {
978 return tevent_req_post(req, ev);
982 cli_session_setup_gensec_local_next(req);
983 if (!tevent_req_is_in_progress(req)) {
984 return tevent_req_post(req, ev);
987 return req;
990 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
992 struct cli_session_setup_gensec_state *state =
993 tevent_req_data(req,
994 struct cli_session_setup_gensec_state);
995 struct tevent_req *subreq = NULL;
997 if (state->local_ready) {
998 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
999 return;
1002 subreq = gensec_update_send(state, state->ev,
1003 state->auth_generic->gensec_security,
1004 state->blob_in);
1005 if (tevent_req_nomem(subreq, req)) {
1006 return;
1008 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1011 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1013 struct tevent_req *req =
1014 tevent_req_callback_data(subreq,
1015 struct tevent_req);
1016 struct cli_session_setup_gensec_state *state =
1017 tevent_req_data(req,
1018 struct cli_session_setup_gensec_state);
1019 NTSTATUS status;
1021 status = gensec_update_recv(subreq, state, &state->blob_out);
1022 TALLOC_FREE(subreq);
1023 state->blob_in = data_blob_null;
1024 if (!NT_STATUS_IS_OK(status) &&
1025 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1027 tevent_req_nterror(req, status);
1028 return;
1031 if (NT_STATUS_IS_OK(status)) {
1032 state->local_ready = true;
1035 if (state->local_ready && state->remote_ready) {
1036 cli_session_setup_gensec_ready(req);
1037 return;
1040 cli_session_setup_gensec_remote_next(req);
1043 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1045 struct cli_session_setup_gensec_state *state =
1046 tevent_req_data(req,
1047 struct cli_session_setup_gensec_state);
1048 struct tevent_req *subreq = NULL;
1050 if (state->remote_ready) {
1051 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1052 return;
1055 subreq = cli_sesssetup_blob_send(state, state->ev,
1056 state->cli, state->blob_out);
1057 if (tevent_req_nomem(subreq, req)) {
1058 return;
1060 tevent_req_set_callback(subreq,
1061 cli_session_setup_gensec_remote_done,
1062 req);
1065 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1067 struct tevent_req *req =
1068 tevent_req_callback_data(subreq,
1069 struct tevent_req);
1070 struct cli_session_setup_gensec_state *state =
1071 tevent_req_data(req,
1072 struct cli_session_setup_gensec_state);
1073 NTSTATUS status;
1075 state->inbuf = NULL;
1076 TALLOC_FREE(state->recv_iov);
1078 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1079 &state->inbuf, &state->recv_iov);
1080 TALLOC_FREE(subreq);
1081 data_blob_free(&state->blob_out);
1082 if (!NT_STATUS_IS_OK(status) &&
1083 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1085 tevent_req_nterror(req, status);
1086 return;
1089 if (NT_STATUS_IS_OK(status)) {
1090 struct smbXcli_session *session = NULL;
1091 bool is_guest = false;
1093 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1094 session = state->cli->smb2.session;
1095 } else {
1096 session = state->cli->smb1.session;
1099 is_guest = smbXcli_session_is_guest(session);
1100 if (is_guest) {
1102 * We can't finish the gensec handshake, we don't
1103 * have a negotiated session key.
1105 * So just pretend we are completely done,
1106 * we need to continue as anonymous from this point,
1107 * as we can't get a session key.
1109 * Note that smbXcli_session_is_guest()
1110 * always returns false if we require signing.
1112 state->blob_in = data_blob_null;
1113 state->local_ready = true;
1114 state->is_anonymous = true;
1117 state->remote_ready = true;
1120 if (state->local_ready && state->remote_ready) {
1121 cli_session_setup_gensec_ready(req);
1122 return;
1125 cli_session_setup_gensec_local_next(req);
1128 static void cli_session_dump_keys(TALLOC_CTX *mem_ctx,
1129 struct smbXcli_session *session,
1130 DATA_BLOB session_key)
1132 NTSTATUS status;
1133 DATA_BLOB sig = data_blob_null;
1134 DATA_BLOB app = data_blob_null;
1135 DATA_BLOB enc = data_blob_null;
1136 DATA_BLOB dec = data_blob_null;
1137 uint64_t sid = smb2cli_session_current_id(session);
1139 status = smb2cli_session_signing_key(session, mem_ctx, &sig);
1140 if (!NT_STATUS_IS_OK(status)) {
1141 goto out;
1143 status = smbXcli_session_application_key(session, mem_ctx, &app);
1144 if (!NT_STATUS_IS_OK(status)) {
1145 goto out;
1147 status = smb2cli_session_encryption_key(session, mem_ctx, &enc);
1148 if (!NT_STATUS_IS_OK(status)) {
1149 goto out;
1151 status = smb2cli_session_decryption_key(session, mem_ctx, &dec);
1152 if (!NT_STATUS_IS_OK(status)) {
1153 goto out;
1156 DEBUG(0, ("debug encryption: dumping generated session keys\n"));
1157 DEBUGADD(0, ("Session Id "));
1158 dump_data(0, (uint8_t*)&sid, sizeof(sid));
1159 DEBUGADD(0, ("Session Key "));
1160 dump_data(0, session_key.data, session_key.length);
1161 DEBUGADD(0, ("Signing Key "));
1162 dump_data(0, sig.data, sig.length);
1163 DEBUGADD(0, ("App Key "));
1164 dump_data(0, app.data, app.length);
1166 /* In client code, ServerIn is the encryption key */
1168 DEBUGADD(0, ("ServerIn Key "));
1169 dump_data(0, enc.data, enc.length);
1170 DEBUGADD(0, ("ServerOut Key "));
1171 dump_data(0, dec.data, dec.length);
1173 out:
1174 data_blob_clear_free(&sig);
1175 data_blob_clear_free(&app);
1176 data_blob_clear_free(&enc);
1177 data_blob_clear_free(&dec);
1180 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1182 struct cli_session_setup_gensec_state *state =
1183 tevent_req_data(req,
1184 struct cli_session_setup_gensec_state);
1185 const char *server_domain = NULL;
1186 NTSTATUS status;
1188 if (state->blob_in.length != 0) {
1189 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1190 return;
1193 if (state->blob_out.length != 0) {
1194 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1195 return;
1199 * gensec_ntlmssp_server_domain() returns NULL
1200 * if NTLMSSP is not used.
1202 * We can remove this later
1203 * and leave the server domain empty for SMB2 and above
1204 * in future releases.
1206 server_domain = gensec_ntlmssp_server_domain(
1207 state->auth_generic->gensec_security);
1209 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1210 TALLOC_FREE(state->cli->server_domain);
1211 state->cli->server_domain = talloc_strdup(state->cli,
1212 server_domain);
1213 if (state->cli->server_domain == NULL) {
1214 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1215 return;
1219 if (state->is_anonymous) {
1221 * Windows server does not set the
1222 * SMB2_SESSION_FLAG_IS_NULL flag.
1224 * This fix makes sure we do not try
1225 * to verify a signature on the final
1226 * session setup response.
1228 tevent_req_done(req);
1229 return;
1232 status = gensec_session_key(state->auth_generic->gensec_security,
1233 state, &state->session_key);
1234 if (tevent_req_nterror(req, status)) {
1235 return;
1238 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1239 struct smbXcli_session *session = state->cli->smb2.session;
1241 status = smb2cli_session_set_session_key(session,
1242 state->session_key,
1243 state->recv_iov);
1244 if (tevent_req_nterror(req, status)) {
1245 return;
1247 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB3_00
1248 && lp_debug_encryption())
1250 cli_session_dump_keys(state, session, state->session_key);
1252 } else {
1253 struct smbXcli_session *session = state->cli->smb1.session;
1254 bool active;
1256 status = smb1cli_session_set_session_key(session,
1257 state->session_key);
1258 if (tevent_req_nterror(req, status)) {
1259 return;
1262 active = smb1cli_conn_activate_signing(state->cli->conn,
1263 state->session_key,
1264 data_blob_null);
1265 if (active) {
1266 bool ok;
1268 ok = smb1cli_conn_check_signing(state->cli->conn,
1269 state->inbuf, 1);
1270 if (!ok) {
1271 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1272 return;
1277 tevent_req_done(req);
1280 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1282 struct cli_session_setup_gensec_state *state =
1283 tevent_req_data(req,
1284 struct cli_session_setup_gensec_state);
1285 NTSTATUS status;
1287 if (tevent_req_is_nterror(req, &status)) {
1288 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1289 return status;
1291 return NT_STATUS_OK;
1294 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1295 const char *principal)
1297 char *account, *p;
1299 account = talloc_strdup(mem_ctx, principal);
1300 if (account == NULL) {
1301 return NULL;
1303 p = strchr_m(account, '@');
1304 if (p != NULL) {
1305 *p = '\0';
1307 return account;
1310 /****************************************************************************
1311 Do a spnego encrypted session setup.
1313 user_domain: The shortname of the domain the user/machine is a member of.
1314 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1315 ****************************************************************************/
1317 struct cli_session_setup_spnego_state {
1318 ADS_STATUS result;
1321 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1323 static struct tevent_req *cli_session_setup_spnego_send(
1324 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1325 struct cli_credentials *creds)
1327 struct tevent_req *req, *subreq;
1328 struct cli_session_setup_spnego_state *state;
1329 const char *target_service = NULL;
1330 const char *target_hostname = NULL;
1331 NTSTATUS status;
1333 req = tevent_req_create(mem_ctx, &state,
1334 struct cli_session_setup_spnego_state);
1335 if (req == NULL) {
1336 return NULL;
1339 target_service = "cifs";
1340 target_hostname = smbXcli_conn_remote_name(cli->conn);
1342 status = cli_session_creds_prepare_krb5(cli, creds);
1343 if (tevent_req_nterror(req, status)) {
1344 return tevent_req_post(req, ev);
1347 DBG_INFO("Connect to %s as %s using SPNEGO\n",
1348 target_hostname,
1349 cli_credentials_get_principal(creds, talloc_tos()));
1351 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1352 target_service, target_hostname);
1353 if (tevent_req_nomem(subreq, req)) {
1354 return tevent_req_post(req, ev);
1356 tevent_req_set_callback(
1357 subreq, cli_session_setup_spnego_done, req);
1358 return req;
1361 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1363 struct tevent_req *req = tevent_req_callback_data(
1364 subreq, struct tevent_req);
1365 NTSTATUS status;
1367 status = cli_session_setup_gensec_recv(subreq);
1368 TALLOC_FREE(subreq);
1369 if (tevent_req_nterror(req, status)) {
1370 return;
1373 tevent_req_done(req);
1376 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1378 struct cli_session_setup_spnego_state *state = tevent_req_data(
1379 req, struct cli_session_setup_spnego_state);
1380 NTSTATUS status;
1382 if (tevent_req_is_nterror(req, &status)) {
1383 state->result = ADS_ERROR_NT(status);
1386 return state->result;
1389 struct cli_session_setup_creds_state {
1390 struct cli_state *cli;
1391 DATA_BLOB apassword_blob;
1392 DATA_BLOB upassword_blob;
1393 DATA_BLOB lm_session_key;
1394 DATA_BLOB session_key;
1395 char *out_native_os;
1396 char *out_native_lm;
1397 char *out_primary_domain;
1400 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1401 enum tevent_req_state req_state)
1403 struct cli_session_setup_creds_state *state = tevent_req_data(
1404 req, struct cli_session_setup_creds_state);
1406 if (req_state != TEVENT_REQ_RECEIVED) {
1407 return;
1411 * We only call data_blob_clear() as
1412 * some of the blobs point to the same memory.
1414 * We let the talloc hierarchy free the memory.
1416 data_blob_clear(&state->apassword_blob);
1417 data_blob_clear(&state->upassword_blob);
1418 data_blob_clear(&state->lm_session_key);
1419 data_blob_clear(&state->session_key);
1420 ZERO_STRUCTP(state);
1423 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1424 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1425 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1427 /****************************************************************************
1428 Send a session setup. The username and workgroup is in UNIX character
1429 format and must be converted to DOS codepage format before sending. If the
1430 password is in plaintext, the same should be done.
1431 ****************************************************************************/
1433 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1434 struct tevent_context *ev,
1435 struct cli_state *cli,
1436 struct cli_credentials *creds)
1438 struct tevent_req *req, *subreq;
1439 struct cli_session_setup_creds_state *state;
1440 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1441 bool use_spnego = false;
1442 int flags = 0;
1443 const char *username = "";
1444 const char *domain = "";
1445 DATA_BLOB target_info = data_blob_null;
1446 DATA_BLOB challenge = data_blob_null;
1447 uint16_t in_buf_size = 0;
1448 uint16_t in_mpx_max = 0;
1449 uint16_t in_vc_num = 0;
1450 uint32_t in_sess_key = 0;
1451 const char *in_native_os = NULL;
1452 const char *in_native_lm = NULL;
1453 enum credentials_use_kerberos krb5_state =
1454 cli_credentials_get_kerberos_state(creds);
1455 NTSTATUS status;
1457 req = tevent_req_create(mem_ctx, &state,
1458 struct cli_session_setup_creds_state);
1459 if (req == NULL) {
1460 return NULL;
1462 state->cli = cli;
1464 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1467 * Now work out what sort of session setup we are going to
1468 * do. I have split this into separate functions to make the flow a bit
1469 * easier to understand (tridge).
1471 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1472 use_spnego = false;
1473 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1474 use_spnego = true;
1475 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1477 * if the server supports extended security then use SPNEGO
1478 * even for anonymous connections.
1480 use_spnego = true;
1481 } else {
1482 use_spnego = false;
1485 if (use_spnego) {
1486 subreq = cli_session_setup_spnego_send(
1487 state, ev, cli, creds);
1488 if (tevent_req_nomem(subreq, req)) {
1489 return tevent_req_post(req, ev);
1491 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1492 req);
1493 return req;
1496 if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
1497 DBG_WARNING("Kerberos authentication requested, but "
1498 "the server does not support SPNEGO authentication\n");
1499 tevent_req_nterror(req, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT);
1500 return tevent_req_post(req, ev);
1503 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1505 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1506 * this step against older servers.
1508 tevent_req_done(req);
1509 return tevent_req_post(req, ev);
1512 if (cli_credentials_is_anonymous(creds)) {
1514 * Do an anonymous session setup
1516 goto non_spnego_creds_done;
1519 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1521 * Do an anonymous session setup,
1522 * the password is passed via the tree connect.
1524 goto non_spnego_creds_done;
1527 cli_credentials_get_ntlm_username_domain(creds, state,
1528 &username,
1529 &domain);
1530 if (tevent_req_nomem(username, req)) {
1531 return tevent_req_post(req, ev);
1533 if (tevent_req_nomem(domain, req)) {
1534 return tevent_req_post(req, ev);
1537 DBG_INFO("Connect to %s as %s using NTLM\n", domain, username);
1539 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1540 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1541 uint8_t *bytes = NULL;
1542 size_t bytes_len = 0;
1543 const char *pw = cli_credentials_get_password(creds);
1544 size_t pw_len = 0;
1546 if (pw == NULL) {
1547 pw = "";
1549 pw_len = strlen(pw) + 1;
1551 if (!lp_client_plaintext_auth()) {
1552 DEBUG(1, ("Server requested PLAINTEXT password but "
1553 "'client plaintext auth = no'\n"));
1554 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1555 return tevent_req_post(req, ev);
1558 bytes = talloc_array(state, uint8_t, 0);
1559 bytes = trans2_bytes_push_str(bytes, use_unicode,
1560 pw, pw_len, &bytes_len);
1561 if (tevent_req_nomem(bytes, req)) {
1562 return tevent_req_post(req, ev);
1565 if (use_unicode) {
1567 * CAP_UNICODE, can only be negotiated by NT1.
1569 state->upassword_blob = data_blob_const(bytes,
1570 bytes_len);
1571 } else {
1572 state->apassword_blob = data_blob_const(bytes,
1573 bytes_len);
1576 goto non_spnego_creds_done;
1579 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1581 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1582 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1584 * Don't send an NTLMv2 response without NTLMSSP if we
1585 * want to use spnego support.
1587 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1588 " but 'client use spnego = yes'"
1589 " and 'client ntlmv2 auth = yes' is set\n"));
1590 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1591 return tevent_req_post(req, ev);
1594 if (lp_client_ntlmv2_auth()) {
1595 flags |= CLI_CRED_NTLMv2_AUTH;
1598 * note that the 'domain' here is a best
1599 * guess - we don't know the server's domain
1600 * at this point. Windows clients also don't
1601 * use hostname...
1603 target_info = NTLMv2_generate_names_blob(state,
1604 NULL,
1605 domain);
1606 if (tevent_req_nomem(target_info.data, req)) {
1607 return tevent_req_post(req, ev);
1609 } else {
1610 flags |= CLI_CRED_NTLM_AUTH;
1611 if (lp_client_lanman_auth()) {
1612 flags |= CLI_CRED_LANMAN_AUTH;
1615 } else {
1616 if (!lp_client_lanman_auth()) {
1617 DEBUG(1, ("Server requested user level LM password but "
1618 "'client lanman auth = no' is set.\n"));
1619 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1620 return tevent_req_post(req, ev);
1623 flags |= CLI_CRED_LANMAN_AUTH;
1626 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1627 challenge, NULL,
1628 target_info,
1629 &state->apassword_blob,
1630 &state->upassword_blob,
1631 &state->lm_session_key,
1632 &state->session_key);
1633 if (tevent_req_nterror(req, status)) {
1634 return tevent_req_post(req, ev);
1637 non_spnego_creds_done:
1639 in_buf_size = CLI_BUFFER_SIZE;
1640 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1641 in_vc_num = cli_state_get_vc_num(cli);
1642 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1643 in_native_os = "Unix";
1644 in_native_lm = "Samba";
1646 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1647 uint32_t in_capabilities = 0;
1649 in_capabilities = cli_session_setup_capabilities(cli, 0);
1652 * For now we keep the same values as before,
1653 * we may remove these in a separate commit later.
1655 in_mpx_max = 2;
1657 subreq = smb1cli_session_setup_nt1_send(state, ev,
1658 cli->conn,
1659 cli->timeout,
1660 cli->smb1.pid,
1661 cli->smb1.session,
1662 in_buf_size,
1663 in_mpx_max,
1664 in_vc_num,
1665 in_sess_key,
1666 username,
1667 domain,
1668 state->apassword_blob,
1669 state->upassword_blob,
1670 in_capabilities,
1671 in_native_os,
1672 in_native_lm);
1673 if (tevent_req_nomem(subreq, req)) {
1674 return tevent_req_post(req, ev);
1676 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1677 req);
1678 return req;
1682 * For now we keep the same values as before,
1683 * we may remove these in a separate commit later.
1685 in_mpx_max = 2;
1686 in_vc_num = 1;
1688 subreq = smb1cli_session_setup_lm21_send(state, ev,
1689 cli->conn,
1690 cli->timeout,
1691 cli->smb1.pid,
1692 cli->smb1.session,
1693 in_buf_size,
1694 in_mpx_max,
1695 in_vc_num,
1696 in_sess_key,
1697 username,
1698 domain,
1699 state->apassword_blob,
1700 in_native_os,
1701 in_native_lm);
1702 if (tevent_req_nomem(subreq, req)) {
1703 return tevent_req_post(req, ev);
1705 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1706 req);
1707 return req;
1710 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1712 struct tevent_req *req = tevent_req_callback_data(
1713 subreq, struct tevent_req);
1714 ADS_STATUS status;
1716 status = cli_session_setup_spnego_recv(subreq);
1717 TALLOC_FREE(subreq);
1718 if (!ADS_ERR_OK(status)) {
1719 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1720 tevent_req_nterror(req, ads_ntstatus(status));
1721 return;
1723 tevent_req_done(req);
1726 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1728 struct tevent_req *req = tevent_req_callback_data(
1729 subreq, struct tevent_req);
1730 struct cli_session_setup_creds_state *state = tevent_req_data(
1731 req, struct cli_session_setup_creds_state);
1732 struct cli_state *cli = state->cli;
1733 NTSTATUS status;
1734 struct iovec *recv_iov = NULL;
1735 const uint8_t *inbuf = NULL;
1736 bool ok;
1738 status = smb1cli_session_setup_nt1_recv(subreq, state,
1739 &recv_iov,
1740 &inbuf,
1741 &state->out_native_os,
1742 &state->out_native_lm,
1743 &state->out_primary_domain);
1744 TALLOC_FREE(subreq);
1745 if (!NT_STATUS_IS_OK(status)) {
1746 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1747 tevent_req_nterror(req, status);
1748 return;
1751 status = cli_state_update_after_sesssetup(state->cli,
1752 state->out_native_os,
1753 state->out_native_lm,
1754 state->out_primary_domain);
1755 if (tevent_req_nterror(req, status)) {
1756 return;
1759 ok = smb1cli_conn_activate_signing(cli->conn,
1760 state->session_key,
1761 state->upassword_blob);
1762 if (ok) {
1763 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1764 if (!ok) {
1765 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1766 return;
1770 if (state->session_key.data) {
1771 struct smbXcli_session *session = cli->smb1.session;
1773 status = smb1cli_session_set_session_key(session,
1774 state->session_key);
1775 if (tevent_req_nterror(req, status)) {
1776 return;
1780 tevent_req_done(req);
1783 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1785 struct tevent_req *req = tevent_req_callback_data(
1786 subreq, struct tevent_req);
1787 struct cli_session_setup_creds_state *state = tevent_req_data(
1788 req, struct cli_session_setup_creds_state);
1789 NTSTATUS status;
1791 status = smb1cli_session_setup_lm21_recv(subreq, state,
1792 &state->out_native_os,
1793 &state->out_native_lm);
1794 TALLOC_FREE(subreq);
1795 if (!NT_STATUS_IS_OK(status)) {
1796 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1797 tevent_req_nterror(req, status);
1798 return;
1801 status = cli_state_update_after_sesssetup(state->cli,
1802 state->out_native_os,
1803 state->out_native_lm,
1804 NULL);
1805 if (tevent_req_nterror(req, status)) {
1806 return;
1809 tevent_req_done(req);
1812 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1814 return tevent_req_simple_recv_ntstatus(req);
1817 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1818 struct cli_credentials *creds)
1820 struct tevent_context *ev;
1821 struct tevent_req *req;
1822 NTSTATUS status = NT_STATUS_NO_MEMORY;
1824 if (smbXcli_conn_has_async_calls(cli->conn)) {
1825 return NT_STATUS_INVALID_PARAMETER;
1827 ev = samba_tevent_context_init(talloc_tos());
1828 if (ev == NULL) {
1829 goto fail;
1831 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1832 if (req == NULL) {
1833 goto fail;
1835 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1836 goto fail;
1838 status = cli_session_setup_creds_recv(req);
1839 fail:
1840 TALLOC_FREE(ev);
1841 return status;
1844 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1846 NTSTATUS status;
1847 struct cli_credentials *creds = NULL;
1849 creds = cli_credentials_init_anon(cli);
1850 if (creds == NULL) {
1851 return NT_STATUS_NO_MEMORY;
1854 status = cli_session_setup_creds(cli, creds);
1855 TALLOC_FREE(creds);
1856 if (!NT_STATUS_IS_OK(status)) {
1857 return status;
1860 return NT_STATUS_OK;
1863 /****************************************************************************
1864 Send a uloggoff.
1865 *****************************************************************************/
1867 struct cli_ulogoff_state {
1868 struct cli_state *cli;
1869 uint16_t vwv[3];
1872 static void cli_ulogoff_done(struct tevent_req *subreq);
1874 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1875 struct tevent_context *ev,
1876 struct cli_state *cli)
1878 struct tevent_req *req, *subreq;
1879 struct cli_ulogoff_state *state;
1881 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1882 if (req == NULL) {
1883 return NULL;
1885 state->cli = cli;
1887 SCVAL(state->vwv+0, 0, 0xFF);
1888 SCVAL(state->vwv+1, 0, 0);
1889 SSVAL(state->vwv+2, 0, 0);
1891 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1892 0, NULL);
1893 if (tevent_req_nomem(subreq, req)) {
1894 return tevent_req_post(req, ev);
1896 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1897 return req;
1900 static void cli_ulogoff_done(struct tevent_req *subreq)
1902 struct tevent_req *req = tevent_req_callback_data(
1903 subreq, struct tevent_req);
1904 struct cli_ulogoff_state *state = tevent_req_data(
1905 req, struct cli_ulogoff_state);
1906 NTSTATUS status;
1908 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1909 if (!NT_STATUS_IS_OK(status)) {
1910 tevent_req_nterror(req, status);
1911 return;
1913 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1914 tevent_req_done(req);
1917 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1919 return tevent_req_simple_recv_ntstatus(req);
1922 NTSTATUS cli_ulogoff(struct cli_state *cli)
1924 struct tevent_context *ev;
1925 struct tevent_req *req;
1926 NTSTATUS status = NT_STATUS_NO_MEMORY;
1928 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1929 status = smb2cli_logoff(cli->conn,
1930 cli->timeout,
1931 cli->smb2.session);
1932 if (!NT_STATUS_IS_OK(status)) {
1933 return status;
1935 smb2cli_session_set_id_and_flags(cli->smb2.session,
1936 UINT64_MAX, 0);
1937 return NT_STATUS_OK;
1940 if (smbXcli_conn_has_async_calls(cli->conn)) {
1941 return NT_STATUS_INVALID_PARAMETER;
1943 ev = samba_tevent_context_init(talloc_tos());
1944 if (ev == NULL) {
1945 goto fail;
1947 req = cli_ulogoff_send(ev, ev, cli);
1948 if (req == NULL) {
1949 goto fail;
1951 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1952 goto fail;
1954 status = cli_ulogoff_recv(req);
1955 fail:
1956 TALLOC_FREE(ev);
1957 return status;
1960 /****************************************************************************
1961 Send a tconX.
1962 ****************************************************************************/
1964 struct cli_tcon_andx_state {
1965 struct cli_state *cli;
1966 uint16_t vwv[4];
1967 struct iovec bytes;
1970 static void cli_tcon_andx_done(struct tevent_req *subreq);
1972 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1973 struct tevent_context *ev,
1974 struct cli_state *cli,
1975 const char *share, const char *dev,
1976 const char *pass, int passlen,
1977 struct tevent_req **psmbreq)
1979 struct tevent_req *req, *subreq;
1980 struct cli_tcon_andx_state *state;
1981 uint8_t p24[24];
1982 uint16_t *vwv;
1983 char *tmp = NULL;
1984 uint8_t *bytes;
1985 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1986 uint16_t tcon_flags = 0;
1988 *psmbreq = NULL;
1990 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1991 if (req == NULL) {
1992 return NULL;
1994 state->cli = cli;
1995 vwv = state->vwv;
1997 TALLOC_FREE(cli->smb1.tcon);
1998 cli->smb1.tcon = smbXcli_tcon_create(cli);
1999 if (tevent_req_nomem(cli->smb1.tcon, req)) {
2000 return tevent_req_post(req, ev);
2002 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
2004 cli->share = talloc_strdup(cli, share);
2005 if (!cli->share) {
2006 return NULL;
2009 /* in user level security don't send a password now */
2010 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2011 passlen = 1;
2012 pass = "";
2013 } else if (pass == NULL) {
2014 DEBUG(1, ("Server not using user level security and no "
2015 "password supplied.\n"));
2016 goto access_denied;
2019 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2020 *pass && passlen != 24) {
2021 if (!lp_client_lanman_auth()) {
2022 DEBUG(1, ("Server requested LANMAN password "
2023 "(share-level security) but "
2024 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2025 goto access_denied;
2029 * Non-encrypted passwords - convert to DOS codepage before
2030 * encryption.
2032 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2033 passlen = 24;
2034 pass = (const char *)p24;
2035 } else {
2036 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2037 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2038 == 0) {
2039 uint8_t *tmp_pass;
2041 if (!lp_client_plaintext_auth() && (*pass)) {
2042 DEBUG(1, ("Server requested PLAINTEXT "
2043 "password but "
2044 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2045 goto access_denied;
2049 * Non-encrypted passwords - convert to DOS codepage
2050 * before using.
2052 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2053 if (tevent_req_nomem(tmp_pass, req)) {
2054 return tevent_req_post(req, ev);
2056 tmp_pass = trans2_bytes_push_str(tmp_pass,
2057 false, /* always DOS */
2058 pass,
2059 passlen,
2060 NULL);
2061 if (tevent_req_nomem(tmp_pass, req)) {
2062 return tevent_req_post(req, ev);
2064 pass = (const char *)tmp_pass;
2065 passlen = talloc_get_size(tmp_pass);
2069 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2070 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2072 SCVAL(vwv+0, 0, 0xFF);
2073 SCVAL(vwv+0, 1, 0);
2074 SSVAL(vwv+1, 0, 0);
2075 SSVAL(vwv+2, 0, tcon_flags);
2076 SSVAL(vwv+3, 0, passlen);
2078 if (passlen && pass) {
2079 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2080 } else {
2081 bytes = talloc_array(state, uint8_t, 0);
2085 * Add the sharename
2087 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2088 smbXcli_conn_remote_name(cli->conn), share);
2089 if (tmp == NULL) {
2090 TALLOC_FREE(req);
2091 return NULL;
2093 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2094 NULL);
2095 TALLOC_FREE(tmp);
2098 * Add the devicetype
2100 tmp = talloc_strdup_upper(talloc_tos(), dev);
2101 if (tmp == NULL) {
2102 TALLOC_FREE(req);
2103 return NULL;
2105 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2106 TALLOC_FREE(tmp);
2108 if (bytes == NULL) {
2109 TALLOC_FREE(req);
2110 return NULL;
2113 state->bytes.iov_base = (void *)bytes;
2114 state->bytes.iov_len = talloc_get_size(bytes);
2116 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2117 1, &state->bytes);
2118 if (subreq == NULL) {
2119 TALLOC_FREE(req);
2120 return NULL;
2122 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2123 *psmbreq = subreq;
2124 return req;
2126 access_denied:
2127 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2128 return tevent_req_post(req, ev);
2131 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2132 struct tevent_context *ev,
2133 struct cli_state *cli,
2134 const char *share, const char *dev,
2135 const char *pass, int passlen)
2137 struct tevent_req *req, *subreq;
2138 NTSTATUS status;
2140 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2141 &subreq);
2142 if (req == NULL) {
2143 return NULL;
2145 if (subreq == NULL) {
2146 return req;
2148 status = smb1cli_req_chain_submit(&subreq, 1);
2149 if (!NT_STATUS_IS_OK(status)) {
2150 tevent_req_nterror(req, status);
2151 return tevent_req_post(req, ev);
2153 return req;
2156 static void cli_tcon_andx_done(struct tevent_req *subreq)
2158 struct tevent_req *req = tevent_req_callback_data(
2159 subreq, struct tevent_req);
2160 struct cli_tcon_andx_state *state = tevent_req_data(
2161 req, struct cli_tcon_andx_state);
2162 struct cli_state *cli = state->cli;
2163 uint8_t *in;
2164 uint8_t *inhdr;
2165 uint8_t wct;
2166 uint16_t *vwv;
2167 uint32_t num_bytes;
2168 uint8_t *bytes;
2169 NTSTATUS status;
2170 uint16_t optional_support = 0;
2172 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2173 &num_bytes, &bytes);
2174 TALLOC_FREE(subreq);
2175 if (!NT_STATUS_IS_OK(status)) {
2176 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 const char *pw = NULL;
2434 if (creds != NULL) {
2435 pw = cli_credentials_get_password(creds);
2438 return cli_tree_connect(cli, share, dev, pw);
2441 /****************************************************************************
2442 Send a tree disconnect.
2443 ****************************************************************************/
2445 struct cli_tdis_state {
2446 struct cli_state *cli;
2449 static void cli_tdis_done(struct tevent_req *subreq);
2451 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2452 struct tevent_context *ev,
2453 struct cli_state *cli)
2455 struct tevent_req *req, *subreq;
2456 struct cli_tdis_state *state;
2458 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2459 if (req == NULL) {
2460 return NULL;
2462 state->cli = cli;
2464 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2465 if (tevent_req_nomem(subreq, req)) {
2466 return tevent_req_post(req, ev);
2468 tevent_req_set_callback(subreq, cli_tdis_done, req);
2469 return req;
2472 static void cli_tdis_done(struct tevent_req *subreq)
2474 struct tevent_req *req = tevent_req_callback_data(
2475 subreq, struct tevent_req);
2476 struct cli_tdis_state *state = tevent_req_data(
2477 req, struct cli_tdis_state);
2478 NTSTATUS status;
2480 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2481 TALLOC_FREE(subreq);
2482 if (!NT_STATUS_IS_OK(status)) {
2483 tevent_req_nterror(req, status);
2484 return;
2486 TALLOC_FREE(state->cli->smb1.tcon);
2487 tevent_req_done(req);
2490 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2492 return tevent_req_simple_recv_ntstatus(req);
2495 NTSTATUS cli_tdis(struct cli_state *cli)
2497 struct tevent_context *ev;
2498 struct tevent_req *req;
2499 NTSTATUS status = NT_STATUS_NO_MEMORY;
2501 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2502 status = smb2cli_tdis(cli->conn,
2503 cli->timeout,
2504 cli->smb2.session,
2505 cli->smb2.tcon);
2506 if (NT_STATUS_IS_OK(status)) {
2507 TALLOC_FREE(cli->smb2.tcon);
2509 return status;
2512 if (smbXcli_conn_has_async_calls(cli->conn)) {
2513 return NT_STATUS_INVALID_PARAMETER;
2515 ev = samba_tevent_context_init(talloc_tos());
2516 if (ev == NULL) {
2517 goto fail;
2519 req = cli_tdis_send(ev, ev, cli);
2520 if (req == NULL) {
2521 goto fail;
2523 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2524 goto fail;
2526 status = cli_tdis_recv(req);
2527 fail:
2528 TALLOC_FREE(ev);
2529 return status;
2532 struct cli_connect_sock_state {
2533 const char **called_names;
2534 const char **calling_names;
2535 int *called_types;
2536 int fd;
2537 uint16_t port;
2540 static void cli_connect_sock_done(struct tevent_req *subreq);
2543 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2544 * nonzero address.
2547 static struct tevent_req *cli_connect_sock_send(
2548 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2549 const char *host, int name_type, const struct sockaddr_storage *pss,
2550 const char *myname, uint16_t port)
2552 struct tevent_req *req, *subreq;
2553 struct cli_connect_sock_state *state;
2554 struct sockaddr_storage *addrs = NULL;
2555 unsigned i;
2556 unsigned num_addrs = 0;
2557 NTSTATUS status;
2559 req = tevent_req_create(mem_ctx, &state,
2560 struct cli_connect_sock_state);
2561 if (req == NULL) {
2562 return NULL;
2565 if ((pss == NULL) || is_zero_addr(pss)) {
2568 * Here we cheat. resolve_name_list is not async at all. So
2569 * this call will only be really async if the name lookup has
2570 * been done externally.
2573 status = resolve_name_list(state, host, name_type,
2574 &addrs, &num_addrs);
2575 if (!NT_STATUS_IS_OK(status)) {
2576 tevent_req_nterror(req, status);
2577 return tevent_req_post(req, ev);
2579 } else {
2580 addrs = talloc_array(state, struct sockaddr_storage, 1);
2581 if (tevent_req_nomem(addrs, req)) {
2582 return tevent_req_post(req, ev);
2584 addrs[0] = *pss;
2585 num_addrs = 1;
2588 state->called_names = talloc_array(state, const char *, num_addrs);
2589 if (tevent_req_nomem(state->called_names, req)) {
2590 return tevent_req_post(req, ev);
2592 state->called_types = talloc_array(state, int, num_addrs);
2593 if (tevent_req_nomem(state->called_types, req)) {
2594 return tevent_req_post(req, ev);
2596 state->calling_names = talloc_array(state, const char *, num_addrs);
2597 if (tevent_req_nomem(state->calling_names, req)) {
2598 return tevent_req_post(req, ev);
2600 for (i=0; i<num_addrs; i++) {
2601 state->called_names[i] = host;
2602 state->called_types[i] = name_type;
2603 state->calling_names[i] = myname;
2606 subreq = smbsock_any_connect_send(
2607 state, ev, addrs, state->called_names, state->called_types,
2608 state->calling_names, NULL, num_addrs, port);
2609 if (tevent_req_nomem(subreq, req)) {
2610 return tevent_req_post(req, ev);
2612 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2613 return req;
2616 static void cli_connect_sock_done(struct tevent_req *subreq)
2618 struct tevent_req *req = tevent_req_callback_data(
2619 subreq, struct tevent_req);
2620 struct cli_connect_sock_state *state = tevent_req_data(
2621 req, struct cli_connect_sock_state);
2622 NTSTATUS status;
2624 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2625 &state->port);
2626 TALLOC_FREE(subreq);
2627 if (tevent_req_nterror(req, status)) {
2628 return;
2630 set_socket_options(state->fd, lp_socket_options());
2631 tevent_req_done(req);
2634 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2635 int *pfd, uint16_t *pport)
2637 struct cli_connect_sock_state *state = tevent_req_data(
2638 req, struct cli_connect_sock_state);
2639 NTSTATUS status;
2641 if (tevent_req_is_nterror(req, &status)) {
2642 return status;
2644 *pfd = state->fd;
2645 *pport = state->port;
2646 return NT_STATUS_OK;
2649 struct cli_connect_nb_state {
2650 const char *desthost;
2651 enum smb_signing_setting signing_state;
2652 int flags;
2653 struct cli_state *cli;
2656 static void cli_connect_nb_done(struct tevent_req *subreq);
2658 static struct tevent_req *cli_connect_nb_send(
2659 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2660 const char *host, const struct sockaddr_storage *dest_ss,
2661 uint16_t port, int name_type, const char *myname,
2662 enum smb_signing_setting signing_state, int flags)
2664 struct tevent_req *req, *subreq;
2665 struct cli_connect_nb_state *state;
2667 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2668 if (req == NULL) {
2669 return NULL;
2671 state->signing_state = signing_state;
2672 state->flags = flags;
2674 if (host != NULL) {
2675 char *p = strchr(host, '#');
2677 if (p != NULL) {
2678 name_type = strtol(p+1, NULL, 16);
2679 host = talloc_strndup(state, host, p - host);
2680 if (tevent_req_nomem(host, req)) {
2681 return tevent_req_post(req, ev);
2685 state->desthost = host;
2686 } else if (dest_ss != NULL) {
2687 state->desthost = print_canonical_sockaddr(state, dest_ss);
2688 if (tevent_req_nomem(state->desthost, req)) {
2689 return tevent_req_post(req, ev);
2691 } else {
2692 /* No host or dest_ss given. Error out. */
2693 tevent_req_error(req, EINVAL);
2694 return tevent_req_post(req, ev);
2697 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2698 myname, port);
2699 if (tevent_req_nomem(subreq, req)) {
2700 return tevent_req_post(req, ev);
2702 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2703 return req;
2706 static void cli_connect_nb_done(struct tevent_req *subreq)
2708 struct tevent_req *req = tevent_req_callback_data(
2709 subreq, struct tevent_req);
2710 struct cli_connect_nb_state *state = tevent_req_data(
2711 req, struct cli_connect_nb_state);
2712 NTSTATUS status;
2713 int fd = 0;
2714 uint16_t port;
2716 status = cli_connect_sock_recv(subreq, &fd, &port);
2717 TALLOC_FREE(subreq);
2718 if (tevent_req_nterror(req, status)) {
2719 return;
2722 state->cli = cli_state_create(state, fd, state->desthost,
2723 state->signing_state, state->flags);
2724 if (tevent_req_nomem(state->cli, req)) {
2725 close(fd);
2726 return;
2728 tevent_req_done(req);
2731 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2732 struct cli_state **pcli)
2734 struct cli_connect_nb_state *state = tevent_req_data(
2735 req, struct cli_connect_nb_state);
2736 NTSTATUS status;
2738 if (tevent_req_is_nterror(req, &status)) {
2739 return status;
2741 *pcli = talloc_move(NULL, &state->cli);
2742 return NT_STATUS_OK;
2745 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2746 uint16_t port, int name_type, const char *myname,
2747 enum smb_signing_setting signing_state, int flags, struct cli_state **pcli)
2749 struct tevent_context *ev;
2750 struct tevent_req *req;
2751 NTSTATUS status = NT_STATUS_NO_MEMORY;
2753 ev = samba_tevent_context_init(talloc_tos());
2754 if (ev == NULL) {
2755 goto fail;
2757 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2758 myname, signing_state, flags);
2759 if (req == NULL) {
2760 goto fail;
2762 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2763 goto fail;
2765 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2766 goto fail;
2768 status = cli_connect_nb_recv(req, pcli);
2769 fail:
2770 TALLOC_FREE(ev);
2771 return status;
2774 struct cli_start_connection_state {
2775 struct tevent_context *ev;
2776 struct cli_state *cli;
2777 int min_protocol;
2778 int max_protocol;
2779 struct smb2_negotiate_contexts *negotiate_contexts;
2782 static void cli_start_connection_connected(struct tevent_req *subreq);
2783 static void cli_start_connection_done(struct tevent_req *subreq);
2786 establishes a connection to after the negprot.
2787 @param output_cli A fully initialised cli structure, non-null only on success
2788 @param dest_host The netbios name of the remote host
2789 @param dest_ss (optional) The destination IP, NULL for name based lookup
2790 @param port (optional) The destination port (0 for default)
2793 static struct tevent_req *cli_start_connection_send(
2794 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2795 const char *my_name, const char *dest_host,
2796 const struct sockaddr_storage *dest_ss, int port,
2797 enum smb_signing_setting signing_state, int flags,
2798 struct smb2_negotiate_contexts *negotiate_contexts)
2800 struct tevent_req *req, *subreq;
2801 struct cli_start_connection_state *state;
2803 req = tevent_req_create(mem_ctx, &state,
2804 struct cli_start_connection_state);
2805 if (req == NULL) {
2806 return NULL;
2808 state->ev = ev;
2810 if (flags & CLI_FULL_CONNECTION_IPC) {
2811 state->min_protocol = lp_client_ipc_min_protocol();
2812 state->max_protocol = lp_client_ipc_max_protocol();
2813 } else {
2814 state->min_protocol = lp_client_min_protocol();
2815 state->max_protocol = lp_client_max_protocol();
2818 if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
2819 state->max_protocol = MIN(state->max_protocol,
2820 PROTOCOL_NT1);
2821 state->min_protocol = MIN(state->min_protocol,
2822 state->max_protocol);
2825 if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
2826 state->min_protocol = MAX(state->min_protocol,
2827 PROTOCOL_SMB2_02);
2828 state->max_protocol = MAX(state->max_protocol,
2829 state->min_protocol);
2832 state->negotiate_contexts = talloc_zero(
2833 state, struct smb2_negotiate_contexts);
2834 if (tevent_req_nomem(state->negotiate_contexts, req)) {
2835 return tevent_req_post(req, ev);
2838 if (flags & CLI_FULL_CONNECTION_REQUEST_POSIX) {
2839 NTSTATUS status;
2841 status = smb2_negotiate_context_add(
2842 state->negotiate_contexts,
2843 state->negotiate_contexts,
2844 SMB2_POSIX_EXTENSIONS_AVAILABLE,
2845 (const uint8_t *)SMB2_CREATE_TAG_POSIX,
2846 strlen(SMB2_CREATE_TAG_POSIX));
2847 if (tevent_req_nterror(req, status)) {
2848 return tevent_req_post(req, ev);
2852 if (negotiate_contexts != NULL) {
2853 uint16_t i;
2855 for (i=0; i<negotiate_contexts->num_contexts; i++) {
2856 struct smb2_negotiate_context *ctx =
2857 &negotiate_contexts->contexts[i];
2858 NTSTATUS status;
2860 status = smb2_negotiate_context_add(
2861 state->negotiate_contexts,
2862 state->negotiate_contexts,
2863 ctx->type,
2864 ctx->data.data,
2865 ctx->data.length);
2866 if (tevent_req_nterror(req, status)) {
2867 return tevent_req_post(req, ev);
2872 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2873 0x20, my_name, signing_state, flags);
2874 if (tevent_req_nomem(subreq, req)) {
2875 return tevent_req_post(req, ev);
2877 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2878 return req;
2881 static void cli_start_connection_connected(struct tevent_req *subreq)
2883 struct tevent_req *req = tevent_req_callback_data(
2884 subreq, struct tevent_req);
2885 struct cli_start_connection_state *state = tevent_req_data(
2886 req, struct cli_start_connection_state);
2887 NTSTATUS status;
2889 status = cli_connect_nb_recv(subreq, &state->cli);
2890 TALLOC_FREE(subreq);
2891 if (tevent_req_nterror(req, status)) {
2892 return;
2895 subreq = smbXcli_negprot_send(
2896 state,
2897 state->ev,
2898 state->cli->conn,
2899 state->cli->timeout,
2900 state->min_protocol,
2901 state->max_protocol,
2902 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK,
2903 state->negotiate_contexts);
2904 if (tevent_req_nomem(subreq, req)) {
2905 return;
2907 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2910 static void cli_start_connection_done(struct tevent_req *subreq)
2912 struct tevent_req *req = tevent_req_callback_data(
2913 subreq, struct tevent_req);
2914 struct cli_start_connection_state *state = tevent_req_data(
2915 req, struct cli_start_connection_state);
2916 NTSTATUS status;
2918 status = smbXcli_negprot_recv(subreq, NULL, NULL);
2919 TALLOC_FREE(subreq);
2920 if (tevent_req_nterror(req, status)) {
2921 return;
2924 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2925 /* Ensure we ask for some initial credits. */
2926 smb2cli_conn_set_max_credits(state->cli->conn,
2927 DEFAULT_SMB2_MAX_CREDITS);
2930 tevent_req_done(req);
2933 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2934 struct cli_state **output_cli)
2936 struct cli_start_connection_state *state = tevent_req_data(
2937 req, struct cli_start_connection_state);
2938 NTSTATUS status;
2940 if (tevent_req_is_nterror(req, &status)) {
2941 return status;
2943 *output_cli = state->cli;
2945 return NT_STATUS_OK;
2948 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2949 const char *my_name,
2950 const char *dest_host,
2951 const struct sockaddr_storage *dest_ss, int port,
2952 enum smb_signing_setting signing_state, int flags)
2954 struct tevent_context *ev;
2955 struct tevent_req *req;
2956 NTSTATUS status = NT_STATUS_NO_MEMORY;
2958 ev = samba_tevent_context_init(talloc_tos());
2959 if (ev == NULL) {
2960 goto fail;
2962 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2963 port, signing_state, flags, NULL);
2964 if (req == NULL) {
2965 goto fail;
2967 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2968 goto fail;
2970 status = cli_start_connection_recv(req, output_cli);
2971 fail:
2972 TALLOC_FREE(ev);
2973 return status;
2976 struct cli_smb1_setup_encryption_blob_state {
2977 uint16_t setup[1];
2978 uint8_t param[4];
2979 NTSTATUS status;
2980 DATA_BLOB out;
2981 uint16_t enc_ctx_id;
2984 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2986 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2987 struct tevent_context *ev,
2988 struct cli_state *cli,
2989 const DATA_BLOB in)
2991 struct tevent_req *req = NULL;
2992 struct cli_smb1_setup_encryption_blob_state *state = NULL;
2993 struct tevent_req *subreq = NULL;
2995 req = tevent_req_create(mem_ctx, &state,
2996 struct cli_smb1_setup_encryption_blob_state);
2997 if (req == NULL) {
2998 return NULL;
3001 if (in.length > CLI_BUFFER_SIZE) {
3002 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3003 return tevent_req_post(req, ev);
3006 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
3007 SSVAL(state->param, 0, 0);
3008 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
3010 subreq = smb1cli_trans_send(state, ev, cli->conn,
3011 SMBtrans2,
3012 0, 0, /* _flags */
3013 0, 0, /* _flags2 */
3014 cli->timeout,
3015 cli->smb1.pid,
3016 cli->smb1.tcon,
3017 cli->smb1.session,
3018 NULL, /* pipe_name */
3019 0, /* fid */
3020 0, /* function */
3021 0, /* flags */
3022 state->setup, 1, 0,
3023 state->param, 4, 2,
3024 in.data, in.length, CLI_BUFFER_SIZE);
3025 if (tevent_req_nomem(subreq, req)) {
3026 return tevent_req_post(req, ev);
3028 tevent_req_set_callback(subreq,
3029 cli_smb1_setup_encryption_blob_done,
3030 req);
3032 return req;
3035 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
3037 struct tevent_req *req =
3038 tevent_req_callback_data(subreq,
3039 struct tevent_req);
3040 struct cli_smb1_setup_encryption_blob_state *state =
3041 tevent_req_data(req,
3042 struct cli_smb1_setup_encryption_blob_state);
3043 uint8_t *rparam=NULL, *rdata=NULL;
3044 uint32_t num_rparam, num_rdata;
3045 NTSTATUS status;
3047 status = smb1cli_trans_recv(subreq, state,
3048 NULL, /* recv_flags */
3049 NULL, 0, NULL, /* rsetup */
3050 &rparam, 0, &num_rparam,
3051 &rdata, 0, &num_rdata);
3052 TALLOC_FREE(subreq);
3053 state->status = status;
3054 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
3055 status = NT_STATUS_OK;
3057 if (tevent_req_nterror(req, status)) {
3058 return;
3061 if (num_rparam == 2) {
3062 state->enc_ctx_id = SVAL(rparam, 0);
3064 TALLOC_FREE(rparam);
3066 state->out = data_blob_const(rdata, num_rdata);
3068 tevent_req_done(req);
3071 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
3072 TALLOC_CTX *mem_ctx,
3073 DATA_BLOB *out,
3074 uint16_t *enc_ctx_id)
3076 struct cli_smb1_setup_encryption_blob_state *state =
3077 tevent_req_data(req,
3078 struct cli_smb1_setup_encryption_blob_state);
3079 NTSTATUS status;
3081 if (tevent_req_is_nterror(req, &status)) {
3082 tevent_req_received(req);
3083 return status;
3086 status = state->status;
3088 *out = state->out;
3089 talloc_steal(mem_ctx, out->data);
3091 *enc_ctx_id = state->enc_ctx_id;
3093 tevent_req_received(req);
3094 return status;
3097 struct cli_smb1_setup_encryption_state {
3098 struct tevent_context *ev;
3099 struct cli_state *cli;
3100 struct smb_trans_enc_state *es;
3101 DATA_BLOB blob_in;
3102 DATA_BLOB blob_out;
3103 bool local_ready;
3104 bool remote_ready;
3107 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
3108 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
3109 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
3110 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
3111 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
3113 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
3114 struct tevent_context *ev,
3115 struct cli_state *cli,
3116 struct cli_credentials *creds)
3118 struct tevent_req *req = NULL;
3119 struct cli_smb1_setup_encryption_state *state = NULL;
3120 struct auth_generic_state *ags = NULL;
3121 const DATA_BLOB *b = NULL;
3122 bool auth_requested = false;
3123 const char *target_service = NULL;
3124 const char *target_hostname = NULL;
3125 NTSTATUS status;
3127 req = tevent_req_create(mem_ctx, &state,
3128 struct cli_smb1_setup_encryption_state);
3129 if (req == NULL) {
3130 return NULL;
3132 state->ev = ev;
3133 state->cli = cli;
3135 auth_requested = cli_credentials_authentication_requested(creds);
3136 if (!auth_requested) {
3137 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3138 return tevent_req_post(req, ev);
3141 target_service = "cifs";
3142 target_hostname = smbXcli_conn_remote_name(cli->conn);
3144 status = cli_session_creds_prepare_krb5(cli, creds);
3145 if (tevent_req_nterror(req, status)) {
3146 return tevent_req_post(req, ev);
3149 state->es = talloc_zero(state, struct smb_trans_enc_state);
3150 if (tevent_req_nomem(state->es, req)) {
3151 return tevent_req_post(req, ev);
3154 status = auth_generic_client_prepare(state->es, &ags);
3155 if (tevent_req_nterror(req, status)) {
3156 return tevent_req_post(req, ev);
3159 gensec_want_feature(ags->gensec_security,
3160 GENSEC_FEATURE_SIGN);
3161 gensec_want_feature(ags->gensec_security,
3162 GENSEC_FEATURE_SEAL);
3164 status = auth_generic_set_creds(ags, creds);
3165 if (tevent_req_nterror(req, status)) {
3166 return tevent_req_post(req, ev);
3169 if (target_service != NULL) {
3170 status = gensec_set_target_service(ags->gensec_security,
3171 target_service);
3172 if (tevent_req_nterror(req, status)) {
3173 return tevent_req_post(req, ev);
3177 if (target_hostname != NULL) {
3178 status = gensec_set_target_hostname(ags->gensec_security,
3179 target_hostname);
3180 if (tevent_req_nterror(req, status)) {
3181 return tevent_req_post(req, ev);
3185 gensec_set_max_update_size(ags->gensec_security,
3186 CLI_BUFFER_SIZE);
3188 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3189 if (b != NULL) {
3190 state->blob_in = *b;
3193 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3194 if (tevent_req_nterror(req, status)) {
3195 return tevent_req_post(req, ev);
3199 * We only need the gensec_security part from here.
3201 state->es->gensec_security = talloc_move(state->es,
3202 &ags->gensec_security);
3203 TALLOC_FREE(ags);
3205 cli_smb1_setup_encryption_local_next(req);
3206 if (!tevent_req_is_in_progress(req)) {
3207 return tevent_req_post(req, ev);
3210 return req;
3213 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3215 struct cli_smb1_setup_encryption_state *state =
3216 tevent_req_data(req,
3217 struct cli_smb1_setup_encryption_state);
3218 struct tevent_req *subreq = NULL;
3220 if (state->local_ready) {
3221 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3222 return;
3225 subreq = gensec_update_send(state, state->ev,
3226 state->es->gensec_security,
3227 state->blob_in);
3228 if (tevent_req_nomem(subreq, req)) {
3229 return;
3231 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3234 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3236 struct tevent_req *req =
3237 tevent_req_callback_data(subreq,
3238 struct tevent_req);
3239 struct cli_smb1_setup_encryption_state *state =
3240 tevent_req_data(req,
3241 struct cli_smb1_setup_encryption_state);
3242 NTSTATUS status;
3244 status = gensec_update_recv(subreq, state, &state->blob_out);
3245 TALLOC_FREE(subreq);
3246 state->blob_in = data_blob_null;
3247 if (!NT_STATUS_IS_OK(status) &&
3248 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3250 tevent_req_nterror(req, status);
3251 return;
3254 if (NT_STATUS_IS_OK(status)) {
3255 state->local_ready = true;
3259 * We always get NT_STATUS_OK from the server even if it is not ready.
3260 * So guess the server is ready when we are ready and already sent
3261 * our last blob to the server.
3263 if (state->local_ready && state->blob_out.length == 0) {
3264 state->remote_ready = true;
3267 if (state->local_ready && state->remote_ready) {
3268 cli_smb1_setup_encryption_ready(req);
3269 return;
3272 cli_smb1_setup_encryption_remote_next(req);
3275 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3277 struct cli_smb1_setup_encryption_state *state =
3278 tevent_req_data(req,
3279 struct cli_smb1_setup_encryption_state);
3280 struct tevent_req *subreq = NULL;
3282 if (state->remote_ready) {
3283 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3284 return;
3287 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3288 state->cli, state->blob_out);
3289 if (tevent_req_nomem(subreq, req)) {
3290 return;
3292 tevent_req_set_callback(subreq,
3293 cli_smb1_setup_encryption_remote_done,
3294 req);
3297 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3299 struct tevent_req *req =
3300 tevent_req_callback_data(subreq,
3301 struct tevent_req);
3302 struct cli_smb1_setup_encryption_state *state =
3303 tevent_req_data(req,
3304 struct cli_smb1_setup_encryption_state);
3305 NTSTATUS status;
3307 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3308 &state->blob_in,
3309 &state->es->enc_ctx_num);
3310 TALLOC_FREE(subreq);
3311 data_blob_free(&state->blob_out);
3312 if (!NT_STATUS_IS_OK(status) &&
3313 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3315 tevent_req_nterror(req, status);
3316 return;
3320 * We always get NT_STATUS_OK even if the server is not ready.
3321 * So guess the server is ready when we are ready and sent
3322 * our last blob to the server.
3324 if (state->local_ready) {
3325 state->remote_ready = true;
3328 if (state->local_ready && state->remote_ready) {
3329 cli_smb1_setup_encryption_ready(req);
3330 return;
3333 cli_smb1_setup_encryption_local_next(req);
3336 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3338 struct cli_smb1_setup_encryption_state *state =
3339 tevent_req_data(req,
3340 struct cli_smb1_setup_encryption_state);
3341 struct smb_trans_enc_state *es = NULL;
3343 if (state->blob_in.length != 0) {
3344 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3345 return;
3348 if (state->blob_out.length != 0) {
3349 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3350 return;
3353 es = talloc_move(state->cli->conn, &state->es);
3354 es->enc_on = true;
3355 smb1cli_conn_set_encryption(state->cli->conn, es);
3356 es = NULL;
3358 tevent_req_done(req);
3361 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3363 return tevent_req_simple_recv_ntstatus(req);
3366 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3367 struct cli_credentials *creds)
3369 struct tevent_context *ev = NULL;
3370 struct tevent_req *req = NULL;
3371 NTSTATUS status = NT_STATUS_NO_MEMORY;
3373 ev = samba_tevent_context_init(talloc_tos());
3374 if (ev == NULL) {
3375 goto fail;
3377 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3378 if (req == NULL) {
3379 goto fail;
3381 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3382 goto fail;
3384 status = cli_smb1_setup_encryption_recv(req);
3385 fail:
3386 TALLOC_FREE(ev);
3387 return status;
3391 establishes a connection right up to doing tconX, password specified.
3392 @param output_cli A fully initialised cli structure, non-null only on success
3393 @param dest_host The netbios name of the remote host
3394 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3395 @param port (optional) The destination port (0 for default)
3396 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3397 @param service_type The 'type' of serivice.
3398 @param creds The used user credentials
3401 struct cli_full_connection_creds_state {
3402 struct tevent_context *ev;
3403 const char *service;
3404 const char *service_type;
3405 struct cli_credentials *creds;
3406 int flags;
3407 struct cli_state *cli;
3410 static int cli_full_connection_creds_state_destructor(
3411 struct cli_full_connection_creds_state *s)
3413 if (s->cli != NULL) {
3414 cli_shutdown(s->cli);
3415 s->cli = NULL;
3417 return 0;
3420 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3421 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3422 static void cli_full_connection_creds_enc_start(struct tevent_req *req);
3423 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq);
3424 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq);
3425 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq);
3426 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req);
3427 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq);
3428 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3429 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3431 struct tevent_req *cli_full_connection_creds_send(
3432 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3433 const char *my_name, const char *dest_host,
3434 const struct sockaddr_storage *dest_ss, int port,
3435 const char *service, const char *service_type,
3436 struct cli_credentials *creds,
3437 int flags,
3438 struct smb2_negotiate_contexts *negotiate_contexts)
3440 struct tevent_req *req, *subreq;
3441 struct cli_full_connection_creds_state *state;
3442 enum smb_signing_setting signing_state;
3443 enum smb_encryption_setting encryption_state =
3444 cli_credentials_get_smb_encryption(creds);
3446 req = tevent_req_create(mem_ctx, &state,
3447 struct cli_full_connection_creds_state);
3448 if (req == NULL) {
3449 return NULL;
3451 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3453 state->ev = ev;
3454 state->service = service;
3455 state->service_type = service_type;
3456 state->creds = creds;
3457 state->flags = flags;
3459 if (flags & CLI_FULL_CONNECTION_IPC) {
3460 signing_state = cli_credentials_get_smb_ipc_signing(creds);
3461 } else {
3462 signing_state = cli_credentials_get_smb_signing(creds);
3465 if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
3466 if (flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK) {
3467 encryption_state = SMB_ENCRYPTION_DESIRED;
3471 if (encryption_state >= SMB_ENCRYPTION_DESIRED) {
3472 signing_state = SMB_SIGNING_REQUIRED;
3475 subreq = cli_start_connection_send(
3476 state, ev, my_name, dest_host, dest_ss, port,
3477 signing_state, flags,
3478 negotiate_contexts);
3479 if (tevent_req_nomem(subreq, req)) {
3480 return tevent_req_post(req, ev);
3482 tevent_req_set_callback(subreq,
3483 cli_full_connection_creds_conn_done,
3484 req);
3485 return req;
3488 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3490 struct tevent_req *req = tevent_req_callback_data(
3491 subreq, struct tevent_req);
3492 struct cli_full_connection_creds_state *state = tevent_req_data(
3493 req, struct cli_full_connection_creds_state);
3494 NTSTATUS status;
3496 status = cli_start_connection_recv(subreq, &state->cli);
3497 TALLOC_FREE(subreq);
3498 if (tevent_req_nterror(req, status)) {
3499 return;
3502 subreq = cli_session_setup_creds_send(
3503 state, state->ev, state->cli, state->creds);
3504 if (tevent_req_nomem(subreq, req)) {
3505 return;
3507 tevent_req_set_callback(subreq,
3508 cli_full_connection_creds_sess_done,
3509 req);
3512 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3514 struct tevent_req *req = tevent_req_callback_data(
3515 subreq, struct tevent_req);
3516 struct cli_full_connection_creds_state *state = tevent_req_data(
3517 req, struct cli_full_connection_creds_state);
3518 NTSTATUS status;
3520 status = cli_session_setup_creds_recv(subreq);
3521 TALLOC_FREE(subreq);
3523 if (!NT_STATUS_IS_OK(status) &&
3524 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3526 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3528 state->creds = cli_credentials_init_anon(state);
3529 if (tevent_req_nomem(state->creds, req)) {
3530 return;
3533 subreq = cli_session_setup_creds_send(
3534 state, state->ev, state->cli, state->creds);
3535 if (tevent_req_nomem(subreq, req)) {
3536 return;
3538 tevent_req_set_callback(subreq,
3539 cli_full_connection_creds_sess_done,
3540 req);
3541 return;
3544 if (tevent_req_nterror(req, status)) {
3545 return;
3548 cli_full_connection_creds_enc_start(req);
3551 static void cli_full_connection_creds_enc_start(struct tevent_req *req)
3553 struct cli_full_connection_creds_state *state = tevent_req_data(
3554 req, struct cli_full_connection_creds_state);
3555 enum smb_encryption_setting encryption_state =
3556 cli_credentials_get_smb_encryption(state->creds);
3557 struct tevent_req *subreq = NULL;
3558 NTSTATUS status;
3560 if (encryption_state < SMB_ENCRYPTION_DESIRED) {
3561 cli_full_connection_creds_tcon_start(req);
3562 return;
3565 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3566 status = smb2cli_session_encryption_on(state->cli->smb2.session);
3567 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
3568 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3569 cli_full_connection_creds_tcon_start(req);
3570 return;
3572 d_printf("Encryption required and "
3573 "server doesn't support "
3574 "SMB3 encryption - failing connect\n");
3575 tevent_req_nterror(req, status);
3576 return;
3577 } else if (!NT_STATUS_IS_OK(status)) {
3578 d_printf("Encryption required and "
3579 "setup failed with error %s.\n",
3580 nt_errstr(status));
3581 tevent_req_nterror(req, status);
3582 return;
3585 cli_full_connection_creds_tcon_start(req);
3586 return;
3589 if (!SERVER_HAS_UNIX_CIFS(state->cli)) {
3590 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3591 cli_full_connection_creds_tcon_start(req);
3592 return;
3595 status = NT_STATUS_NOT_SUPPORTED;
3596 d_printf("Encryption required and "
3597 "server doesn't support "
3598 "SMB1 Unix Extensions - failing connect\n");
3599 tevent_req_nterror(req, status);
3600 return;
3604 * We do a tcon on IPC$ just to setup the encryption,
3605 * the real tcon will be encrypted then.
3607 subreq = cli_tree_connect_send(state, state->ev, state->cli,
3608 "IPC$", "IPC", NULL);
3609 if (tevent_req_nomem(subreq, req)) {
3610 return;
3612 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_tcon, req);
3615 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq)
3617 struct tevent_req *req = tevent_req_callback_data(
3618 subreq, struct tevent_req);
3619 struct cli_full_connection_creds_state *state = tevent_req_data(
3620 req, struct cli_full_connection_creds_state);
3621 NTSTATUS status;
3623 status = cli_tree_connect_recv(subreq);
3624 TALLOC_FREE(subreq);
3625 if (tevent_req_nterror(req, status)) {
3626 return;
3629 subreq = cli_unix_extensions_version_send(state, state->ev, state->cli);
3630 if (tevent_req_nomem(subreq, req)) {
3631 return;
3633 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_ver, req);
3636 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq)
3638 struct tevent_req *req = tevent_req_callback_data(
3639 subreq, struct tevent_req);
3640 struct cli_full_connection_creds_state *state = tevent_req_data(
3641 req, struct cli_full_connection_creds_state);
3642 enum smb_encryption_setting encryption_state =
3643 cli_credentials_get_smb_encryption(state->creds);
3644 uint16_t major, minor;
3645 uint32_t caplow, caphigh;
3646 NTSTATUS status;
3648 status = cli_unix_extensions_version_recv(subreq,
3649 &major, &minor,
3650 &caplow,
3651 &caphigh);
3652 TALLOC_FREE(subreq);
3653 if (!NT_STATUS_IS_OK(status)) {
3654 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3655 /* disconnect ipc$ followed by the real tree connect */
3656 cli_full_connection_creds_enc_tdis(req);
3657 return;
3659 DEBUG(10, ("%s: cli_unix_extensions_version "
3660 "returned %s\n", __func__, nt_errstr(status)));
3661 tevent_req_nterror(req, NT_STATUS_UNKNOWN_REVISION);
3662 return;
3665 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
3666 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3667 /* disconnect ipc$ followed by the real tree connect */
3668 cli_full_connection_creds_enc_tdis(req);
3669 return;
3671 DEBUG(10, ("%s: CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP "
3672 "not supported\n", __func__));
3673 tevent_req_nterror(req, NT_STATUS_UNSUPPORTED_COMPRESSION);
3674 return;
3677 subreq = cli_smb1_setup_encryption_send(state, state->ev,
3678 state->cli,
3679 state->creds);
3680 if (tevent_req_nomem(subreq, req)) {
3681 return;
3683 tevent_req_set_callback(subreq,
3684 cli_full_connection_creds_enc_done,
3685 req);
3688 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq)
3690 struct tevent_req *req = tevent_req_callback_data(
3691 subreq, struct tevent_req);
3692 NTSTATUS status;
3694 status = cli_smb1_setup_encryption_recv(subreq);
3695 TALLOC_FREE(subreq);
3696 if (tevent_req_nterror(req, status)) {
3697 return;
3700 /* disconnect ipc$ followed by the real tree connect */
3701 cli_full_connection_creds_enc_tdis(req);
3704 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req)
3706 struct cli_full_connection_creds_state *state = tevent_req_data(
3707 req, struct cli_full_connection_creds_state);
3708 struct tevent_req *subreq = NULL;
3710 subreq = cli_tdis_send(state, state->ev, state->cli);
3711 if (tevent_req_nomem(subreq, req)) {
3712 return;
3714 tevent_req_set_callback(subreq,
3715 cli_full_connection_creds_enc_finished,
3716 req);
3719 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq)
3721 struct tevent_req *req = tevent_req_callback_data(
3722 subreq, struct tevent_req);
3723 NTSTATUS status;
3725 status = cli_tdis_recv(subreq);
3726 TALLOC_FREE(subreq);
3727 if (tevent_req_nterror(req, status)) {
3728 return;
3731 cli_full_connection_creds_tcon_start(req);
3734 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3736 struct cli_full_connection_creds_state *state = tevent_req_data(
3737 req, struct cli_full_connection_creds_state);
3738 struct tevent_req *subreq = NULL;
3739 const char *password = NULL;
3741 if (state->service == NULL) {
3742 tevent_req_done(req);
3743 return;
3746 password = cli_credentials_get_password(state->creds);
3748 subreq = cli_tree_connect_send(state, state->ev,
3749 state->cli,
3750 state->service,
3751 state->service_type,
3752 password);
3753 if (tevent_req_nomem(subreq, req)) {
3754 return;
3756 tevent_req_set_callback(subreq,
3757 cli_full_connection_creds_tcon_done,
3758 req);
3761 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3763 struct tevent_req *req = tevent_req_callback_data(
3764 subreq, struct tevent_req);
3765 NTSTATUS status;
3767 status = cli_tree_connect_recv(subreq);
3768 TALLOC_FREE(subreq);
3769 if (tevent_req_nterror(req, status)) {
3770 return;
3773 tevent_req_done(req);
3776 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3777 struct cli_state **output_cli)
3779 struct cli_full_connection_creds_state *state = tevent_req_data(
3780 req, struct cli_full_connection_creds_state);
3781 NTSTATUS status;
3783 if (tevent_req_is_nterror(req, &status)) {
3784 return status;
3786 *output_cli = state->cli;
3787 talloc_set_destructor(state, NULL);
3788 return NT_STATUS_OK;
3791 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3792 const char *my_name,
3793 const char *dest_host,
3794 const struct sockaddr_storage *dest_ss, int port,
3795 const char *service, const char *service_type,
3796 struct cli_credentials *creds,
3797 int flags)
3799 struct tevent_context *ev;
3800 struct tevent_req *req;
3801 NTSTATUS status = NT_STATUS_NO_MEMORY;
3803 ev = samba_tevent_context_init(talloc_tos());
3804 if (ev == NULL) {
3805 goto fail;
3807 req = cli_full_connection_creds_send(
3808 ev, ev, my_name, dest_host, dest_ss, port, service,
3809 service_type, creds, flags,
3810 NULL);
3811 if (req == NULL) {
3812 goto fail;
3814 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3815 goto fail;
3817 status = cli_full_connection_creds_recv(req, output_cli);
3818 fail:
3819 TALLOC_FREE(ev);
3820 return status;
3823 /****************************************************************************
3824 Send an old style tcon.
3825 ****************************************************************************/
3826 struct cli_raw_tcon_state {
3827 uint16_t *ret_vwv;
3830 static void cli_raw_tcon_done(struct tevent_req *subreq);
3832 static struct tevent_req *cli_raw_tcon_send(
3833 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3834 const char *service, const char *pass, const char *dev)
3836 struct tevent_req *req, *subreq;
3837 struct cli_raw_tcon_state *state;
3838 uint8_t *bytes;
3840 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3841 if (req == NULL) {
3842 return NULL;
3845 if (!lp_client_plaintext_auth() && (*pass)) {
3846 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3847 " or 'client ntlmv2 auth = yes'\n"));
3848 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3849 return tevent_req_post(req, ev);
3852 TALLOC_FREE(cli->smb1.tcon);
3853 cli->smb1.tcon = smbXcli_tcon_create(cli);
3854 if (tevent_req_nomem(cli->smb1.tcon, req)) {
3855 return tevent_req_post(req, ev);
3857 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
3859 bytes = talloc_array(state, uint8_t, 0);
3860 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3861 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3862 service, strlen(service)+1, NULL);
3863 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3864 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3865 pass, strlen(pass)+1, NULL);
3866 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3867 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3868 dev, strlen(dev)+1, NULL);
3870 if (tevent_req_nomem(bytes, req)) {
3871 return tevent_req_post(req, ev);
3874 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3875 talloc_get_size(bytes), bytes);
3876 if (tevent_req_nomem(subreq, req)) {
3877 return tevent_req_post(req, ev);
3879 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3880 return req;
3883 static void cli_raw_tcon_done(struct tevent_req *subreq)
3885 struct tevent_req *req = tevent_req_callback_data(
3886 subreq, struct tevent_req);
3887 struct cli_raw_tcon_state *state = tevent_req_data(
3888 req, struct cli_raw_tcon_state);
3889 NTSTATUS status;
3891 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3892 NULL, NULL);
3893 TALLOC_FREE(subreq);
3894 if (tevent_req_nterror(req, status)) {
3895 return;
3897 tevent_req_done(req);
3900 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3901 uint16_t *max_xmit, uint16_t *tid)
3903 struct cli_raw_tcon_state *state = tevent_req_data(
3904 req, struct cli_raw_tcon_state);
3905 NTSTATUS status;
3907 if (tevent_req_is_nterror(req, &status)) {
3908 return status;
3910 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3911 *tid = SVAL(state->ret_vwv + 1, 0);
3912 return NT_STATUS_OK;
3915 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3916 const char *service, const char *pass, const char *dev,
3917 uint16_t *max_xmit, uint16_t *tid)
3919 struct tevent_context *ev;
3920 struct tevent_req *req;
3921 NTSTATUS status = NT_STATUS_NO_MEMORY;
3923 ev = samba_tevent_context_init(talloc_tos());
3924 if (ev == NULL) {
3925 goto fail;
3927 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3928 if (req == NULL) {
3929 goto fail;
3931 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3932 goto fail;
3934 status = cli_raw_tcon_recv(req, max_xmit, tid);
3935 fail:
3936 TALLOC_FREE(ev);
3937 return status;
3940 /* Return a cli_state pointing at the IPC$ share for the given server */
3942 struct cli_state *get_ipc_connect(char *server,
3943 struct sockaddr_storage *server_ss,
3944 struct cli_credentials *creds)
3946 struct cli_state *cli;
3947 NTSTATUS nt_status;
3948 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3950 flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
3951 flags |= CLI_FULL_CONNECTION_IPC;
3953 nt_status = cli_full_connection_creds(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3954 creds,
3955 flags);
3957 if (NT_STATUS_IS_OK(nt_status)) {
3958 return cli;
3960 if (is_ipaddress(server)) {
3961 /* windows 9* needs a correct NMB name for connections */
3962 fstring remote_name;
3964 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3965 cli = get_ipc_connect(remote_name, server_ss, creds);
3966 if (cli)
3967 return cli;
3970 return NULL;
3974 * Given the IP address of a master browser on the network, return its
3975 * workgroup and connect to it.
3977 * This function is provided to allow additional processing beyond what
3978 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3979 * browsers and obtain each master browsers' list of domains (in case the
3980 * first master browser is recently on the network and has not yet
3981 * synchronized with other master browsers and therefore does not yet have the
3982 * entire network browse list)
3985 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3986 struct sockaddr_storage *mb_ip,
3987 struct cli_credentials *creds,
3988 char **pp_workgroup_out)
3990 char addr[INET6_ADDRSTRLEN];
3991 fstring name;
3992 struct cli_state *cli;
3993 struct sockaddr_storage server_ss;
3995 *pp_workgroup_out = NULL;
3997 print_sockaddr(addr, sizeof(addr), mb_ip);
3998 DEBUG(99, ("Looking up name of master browser %s\n",
3999 addr));
4002 * Do a name status query to find out the name of the master browser.
4003 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
4004 * master browser will not respond to a wildcard query (or, at least,
4005 * an NT4 server acting as the domain master browser will not).
4007 * We might be able to use ONLY the query on MSBROWSE, but that's not
4008 * yet been tested with all Windows versions, so until it is, leave
4009 * the original wildcard query as the first choice and fall back to
4010 * MSBROWSE if the wildcard query fails.
4012 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
4013 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
4015 DEBUG(99, ("Could not retrieve name status for %s\n",
4016 addr));
4017 return NULL;
4020 if (!find_master_ip(name, &server_ss)) {
4021 DEBUG(99, ("Could not find master ip for %s\n", name));
4022 return NULL;
4025 *pp_workgroup_out = talloc_strdup(ctx, name);
4027 DEBUG(4, ("found master browser %s, %s\n", name, addr));
4029 print_sockaddr(addr, sizeof(addr), &server_ss);
4030 cli = get_ipc_connect(addr, &server_ss, creds);
4032 return cli;