CVE-2023-3961:s3:torture: Add test SMB2-INVALID-PIPENAME to show we allow bad pipenam...
[Samba.git] / source3 / libsmb / cliconnect.c
blobaf9f215dc754613338c17cfebbdd29c182844ca0
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 (tevent_req_nterror(req, status)) {
1746 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1747 return;
1750 status = cli_state_update_after_sesssetup(state->cli,
1751 state->out_native_os,
1752 state->out_native_lm,
1753 state->out_primary_domain);
1754 if (tevent_req_nterror(req, status)) {
1755 return;
1758 ok = smb1cli_conn_activate_signing(cli->conn,
1759 state->session_key,
1760 state->upassword_blob);
1761 if (ok) {
1762 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1763 if (!ok) {
1764 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1765 return;
1769 if (state->session_key.data) {
1770 struct smbXcli_session *session = cli->smb1.session;
1772 status = smb1cli_session_set_session_key(session,
1773 state->session_key);
1774 if (tevent_req_nterror(req, status)) {
1775 return;
1779 tevent_req_done(req);
1782 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1784 struct tevent_req *req = tevent_req_callback_data(
1785 subreq, struct tevent_req);
1786 struct cli_session_setup_creds_state *state = tevent_req_data(
1787 req, struct cli_session_setup_creds_state);
1788 NTSTATUS status;
1790 status = smb1cli_session_setup_lm21_recv(subreq, state,
1791 &state->out_native_os,
1792 &state->out_native_lm);
1793 TALLOC_FREE(subreq);
1794 if (tevent_req_nterror(req, status)) {
1795 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1796 return;
1799 status = cli_state_update_after_sesssetup(state->cli,
1800 state->out_native_os,
1801 state->out_native_lm,
1802 NULL);
1803 if (tevent_req_nterror(req, status)) {
1804 return;
1807 tevent_req_done(req);
1810 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1812 return tevent_req_simple_recv_ntstatus(req);
1815 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1816 struct cli_credentials *creds)
1818 struct tevent_context *ev;
1819 struct tevent_req *req;
1820 NTSTATUS status = NT_STATUS_NO_MEMORY;
1822 if (smbXcli_conn_has_async_calls(cli->conn)) {
1823 return NT_STATUS_INVALID_PARAMETER;
1825 ev = samba_tevent_context_init(talloc_tos());
1826 if (ev == NULL) {
1827 goto fail;
1829 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1830 if (req == NULL) {
1831 goto fail;
1833 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1834 goto fail;
1836 status = cli_session_setup_creds_recv(req);
1837 fail:
1838 TALLOC_FREE(ev);
1839 return status;
1842 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1844 NTSTATUS status;
1845 struct cli_credentials *creds = NULL;
1847 creds = cli_credentials_init_anon(cli);
1848 if (creds == NULL) {
1849 return NT_STATUS_NO_MEMORY;
1852 status = cli_session_setup_creds(cli, creds);
1853 TALLOC_FREE(creds);
1854 if (!NT_STATUS_IS_OK(status)) {
1855 return status;
1858 return NT_STATUS_OK;
1861 /****************************************************************************
1862 Send a uloggoff.
1863 *****************************************************************************/
1865 struct cli_ulogoff_state {
1866 struct cli_state *cli;
1867 uint16_t vwv[3];
1870 static void cli_ulogoff_done(struct tevent_req *subreq);
1872 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1873 struct tevent_context *ev,
1874 struct cli_state *cli)
1876 struct tevent_req *req, *subreq;
1877 struct cli_ulogoff_state *state;
1879 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1880 if (req == NULL) {
1881 return NULL;
1883 state->cli = cli;
1885 SCVAL(state->vwv+0, 0, 0xFF);
1886 SCVAL(state->vwv+1, 0, 0);
1887 SSVAL(state->vwv+2, 0, 0);
1889 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1890 0, NULL);
1891 if (tevent_req_nomem(subreq, req)) {
1892 return tevent_req_post(req, ev);
1894 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1895 return req;
1898 static void cli_ulogoff_done(struct tevent_req *subreq)
1900 struct tevent_req *req = tevent_req_callback_data(
1901 subreq, struct tevent_req);
1902 struct cli_ulogoff_state *state = tevent_req_data(
1903 req, struct cli_ulogoff_state);
1904 NTSTATUS status;
1906 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1907 if (tevent_req_nterror(req, status)) {
1908 return;
1910 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1911 tevent_req_done(req);
1914 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1916 return tevent_req_simple_recv_ntstatus(req);
1919 NTSTATUS cli_ulogoff(struct cli_state *cli)
1921 struct tevent_context *ev;
1922 struct tevent_req *req;
1923 NTSTATUS status = NT_STATUS_NO_MEMORY;
1925 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1926 status = smb2cli_logoff(cli->conn,
1927 cli->timeout,
1928 cli->smb2.session);
1929 if (!NT_STATUS_IS_OK(status)) {
1930 return status;
1932 smb2cli_session_set_id_and_flags(cli->smb2.session,
1933 UINT64_MAX, 0);
1934 return NT_STATUS_OK;
1937 if (smbXcli_conn_has_async_calls(cli->conn)) {
1938 return NT_STATUS_INVALID_PARAMETER;
1940 ev = samba_tevent_context_init(talloc_tos());
1941 if (ev == NULL) {
1942 goto fail;
1944 req = cli_ulogoff_send(ev, ev, cli);
1945 if (req == NULL) {
1946 goto fail;
1948 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1949 goto fail;
1951 status = cli_ulogoff_recv(req);
1952 fail:
1953 TALLOC_FREE(ev);
1954 return status;
1957 /****************************************************************************
1958 Send a tconX.
1959 ****************************************************************************/
1961 struct cli_tcon_andx_state {
1962 struct cli_state *cli;
1963 uint16_t vwv[4];
1964 struct iovec bytes;
1967 static void cli_tcon_andx_done(struct tevent_req *subreq);
1969 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1970 struct tevent_context *ev,
1971 struct cli_state *cli,
1972 const char *share, const char *dev,
1973 const char *pass, int passlen,
1974 struct tevent_req **psmbreq)
1976 struct tevent_req *req, *subreq;
1977 struct cli_tcon_andx_state *state;
1978 uint8_t p24[24];
1979 uint16_t *vwv;
1980 char *tmp = NULL;
1981 uint8_t *bytes;
1982 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1983 uint16_t tcon_flags = 0;
1985 *psmbreq = NULL;
1987 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1988 if (req == NULL) {
1989 return NULL;
1991 state->cli = cli;
1992 vwv = state->vwv;
1994 TALLOC_FREE(cli->smb1.tcon);
1995 cli->smb1.tcon = smbXcli_tcon_create(cli);
1996 if (tevent_req_nomem(cli->smb1.tcon, req)) {
1997 return tevent_req_post(req, ev);
1999 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
2001 cli->share = talloc_strdup(cli, share);
2002 if (!cli->share) {
2003 return NULL;
2006 /* in user level security don't send a password now */
2007 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2008 passlen = 1;
2009 pass = "";
2010 } else if (pass == NULL) {
2011 DEBUG(1, ("Server not using user level security and no "
2012 "password supplied.\n"));
2013 goto access_denied;
2016 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2017 *pass && passlen != 24) {
2018 if (!lp_client_lanman_auth()) {
2019 DEBUG(1, ("Server requested LANMAN password "
2020 "(share-level security) but "
2021 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2022 goto access_denied;
2026 * Non-encrypted passwords - convert to DOS codepage before
2027 * encryption.
2029 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2030 passlen = 24;
2031 pass = (const char *)p24;
2032 } else {
2033 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2034 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2035 == 0) {
2036 uint8_t *tmp_pass;
2038 if (!lp_client_plaintext_auth() && (*pass)) {
2039 DEBUG(1, ("Server requested PLAINTEXT "
2040 "password but "
2041 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2042 goto access_denied;
2046 * Non-encrypted passwords - convert to DOS codepage
2047 * before using.
2049 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2050 if (tevent_req_nomem(tmp_pass, req)) {
2051 return tevent_req_post(req, ev);
2053 tmp_pass = trans2_bytes_push_str(tmp_pass,
2054 false, /* always DOS */
2055 pass,
2056 passlen,
2057 NULL);
2058 if (tevent_req_nomem(tmp_pass, req)) {
2059 return tevent_req_post(req, ev);
2061 pass = (const char *)tmp_pass;
2062 passlen = talloc_get_size(tmp_pass);
2066 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2067 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2069 SCVAL(vwv+0, 0, 0xFF);
2070 SCVAL(vwv+0, 1, 0);
2071 SSVAL(vwv+1, 0, 0);
2072 SSVAL(vwv+2, 0, tcon_flags);
2073 SSVAL(vwv+3, 0, passlen);
2075 if (passlen && pass) {
2076 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2077 } else {
2078 bytes = talloc_array(state, uint8_t, 0);
2082 * Add the sharename
2084 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2085 smbXcli_conn_remote_name(cli->conn), share);
2086 if (tmp == NULL) {
2087 TALLOC_FREE(req);
2088 return NULL;
2090 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2091 NULL);
2092 TALLOC_FREE(tmp);
2095 * Add the devicetype
2097 tmp = talloc_strdup_upper(talloc_tos(), dev);
2098 if (tmp == NULL) {
2099 TALLOC_FREE(req);
2100 return NULL;
2102 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2103 TALLOC_FREE(tmp);
2105 if (bytes == NULL) {
2106 TALLOC_FREE(req);
2107 return NULL;
2110 state->bytes.iov_base = (void *)bytes;
2111 state->bytes.iov_len = talloc_get_size(bytes);
2113 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2114 1, &state->bytes);
2115 if (subreq == NULL) {
2116 TALLOC_FREE(req);
2117 return NULL;
2119 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2120 *psmbreq = subreq;
2121 return req;
2123 access_denied:
2124 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2125 return tevent_req_post(req, ev);
2128 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2129 struct tevent_context *ev,
2130 struct cli_state *cli,
2131 const char *share, const char *dev,
2132 const char *pass, int passlen)
2134 struct tevent_req *req, *subreq;
2135 NTSTATUS status;
2137 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2138 &subreq);
2139 if (req == NULL) {
2140 return NULL;
2142 if (subreq == NULL) {
2143 return req;
2145 status = smb1cli_req_chain_submit(&subreq, 1);
2146 if (tevent_req_nterror(req, status)) {
2147 return tevent_req_post(req, ev);
2149 return req;
2152 static void cli_tcon_andx_done(struct tevent_req *subreq)
2154 struct tevent_req *req = tevent_req_callback_data(
2155 subreq, struct tevent_req);
2156 struct cli_tcon_andx_state *state = tevent_req_data(
2157 req, struct cli_tcon_andx_state);
2158 struct cli_state *cli = state->cli;
2159 uint8_t *in;
2160 uint8_t *inhdr;
2161 uint8_t wct;
2162 uint16_t *vwv;
2163 uint32_t num_bytes;
2164 uint8_t *bytes;
2165 NTSTATUS status;
2166 uint16_t optional_support = 0;
2168 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2169 &num_bytes, &bytes);
2170 TALLOC_FREE(subreq);
2171 if (tevent_req_nterror(req, status)) {
2172 return;
2175 inhdr = in + NBT_HDR_SIZE;
2177 if (num_bytes) {
2178 if (pull_string_talloc(cli,
2179 (const char *)inhdr,
2180 SVAL(inhdr, HDR_FLG2),
2181 &cli->dev,
2182 bytes,
2183 num_bytes,
2184 STR_TERMINATE|STR_ASCII) == -1) {
2185 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2186 return;
2188 } else {
2189 cli->dev = talloc_strdup(cli, "");
2190 if (cli->dev == NULL) {
2191 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2192 return;
2196 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2197 /* almost certainly win95 - enable bug fixes */
2198 cli->win95 = True;
2202 * Make sure that we have the optional support 16-bit field. WCT > 2.
2203 * Avoids issues when connecting to Win9x boxes sharing files
2206 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2207 optional_support = SVAL(vwv+2, 0);
2210 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2211 smb1cli_session_protect_session_key(cli->smb1.session);
2214 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2215 SVAL(inhdr, HDR_TID),
2216 optional_support,
2217 0, /* maximal_access */
2218 0, /* guest_maximal_access */
2219 NULL, /* service */
2220 NULL); /* fs_type */
2222 tevent_req_done(req);
2225 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2227 return tevent_req_simple_recv_ntstatus(req);
2230 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2231 const char *dev, const char *pass, int passlen)
2233 TALLOC_CTX *frame = talloc_stackframe();
2234 struct tevent_context *ev;
2235 struct tevent_req *req;
2236 NTSTATUS status = NT_STATUS_NO_MEMORY;
2238 if (smbXcli_conn_has_async_calls(cli->conn)) {
2240 * Can't use sync call while an async call is in flight
2242 status = NT_STATUS_INVALID_PARAMETER;
2243 goto fail;
2246 ev = samba_tevent_context_init(frame);
2247 if (ev == NULL) {
2248 goto fail;
2251 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2252 if (req == NULL) {
2253 goto fail;
2256 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2257 goto fail;
2260 status = cli_tcon_andx_recv(req);
2261 fail:
2262 TALLOC_FREE(frame);
2263 return status;
2266 struct cli_tree_connect_state {
2267 struct cli_state *cli;
2270 static struct tevent_req *cli_raw_tcon_send(
2271 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2272 const char *service, const char *pass, const char *dev);
2273 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2274 uint16_t *max_xmit, uint16_t *tid);
2276 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2277 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2278 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2280 static struct tevent_req *cli_tree_connect_send(
2281 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2282 const char *share, const char *dev, const char *pass)
2284 struct tevent_req *req, *subreq;
2285 struct cli_tree_connect_state *state;
2286 int passlen;
2288 if (pass == NULL) {
2289 pass = "";
2291 passlen = strlen(pass) + 1;
2293 req = tevent_req_create(mem_ctx, &state,
2294 struct cli_tree_connect_state);
2295 if (req == NULL) {
2296 return NULL;
2298 state->cli = cli;
2300 cli->share = talloc_strdup(cli, share);
2301 if (tevent_req_nomem(cli->share, req)) {
2302 return tevent_req_post(req, ev);
2305 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2306 char *unc;
2308 TALLOC_FREE(cli->smb2.tcon);
2309 cli->smb2.tcon = smbXcli_tcon_create(cli);
2310 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2311 return tevent_req_post(req, ev);
2314 unc = talloc_asprintf(state, "\\\\%s\\%s",
2315 smbXcli_conn_remote_name(cli->conn),
2316 share);
2317 if (tevent_req_nomem(unc, req)) {
2318 return tevent_req_post(req, ev);
2321 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2322 cli->smb2.session, cli->smb2.tcon,
2323 0, /* flags */
2324 unc);
2325 if (tevent_req_nomem(subreq, req)) {
2326 return tevent_req_post(req, ev);
2328 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2329 req);
2330 return req;
2333 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2334 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2335 pass, passlen);
2336 if (tevent_req_nomem(subreq, req)) {
2337 return tevent_req_post(req, ev);
2339 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2340 req);
2341 return req;
2344 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2345 if (tevent_req_nomem(subreq, req)) {
2346 return tevent_req_post(req, ev);
2348 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2350 return req;
2353 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2355 NTSTATUS status = smb2cli_tcon_recv(subreq);
2356 tevent_req_simple_finish_ntstatus(subreq, status);
2359 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2361 NTSTATUS status = cli_tcon_andx_recv(subreq);
2362 tevent_req_simple_finish_ntstatus(subreq, status);
2365 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2367 struct tevent_req *req = tevent_req_callback_data(
2368 subreq, struct tevent_req);
2369 struct cli_tree_connect_state *state = tevent_req_data(
2370 req, struct cli_tree_connect_state);
2371 NTSTATUS status;
2372 uint16_t max_xmit = 0;
2373 uint16_t tid = 0;
2375 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2376 if (tevent_req_nterror(req, status)) {
2377 return;
2380 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2381 tid,
2382 0, /* optional_support */
2383 0, /* maximal_access */
2384 0, /* guest_maximal_access */
2385 NULL, /* service */
2386 NULL); /* fs_type */
2388 tevent_req_done(req);
2391 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2393 return tevent_req_simple_recv_ntstatus(req);
2396 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2397 const char *dev, const char *pass)
2399 struct tevent_context *ev;
2400 struct tevent_req *req;
2401 NTSTATUS status = NT_STATUS_NO_MEMORY;
2403 if (smbXcli_conn_has_async_calls(cli->conn)) {
2404 return NT_STATUS_INVALID_PARAMETER;
2406 ev = samba_tevent_context_init(talloc_tos());
2407 if (ev == NULL) {
2408 goto fail;
2410 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2411 if (req == NULL) {
2412 goto fail;
2414 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2415 goto fail;
2417 status = cli_tree_connect_recv(req);
2418 fail:
2419 TALLOC_FREE(ev);
2420 return status;
2423 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2424 const char *share, const char *dev,
2425 struct cli_credentials *creds)
2427 const char *pw = NULL;
2429 if (creds != NULL) {
2430 pw = cli_credentials_get_password(creds);
2433 return cli_tree_connect(cli, share, dev, pw);
2436 /****************************************************************************
2437 Send a tree disconnect.
2438 ****************************************************************************/
2440 struct cli_tdis_state {
2441 struct cli_state *cli;
2444 static void cli_tdis_done(struct tevent_req *subreq);
2446 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2447 struct tevent_context *ev,
2448 struct cli_state *cli)
2450 struct tevent_req *req, *subreq;
2451 struct cli_tdis_state *state;
2453 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2454 if (req == NULL) {
2455 return NULL;
2457 state->cli = cli;
2459 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2460 if (tevent_req_nomem(subreq, req)) {
2461 return tevent_req_post(req, ev);
2463 tevent_req_set_callback(subreq, cli_tdis_done, req);
2464 return req;
2467 static void cli_tdis_done(struct tevent_req *subreq)
2469 struct tevent_req *req = tevent_req_callback_data(
2470 subreq, struct tevent_req);
2471 struct cli_tdis_state *state = tevent_req_data(
2472 req, struct cli_tdis_state);
2473 NTSTATUS status;
2475 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2476 TALLOC_FREE(subreq);
2477 if (tevent_req_nterror(req, status)) {
2478 return;
2480 TALLOC_FREE(state->cli->smb1.tcon);
2481 tevent_req_done(req);
2484 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2486 return tevent_req_simple_recv_ntstatus(req);
2489 NTSTATUS cli_tdis(struct cli_state *cli)
2491 struct tevent_context *ev;
2492 struct tevent_req *req;
2493 NTSTATUS status = NT_STATUS_NO_MEMORY;
2495 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2496 status = smb2cli_tdis(cli->conn,
2497 cli->timeout,
2498 cli->smb2.session,
2499 cli->smb2.tcon);
2500 if (NT_STATUS_IS_OK(status)) {
2501 TALLOC_FREE(cli->smb2.tcon);
2503 return status;
2506 if (smbXcli_conn_has_async_calls(cli->conn)) {
2507 return NT_STATUS_INVALID_PARAMETER;
2509 ev = samba_tevent_context_init(talloc_tos());
2510 if (ev == NULL) {
2511 goto fail;
2513 req = cli_tdis_send(ev, ev, cli);
2514 if (req == NULL) {
2515 goto fail;
2517 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2518 goto fail;
2520 status = cli_tdis_recv(req);
2521 fail:
2522 TALLOC_FREE(ev);
2523 return status;
2526 struct cli_connect_sock_state {
2527 const char **called_names;
2528 const char **calling_names;
2529 int *called_types;
2530 int fd;
2531 uint16_t port;
2534 static void cli_connect_sock_done(struct tevent_req *subreq);
2537 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2538 * nonzero address.
2541 static struct tevent_req *cli_connect_sock_send(
2542 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2543 const char *host, int name_type, const struct sockaddr_storage *pss,
2544 const char *myname, uint16_t port)
2546 struct tevent_req *req, *subreq;
2547 struct cli_connect_sock_state *state;
2548 struct sockaddr_storage *addrs = NULL;
2549 unsigned i;
2550 unsigned num_addrs = 0;
2551 NTSTATUS status;
2553 req = tevent_req_create(mem_ctx, &state,
2554 struct cli_connect_sock_state);
2555 if (req == NULL) {
2556 return NULL;
2559 if ((pss == NULL) || is_zero_addr(pss)) {
2562 * Here we cheat. resolve_name_list is not async at all. So
2563 * this call will only be really async if the name lookup has
2564 * been done externally.
2567 status = resolve_name_list(state, host, name_type,
2568 &addrs, &num_addrs);
2569 if (tevent_req_nterror(req, status)) {
2570 return tevent_req_post(req, ev);
2572 } else {
2573 addrs = talloc_array(state, struct sockaddr_storage, 1);
2574 if (tevent_req_nomem(addrs, req)) {
2575 return tevent_req_post(req, ev);
2577 addrs[0] = *pss;
2578 num_addrs = 1;
2581 state->called_names = talloc_array(state, const char *, num_addrs);
2582 if (tevent_req_nomem(state->called_names, req)) {
2583 return tevent_req_post(req, ev);
2585 state->called_types = talloc_array(state, int, num_addrs);
2586 if (tevent_req_nomem(state->called_types, req)) {
2587 return tevent_req_post(req, ev);
2589 state->calling_names = talloc_array(state, const char *, num_addrs);
2590 if (tevent_req_nomem(state->calling_names, req)) {
2591 return tevent_req_post(req, ev);
2593 for (i=0; i<num_addrs; i++) {
2594 state->called_names[i] = host;
2595 state->called_types[i] = name_type;
2596 state->calling_names[i] = myname;
2599 subreq = smbsock_any_connect_send(
2600 state, ev, addrs, state->called_names, state->called_types,
2601 state->calling_names, NULL, num_addrs, port);
2602 if (tevent_req_nomem(subreq, req)) {
2603 return tevent_req_post(req, ev);
2605 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2606 return req;
2609 static void cli_connect_sock_done(struct tevent_req *subreq)
2611 struct tevent_req *req = tevent_req_callback_data(
2612 subreq, struct tevent_req);
2613 struct cli_connect_sock_state *state = tevent_req_data(
2614 req, struct cli_connect_sock_state);
2615 NTSTATUS status;
2617 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2618 &state->port);
2619 TALLOC_FREE(subreq);
2620 if (tevent_req_nterror(req, status)) {
2621 return;
2623 set_socket_options(state->fd, lp_socket_options());
2624 tevent_req_done(req);
2627 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2628 int *pfd, uint16_t *pport)
2630 struct cli_connect_sock_state *state = tevent_req_data(
2631 req, struct cli_connect_sock_state);
2632 NTSTATUS status;
2634 if (tevent_req_is_nterror(req, &status)) {
2635 return status;
2637 *pfd = state->fd;
2638 *pport = state->port;
2639 return NT_STATUS_OK;
2642 struct cli_connect_nb_state {
2643 const char *desthost;
2644 enum smb_signing_setting signing_state;
2645 int flags;
2646 struct cli_state *cli;
2649 static void cli_connect_nb_done(struct tevent_req *subreq);
2651 static struct tevent_req *cli_connect_nb_send(
2652 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2653 const char *host, const struct sockaddr_storage *dest_ss,
2654 uint16_t port, int name_type, const char *myname,
2655 enum smb_signing_setting signing_state, int flags)
2657 struct tevent_req *req, *subreq;
2658 struct cli_connect_nb_state *state;
2660 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2661 if (req == NULL) {
2662 return NULL;
2664 state->signing_state = signing_state;
2665 state->flags = flags;
2667 if (host != NULL) {
2668 char *p = strchr(host, '#');
2670 if (p != NULL) {
2671 name_type = strtol(p+1, NULL, 16);
2672 host = talloc_strndup(state, host, p - host);
2673 if (tevent_req_nomem(host, req)) {
2674 return tevent_req_post(req, ev);
2678 state->desthost = host;
2679 } else if (dest_ss != NULL) {
2680 state->desthost = print_canonical_sockaddr(state, dest_ss);
2681 if (tevent_req_nomem(state->desthost, req)) {
2682 return tevent_req_post(req, ev);
2684 } else {
2685 /* No host or dest_ss given. Error out. */
2686 tevent_req_error(req, EINVAL);
2687 return tevent_req_post(req, ev);
2690 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2691 myname, port);
2692 if (tevent_req_nomem(subreq, req)) {
2693 return tevent_req_post(req, ev);
2695 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2696 return req;
2699 static void cli_connect_nb_done(struct tevent_req *subreq)
2701 struct tevent_req *req = tevent_req_callback_data(
2702 subreq, struct tevent_req);
2703 struct cli_connect_nb_state *state = tevent_req_data(
2704 req, struct cli_connect_nb_state);
2705 NTSTATUS status;
2706 int fd = 0;
2707 uint16_t port;
2709 status = cli_connect_sock_recv(subreq, &fd, &port);
2710 TALLOC_FREE(subreq);
2711 if (tevent_req_nterror(req, status)) {
2712 return;
2715 state->cli = cli_state_create(state, fd, state->desthost,
2716 state->signing_state, state->flags);
2717 if (tevent_req_nomem(state->cli, req)) {
2718 close(fd);
2719 return;
2721 tevent_req_done(req);
2724 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2725 struct cli_state **pcli)
2727 struct cli_connect_nb_state *state = tevent_req_data(
2728 req, struct cli_connect_nb_state);
2729 NTSTATUS status;
2731 if (tevent_req_is_nterror(req, &status)) {
2732 return status;
2734 *pcli = talloc_move(NULL, &state->cli);
2735 return NT_STATUS_OK;
2738 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2739 uint16_t port, int name_type, const char *myname,
2740 enum smb_signing_setting signing_state, int flags, struct cli_state **pcli)
2742 struct tevent_context *ev;
2743 struct tevent_req *req;
2744 NTSTATUS status = NT_STATUS_NO_MEMORY;
2746 ev = samba_tevent_context_init(talloc_tos());
2747 if (ev == NULL) {
2748 goto fail;
2750 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2751 myname, signing_state, flags);
2752 if (req == NULL) {
2753 goto fail;
2755 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2756 goto fail;
2758 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2759 goto fail;
2761 status = cli_connect_nb_recv(req, pcli);
2762 fail:
2763 TALLOC_FREE(ev);
2764 return status;
2767 struct cli_start_connection_state {
2768 struct tevent_context *ev;
2769 struct cli_state *cli;
2770 int min_protocol;
2771 int max_protocol;
2772 struct smb2_negotiate_contexts *negotiate_contexts;
2775 static void cli_start_connection_connected(struct tevent_req *subreq);
2776 static void cli_start_connection_done(struct tevent_req *subreq);
2779 establishes a connection to after the negprot.
2780 @param output_cli A fully initialised cli structure, non-null only on success
2781 @param dest_host The netbios name of the remote host
2782 @param dest_ss (optional) The destination IP, NULL for name based lookup
2783 @param port (optional) The destination port (0 for default)
2786 static struct tevent_req *cli_start_connection_send(
2787 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2788 const char *my_name, const char *dest_host,
2789 const struct sockaddr_storage *dest_ss, int port,
2790 enum smb_signing_setting signing_state, int flags,
2791 struct smb2_negotiate_contexts *negotiate_contexts)
2793 struct tevent_req *req, *subreq;
2794 struct cli_start_connection_state *state;
2796 req = tevent_req_create(mem_ctx, &state,
2797 struct cli_start_connection_state);
2798 if (req == NULL) {
2799 return NULL;
2801 state->ev = ev;
2803 if (flags & CLI_FULL_CONNECTION_IPC) {
2804 state->min_protocol = lp_client_ipc_min_protocol();
2805 state->max_protocol = lp_client_ipc_max_protocol();
2806 } else {
2807 state->min_protocol = lp_client_min_protocol();
2808 state->max_protocol = lp_client_max_protocol();
2811 if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
2812 state->max_protocol = MIN(state->max_protocol,
2813 PROTOCOL_NT1);
2814 state->min_protocol = MIN(state->min_protocol,
2815 state->max_protocol);
2818 if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
2819 state->min_protocol = MAX(state->min_protocol,
2820 PROTOCOL_SMB2_02);
2821 state->max_protocol = MAX(state->max_protocol,
2822 state->min_protocol);
2825 state->negotiate_contexts = talloc_zero(
2826 state, struct smb2_negotiate_contexts);
2827 if (tevent_req_nomem(state->negotiate_contexts, req)) {
2828 return tevent_req_post(req, ev);
2831 if (flags & CLI_FULL_CONNECTION_REQUEST_POSIX) {
2832 NTSTATUS status;
2834 status = smb2_negotiate_context_add(
2835 state->negotiate_contexts,
2836 state->negotiate_contexts,
2837 SMB2_POSIX_EXTENSIONS_AVAILABLE,
2838 (const uint8_t *)SMB2_CREATE_TAG_POSIX,
2839 strlen(SMB2_CREATE_TAG_POSIX));
2840 if (tevent_req_nterror(req, status)) {
2841 return tevent_req_post(req, ev);
2845 if (negotiate_contexts != NULL) {
2846 uint16_t i;
2848 for (i=0; i<negotiate_contexts->num_contexts; i++) {
2849 struct smb2_negotiate_context *ctx =
2850 &negotiate_contexts->contexts[i];
2851 NTSTATUS status;
2853 status = smb2_negotiate_context_add(
2854 state->negotiate_contexts,
2855 state->negotiate_contexts,
2856 ctx->type,
2857 ctx->data.data,
2858 ctx->data.length);
2859 if (tevent_req_nterror(req, status)) {
2860 return tevent_req_post(req, ev);
2865 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2866 0x20, my_name, signing_state, flags);
2867 if (tevent_req_nomem(subreq, req)) {
2868 return tevent_req_post(req, ev);
2870 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2871 return req;
2874 static void cli_start_connection_connected(struct tevent_req *subreq)
2876 struct tevent_req *req = tevent_req_callback_data(
2877 subreq, struct tevent_req);
2878 struct cli_start_connection_state *state = tevent_req_data(
2879 req, struct cli_start_connection_state);
2880 NTSTATUS status;
2882 status = cli_connect_nb_recv(subreq, &state->cli);
2883 TALLOC_FREE(subreq);
2884 if (tevent_req_nterror(req, status)) {
2885 return;
2888 subreq = smbXcli_negprot_send(
2889 state,
2890 state->ev,
2891 state->cli->conn,
2892 state->cli->timeout,
2893 state->min_protocol,
2894 state->max_protocol,
2895 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK,
2896 state->negotiate_contexts);
2897 if (tevent_req_nomem(subreq, req)) {
2898 return;
2900 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2903 static void cli_start_connection_done(struct tevent_req *subreq)
2905 struct tevent_req *req = tevent_req_callback_data(
2906 subreq, struct tevent_req);
2907 struct cli_start_connection_state *state = tevent_req_data(
2908 req, struct cli_start_connection_state);
2909 NTSTATUS status;
2911 status = smbXcli_negprot_recv(subreq, NULL, NULL);
2912 TALLOC_FREE(subreq);
2913 if (tevent_req_nterror(req, status)) {
2914 return;
2917 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2918 /* Ensure we ask for some initial credits. */
2919 smb2cli_conn_set_max_credits(state->cli->conn,
2920 DEFAULT_SMB2_MAX_CREDITS);
2923 tevent_req_done(req);
2926 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2927 struct cli_state **output_cli)
2929 struct cli_start_connection_state *state = tevent_req_data(
2930 req, struct cli_start_connection_state);
2931 NTSTATUS status;
2933 if (tevent_req_is_nterror(req, &status)) {
2934 return status;
2936 *output_cli = state->cli;
2938 return NT_STATUS_OK;
2941 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2942 const char *my_name,
2943 const char *dest_host,
2944 const struct sockaddr_storage *dest_ss, int port,
2945 enum smb_signing_setting signing_state, int flags)
2947 struct tevent_context *ev;
2948 struct tevent_req *req;
2949 NTSTATUS status = NT_STATUS_NO_MEMORY;
2951 ev = samba_tevent_context_init(talloc_tos());
2952 if (ev == NULL) {
2953 goto fail;
2955 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2956 port, signing_state, flags, NULL);
2957 if (req == NULL) {
2958 goto fail;
2960 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2961 goto fail;
2963 status = cli_start_connection_recv(req, output_cli);
2964 fail:
2965 TALLOC_FREE(ev);
2966 return status;
2969 struct cli_smb1_setup_encryption_blob_state {
2970 uint16_t setup[1];
2971 uint8_t param[4];
2972 NTSTATUS status;
2973 DATA_BLOB out;
2974 uint16_t enc_ctx_id;
2977 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2979 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2980 struct tevent_context *ev,
2981 struct cli_state *cli,
2982 const DATA_BLOB in)
2984 struct tevent_req *req = NULL;
2985 struct cli_smb1_setup_encryption_blob_state *state = NULL;
2986 struct tevent_req *subreq = NULL;
2988 req = tevent_req_create(mem_ctx, &state,
2989 struct cli_smb1_setup_encryption_blob_state);
2990 if (req == NULL) {
2991 return NULL;
2994 if (in.length > CLI_BUFFER_SIZE) {
2995 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2996 return tevent_req_post(req, ev);
2999 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
3000 SSVAL(state->param, 0, 0);
3001 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
3003 subreq = smb1cli_trans_send(state, ev, cli->conn,
3004 SMBtrans2,
3005 0, 0, /* _flags */
3006 0, 0, /* _flags2 */
3007 cli->timeout,
3008 cli->smb1.pid,
3009 cli->smb1.tcon,
3010 cli->smb1.session,
3011 NULL, /* pipe_name */
3012 0, /* fid */
3013 0, /* function */
3014 0, /* flags */
3015 state->setup, 1, 0,
3016 state->param, 4, 2,
3017 in.data, in.length, CLI_BUFFER_SIZE);
3018 if (tevent_req_nomem(subreq, req)) {
3019 return tevent_req_post(req, ev);
3021 tevent_req_set_callback(subreq,
3022 cli_smb1_setup_encryption_blob_done,
3023 req);
3025 return req;
3028 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
3030 struct tevent_req *req =
3031 tevent_req_callback_data(subreq,
3032 struct tevent_req);
3033 struct cli_smb1_setup_encryption_blob_state *state =
3034 tevent_req_data(req,
3035 struct cli_smb1_setup_encryption_blob_state);
3036 uint8_t *rparam=NULL, *rdata=NULL;
3037 uint32_t num_rparam, num_rdata;
3038 NTSTATUS status;
3040 status = smb1cli_trans_recv(subreq, state,
3041 NULL, /* recv_flags */
3042 NULL, 0, NULL, /* rsetup */
3043 &rparam, 0, &num_rparam,
3044 &rdata, 0, &num_rdata);
3045 TALLOC_FREE(subreq);
3046 state->status = status;
3047 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
3048 status = NT_STATUS_OK;
3050 if (tevent_req_nterror(req, status)) {
3051 return;
3054 if (num_rparam == 2) {
3055 state->enc_ctx_id = SVAL(rparam, 0);
3057 TALLOC_FREE(rparam);
3059 state->out = data_blob_const(rdata, num_rdata);
3061 tevent_req_done(req);
3064 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
3065 TALLOC_CTX *mem_ctx,
3066 DATA_BLOB *out,
3067 uint16_t *enc_ctx_id)
3069 struct cli_smb1_setup_encryption_blob_state *state =
3070 tevent_req_data(req,
3071 struct cli_smb1_setup_encryption_blob_state);
3072 NTSTATUS status;
3074 if (tevent_req_is_nterror(req, &status)) {
3075 tevent_req_received(req);
3076 return status;
3079 status = state->status;
3081 *out = state->out;
3082 talloc_steal(mem_ctx, out->data);
3084 *enc_ctx_id = state->enc_ctx_id;
3086 tevent_req_received(req);
3087 return status;
3090 struct cli_smb1_setup_encryption_state {
3091 struct tevent_context *ev;
3092 struct cli_state *cli;
3093 struct smb_trans_enc_state *es;
3094 DATA_BLOB blob_in;
3095 DATA_BLOB blob_out;
3096 bool local_ready;
3097 bool remote_ready;
3100 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
3101 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
3102 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
3103 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
3104 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
3106 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
3107 struct tevent_context *ev,
3108 struct cli_state *cli,
3109 struct cli_credentials *creds)
3111 struct tevent_req *req = NULL;
3112 struct cli_smb1_setup_encryption_state *state = NULL;
3113 struct auth_generic_state *ags = NULL;
3114 const DATA_BLOB *b = NULL;
3115 bool auth_requested = false;
3116 const char *target_service = NULL;
3117 const char *target_hostname = NULL;
3118 NTSTATUS status;
3120 req = tevent_req_create(mem_ctx, &state,
3121 struct cli_smb1_setup_encryption_state);
3122 if (req == NULL) {
3123 return NULL;
3125 state->ev = ev;
3126 state->cli = cli;
3128 auth_requested = cli_credentials_authentication_requested(creds);
3129 if (!auth_requested) {
3130 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3131 return tevent_req_post(req, ev);
3134 target_service = "cifs";
3135 target_hostname = smbXcli_conn_remote_name(cli->conn);
3137 status = cli_session_creds_prepare_krb5(cli, creds);
3138 if (tevent_req_nterror(req, status)) {
3139 return tevent_req_post(req, ev);
3142 state->es = talloc_zero(state, struct smb_trans_enc_state);
3143 if (tevent_req_nomem(state->es, req)) {
3144 return tevent_req_post(req, ev);
3147 status = auth_generic_client_prepare(state->es, &ags);
3148 if (tevent_req_nterror(req, status)) {
3149 return tevent_req_post(req, ev);
3152 gensec_want_feature(ags->gensec_security,
3153 GENSEC_FEATURE_SIGN);
3154 gensec_want_feature(ags->gensec_security,
3155 GENSEC_FEATURE_SEAL);
3157 status = auth_generic_set_creds(ags, creds);
3158 if (tevent_req_nterror(req, status)) {
3159 return tevent_req_post(req, ev);
3162 if (target_service != NULL) {
3163 status = gensec_set_target_service(ags->gensec_security,
3164 target_service);
3165 if (tevent_req_nterror(req, status)) {
3166 return tevent_req_post(req, ev);
3170 if (target_hostname != NULL) {
3171 status = gensec_set_target_hostname(ags->gensec_security,
3172 target_hostname);
3173 if (tevent_req_nterror(req, status)) {
3174 return tevent_req_post(req, ev);
3178 gensec_set_max_update_size(ags->gensec_security,
3179 CLI_BUFFER_SIZE);
3181 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3182 if (b != NULL) {
3183 state->blob_in = *b;
3186 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3187 if (tevent_req_nterror(req, status)) {
3188 return tevent_req_post(req, ev);
3192 * We only need the gensec_security part from here.
3194 state->es->gensec_security = talloc_move(state->es,
3195 &ags->gensec_security);
3196 TALLOC_FREE(ags);
3198 cli_smb1_setup_encryption_local_next(req);
3199 if (!tevent_req_is_in_progress(req)) {
3200 return tevent_req_post(req, ev);
3203 return req;
3206 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3208 struct cli_smb1_setup_encryption_state *state =
3209 tevent_req_data(req,
3210 struct cli_smb1_setup_encryption_state);
3211 struct tevent_req *subreq = NULL;
3213 if (state->local_ready) {
3214 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3215 return;
3218 subreq = gensec_update_send(state, state->ev,
3219 state->es->gensec_security,
3220 state->blob_in);
3221 if (tevent_req_nomem(subreq, req)) {
3222 return;
3224 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3227 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3229 struct tevent_req *req =
3230 tevent_req_callback_data(subreq,
3231 struct tevent_req);
3232 struct cli_smb1_setup_encryption_state *state =
3233 tevent_req_data(req,
3234 struct cli_smb1_setup_encryption_state);
3235 NTSTATUS status;
3237 status = gensec_update_recv(subreq, state, &state->blob_out);
3238 TALLOC_FREE(subreq);
3239 state->blob_in = data_blob_null;
3240 if (!NT_STATUS_IS_OK(status) &&
3241 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3243 tevent_req_nterror(req, status);
3244 return;
3247 if (NT_STATUS_IS_OK(status)) {
3248 state->local_ready = true;
3252 * We always get NT_STATUS_OK from the server even if it is not ready.
3253 * So guess the server is ready when we are ready and already sent
3254 * our last blob to the server.
3256 if (state->local_ready && state->blob_out.length == 0) {
3257 state->remote_ready = true;
3260 if (state->local_ready && state->remote_ready) {
3261 cli_smb1_setup_encryption_ready(req);
3262 return;
3265 cli_smb1_setup_encryption_remote_next(req);
3268 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3270 struct cli_smb1_setup_encryption_state *state =
3271 tevent_req_data(req,
3272 struct cli_smb1_setup_encryption_state);
3273 struct tevent_req *subreq = NULL;
3275 if (state->remote_ready) {
3276 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3277 return;
3280 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3281 state->cli, state->blob_out);
3282 if (tevent_req_nomem(subreq, req)) {
3283 return;
3285 tevent_req_set_callback(subreq,
3286 cli_smb1_setup_encryption_remote_done,
3287 req);
3290 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3292 struct tevent_req *req =
3293 tevent_req_callback_data(subreq,
3294 struct tevent_req);
3295 struct cli_smb1_setup_encryption_state *state =
3296 tevent_req_data(req,
3297 struct cli_smb1_setup_encryption_state);
3298 NTSTATUS status;
3300 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3301 &state->blob_in,
3302 &state->es->enc_ctx_num);
3303 TALLOC_FREE(subreq);
3304 data_blob_free(&state->blob_out);
3305 if (!NT_STATUS_IS_OK(status) &&
3306 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3308 tevent_req_nterror(req, status);
3309 return;
3313 * We always get NT_STATUS_OK even if the server is not ready.
3314 * So guess the server is ready when we are ready and sent
3315 * our last blob to the server.
3317 if (state->local_ready) {
3318 state->remote_ready = true;
3321 if (state->local_ready && state->remote_ready) {
3322 cli_smb1_setup_encryption_ready(req);
3323 return;
3326 cli_smb1_setup_encryption_local_next(req);
3329 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3331 struct cli_smb1_setup_encryption_state *state =
3332 tevent_req_data(req,
3333 struct cli_smb1_setup_encryption_state);
3334 struct smb_trans_enc_state *es = NULL;
3336 if (state->blob_in.length != 0) {
3337 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3338 return;
3341 if (state->blob_out.length != 0) {
3342 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3343 return;
3346 es = talloc_move(state->cli->conn, &state->es);
3347 es->enc_on = true;
3348 smb1cli_conn_set_encryption(state->cli->conn, es);
3349 es = NULL;
3351 tevent_req_done(req);
3354 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3356 return tevent_req_simple_recv_ntstatus(req);
3359 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3360 struct cli_credentials *creds)
3362 struct tevent_context *ev = NULL;
3363 struct tevent_req *req = NULL;
3364 NTSTATUS status = NT_STATUS_NO_MEMORY;
3366 ev = samba_tevent_context_init(talloc_tos());
3367 if (ev == NULL) {
3368 goto fail;
3370 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3371 if (req == NULL) {
3372 goto fail;
3374 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3375 goto fail;
3377 status = cli_smb1_setup_encryption_recv(req);
3378 fail:
3379 TALLOC_FREE(ev);
3380 return status;
3384 establishes a connection right up to doing tconX, password specified.
3385 @param output_cli A fully initialised cli structure, non-null only on success
3386 @param dest_host The netbios name of the remote host
3387 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3388 @param port (optional) The destination port (0 for default)
3389 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3390 @param service_type The 'type' of serivice.
3391 @param creds The used user credentials
3394 struct cli_full_connection_creds_state {
3395 struct tevent_context *ev;
3396 const char *service;
3397 const char *service_type;
3398 struct cli_credentials *creds;
3399 int flags;
3400 struct cli_state *cli;
3403 static int cli_full_connection_creds_state_destructor(
3404 struct cli_full_connection_creds_state *s)
3406 if (s->cli != NULL) {
3407 cli_shutdown(s->cli);
3408 s->cli = NULL;
3410 return 0;
3413 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3414 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3415 static void cli_full_connection_creds_enc_start(struct tevent_req *req);
3416 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq);
3417 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq);
3418 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq);
3419 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req);
3420 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq);
3421 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3422 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3424 struct tevent_req *cli_full_connection_creds_send(
3425 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3426 const char *my_name, const char *dest_host,
3427 const struct sockaddr_storage *dest_ss, int port,
3428 const char *service, const char *service_type,
3429 struct cli_credentials *creds,
3430 int flags,
3431 struct smb2_negotiate_contexts *negotiate_contexts)
3433 struct tevent_req *req, *subreq;
3434 struct cli_full_connection_creds_state *state;
3435 enum smb_signing_setting signing_state;
3436 enum smb_encryption_setting encryption_state =
3437 cli_credentials_get_smb_encryption(creds);
3439 req = tevent_req_create(mem_ctx, &state,
3440 struct cli_full_connection_creds_state);
3441 if (req == NULL) {
3442 return NULL;
3444 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3446 state->ev = ev;
3447 state->service = service;
3448 state->service_type = service_type;
3449 state->creds = creds;
3450 state->flags = flags;
3452 if (flags & CLI_FULL_CONNECTION_IPC) {
3453 signing_state = cli_credentials_get_smb_ipc_signing(creds);
3454 } else {
3455 signing_state = cli_credentials_get_smb_signing(creds);
3458 if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
3459 if (flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK) {
3460 encryption_state = SMB_ENCRYPTION_DESIRED;
3464 if (encryption_state >= SMB_ENCRYPTION_DESIRED) {
3465 signing_state = SMB_SIGNING_REQUIRED;
3468 subreq = cli_start_connection_send(
3469 state, ev, my_name, dest_host, dest_ss, port,
3470 signing_state, flags,
3471 negotiate_contexts);
3472 if (tevent_req_nomem(subreq, req)) {
3473 return tevent_req_post(req, ev);
3475 tevent_req_set_callback(subreq,
3476 cli_full_connection_creds_conn_done,
3477 req);
3478 return req;
3481 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3483 struct tevent_req *req = tevent_req_callback_data(
3484 subreq, struct tevent_req);
3485 struct cli_full_connection_creds_state *state = tevent_req_data(
3486 req, struct cli_full_connection_creds_state);
3487 NTSTATUS status;
3489 status = cli_start_connection_recv(subreq, &state->cli);
3490 TALLOC_FREE(subreq);
3491 if (tevent_req_nterror(req, status)) {
3492 return;
3495 subreq = cli_session_setup_creds_send(
3496 state, state->ev, state->cli, state->creds);
3497 if (tevent_req_nomem(subreq, req)) {
3498 return;
3500 tevent_req_set_callback(subreq,
3501 cli_full_connection_creds_sess_done,
3502 req);
3505 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3507 struct tevent_req *req = tevent_req_callback_data(
3508 subreq, struct tevent_req);
3509 struct cli_full_connection_creds_state *state = tevent_req_data(
3510 req, struct cli_full_connection_creds_state);
3511 NTSTATUS status;
3513 status = cli_session_setup_creds_recv(subreq);
3514 TALLOC_FREE(subreq);
3516 if (!NT_STATUS_IS_OK(status) &&
3517 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3519 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3521 state->creds = cli_credentials_init_anon(state);
3522 if (tevent_req_nomem(state->creds, req)) {
3523 return;
3526 subreq = cli_session_setup_creds_send(
3527 state, state->ev, state->cli, state->creds);
3528 if (tevent_req_nomem(subreq, req)) {
3529 return;
3531 tevent_req_set_callback(subreq,
3532 cli_full_connection_creds_sess_done,
3533 req);
3534 return;
3537 if (tevent_req_nterror(req, status)) {
3538 return;
3541 cli_full_connection_creds_enc_start(req);
3544 static void cli_full_connection_creds_enc_start(struct tevent_req *req)
3546 struct cli_full_connection_creds_state *state = tevent_req_data(
3547 req, struct cli_full_connection_creds_state);
3548 enum smb_encryption_setting encryption_state =
3549 cli_credentials_get_smb_encryption(state->creds);
3550 struct tevent_req *subreq = NULL;
3551 NTSTATUS status;
3553 if (encryption_state < SMB_ENCRYPTION_DESIRED) {
3554 cli_full_connection_creds_tcon_start(req);
3555 return;
3558 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3559 status = smb2cli_session_encryption_on(state->cli->smb2.session);
3560 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
3561 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3562 cli_full_connection_creds_tcon_start(req);
3563 return;
3565 d_printf("Encryption required and "
3566 "server doesn't support "
3567 "SMB3 encryption - failing connect\n");
3568 tevent_req_nterror(req, status);
3569 return;
3570 } else if (!NT_STATUS_IS_OK(status)) {
3571 d_printf("Encryption required and "
3572 "setup failed with error %s.\n",
3573 nt_errstr(status));
3574 tevent_req_nterror(req, status);
3575 return;
3578 cli_full_connection_creds_tcon_start(req);
3579 return;
3582 if (!SERVER_HAS_UNIX_CIFS(state->cli)) {
3583 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3584 cli_full_connection_creds_tcon_start(req);
3585 return;
3588 status = NT_STATUS_NOT_SUPPORTED;
3589 d_printf("Encryption required and "
3590 "server doesn't support "
3591 "SMB1 Unix Extensions - failing connect\n");
3592 tevent_req_nterror(req, status);
3593 return;
3597 * We do a tcon on IPC$ just to setup the encryption,
3598 * the real tcon will be encrypted then.
3600 subreq = cli_tree_connect_send(state, state->ev, state->cli,
3601 "IPC$", "IPC", NULL);
3602 if (tevent_req_nomem(subreq, req)) {
3603 return;
3605 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_tcon, req);
3608 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq)
3610 struct tevent_req *req = tevent_req_callback_data(
3611 subreq, struct tevent_req);
3612 struct cli_full_connection_creds_state *state = tevent_req_data(
3613 req, struct cli_full_connection_creds_state);
3614 NTSTATUS status;
3616 status = cli_tree_connect_recv(subreq);
3617 TALLOC_FREE(subreq);
3618 if (tevent_req_nterror(req, status)) {
3619 return;
3622 subreq = cli_unix_extensions_version_send(state, state->ev, state->cli);
3623 if (tevent_req_nomem(subreq, req)) {
3624 return;
3626 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_ver, req);
3629 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq)
3631 struct tevent_req *req = tevent_req_callback_data(
3632 subreq, struct tevent_req);
3633 struct cli_full_connection_creds_state *state = tevent_req_data(
3634 req, struct cli_full_connection_creds_state);
3635 enum smb_encryption_setting encryption_state =
3636 cli_credentials_get_smb_encryption(state->creds);
3637 uint16_t major, minor;
3638 uint32_t caplow, caphigh;
3639 NTSTATUS status;
3641 status = cli_unix_extensions_version_recv(subreq,
3642 &major, &minor,
3643 &caplow,
3644 &caphigh);
3645 TALLOC_FREE(subreq);
3646 if (!NT_STATUS_IS_OK(status)) {
3647 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3648 /* disconnect ipc$ followed by the real tree connect */
3649 cli_full_connection_creds_enc_tdis(req);
3650 return;
3652 DEBUG(10, ("%s: cli_unix_extensions_version "
3653 "returned %s\n", __func__, nt_errstr(status)));
3654 tevent_req_nterror(req, NT_STATUS_UNKNOWN_REVISION);
3655 return;
3658 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
3659 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3660 /* disconnect ipc$ followed by the real tree connect */
3661 cli_full_connection_creds_enc_tdis(req);
3662 return;
3664 DEBUG(10, ("%s: CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP "
3665 "not supported\n", __func__));
3666 tevent_req_nterror(req, NT_STATUS_UNSUPPORTED_COMPRESSION);
3667 return;
3670 subreq = cli_smb1_setup_encryption_send(state, state->ev,
3671 state->cli,
3672 state->creds);
3673 if (tevent_req_nomem(subreq, req)) {
3674 return;
3676 tevent_req_set_callback(subreq,
3677 cli_full_connection_creds_enc_done,
3678 req);
3681 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq)
3683 struct tevent_req *req = tevent_req_callback_data(
3684 subreq, struct tevent_req);
3685 NTSTATUS status;
3687 status = cli_smb1_setup_encryption_recv(subreq);
3688 TALLOC_FREE(subreq);
3689 if (tevent_req_nterror(req, status)) {
3690 return;
3693 /* disconnect ipc$ followed by the real tree connect */
3694 cli_full_connection_creds_enc_tdis(req);
3697 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req)
3699 struct cli_full_connection_creds_state *state = tevent_req_data(
3700 req, struct cli_full_connection_creds_state);
3701 struct tevent_req *subreq = NULL;
3703 subreq = cli_tdis_send(state, state->ev, state->cli);
3704 if (tevent_req_nomem(subreq, req)) {
3705 return;
3707 tevent_req_set_callback(subreq,
3708 cli_full_connection_creds_enc_finished,
3709 req);
3712 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq)
3714 struct tevent_req *req = tevent_req_callback_data(
3715 subreq, struct tevent_req);
3716 NTSTATUS status;
3718 status = cli_tdis_recv(subreq);
3719 TALLOC_FREE(subreq);
3720 if (tevent_req_nterror(req, status)) {
3721 return;
3724 cli_full_connection_creds_tcon_start(req);
3727 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3729 struct cli_full_connection_creds_state *state = tevent_req_data(
3730 req, struct cli_full_connection_creds_state);
3731 struct tevent_req *subreq = NULL;
3732 const char *password = NULL;
3734 if (state->service == NULL) {
3735 tevent_req_done(req);
3736 return;
3739 password = cli_credentials_get_password(state->creds);
3741 subreq = cli_tree_connect_send(state, state->ev,
3742 state->cli,
3743 state->service,
3744 state->service_type,
3745 password);
3746 if (tevent_req_nomem(subreq, req)) {
3747 return;
3749 tevent_req_set_callback(subreq,
3750 cli_full_connection_creds_tcon_done,
3751 req);
3754 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3756 struct tevent_req *req = tevent_req_callback_data(
3757 subreq, struct tevent_req);
3758 NTSTATUS status;
3760 status = cli_tree_connect_recv(subreq);
3761 TALLOC_FREE(subreq);
3762 if (tevent_req_nterror(req, status)) {
3763 return;
3766 tevent_req_done(req);
3769 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3770 struct cli_state **output_cli)
3772 struct cli_full_connection_creds_state *state = tevent_req_data(
3773 req, struct cli_full_connection_creds_state);
3774 NTSTATUS status;
3776 if (tevent_req_is_nterror(req, &status)) {
3777 return status;
3779 *output_cli = state->cli;
3780 talloc_set_destructor(state, NULL);
3781 return NT_STATUS_OK;
3784 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3785 const char *my_name,
3786 const char *dest_host,
3787 const struct sockaddr_storage *dest_ss, int port,
3788 const char *service, const char *service_type,
3789 struct cli_credentials *creds,
3790 int flags)
3792 struct tevent_context *ev;
3793 struct tevent_req *req;
3794 NTSTATUS status = NT_STATUS_NO_MEMORY;
3796 ev = samba_tevent_context_init(talloc_tos());
3797 if (ev == NULL) {
3798 goto fail;
3800 req = cli_full_connection_creds_send(
3801 ev, ev, my_name, dest_host, dest_ss, port, service,
3802 service_type, creds, flags,
3803 NULL);
3804 if (req == NULL) {
3805 goto fail;
3807 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3808 goto fail;
3810 status = cli_full_connection_creds_recv(req, output_cli);
3811 fail:
3812 TALLOC_FREE(ev);
3813 return status;
3816 /****************************************************************************
3817 Send an old style tcon.
3818 ****************************************************************************/
3819 struct cli_raw_tcon_state {
3820 uint16_t *ret_vwv;
3823 static void cli_raw_tcon_done(struct tevent_req *subreq);
3825 static struct tevent_req *cli_raw_tcon_send(
3826 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3827 const char *service, const char *pass, const char *dev)
3829 struct tevent_req *req, *subreq;
3830 struct cli_raw_tcon_state *state;
3831 uint8_t *bytes;
3833 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3834 if (req == NULL) {
3835 return NULL;
3838 if (!lp_client_plaintext_auth() && (*pass)) {
3839 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3840 " or 'client ntlmv2 auth = yes'\n"));
3841 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3842 return tevent_req_post(req, ev);
3845 TALLOC_FREE(cli->smb1.tcon);
3846 cli->smb1.tcon = smbXcli_tcon_create(cli);
3847 if (tevent_req_nomem(cli->smb1.tcon, req)) {
3848 return tevent_req_post(req, ev);
3850 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
3852 bytes = talloc_array(state, uint8_t, 0);
3853 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3854 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3855 service, strlen(service)+1, NULL);
3856 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3857 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3858 pass, strlen(pass)+1, NULL);
3859 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3860 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3861 dev, strlen(dev)+1, NULL);
3863 if (tevent_req_nomem(bytes, req)) {
3864 return tevent_req_post(req, ev);
3867 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3868 talloc_get_size(bytes), bytes);
3869 if (tevent_req_nomem(subreq, req)) {
3870 return tevent_req_post(req, ev);
3872 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3873 return req;
3876 static void cli_raw_tcon_done(struct tevent_req *subreq)
3878 struct tevent_req *req = tevent_req_callback_data(
3879 subreq, struct tevent_req);
3880 struct cli_raw_tcon_state *state = tevent_req_data(
3881 req, struct cli_raw_tcon_state);
3882 NTSTATUS status;
3884 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3885 NULL, NULL);
3886 TALLOC_FREE(subreq);
3887 if (tevent_req_nterror(req, status)) {
3888 return;
3890 tevent_req_done(req);
3893 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3894 uint16_t *max_xmit, uint16_t *tid)
3896 struct cli_raw_tcon_state *state = tevent_req_data(
3897 req, struct cli_raw_tcon_state);
3898 NTSTATUS status;
3900 if (tevent_req_is_nterror(req, &status)) {
3901 return status;
3903 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3904 *tid = SVAL(state->ret_vwv + 1, 0);
3905 return NT_STATUS_OK;
3908 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3909 const char *service, const char *pass, const char *dev,
3910 uint16_t *max_xmit, uint16_t *tid)
3912 struct tevent_context *ev;
3913 struct tevent_req *req;
3914 NTSTATUS status = NT_STATUS_NO_MEMORY;
3916 ev = samba_tevent_context_init(talloc_tos());
3917 if (ev == NULL) {
3918 goto fail;
3920 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3921 if (req == NULL) {
3922 goto fail;
3924 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3925 goto fail;
3927 status = cli_raw_tcon_recv(req, max_xmit, tid);
3928 fail:
3929 TALLOC_FREE(ev);
3930 return status;
3933 /* Return a cli_state pointing at the IPC$ share for the given server */
3935 struct cli_state *get_ipc_connect(char *server,
3936 struct sockaddr_storage *server_ss,
3937 struct cli_credentials *creds)
3939 struct cli_state *cli;
3940 NTSTATUS nt_status;
3941 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3943 flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
3944 flags |= CLI_FULL_CONNECTION_IPC;
3946 nt_status = cli_full_connection_creds(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3947 creds,
3948 flags);
3950 if (NT_STATUS_IS_OK(nt_status)) {
3951 return cli;
3953 if (is_ipaddress(server)) {
3954 /* windows 9* needs a correct NMB name for connections */
3955 fstring remote_name;
3957 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3958 cli = get_ipc_connect(remote_name, server_ss, creds);
3959 if (cli)
3960 return cli;
3963 return NULL;
3967 * Given the IP address of a master browser on the network, return its
3968 * workgroup and connect to it.
3970 * This function is provided to allow additional processing beyond what
3971 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3972 * browsers and obtain each master browsers' list of domains (in case the
3973 * first master browser is recently on the network and has not yet
3974 * synchronized with other master browsers and therefore does not yet have the
3975 * entire network browse list)
3978 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3979 struct sockaddr_storage *mb_ip,
3980 struct cli_credentials *creds,
3981 char **pp_workgroup_out)
3983 char addr[INET6_ADDRSTRLEN];
3984 fstring name;
3985 struct cli_state *cli;
3986 struct sockaddr_storage server_ss;
3988 *pp_workgroup_out = NULL;
3990 print_sockaddr(addr, sizeof(addr), mb_ip);
3991 DEBUG(99, ("Looking up name of master browser %s\n",
3992 addr));
3995 * Do a name status query to find out the name of the master browser.
3996 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3997 * master browser will not respond to a wildcard query (or, at least,
3998 * an NT4 server acting as the domain master browser will not).
4000 * We might be able to use ONLY the query on MSBROWSE, but that's not
4001 * yet been tested with all Windows versions, so until it is, leave
4002 * the original wildcard query as the first choice and fall back to
4003 * MSBROWSE if the wildcard query fails.
4005 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
4006 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
4008 DEBUG(99, ("Could not retrieve name status for %s\n",
4009 addr));
4010 return NULL;
4013 if (!find_master_ip(name, &server_ss)) {
4014 DEBUG(99, ("Could not find master ip for %s\n", name));
4015 return NULL;
4018 *pp_workgroup_out = talloc_strdup(ctx, name);
4020 DEBUG(4, ("found master browser %s, %s\n", name, addr));
4022 print_sockaddr(addr, sizeof(addr), &server_ss);
4023 cli = get_ipc_connect(addr, &server_ss, creds);
4025 return cli;