s3:idmap_ad: add support for ADS_AUTH_SASL_{STARTTLS,LDAPS}
[Samba.git] / source3 / libsmb / cliconnect.c
blobb8f06330260f75fceb6b4233dbcc2494b875a44b
1 /*
2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
6 Copyright (C) Volker Lendecke 2011
7 Copyright (C) Jeremy Allison 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "libsmb/libsmb.h"
25 #include "libsmb/namequery.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "smb_krb5.h"
28 #include "auth/credentials/credentials.h"
29 #include "auth/gensec/gensec.h"
30 #include "auth/ntlmssp/ntlmssp.h"
31 #include "auth_generic.h"
32 #include "libads/kerberos_proto.h"
33 #include "krb5_env.h"
34 #include "../lib/util/tevent_ntstatus.h"
35 #include "async_smb.h"
36 #include "libsmb/nmblib.h"
37 #include "librpc/ndr/libndr.h"
38 #include "../libcli/smb/smbXcli_base.h"
39 #include "../libcli/smb/smb_seal.h"
40 #include "lib/param/param.h"
41 #include "../libcli/smb/smb2_negotiate_context.h"
43 #define STAR_SMBSERVER "*SMBSERVER"
45 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
46 const char *principal);
48 struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
49 const char *username,
50 const char *domain,
51 const char *realm,
52 const char *password,
53 bool use_kerberos,
54 bool fallback_after_kerberos,
55 bool use_ccache,
56 bool password_is_nt_hash)
58 struct loadparm_context *lp_ctx = NULL;
59 struct cli_credentials *creds = NULL;
60 const char *principal = NULL;
61 char *tmp = NULL;
62 char *p = NULL;
63 bool ok;
65 creds = cli_credentials_init(mem_ctx);
66 if (creds == NULL) {
67 return NULL;
70 lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
71 if (lp_ctx == NULL) {
72 goto fail;
74 ok = cli_credentials_set_conf(creds, lp_ctx);
75 if (!ok) {
76 goto fail;
79 if (username == NULL) {
80 username = "";
83 if (strlen(username) == 0) {
84 if (password != NULL && strlen(password) == 0) {
86 * some callers pass "" as no password
88 * gensec only handles NULL as no password.
90 password = NULL;
92 if (password == NULL) {
93 cli_credentials_set_anonymous(creds);
94 return creds;
98 tmp = talloc_strdup(creds, username);
99 if (tmp == NULL) {
100 goto fail;
102 username = tmp;
104 /* allow for workgroups as part of the username */
105 if ((p = strchr_m(tmp, '\\')) ||
106 (p = strchr_m(tmp, '/')) ||
107 (p = strchr_m(tmp, *lp_winbind_separator()))) {
108 *p = 0;
109 username = p + 1;
110 domain = tmp;
113 principal = username;
114 username = cli_session_setup_get_account(creds, principal);
115 if (username == NULL) {
116 goto fail;
118 ok = strequal(username, principal);
119 if (ok) {
121 * Ok still the same, so it's not a principal
123 principal = NULL;
126 if (use_kerberos && fallback_after_kerberos) {
127 cli_credentials_set_kerberos_state(creds,
128 CRED_USE_KERBEROS_DESIRED,
129 CRED_SPECIFIED);
130 } else if (use_kerberos) {
131 cli_credentials_set_kerberos_state(creds,
132 CRED_USE_KERBEROS_REQUIRED,
133 CRED_SPECIFIED);
134 } else {
135 cli_credentials_set_kerberos_state(creds,
136 CRED_USE_KERBEROS_DISABLED,
137 CRED_SPECIFIED);
140 if (use_ccache) {
141 uint32_t features;
143 features = cli_credentials_get_gensec_features(creds);
144 features |= GENSEC_FEATURE_NTLM_CCACHE;
145 cli_credentials_set_gensec_features(creds,
146 features,
147 CRED_SPECIFIED);
149 if (password != NULL && strlen(password) == 0) {
151 * some callers pass "" as no password
153 * GENSEC_FEATURE_NTLM_CCACHE only handles
154 * NULL as no password.
156 password = NULL;
160 ok = cli_credentials_set_username(creds,
161 username,
162 CRED_SPECIFIED);
163 if (!ok) {
164 goto fail;
167 if (domain != NULL) {
168 ok = cli_credentials_set_domain(creds,
169 domain,
170 CRED_SPECIFIED);
171 if (!ok) {
172 goto fail;
176 if (principal != NULL) {
177 ok = cli_credentials_set_principal(creds,
178 principal,
179 CRED_SPECIFIED);
180 if (!ok) {
181 goto fail;
185 if (realm != NULL) {
186 ok = cli_credentials_set_realm(creds,
187 realm,
188 CRED_SPECIFIED);
189 if (!ok) {
190 goto fail;
194 if (password != NULL && strlen(password) > 0) {
195 if (password_is_nt_hash) {
196 struct samr_Password nt_hash;
197 size_t converted;
199 converted = strhex_to_str((char *)nt_hash.hash,
200 sizeof(nt_hash.hash),
201 password,
202 strlen(password));
203 if (converted != sizeof(nt_hash.hash)) {
204 goto fail;
207 ok = cli_credentials_set_nt_hash(creds,
208 &nt_hash,
209 CRED_SPECIFIED);
210 if (!ok) {
211 goto fail;
213 } else {
214 ok = cli_credentials_set_password(creds,
215 password,
216 CRED_SPECIFIED);
217 if (!ok) {
218 goto fail;
223 return creds;
224 fail:
225 TALLOC_FREE(creds);
226 return NULL;
229 NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
230 struct cli_credentials *creds)
232 TALLOC_CTX *frame = talloc_stackframe();
233 const char *user_principal = NULL;
234 const char *user_account = NULL;
235 const char *user_domain = NULL;
236 const char *pass = NULL;
237 char *canon_principal = NULL;
238 char *canon_realm = NULL;
239 const char *target_hostname = NULL;
240 enum credentials_use_kerberos krb5_state;
241 bool try_kerberos = false;
242 bool need_kinit = false;
243 bool auth_requested = true;
244 int ret;
245 bool ok;
247 target_hostname = smbXcli_conn_remote_name(cli->conn);
249 auth_requested = cli_credentials_authentication_requested(creds);
250 if (auth_requested) {
251 errno = 0;
252 user_principal = cli_credentials_get_principal(creds, frame);
253 if (errno != 0) {
254 TALLOC_FREE(frame);
255 return NT_STATUS_NO_MEMORY;
258 user_account = cli_credentials_get_username(creds);
259 user_domain = cli_credentials_get_domain(creds);
260 pass = cli_credentials_get_password(creds);
262 krb5_state = cli_credentials_get_kerberos_state(creds);
264 if (krb5_state != CRED_USE_KERBEROS_DISABLED) {
265 try_kerberos = true;
268 if (user_principal == NULL) {
269 try_kerberos = false;
272 if (target_hostname == NULL) {
273 try_kerberos = false;
274 } else if (is_ipaddress(target_hostname)) {
275 try_kerberos = false;
276 } else if (strequal(target_hostname, "localhost")) {
277 try_kerberos = false;
278 } else if (strequal(target_hostname, STAR_SMBSERVER)) {
279 try_kerberos = false;
280 } else if (!auth_requested) {
281 try_kerberos = false;
284 if (krb5_state == CRED_USE_KERBEROS_REQUIRED && !try_kerberos) {
285 DEBUG(0, ("Kerberos auth with '%s' (%s\\%s) to access "
286 "'%s' not possible\n",
287 user_principal, user_domain, user_account,
288 target_hostname));
289 TALLOC_FREE(frame);
290 return NT_STATUS_ACCESS_DENIED;
293 if (pass == NULL || strlen(pass) == 0) {
294 need_kinit = false;
295 } else if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
296 need_kinit = try_kerberos;
297 } else {
298 need_kinit = try_kerberos;
301 if (!need_kinit) {
302 TALLOC_FREE(frame);
303 return NT_STATUS_OK;
306 DBG_INFO("Doing kinit for %s to access %s\n",
307 user_principal, target_hostname);
310 * TODO: This should be done within the gensec layer
311 * only if required!
313 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
314 ret = kerberos_kinit_password_ext(user_principal,
315 pass,
319 NULL,
320 false,
321 false,
323 frame,
324 &canon_principal,
325 &canon_realm,
326 NULL);
327 if (ret != 0) {
328 int dbglvl = DBGLVL_NOTICE;
330 if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
331 dbglvl = DBGLVL_ERR;
334 DEBUG(dbglvl, ("Kinit for %s to access %s failed: %s\n",
335 user_principal, target_hostname,
336 error_message(ret)));
337 if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
338 TALLOC_FREE(frame);
339 return krb5_to_nt_status(ret);
343 * Ignore the error and hope that NTLM will work
345 TALLOC_FREE(frame);
346 return NT_STATUS_OK;
349 ok = cli_credentials_set_principal(creds,
350 canon_principal,
351 CRED_SPECIFIED);
352 if (!ok) {
353 TALLOC_FREE(frame);
354 return NT_STATUS_NO_MEMORY;
357 ok = cli_credentials_set_realm(creds,
358 canon_realm,
359 CRED_SPECIFIED);
360 if (!ok) {
361 TALLOC_FREE(frame);
362 return NT_STATUS_NO_MEMORY;
365 DBG_DEBUG("Successfully authenticated as %s (%s) to access %s using "
366 "Kerberos\n",
367 user_principal,
368 canon_principal,
369 target_hostname);
371 TALLOC_FREE(frame);
372 return NT_STATUS_OK;
375 static NTSTATUS cli_state_update_after_sesssetup(struct cli_state *cli,
376 const char *native_os,
377 const char *native_lm,
378 const char *primary_domain)
380 #define _VALID_STR(p) ((p) != NULL && (p)[0] != '\0')
382 if (!_VALID_STR(cli->server_os) && _VALID_STR(native_os)) {
383 cli->server_os = talloc_strdup(cli, native_os);
384 if (cli->server_os == NULL) {
385 return NT_STATUS_NO_MEMORY;
389 if (!_VALID_STR(cli->server_type) && _VALID_STR(native_lm)) {
390 cli->server_type = talloc_strdup(cli, native_lm);
391 if (cli->server_type == NULL) {
392 return NT_STATUS_NO_MEMORY;
396 if (!_VALID_STR(cli->server_domain) && _VALID_STR(primary_domain)) {
397 cli->server_domain = talloc_strdup(cli, primary_domain);
398 if (cli->server_domain == NULL) {
399 return NT_STATUS_NO_MEMORY;
403 #undef _VALID_STRING
404 return NT_STATUS_OK;
407 /********************************************************
408 Utility function to ensure we always return at least
409 a valid char * pointer to an empty string for the
410 cli->server_os, cli->server_type and cli->server_domain
411 strings.
412 *******************************************************/
414 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
415 const uint8_t *hdr,
416 char **dest,
417 uint8_t *src,
418 size_t srclen,
419 ssize_t *destlen)
421 *destlen = pull_string_talloc(mem_ctx,
422 (const char *)hdr,
423 SVAL(hdr, HDR_FLG2),
424 dest,
425 (char *)src,
426 srclen,
427 STR_TERMINATE);
428 if (*destlen == -1) {
429 return NT_STATUS_NO_MEMORY;
432 if (*dest == NULL) {
433 *dest = talloc_strdup(mem_ctx, "");
434 if (*dest == NULL) {
435 return NT_STATUS_NO_MEMORY;
438 return NT_STATUS_OK;
441 /****************************************************************************
442 Work out suitable capabilities to offer the server.
443 ****************************************************************************/
445 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
446 uint32_t sesssetup_capabilities)
448 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
451 * We only send capabilities based on the mask for:
452 * - client only flags
453 * - flags used in both directions
455 * We do not echo the server only flags, except some legacy flags.
457 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
458 * CAP_LARGE_WRITEX in order to allow us to do large reads
459 * against old Samba releases (<= 3.6.x).
461 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
464 * Session Setup specific flags CAP_DYNAMIC_REAUTH
465 * and CAP_EXTENDED_SECURITY are passed by the caller.
466 * We need that in order to do guest logins even if
467 * CAP_EXTENDED_SECURITY is negotiated.
469 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
470 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
471 client_capabilities |= sesssetup_capabilities;
473 return client_capabilities;
476 /****************************************************************************
477 Do a NT1 guest session setup.
478 ****************************************************************************/
480 struct cli_session_setup_guest_state {
481 struct cli_state *cli;
482 uint16_t vwv[13];
483 struct iovec bytes;
486 static void cli_session_setup_guest_done(struct tevent_req *subreq);
488 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
489 struct tevent_context *ev,
490 struct cli_state *cli,
491 struct tevent_req **psmbreq)
493 struct tevent_req *req, *subreq;
494 struct cli_session_setup_guest_state *state;
495 uint16_t *vwv;
496 uint8_t *bytes;
498 req = tevent_req_create(mem_ctx, &state,
499 struct cli_session_setup_guest_state);
500 if (req == NULL) {
501 return NULL;
503 state->cli = cli;
504 vwv = state->vwv;
506 SCVAL(vwv+0, 0, 0xFF);
507 SCVAL(vwv+0, 1, 0);
508 SSVAL(vwv+1, 0, 0);
509 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
510 SSVAL(vwv+3, 0, 2);
511 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
512 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
513 SSVAL(vwv+7, 0, 0);
514 SSVAL(vwv+8, 0, 0);
515 SSVAL(vwv+9, 0, 0);
516 SSVAL(vwv+10, 0, 0);
517 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
519 bytes = talloc_array(state, uint8_t, 0);
521 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
522 NULL);
523 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
524 NULL);
525 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
526 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
528 if (bytes == NULL) {
529 TALLOC_FREE(req);
530 return NULL;
533 state->bytes.iov_base = (void *)bytes;
534 state->bytes.iov_len = talloc_get_size(bytes);
536 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
537 vwv, 1, &state->bytes);
538 if (subreq == NULL) {
539 TALLOC_FREE(req);
540 return NULL;
542 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
543 *psmbreq = subreq;
544 return req;
547 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
548 struct tevent_context *ev,
549 struct cli_state *cli)
551 struct tevent_req *req, *subreq;
552 NTSTATUS status;
554 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
555 if (req == NULL) {
556 return NULL;
559 status = smb1cli_req_chain_submit(&subreq, 1);
560 if (!NT_STATUS_IS_OK(status)) {
561 tevent_req_nterror(req, status);
562 return tevent_req_post(req, ev);
564 return req;
567 static void cli_session_setup_guest_done(struct tevent_req *subreq)
569 struct tevent_req *req = tevent_req_callback_data(
570 subreq, struct tevent_req);
571 struct cli_session_setup_guest_state *state = tevent_req_data(
572 req, struct cli_session_setup_guest_state);
573 struct cli_state *cli = state->cli;
574 uint32_t num_bytes;
575 uint8_t *in;
576 uint8_t *inhdr;
577 uint8_t *bytes;
578 uint8_t *p;
579 NTSTATUS status;
580 ssize_t ret;
581 uint8_t wct;
582 uint16_t *vwv;
584 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
585 &num_bytes, &bytes);
586 TALLOC_FREE(subreq);
587 if (!NT_STATUS_IS_OK(status)) {
588 tevent_req_nterror(req, status);
589 return;
592 inhdr = in + NBT_HDR_SIZE;
593 p = bytes;
595 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
596 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
598 status = smb_bytes_talloc_string(cli,
599 inhdr,
600 &cli->server_os,
602 bytes+num_bytes-p,
603 &ret);
605 if (!NT_STATUS_IS_OK(status)) {
606 tevent_req_nterror(req, status);
607 return;
609 p += ret;
611 status = smb_bytes_talloc_string(cli,
612 inhdr,
613 &cli->server_type,
615 bytes+num_bytes-p,
616 &ret);
618 if (!NT_STATUS_IS_OK(status)) {
619 tevent_req_nterror(req, status);
620 return;
622 p += ret;
624 status = smb_bytes_talloc_string(cli,
625 inhdr,
626 &cli->server_domain,
628 bytes+num_bytes-p,
629 &ret);
631 if (!NT_STATUS_IS_OK(status)) {
632 tevent_req_nterror(req, status);
633 return;
636 tevent_req_done(req);
639 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
641 return tevent_req_simple_recv_ntstatus(req);
644 /* The following is calculated from :
645 * (smb_size-4) = 35
646 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
647 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
648 * end of packet.
651 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
653 struct cli_sesssetup_blob_state {
654 struct tevent_context *ev;
655 struct cli_state *cli;
656 DATA_BLOB blob;
657 uint16_t max_blob_size;
659 DATA_BLOB this_blob;
660 struct iovec *recv_iov;
662 NTSTATUS status;
663 const uint8_t *inbuf;
664 DATA_BLOB ret_blob;
666 char *out_native_os;
667 char *out_native_lm;
670 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
671 struct tevent_req **psubreq);
672 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
674 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
675 struct tevent_context *ev,
676 struct cli_state *cli,
677 DATA_BLOB blob)
679 struct tevent_req *req, *subreq;
680 struct cli_sesssetup_blob_state *state;
681 uint32_t usable_space;
683 req = tevent_req_create(mem_ctx, &state,
684 struct cli_sesssetup_blob_state);
685 if (req == NULL) {
686 return NULL;
688 state->ev = ev;
689 state->blob = blob;
690 state->cli = cli;
692 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
693 usable_space = UINT16_MAX;
694 } else {
695 usable_space = cli_state_available_size(cli,
696 BASE_SESSSETUP_BLOB_PACKET_SIZE);
699 if (usable_space == 0) {
700 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
701 "(not possible to send %u bytes)\n",
702 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
703 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
704 return tevent_req_post(req, ev);
706 state->max_blob_size = MIN(usable_space, 0xFFFF);
708 if (!cli_sesssetup_blob_next(state, &subreq)) {
709 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
710 return tevent_req_post(req, ev);
712 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
713 return req;
716 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
717 struct tevent_req **psubreq)
719 struct tevent_req *subreq;
720 uint16_t thistime;
722 thistime = MIN(state->blob.length, state->max_blob_size);
724 state->this_blob.data = state->blob.data;
725 state->this_blob.length = thistime;
727 state->blob.data += thistime;
728 state->blob.length -= thistime;
730 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
731 subreq = smb2cli_session_setup_send(state, state->ev,
732 state->cli->conn,
733 state->cli->timeout,
734 state->cli->smb2.session,
735 0, /* in_flags */
736 SMB2_CAP_DFS, /* in_capabilities */
737 0, /* in_channel */
738 0, /* in_previous_session_id */
739 &state->this_blob);
740 if (subreq == NULL) {
741 return false;
743 } else {
744 uint16_t in_buf_size = 0;
745 uint16_t in_mpx_max = 0;
746 uint16_t in_vc_num = 0;
747 uint32_t in_sess_key = 0;
748 uint32_t in_capabilities = 0;
749 const char *in_native_os = NULL;
750 const char *in_native_lm = NULL;
752 in_buf_size = CLI_BUFFER_SIZE;
753 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
754 in_vc_num = cli_state_get_vc_num(state->cli);
755 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
756 in_capabilities = cli_session_setup_capabilities(state->cli,
757 CAP_EXTENDED_SECURITY);
758 in_native_os = "Unix";
759 in_native_lm = "Samba";
762 * For now we keep the same values as before,
763 * we may remove these in a separate commit later.
765 in_mpx_max = 2;
766 in_vc_num = 1;
767 in_sess_key = 0;
769 subreq = smb1cli_session_setup_ext_send(state, state->ev,
770 state->cli->conn,
771 state->cli->timeout,
772 state->cli->smb1.pid,
773 state->cli->smb1.session,
774 in_buf_size,
775 in_mpx_max,
776 in_vc_num,
777 in_sess_key,
778 state->this_blob,
779 in_capabilities,
780 in_native_os,
781 in_native_lm);
782 if (subreq == NULL) {
783 return false;
786 *psubreq = subreq;
787 return true;
790 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
792 struct tevent_req *req = tevent_req_callback_data(
793 subreq, struct tevent_req);
794 struct cli_sesssetup_blob_state *state = tevent_req_data(
795 req, struct cli_sesssetup_blob_state);
796 NTSTATUS status;
798 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
799 status = smb2cli_session_setup_recv(subreq, state,
800 &state->recv_iov,
801 &state->ret_blob);
802 } else {
803 status = smb1cli_session_setup_ext_recv(subreq, state,
804 &state->recv_iov,
805 &state->inbuf,
806 &state->ret_blob,
807 &state->out_native_os,
808 &state->out_native_lm);
810 TALLOC_FREE(subreq);
811 if (!NT_STATUS_IS_OK(status)
812 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
813 tevent_req_nterror(req, status);
814 return;
817 state->status = status;
819 status = cli_state_update_after_sesssetup(state->cli,
820 state->out_native_os,
821 state->out_native_lm,
822 NULL);
823 if (tevent_req_nterror(req, status)) {
824 return;
827 if (state->blob.length != 0) {
829 * More to send
831 if (!cli_sesssetup_blob_next(state, &subreq)) {
832 tevent_req_oom(req);
833 return;
835 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
836 return;
838 tevent_req_done(req);
841 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
842 TALLOC_CTX *mem_ctx,
843 DATA_BLOB *pblob,
844 const uint8_t **pinbuf,
845 struct iovec **precv_iov)
847 struct cli_sesssetup_blob_state *state = tevent_req_data(
848 req, struct cli_sesssetup_blob_state);
849 NTSTATUS status;
850 struct iovec *recv_iov;
852 if (tevent_req_is_nterror(req, &status)) {
853 TALLOC_FREE(state->cli->smb2.session);
854 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
855 tevent_req_received(req);
856 return status;
859 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
860 if (pblob != NULL) {
861 *pblob = state->ret_blob;
863 if (pinbuf != NULL) {
864 *pinbuf = state->inbuf;
866 if (precv_iov != NULL) {
867 *precv_iov = recv_iov;
869 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
870 status = state->status;
871 tevent_req_received(req);
872 return status;
875 /****************************************************************************
876 Do a spnego/NTLMSSP encrypted session setup.
877 ****************************************************************************/
879 struct cli_session_setup_gensec_state {
880 struct tevent_context *ev;
881 struct cli_state *cli;
882 struct auth_generic_state *auth_generic;
883 bool is_anonymous;
884 DATA_BLOB blob_in;
885 const uint8_t *inbuf;
886 struct iovec *recv_iov;
887 DATA_BLOB blob_out;
888 bool local_ready;
889 bool remote_ready;
890 DATA_BLOB session_key;
893 static int cli_session_setup_gensec_state_destructor(
894 struct cli_session_setup_gensec_state *state)
896 TALLOC_FREE(state->auth_generic);
897 data_blob_clear_free(&state->session_key);
898 return 0;
901 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
902 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
903 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
904 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
905 static void cli_session_setup_gensec_ready(struct tevent_req *req);
907 static struct tevent_req *cli_session_setup_gensec_send(
908 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
909 struct cli_credentials *creds,
910 const char *target_service,
911 const char *target_hostname)
913 struct tevent_req *req;
914 struct cli_session_setup_gensec_state *state;
915 NTSTATUS status;
916 const DATA_BLOB *b = NULL;
918 req = tevent_req_create(mem_ctx, &state,
919 struct cli_session_setup_gensec_state);
920 if (req == NULL) {
921 return NULL;
923 state->ev = ev;
924 state->cli = cli;
926 talloc_set_destructor(
927 state, cli_session_setup_gensec_state_destructor);
929 status = auth_generic_client_prepare(state, &state->auth_generic);
930 if (tevent_req_nterror(req, status)) {
931 return tevent_req_post(req, ev);
934 status = auth_generic_set_creds(state->auth_generic, creds);
935 if (tevent_req_nterror(req, status)) {
936 return tevent_req_post(req, ev);
939 gensec_want_feature(state->auth_generic->gensec_security,
940 GENSEC_FEATURE_SESSION_KEY);
942 if (target_service != NULL) {
943 status = gensec_set_target_service(
944 state->auth_generic->gensec_security,
945 target_service);
946 if (tevent_req_nterror(req, status)) {
947 return tevent_req_post(req, ev);
951 if (target_hostname != NULL) {
952 status = gensec_set_target_hostname(
953 state->auth_generic->gensec_security,
954 target_hostname);
955 if (tevent_req_nterror(req, status)) {
956 return tevent_req_post(req, ev);
960 b = smbXcli_conn_server_gss_blob(cli->conn);
961 if (b != NULL) {
962 state->blob_in = *b;
965 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
967 status = auth_generic_client_start(state->auth_generic,
968 GENSEC_OID_SPNEGO);
969 if (tevent_req_nterror(req, status)) {
970 return tevent_req_post(req, ev);
973 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
974 state->cli->smb2.session = smbXcli_session_create(cli,
975 cli->conn);
976 if (tevent_req_nomem(state->cli->smb2.session, req)) {
977 return tevent_req_post(req, ev);
981 cli_session_setup_gensec_local_next(req);
982 if (!tevent_req_is_in_progress(req)) {
983 return tevent_req_post(req, ev);
986 return req;
989 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
991 struct cli_session_setup_gensec_state *state =
992 tevent_req_data(req,
993 struct cli_session_setup_gensec_state);
994 struct tevent_req *subreq = NULL;
996 if (state->local_ready) {
997 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
998 return;
1001 subreq = gensec_update_send(state, state->ev,
1002 state->auth_generic->gensec_security,
1003 state->blob_in);
1004 if (tevent_req_nomem(subreq, req)) {
1005 return;
1007 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1010 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1012 struct tevent_req *req =
1013 tevent_req_callback_data(subreq,
1014 struct tevent_req);
1015 struct cli_session_setup_gensec_state *state =
1016 tevent_req_data(req,
1017 struct cli_session_setup_gensec_state);
1018 NTSTATUS status;
1020 status = gensec_update_recv(subreq, state, &state->blob_out);
1021 TALLOC_FREE(subreq);
1022 state->blob_in = data_blob_null;
1023 if (!NT_STATUS_IS_OK(status) &&
1024 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1026 tevent_req_nterror(req, status);
1027 return;
1030 if (NT_STATUS_IS_OK(status)) {
1031 state->local_ready = true;
1034 if (state->local_ready && state->remote_ready) {
1035 cli_session_setup_gensec_ready(req);
1036 return;
1039 cli_session_setup_gensec_remote_next(req);
1042 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1044 struct cli_session_setup_gensec_state *state =
1045 tevent_req_data(req,
1046 struct cli_session_setup_gensec_state);
1047 struct tevent_req *subreq = NULL;
1049 if (state->remote_ready) {
1050 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1051 return;
1054 subreq = cli_sesssetup_blob_send(state, state->ev,
1055 state->cli, state->blob_out);
1056 if (tevent_req_nomem(subreq, req)) {
1057 return;
1059 tevent_req_set_callback(subreq,
1060 cli_session_setup_gensec_remote_done,
1061 req);
1064 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1066 struct tevent_req *req =
1067 tevent_req_callback_data(subreq,
1068 struct tevent_req);
1069 struct cli_session_setup_gensec_state *state =
1070 tevent_req_data(req,
1071 struct cli_session_setup_gensec_state);
1072 NTSTATUS status;
1074 state->inbuf = NULL;
1075 TALLOC_FREE(state->recv_iov);
1077 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1078 &state->inbuf, &state->recv_iov);
1079 TALLOC_FREE(subreq);
1080 data_blob_free(&state->blob_out);
1081 if (!NT_STATUS_IS_OK(status) &&
1082 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1084 tevent_req_nterror(req, status);
1085 return;
1088 if (NT_STATUS_IS_OK(status)) {
1089 struct smbXcli_session *session = NULL;
1090 bool is_guest = false;
1092 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1093 session = state->cli->smb2.session;
1094 } else {
1095 session = state->cli->smb1.session;
1098 is_guest = smbXcli_session_is_guest(session);
1099 if (is_guest) {
1101 * We can't finish the gensec handshake, we don't
1102 * have a negotiated session key.
1104 * So just pretend we are completely done,
1105 * we need to continue as anonymous from this point,
1106 * as we can't get a session key.
1108 * Note that smbXcli_session_is_guest()
1109 * always returns false if we require signing.
1111 state->blob_in = data_blob_null;
1112 state->local_ready = true;
1113 state->is_anonymous = true;
1116 state->remote_ready = true;
1119 if (state->local_ready && state->remote_ready) {
1120 cli_session_setup_gensec_ready(req);
1121 return;
1124 cli_session_setup_gensec_local_next(req);
1127 static void cli_session_dump_keys(TALLOC_CTX *mem_ctx,
1128 struct smbXcli_session *session,
1129 DATA_BLOB session_key)
1131 NTSTATUS status;
1132 DATA_BLOB sig = data_blob_null;
1133 DATA_BLOB app = data_blob_null;
1134 DATA_BLOB enc = data_blob_null;
1135 DATA_BLOB dec = data_blob_null;
1136 uint64_t sid = smb2cli_session_current_id(session);
1138 status = smb2cli_session_signing_key(session, mem_ctx, &sig);
1139 if (!NT_STATUS_IS_OK(status)) {
1140 goto out;
1142 status = smbXcli_session_application_key(session, mem_ctx, &app);
1143 if (!NT_STATUS_IS_OK(status)) {
1144 goto out;
1146 status = smb2cli_session_encryption_key(session, mem_ctx, &enc);
1147 if (!NT_STATUS_IS_OK(status)) {
1148 goto out;
1150 status = smb2cli_session_decryption_key(session, mem_ctx, &dec);
1151 if (!NT_STATUS_IS_OK(status)) {
1152 goto out;
1155 DEBUG(0, ("debug encryption: dumping generated session keys\n"));
1156 DEBUGADD(0, ("Session Id "));
1157 dump_data(0, (uint8_t*)&sid, sizeof(sid));
1158 DEBUGADD(0, ("Session Key "));
1159 dump_data(0, session_key.data, session_key.length);
1160 DEBUGADD(0, ("Signing Key "));
1161 dump_data(0, sig.data, sig.length);
1162 DEBUGADD(0, ("App Key "));
1163 dump_data(0, app.data, app.length);
1165 /* In client code, ServerIn is the encryption key */
1167 DEBUGADD(0, ("ServerIn Key "));
1168 dump_data(0, enc.data, enc.length);
1169 DEBUGADD(0, ("ServerOut Key "));
1170 dump_data(0, dec.data, dec.length);
1172 out:
1173 data_blob_clear_free(&sig);
1174 data_blob_clear_free(&app);
1175 data_blob_clear_free(&enc);
1176 data_blob_clear_free(&dec);
1179 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1181 struct cli_session_setup_gensec_state *state =
1182 tevent_req_data(req,
1183 struct cli_session_setup_gensec_state);
1184 const char *server_domain = NULL;
1185 NTSTATUS status;
1187 if (state->blob_in.length != 0) {
1188 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1189 return;
1192 if (state->blob_out.length != 0) {
1193 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1194 return;
1198 * gensec_ntlmssp_server_domain() returns NULL
1199 * if NTLMSSP is not used.
1201 * We can remove this later
1202 * and leave the server domain empty for SMB2 and above
1203 * in future releases.
1205 server_domain = gensec_ntlmssp_server_domain(
1206 state->auth_generic->gensec_security);
1208 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1209 TALLOC_FREE(state->cli->server_domain);
1210 state->cli->server_domain = talloc_strdup(state->cli,
1211 server_domain);
1212 if (state->cli->server_domain == NULL) {
1213 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1214 return;
1218 if (state->is_anonymous) {
1220 * Windows server does not set the
1221 * SMB2_SESSION_FLAG_IS_NULL flag.
1223 * This fix makes sure we do not try
1224 * to verify a signature on the final
1225 * session setup response.
1227 tevent_req_done(req);
1228 return;
1231 status = gensec_session_key(state->auth_generic->gensec_security,
1232 state, &state->session_key);
1233 if (tevent_req_nterror(req, status)) {
1234 return;
1237 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1238 struct smbXcli_session *session = state->cli->smb2.session;
1240 status = smb2cli_session_set_session_key(session,
1241 state->session_key,
1242 state->recv_iov);
1243 if (tevent_req_nterror(req, status)) {
1244 return;
1246 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB3_00
1247 && lp_debug_encryption())
1249 cli_session_dump_keys(state, session, state->session_key);
1251 } else {
1252 struct smbXcli_session *session = state->cli->smb1.session;
1253 bool active;
1255 status = smb1cli_session_set_session_key(session,
1256 state->session_key);
1257 if (tevent_req_nterror(req, status)) {
1258 return;
1261 active = smb1cli_conn_activate_signing(state->cli->conn,
1262 state->session_key,
1263 data_blob_null);
1264 if (active) {
1265 bool ok;
1267 ok = smb1cli_conn_check_signing(state->cli->conn,
1268 state->inbuf, 1);
1269 if (!ok) {
1270 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1271 return;
1276 tevent_req_done(req);
1279 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1281 struct cli_session_setup_gensec_state *state =
1282 tevent_req_data(req,
1283 struct cli_session_setup_gensec_state);
1284 NTSTATUS status;
1286 if (tevent_req_is_nterror(req, &status)) {
1287 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1288 return status;
1290 return NT_STATUS_OK;
1293 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1294 const char *principal)
1296 char *account, *p;
1298 account = talloc_strdup(mem_ctx, principal);
1299 if (account == NULL) {
1300 return NULL;
1302 p = strchr_m(account, '@');
1303 if (p != NULL) {
1304 *p = '\0';
1306 return account;
1309 /****************************************************************************
1310 Do a spnego encrypted session setup.
1312 user_domain: The shortname of the domain the user/machine is a member of.
1313 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1314 ****************************************************************************/
1316 struct cli_session_setup_spnego_state {
1317 ADS_STATUS result;
1320 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1322 static struct tevent_req *cli_session_setup_spnego_send(
1323 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1324 struct cli_credentials *creds)
1326 struct tevent_req *req, *subreq;
1327 struct cli_session_setup_spnego_state *state;
1328 const char *target_service = NULL;
1329 const char *target_hostname = NULL;
1330 NTSTATUS status;
1332 req = tevent_req_create(mem_ctx, &state,
1333 struct cli_session_setup_spnego_state);
1334 if (req == NULL) {
1335 return NULL;
1338 target_service = "cifs";
1339 target_hostname = smbXcli_conn_remote_name(cli->conn);
1341 status = cli_session_creds_prepare_krb5(cli, creds);
1342 if (tevent_req_nterror(req, status)) {
1343 return tevent_req_post(req, ev);
1346 DBG_INFO("Connect to %s as %s using SPNEGO\n",
1347 target_hostname,
1348 cli_credentials_get_principal(creds, talloc_tos()));
1350 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1351 target_service, target_hostname);
1352 if (tevent_req_nomem(subreq, req)) {
1353 return tevent_req_post(req, ev);
1355 tevent_req_set_callback(
1356 subreq, cli_session_setup_spnego_done, req);
1357 return req;
1360 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1362 struct tevent_req *req = tevent_req_callback_data(
1363 subreq, struct tevent_req);
1364 NTSTATUS status;
1366 status = cli_session_setup_gensec_recv(subreq);
1367 TALLOC_FREE(subreq);
1368 if (tevent_req_nterror(req, status)) {
1369 return;
1372 tevent_req_done(req);
1375 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1377 struct cli_session_setup_spnego_state *state = tevent_req_data(
1378 req, struct cli_session_setup_spnego_state);
1379 NTSTATUS status;
1381 if (tevent_req_is_nterror(req, &status)) {
1382 state->result = ADS_ERROR_NT(status);
1385 return state->result;
1388 struct cli_session_setup_creds_state {
1389 struct cli_state *cli;
1390 DATA_BLOB apassword_blob;
1391 DATA_BLOB upassword_blob;
1392 DATA_BLOB lm_session_key;
1393 DATA_BLOB session_key;
1394 char *out_native_os;
1395 char *out_native_lm;
1396 char *out_primary_domain;
1399 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1400 enum tevent_req_state req_state)
1402 struct cli_session_setup_creds_state *state = tevent_req_data(
1403 req, struct cli_session_setup_creds_state);
1405 if (req_state != TEVENT_REQ_RECEIVED) {
1406 return;
1410 * We only call data_blob_clear() as
1411 * some of the blobs point to the same memory.
1413 * We let the talloc hierarchy free the memory.
1415 data_blob_clear(&state->apassword_blob);
1416 data_blob_clear(&state->upassword_blob);
1417 data_blob_clear(&state->lm_session_key);
1418 data_blob_clear(&state->session_key);
1419 ZERO_STRUCTP(state);
1422 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1423 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1424 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1426 /****************************************************************************
1427 Send a session setup. The username and workgroup is in UNIX character
1428 format and must be converted to DOS codepage format before sending. If the
1429 password is in plaintext, the same should be done.
1430 ****************************************************************************/
1432 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1433 struct tevent_context *ev,
1434 struct cli_state *cli,
1435 struct cli_credentials *creds)
1437 struct tevent_req *req, *subreq;
1438 struct cli_session_setup_creds_state *state;
1439 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1440 bool use_spnego = false;
1441 int flags = 0;
1442 const char *username = "";
1443 const char *domain = "";
1444 DATA_BLOB target_info = data_blob_null;
1445 DATA_BLOB challenge = data_blob_null;
1446 uint16_t in_buf_size = 0;
1447 uint16_t in_mpx_max = 0;
1448 uint16_t in_vc_num = 0;
1449 uint32_t in_sess_key = 0;
1450 const char *in_native_os = NULL;
1451 const char *in_native_lm = NULL;
1452 enum credentials_use_kerberos krb5_state =
1453 cli_credentials_get_kerberos_state(creds);
1454 NTSTATUS status;
1456 req = tevent_req_create(mem_ctx, &state,
1457 struct cli_session_setup_creds_state);
1458 if (req == NULL) {
1459 return NULL;
1461 state->cli = cli;
1463 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1466 * Now work out what sort of session setup we are going to
1467 * do. I have split this into separate functions to make the flow a bit
1468 * easier to understand (tridge).
1470 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1471 use_spnego = false;
1472 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1473 use_spnego = true;
1474 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1476 * if the server supports extended security then use SPNEGO
1477 * even for anonymous connections.
1479 use_spnego = true;
1480 } else {
1481 use_spnego = false;
1484 if (use_spnego) {
1485 subreq = cli_session_setup_spnego_send(
1486 state, ev, cli, creds);
1487 if (tevent_req_nomem(subreq, req)) {
1488 return tevent_req_post(req, ev);
1490 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1491 req);
1492 return req;
1495 if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
1496 DBG_WARNING("Kerberos authentication requested, but "
1497 "the server does not support SPNEGO authentication\n");
1498 tevent_req_nterror(req, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT);
1499 return tevent_req_post(req, ev);
1502 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1504 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1505 * this step against older servers.
1507 tevent_req_done(req);
1508 return tevent_req_post(req, ev);
1511 if (cli_credentials_is_anonymous(creds)) {
1513 * Do an anonymous session setup
1515 goto non_spnego_creds_done;
1518 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1520 * Do an anonymous session setup,
1521 * the password is passed via the tree connect.
1523 goto non_spnego_creds_done;
1526 cli_credentials_get_ntlm_username_domain(creds, state,
1527 &username,
1528 &domain);
1529 if (tevent_req_nomem(username, req)) {
1530 return tevent_req_post(req, ev);
1532 if (tevent_req_nomem(domain, req)) {
1533 return tevent_req_post(req, ev);
1536 DBG_INFO("Connect to %s as %s using NTLM\n", domain, username);
1538 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1539 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1540 uint8_t *bytes = NULL;
1541 size_t bytes_len = 0;
1542 const char *pw = cli_credentials_get_password(creds);
1543 size_t pw_len = 0;
1545 if (pw == NULL) {
1546 pw = "";
1548 pw_len = strlen(pw) + 1;
1550 if (!lp_client_plaintext_auth()) {
1551 DEBUG(1, ("Server requested PLAINTEXT password but "
1552 "'client plaintext auth = no'\n"));
1553 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1554 return tevent_req_post(req, ev);
1557 bytes = talloc_array(state, uint8_t, 0);
1558 bytes = trans2_bytes_push_str(bytes, use_unicode,
1559 pw, pw_len, &bytes_len);
1560 if (tevent_req_nomem(bytes, req)) {
1561 return tevent_req_post(req, ev);
1564 if (use_unicode) {
1566 * CAP_UNICODE, can only be negotiated by NT1.
1568 state->upassword_blob = data_blob_const(bytes,
1569 bytes_len);
1570 } else {
1571 state->apassword_blob = data_blob_const(bytes,
1572 bytes_len);
1575 goto non_spnego_creds_done;
1578 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1580 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1581 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1583 * Don't send an NTLMv2 response without NTLMSSP if we
1584 * want to use spnego support.
1586 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1587 " but 'client use spnego = yes'"
1588 " and 'client ntlmv2 auth = yes' is set\n"));
1589 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1590 return tevent_req_post(req, ev);
1593 if (lp_client_ntlmv2_auth()) {
1594 flags |= CLI_CRED_NTLMv2_AUTH;
1597 * note that the 'domain' here is a best
1598 * guess - we don't know the server's domain
1599 * at this point. Windows clients also don't
1600 * use hostname...
1602 target_info = NTLMv2_generate_names_blob(state,
1603 NULL,
1604 domain);
1605 if (tevent_req_nomem(target_info.data, req)) {
1606 return tevent_req_post(req, ev);
1608 } else {
1609 flags |= CLI_CRED_NTLM_AUTH;
1610 if (lp_client_lanman_auth()) {
1611 flags |= CLI_CRED_LANMAN_AUTH;
1614 } else {
1615 if (!lp_client_lanman_auth()) {
1616 DEBUG(1, ("Server requested user level LM password but "
1617 "'client lanman auth = no' is set.\n"));
1618 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1619 return tevent_req_post(req, ev);
1622 flags |= CLI_CRED_LANMAN_AUTH;
1625 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1626 challenge, NULL,
1627 target_info,
1628 &state->apassword_blob,
1629 &state->upassword_blob,
1630 &state->lm_session_key,
1631 &state->session_key);
1632 if (tevent_req_nterror(req, status)) {
1633 return tevent_req_post(req, ev);
1636 non_spnego_creds_done:
1638 in_buf_size = CLI_BUFFER_SIZE;
1639 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1640 in_vc_num = cli_state_get_vc_num(cli);
1641 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1642 in_native_os = "Unix";
1643 in_native_lm = "Samba";
1645 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1646 uint32_t in_capabilities = 0;
1648 in_capabilities = cli_session_setup_capabilities(cli, 0);
1651 * For now we keep the same values as before,
1652 * we may remove these in a separate commit later.
1654 in_mpx_max = 2;
1656 subreq = smb1cli_session_setup_nt1_send(state, ev,
1657 cli->conn,
1658 cli->timeout,
1659 cli->smb1.pid,
1660 cli->smb1.session,
1661 in_buf_size,
1662 in_mpx_max,
1663 in_vc_num,
1664 in_sess_key,
1665 username,
1666 domain,
1667 state->apassword_blob,
1668 state->upassword_blob,
1669 in_capabilities,
1670 in_native_os,
1671 in_native_lm);
1672 if (tevent_req_nomem(subreq, req)) {
1673 return tevent_req_post(req, ev);
1675 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1676 req);
1677 return req;
1681 * For now we keep the same values as before,
1682 * we may remove these in a separate commit later.
1684 in_mpx_max = 2;
1685 in_vc_num = 1;
1687 subreq = smb1cli_session_setup_lm21_send(state, ev,
1688 cli->conn,
1689 cli->timeout,
1690 cli->smb1.pid,
1691 cli->smb1.session,
1692 in_buf_size,
1693 in_mpx_max,
1694 in_vc_num,
1695 in_sess_key,
1696 username,
1697 domain,
1698 state->apassword_blob,
1699 in_native_os,
1700 in_native_lm);
1701 if (tevent_req_nomem(subreq, req)) {
1702 return tevent_req_post(req, ev);
1704 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1705 req);
1706 return req;
1709 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1711 struct tevent_req *req = tevent_req_callback_data(
1712 subreq, struct tevent_req);
1713 ADS_STATUS status;
1715 status = cli_session_setup_spnego_recv(subreq);
1716 TALLOC_FREE(subreq);
1717 if (!ADS_ERR_OK(status)) {
1718 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1719 tevent_req_nterror(req, ads_ntstatus(status));
1720 return;
1722 tevent_req_done(req);
1725 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1727 struct tevent_req *req = tevent_req_callback_data(
1728 subreq, struct tevent_req);
1729 struct cli_session_setup_creds_state *state = tevent_req_data(
1730 req, struct cli_session_setup_creds_state);
1731 struct cli_state *cli = state->cli;
1732 NTSTATUS status;
1733 struct iovec *recv_iov = NULL;
1734 const uint8_t *inbuf = NULL;
1735 bool ok;
1737 status = smb1cli_session_setup_nt1_recv(subreq, state,
1738 &recv_iov,
1739 &inbuf,
1740 &state->out_native_os,
1741 &state->out_native_lm,
1742 &state->out_primary_domain);
1743 TALLOC_FREE(subreq);
1744 if (tevent_req_nterror(req, status)) {
1745 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1746 return;
1749 status = cli_state_update_after_sesssetup(state->cli,
1750 state->out_native_os,
1751 state->out_native_lm,
1752 state->out_primary_domain);
1753 if (tevent_req_nterror(req, status)) {
1754 return;
1757 ok = smb1cli_conn_activate_signing(cli->conn,
1758 state->session_key,
1759 state->upassword_blob);
1760 if (ok) {
1761 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1762 if (!ok) {
1763 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1764 return;
1768 if (state->session_key.data) {
1769 struct smbXcli_session *session = cli->smb1.session;
1771 status = smb1cli_session_set_session_key(session,
1772 state->session_key);
1773 if (tevent_req_nterror(req, status)) {
1774 return;
1778 tevent_req_done(req);
1781 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1783 struct tevent_req *req = tevent_req_callback_data(
1784 subreq, struct tevent_req);
1785 struct cli_session_setup_creds_state *state = tevent_req_data(
1786 req, struct cli_session_setup_creds_state);
1787 NTSTATUS status;
1789 status = smb1cli_session_setup_lm21_recv(subreq, state,
1790 &state->out_native_os,
1791 &state->out_native_lm);
1792 TALLOC_FREE(subreq);
1793 if (tevent_req_nterror(req, status)) {
1794 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1795 return;
1798 status = cli_state_update_after_sesssetup(state->cli,
1799 state->out_native_os,
1800 state->out_native_lm,
1801 NULL);
1802 if (tevent_req_nterror(req, status)) {
1803 return;
1806 tevent_req_done(req);
1809 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1811 return tevent_req_simple_recv_ntstatus(req);
1814 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1815 struct cli_credentials *creds)
1817 struct tevent_context *ev;
1818 struct tevent_req *req;
1819 NTSTATUS status = NT_STATUS_NO_MEMORY;
1821 if (smbXcli_conn_has_async_calls(cli->conn)) {
1822 return NT_STATUS_INVALID_PARAMETER;
1824 ev = samba_tevent_context_init(talloc_tos());
1825 if (ev == NULL) {
1826 goto fail;
1828 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1829 if (req == NULL) {
1830 goto fail;
1832 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1833 goto fail;
1835 status = cli_session_setup_creds_recv(req);
1836 fail:
1837 TALLOC_FREE(ev);
1838 return status;
1841 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1843 NTSTATUS status;
1844 struct cli_credentials *creds = NULL;
1846 creds = cli_credentials_init_anon(cli);
1847 if (creds == NULL) {
1848 return NT_STATUS_NO_MEMORY;
1851 status = cli_session_setup_creds(cli, creds);
1852 TALLOC_FREE(creds);
1853 if (!NT_STATUS_IS_OK(status)) {
1854 return status;
1857 return NT_STATUS_OK;
1860 /****************************************************************************
1861 Send a uloggoff.
1862 *****************************************************************************/
1864 struct cli_ulogoff_state {
1865 struct cli_state *cli;
1866 uint16_t vwv[3];
1869 static void cli_ulogoff_done(struct tevent_req *subreq);
1871 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1872 struct tevent_context *ev,
1873 struct cli_state *cli)
1875 struct tevent_req *req, *subreq;
1876 struct cli_ulogoff_state *state;
1878 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1879 if (req == NULL) {
1880 return NULL;
1882 state->cli = cli;
1884 SCVAL(state->vwv+0, 0, 0xFF);
1885 SCVAL(state->vwv+1, 0, 0);
1886 SSVAL(state->vwv+2, 0, 0);
1888 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1889 0, NULL);
1890 if (tevent_req_nomem(subreq, req)) {
1891 return tevent_req_post(req, ev);
1893 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1894 return req;
1897 static void cli_ulogoff_done(struct tevent_req *subreq)
1899 struct tevent_req *req = tevent_req_callback_data(
1900 subreq, struct tevent_req);
1901 struct cli_ulogoff_state *state = tevent_req_data(
1902 req, struct cli_ulogoff_state);
1903 NTSTATUS status;
1905 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1906 if (tevent_req_nterror(req, status)) {
1907 return;
1909 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1910 tevent_req_done(req);
1913 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1915 return tevent_req_simple_recv_ntstatus(req);
1918 NTSTATUS cli_ulogoff(struct cli_state *cli)
1920 struct tevent_context *ev;
1921 struct tevent_req *req;
1922 NTSTATUS status = NT_STATUS_NO_MEMORY;
1924 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1925 status = smb2cli_logoff(cli->conn,
1926 cli->timeout,
1927 cli->smb2.session);
1928 if (!NT_STATUS_IS_OK(status)) {
1929 return status;
1931 smb2cli_session_set_id_and_flags(cli->smb2.session,
1932 UINT64_MAX, 0);
1933 return NT_STATUS_OK;
1936 if (smbXcli_conn_has_async_calls(cli->conn)) {
1937 return NT_STATUS_INVALID_PARAMETER;
1939 ev = samba_tevent_context_init(talloc_tos());
1940 if (ev == NULL) {
1941 goto fail;
1943 req = cli_ulogoff_send(ev, ev, cli);
1944 if (req == NULL) {
1945 goto fail;
1947 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1948 goto fail;
1950 status = cli_ulogoff_recv(req);
1951 fail:
1952 TALLOC_FREE(ev);
1953 return status;
1956 /****************************************************************************
1957 Send a tconX.
1958 ****************************************************************************/
1960 struct cli_tcon_andx_state {
1961 struct cli_state *cli;
1962 uint16_t vwv[4];
1963 struct iovec bytes;
1966 static void cli_tcon_andx_done(struct tevent_req *subreq);
1968 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1969 struct tevent_context *ev,
1970 struct cli_state *cli,
1971 const char *share, const char *dev,
1972 const char *pass, int passlen,
1973 struct tevent_req **psmbreq)
1975 struct tevent_req *req, *subreq;
1976 struct cli_tcon_andx_state *state;
1977 uint8_t p24[24];
1978 uint16_t *vwv;
1979 char *tmp = NULL;
1980 uint8_t *bytes;
1981 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1982 uint16_t tcon_flags = 0;
1984 *psmbreq = NULL;
1986 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1987 if (req == NULL) {
1988 return NULL;
1990 state->cli = cli;
1991 vwv = state->vwv;
1993 TALLOC_FREE(cli->smb1.tcon);
1994 cli->smb1.tcon = smbXcli_tcon_create(cli);
1995 if (tevent_req_nomem(cli->smb1.tcon, req)) {
1996 return tevent_req_post(req, ev);
1998 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
2000 cli->share = talloc_strdup(cli, share);
2001 if (!cli->share) {
2002 return NULL;
2005 /* in user level security don't send a password now */
2006 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2007 passlen = 1;
2008 pass = "";
2009 } else if (pass == NULL) {
2010 DEBUG(1, ("Server not using user level security and no "
2011 "password supplied.\n"));
2012 goto access_denied;
2015 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2016 *pass && passlen != 24) {
2017 if (!lp_client_lanman_auth()) {
2018 DEBUG(1, ("Server requested LANMAN password "
2019 "(share-level security) but "
2020 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2021 goto access_denied;
2025 * Non-encrypted passwords - convert to DOS codepage before
2026 * encryption.
2028 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2029 passlen = 24;
2030 pass = (const char *)p24;
2031 } else {
2032 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2033 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2034 == 0) {
2035 uint8_t *tmp_pass;
2037 if (!lp_client_plaintext_auth() && (*pass)) {
2038 DEBUG(1, ("Server requested PLAINTEXT "
2039 "password but "
2040 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2041 goto access_denied;
2045 * Non-encrypted passwords - convert to DOS codepage
2046 * before using.
2048 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2049 if (tevent_req_nomem(tmp_pass, req)) {
2050 return tevent_req_post(req, ev);
2052 tmp_pass = trans2_bytes_push_str(tmp_pass,
2053 false, /* always DOS */
2054 pass,
2055 passlen,
2056 NULL);
2057 if (tevent_req_nomem(tmp_pass, req)) {
2058 return tevent_req_post(req, ev);
2060 pass = (const char *)tmp_pass;
2061 passlen = talloc_get_size(tmp_pass);
2065 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2066 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2068 SCVAL(vwv+0, 0, 0xFF);
2069 SCVAL(vwv+0, 1, 0);
2070 SSVAL(vwv+1, 0, 0);
2071 SSVAL(vwv+2, 0, tcon_flags);
2072 SSVAL(vwv+3, 0, passlen);
2074 if (passlen && pass) {
2075 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2076 } else {
2077 bytes = talloc_array(state, uint8_t, 0);
2081 * Add the sharename
2083 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2084 smbXcli_conn_remote_name(cli->conn), share);
2085 if (tmp == NULL) {
2086 TALLOC_FREE(req);
2087 return NULL;
2089 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2090 NULL);
2091 TALLOC_FREE(tmp);
2094 * Add the devicetype
2096 tmp = talloc_strdup_upper(talloc_tos(), dev);
2097 if (tmp == NULL) {
2098 TALLOC_FREE(req);
2099 return NULL;
2101 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2102 TALLOC_FREE(tmp);
2104 if (bytes == NULL) {
2105 TALLOC_FREE(req);
2106 return NULL;
2109 state->bytes.iov_base = (void *)bytes;
2110 state->bytes.iov_len = talloc_get_size(bytes);
2112 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2113 1, &state->bytes);
2114 if (subreq == NULL) {
2115 TALLOC_FREE(req);
2116 return NULL;
2118 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2119 *psmbreq = subreq;
2120 return req;
2122 access_denied:
2123 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2124 return tevent_req_post(req, ev);
2127 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2128 struct tevent_context *ev,
2129 struct cli_state *cli,
2130 const char *share, const char *dev,
2131 const char *pass, int passlen)
2133 struct tevent_req *req, *subreq;
2134 NTSTATUS status;
2136 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2137 &subreq);
2138 if (req == NULL) {
2139 return NULL;
2141 if (subreq == NULL) {
2142 return req;
2144 status = smb1cli_req_chain_submit(&subreq, 1);
2145 if (tevent_req_nterror(req, status)) {
2146 return tevent_req_post(req, ev);
2148 return req;
2151 static void cli_tcon_andx_done(struct tevent_req *subreq)
2153 struct tevent_req *req = tevent_req_callback_data(
2154 subreq, struct tevent_req);
2155 struct cli_tcon_andx_state *state = tevent_req_data(
2156 req, struct cli_tcon_andx_state);
2157 struct cli_state *cli = state->cli;
2158 uint8_t *in;
2159 uint8_t *inhdr;
2160 uint8_t wct;
2161 uint16_t *vwv;
2162 uint32_t num_bytes;
2163 uint8_t *bytes;
2164 NTSTATUS status;
2165 uint16_t optional_support = 0;
2167 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2168 &num_bytes, &bytes);
2169 TALLOC_FREE(subreq);
2170 if (tevent_req_nterror(req, status)) {
2171 return;
2174 inhdr = in + NBT_HDR_SIZE;
2176 if (num_bytes) {
2177 if (pull_string_talloc(cli,
2178 (const char *)inhdr,
2179 SVAL(inhdr, HDR_FLG2),
2180 &cli->dev,
2181 bytes,
2182 num_bytes,
2183 STR_TERMINATE|STR_ASCII) == -1) {
2184 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2185 return;
2187 } else {
2188 cli->dev = talloc_strdup(cli, "");
2189 if (cli->dev == NULL) {
2190 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2191 return;
2195 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2196 /* almost certainly win95 - enable bug fixes */
2197 cli->win95 = True;
2201 * Make sure that we have the optional support 16-bit field. WCT > 2.
2202 * Avoids issues when connecting to Win9x boxes sharing files
2205 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2206 optional_support = SVAL(vwv+2, 0);
2209 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2210 smb1cli_session_protect_session_key(cli->smb1.session);
2213 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2214 SVAL(inhdr, HDR_TID),
2215 optional_support,
2216 0, /* maximal_access */
2217 0, /* guest_maximal_access */
2218 NULL, /* service */
2219 NULL); /* fs_type */
2221 tevent_req_done(req);
2224 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2226 return tevent_req_simple_recv_ntstatus(req);
2229 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2230 const char *dev, const char *pass, int passlen)
2232 TALLOC_CTX *frame = talloc_stackframe();
2233 struct tevent_context *ev;
2234 struct tevent_req *req;
2235 NTSTATUS status = NT_STATUS_NO_MEMORY;
2237 if (smbXcli_conn_has_async_calls(cli->conn)) {
2239 * Can't use sync call while an async call is in flight
2241 status = NT_STATUS_INVALID_PARAMETER;
2242 goto fail;
2245 ev = samba_tevent_context_init(frame);
2246 if (ev == NULL) {
2247 goto fail;
2250 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2251 if (req == NULL) {
2252 goto fail;
2255 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2256 goto fail;
2259 status = cli_tcon_andx_recv(req);
2260 fail:
2261 TALLOC_FREE(frame);
2262 return status;
2265 struct cli_tree_connect_state {
2266 struct cli_state *cli;
2269 static struct tevent_req *cli_raw_tcon_send(
2270 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2271 const char *service, const char *pass, const char *dev);
2272 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2273 uint16_t *max_xmit, uint16_t *tid);
2275 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2276 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2277 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2279 static struct tevent_req *cli_tree_connect_send(
2280 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2281 const char *share, const char *dev, const char *pass)
2283 struct tevent_req *req, *subreq;
2284 struct cli_tree_connect_state *state;
2285 int passlen;
2287 if (pass == NULL) {
2288 pass = "";
2290 passlen = strlen(pass) + 1;
2292 req = tevent_req_create(mem_ctx, &state,
2293 struct cli_tree_connect_state);
2294 if (req == NULL) {
2295 return NULL;
2297 state->cli = cli;
2299 cli->share = talloc_strdup(cli, share);
2300 if (tevent_req_nomem(cli->share, req)) {
2301 return tevent_req_post(req, ev);
2304 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2305 char *unc;
2307 TALLOC_FREE(cli->smb2.tcon);
2308 cli->smb2.tcon = smbXcli_tcon_create(cli);
2309 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2310 return tevent_req_post(req, ev);
2313 unc = talloc_asprintf(state, "\\\\%s\\%s",
2314 smbXcli_conn_remote_name(cli->conn),
2315 share);
2316 if (tevent_req_nomem(unc, req)) {
2317 return tevent_req_post(req, ev);
2320 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2321 cli->smb2.session, cli->smb2.tcon,
2322 0, /* flags */
2323 unc);
2324 if (tevent_req_nomem(subreq, req)) {
2325 return tevent_req_post(req, ev);
2327 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2328 req);
2329 return req;
2332 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2333 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2334 pass, passlen);
2335 if (tevent_req_nomem(subreq, req)) {
2336 return tevent_req_post(req, ev);
2338 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2339 req);
2340 return req;
2343 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2344 if (tevent_req_nomem(subreq, req)) {
2345 return tevent_req_post(req, ev);
2347 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2349 return req;
2352 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2354 NTSTATUS status = smb2cli_tcon_recv(subreq);
2355 tevent_req_simple_finish_ntstatus(subreq, status);
2358 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2360 NTSTATUS status = cli_tcon_andx_recv(subreq);
2361 tevent_req_simple_finish_ntstatus(subreq, status);
2364 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2366 struct tevent_req *req = tevent_req_callback_data(
2367 subreq, struct tevent_req);
2368 struct cli_tree_connect_state *state = tevent_req_data(
2369 req, struct cli_tree_connect_state);
2370 NTSTATUS status;
2371 uint16_t max_xmit = 0;
2372 uint16_t tid = 0;
2374 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2375 if (tevent_req_nterror(req, status)) {
2376 return;
2379 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2380 tid,
2381 0, /* optional_support */
2382 0, /* maximal_access */
2383 0, /* guest_maximal_access */
2384 NULL, /* service */
2385 NULL); /* fs_type */
2387 tevent_req_done(req);
2390 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2392 return tevent_req_simple_recv_ntstatus(req);
2395 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2396 const char *dev, const char *pass)
2398 struct tevent_context *ev;
2399 struct tevent_req *req;
2400 NTSTATUS status = NT_STATUS_NO_MEMORY;
2402 if (smbXcli_conn_has_async_calls(cli->conn)) {
2403 return NT_STATUS_INVALID_PARAMETER;
2405 ev = samba_tevent_context_init(talloc_tos());
2406 if (ev == NULL) {
2407 goto fail;
2409 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2410 if (req == NULL) {
2411 goto fail;
2413 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2414 goto fail;
2416 status = cli_tree_connect_recv(req);
2417 fail:
2418 TALLOC_FREE(ev);
2419 return status;
2422 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2423 const char *share, const char *dev,
2424 struct cli_credentials *creds)
2426 bool need_pass = false;
2427 const char *pw = NULL;
2430 * We should work out if the protocol
2431 * will make use of a password for share level
2432 * authentication before we may cause
2433 * the password prompt to be called.
2435 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2436 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2438 /* in user level security don't send a password now */
2439 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
2440 need_pass = true;
2444 if (need_pass && creds != NULL) {
2445 pw = cli_credentials_get_password(creds);
2448 return cli_tree_connect(cli, share, dev, pw);
2451 /****************************************************************************
2452 Send a tree disconnect.
2453 ****************************************************************************/
2455 struct cli_tdis_state {
2456 struct cli_state *cli;
2459 static void cli_tdis_done(struct tevent_req *subreq);
2461 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2462 struct tevent_context *ev,
2463 struct cli_state *cli)
2465 struct tevent_req *req, *subreq;
2466 struct cli_tdis_state *state;
2468 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2469 if (req == NULL) {
2470 return NULL;
2472 state->cli = cli;
2474 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2475 if (tevent_req_nomem(subreq, req)) {
2476 return tevent_req_post(req, ev);
2478 tevent_req_set_callback(subreq, cli_tdis_done, req);
2479 return req;
2482 static void cli_tdis_done(struct tevent_req *subreq)
2484 struct tevent_req *req = tevent_req_callback_data(
2485 subreq, struct tevent_req);
2486 struct cli_tdis_state *state = tevent_req_data(
2487 req, struct cli_tdis_state);
2488 NTSTATUS status;
2490 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2491 TALLOC_FREE(subreq);
2492 if (tevent_req_nterror(req, status)) {
2493 return;
2495 TALLOC_FREE(state->cli->smb1.tcon);
2496 tevent_req_done(req);
2499 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2501 return tevent_req_simple_recv_ntstatus(req);
2504 NTSTATUS cli_tdis(struct cli_state *cli)
2506 struct tevent_context *ev;
2507 struct tevent_req *req;
2508 NTSTATUS status = NT_STATUS_NO_MEMORY;
2510 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2511 status = smb2cli_tdis(cli->conn,
2512 cli->timeout,
2513 cli->smb2.session,
2514 cli->smb2.tcon);
2515 if (NT_STATUS_IS_OK(status)) {
2516 TALLOC_FREE(cli->smb2.tcon);
2518 return status;
2521 if (smbXcli_conn_has_async_calls(cli->conn)) {
2522 return NT_STATUS_INVALID_PARAMETER;
2524 ev = samba_tevent_context_init(talloc_tos());
2525 if (ev == NULL) {
2526 goto fail;
2528 req = cli_tdis_send(ev, ev, cli);
2529 if (req == NULL) {
2530 goto fail;
2532 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2533 goto fail;
2535 status = cli_tdis_recv(req);
2536 fail:
2537 TALLOC_FREE(ev);
2538 return status;
2541 struct cli_connect_sock_state {
2542 const char **called_names;
2543 const char **calling_names;
2544 int *called_types;
2545 int fd;
2546 uint16_t port;
2549 static void cli_connect_sock_done(struct tevent_req *subreq);
2552 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2553 * nonzero address.
2556 static struct tevent_req *cli_connect_sock_send(
2557 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2558 const char *host, int name_type, const struct sockaddr_storage *pss,
2559 const char *myname, uint16_t port)
2561 struct tevent_req *req, *subreq;
2562 struct cli_connect_sock_state *state;
2563 struct sockaddr_storage *addrs = NULL;
2564 unsigned i;
2565 unsigned num_addrs = 0;
2566 NTSTATUS status;
2568 req = tevent_req_create(mem_ctx, &state,
2569 struct cli_connect_sock_state);
2570 if (req == NULL) {
2571 return NULL;
2574 if ((pss == NULL) || is_zero_addr(pss)) {
2577 * Here we cheat. resolve_name_list is not async at all. So
2578 * this call will only be really async if the name lookup has
2579 * been done externally.
2582 status = resolve_name_list(state, host, name_type,
2583 &addrs, &num_addrs);
2584 if (tevent_req_nterror(req, status)) {
2585 return tevent_req_post(req, ev);
2587 } else {
2588 addrs = talloc_array(state, struct sockaddr_storage, 1);
2589 if (tevent_req_nomem(addrs, req)) {
2590 return tevent_req_post(req, ev);
2592 addrs[0] = *pss;
2593 num_addrs = 1;
2596 state->called_names = talloc_array(state, const char *, num_addrs);
2597 if (tevent_req_nomem(state->called_names, req)) {
2598 return tevent_req_post(req, ev);
2600 state->called_types = talloc_array(state, int, num_addrs);
2601 if (tevent_req_nomem(state->called_types, req)) {
2602 return tevent_req_post(req, ev);
2604 state->calling_names = talloc_array(state, const char *, num_addrs);
2605 if (tevent_req_nomem(state->calling_names, req)) {
2606 return tevent_req_post(req, ev);
2608 for (i=0; i<num_addrs; i++) {
2609 state->called_names[i] = host;
2610 state->called_types[i] = name_type;
2611 state->calling_names[i] = myname;
2614 subreq = smbsock_any_connect_send(
2615 state, ev, addrs, state->called_names, state->called_types,
2616 state->calling_names, NULL, num_addrs, port);
2617 if (tevent_req_nomem(subreq, req)) {
2618 return tevent_req_post(req, ev);
2620 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2621 return req;
2624 static void cli_connect_sock_done(struct tevent_req *subreq)
2626 struct tevent_req *req = tevent_req_callback_data(
2627 subreq, struct tevent_req);
2628 struct cli_connect_sock_state *state = tevent_req_data(
2629 req, struct cli_connect_sock_state);
2630 NTSTATUS status;
2632 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2633 &state->port);
2634 TALLOC_FREE(subreq);
2635 if (tevent_req_nterror(req, status)) {
2636 return;
2638 set_socket_options(state->fd, lp_socket_options());
2639 tevent_req_done(req);
2642 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2643 int *pfd, uint16_t *pport)
2645 struct cli_connect_sock_state *state = tevent_req_data(
2646 req, struct cli_connect_sock_state);
2647 NTSTATUS status;
2649 if (tevent_req_is_nterror(req, &status)) {
2650 return status;
2652 *pfd = state->fd;
2653 *pport = state->port;
2654 return NT_STATUS_OK;
2657 struct cli_connect_nb_state {
2658 const char *desthost;
2659 enum smb_signing_setting signing_state;
2660 int flags;
2661 struct cli_state *cli;
2664 static void cli_connect_nb_done(struct tevent_req *subreq);
2666 static struct tevent_req *cli_connect_nb_send(
2667 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2668 const char *host, const struct sockaddr_storage *dest_ss,
2669 uint16_t port, int name_type, const char *myname,
2670 enum smb_signing_setting signing_state, int flags)
2672 struct tevent_req *req, *subreq;
2673 struct cli_connect_nb_state *state;
2675 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2676 if (req == NULL) {
2677 return NULL;
2679 state->signing_state = signing_state;
2680 state->flags = flags;
2682 if (host != NULL) {
2683 char *p = strchr(host, '#');
2685 if (p != NULL) {
2686 name_type = strtol(p+1, NULL, 16);
2687 host = talloc_strndup(state, host, p - host);
2688 if (tevent_req_nomem(host, req)) {
2689 return tevent_req_post(req, ev);
2693 state->desthost = host;
2694 } else if (dest_ss != NULL) {
2695 state->desthost = print_canonical_sockaddr(state, dest_ss);
2696 if (tevent_req_nomem(state->desthost, req)) {
2697 return tevent_req_post(req, ev);
2699 } else {
2700 /* No host or dest_ss given. Error out. */
2701 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2702 return tevent_req_post(req, ev);
2705 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2706 myname, port);
2707 if (tevent_req_nomem(subreq, req)) {
2708 return tevent_req_post(req, ev);
2710 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2711 return req;
2714 static void cli_connect_nb_done(struct tevent_req *subreq)
2716 struct tevent_req *req = tevent_req_callback_data(
2717 subreq, struct tevent_req);
2718 struct cli_connect_nb_state *state = tevent_req_data(
2719 req, struct cli_connect_nb_state);
2720 NTSTATUS status;
2721 int fd = 0;
2722 uint16_t port;
2724 status = cli_connect_sock_recv(subreq, &fd, &port);
2725 TALLOC_FREE(subreq);
2726 if (tevent_req_nterror(req, status)) {
2727 return;
2730 state->cli = cli_state_create(state, fd, state->desthost,
2731 state->signing_state, state->flags);
2732 if (tevent_req_nomem(state->cli, req)) {
2733 close(fd);
2734 return;
2736 tevent_req_done(req);
2739 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2740 struct cli_state **pcli)
2742 struct cli_connect_nb_state *state = tevent_req_data(
2743 req, struct cli_connect_nb_state);
2744 NTSTATUS status;
2746 if (tevent_req_is_nterror(req, &status)) {
2747 return status;
2749 *pcli = talloc_move(NULL, &state->cli);
2750 return NT_STATUS_OK;
2753 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2754 uint16_t port, int name_type, const char *myname,
2755 enum smb_signing_setting signing_state, int flags, struct cli_state **pcli)
2757 struct tevent_context *ev;
2758 struct tevent_req *req;
2759 NTSTATUS status = NT_STATUS_NO_MEMORY;
2761 ev = samba_tevent_context_init(talloc_tos());
2762 if (ev == NULL) {
2763 goto fail;
2765 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2766 myname, signing_state, flags);
2767 if (req == NULL) {
2768 goto fail;
2770 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2771 goto fail;
2773 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2774 goto fail;
2776 status = cli_connect_nb_recv(req, pcli);
2777 fail:
2778 TALLOC_FREE(ev);
2779 return status;
2782 struct cli_start_connection_state {
2783 struct tevent_context *ev;
2784 struct cli_state *cli;
2785 int min_protocol;
2786 int max_protocol;
2787 struct smb2_negotiate_contexts *negotiate_contexts;
2790 static void cli_start_connection_connected(struct tevent_req *subreq);
2791 static void cli_start_connection_done(struct tevent_req *subreq);
2794 establishes a connection to after the negprot.
2795 @param output_cli A fully initialised cli structure, non-null only on success
2796 @param dest_host The netbios name of the remote host
2797 @param dest_ss (optional) The destination IP, NULL for name based lookup
2798 @param port (optional) The destination port (0 for default)
2801 static struct tevent_req *cli_start_connection_send(
2802 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2803 const char *my_name, const char *dest_host,
2804 const struct sockaddr_storage *dest_ss, int port,
2805 enum smb_signing_setting signing_state, int flags,
2806 struct smb2_negotiate_contexts *negotiate_contexts)
2808 struct tevent_req *req, *subreq;
2809 struct cli_start_connection_state *state;
2811 req = tevent_req_create(mem_ctx, &state,
2812 struct cli_start_connection_state);
2813 if (req == NULL) {
2814 return NULL;
2816 state->ev = ev;
2818 if (flags & CLI_FULL_CONNECTION_IPC) {
2819 state->min_protocol = lp_client_ipc_min_protocol();
2820 state->max_protocol = lp_client_ipc_max_protocol();
2821 } else {
2822 state->min_protocol = lp_client_min_protocol();
2823 state->max_protocol = lp_client_max_protocol();
2826 if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
2827 state->max_protocol = MIN(state->max_protocol,
2828 PROTOCOL_NT1);
2829 state->min_protocol = MIN(state->min_protocol,
2830 state->max_protocol);
2833 if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
2834 state->min_protocol = MAX(state->min_protocol,
2835 PROTOCOL_SMB2_02);
2836 state->max_protocol = MAX(state->max_protocol,
2837 state->min_protocol);
2840 state->negotiate_contexts = talloc_zero(
2841 state, struct smb2_negotiate_contexts);
2842 if (tevent_req_nomem(state->negotiate_contexts, req)) {
2843 return tevent_req_post(req, ev);
2846 if (flags & CLI_FULL_CONNECTION_REQUEST_POSIX) {
2847 NTSTATUS status;
2849 status = smb2_negotiate_context_add(
2850 state->negotiate_contexts,
2851 state->negotiate_contexts,
2852 SMB2_POSIX_EXTENSIONS_AVAILABLE,
2853 (const uint8_t *)SMB2_CREATE_TAG_POSIX,
2854 strlen(SMB2_CREATE_TAG_POSIX));
2855 if (tevent_req_nterror(req, status)) {
2856 return tevent_req_post(req, ev);
2860 if (negotiate_contexts != NULL) {
2861 uint16_t i;
2863 for (i=0; i<negotiate_contexts->num_contexts; i++) {
2864 struct smb2_negotiate_context *ctx =
2865 &negotiate_contexts->contexts[i];
2866 NTSTATUS status;
2868 status = smb2_negotiate_context_add(
2869 state->negotiate_contexts,
2870 state->negotiate_contexts,
2871 ctx->type,
2872 ctx->data.data,
2873 ctx->data.length);
2874 if (tevent_req_nterror(req, status)) {
2875 return tevent_req_post(req, ev);
2880 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2881 0x20, my_name, signing_state, flags);
2882 if (tevent_req_nomem(subreq, req)) {
2883 return tevent_req_post(req, ev);
2885 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2886 return req;
2889 static void cli_start_connection_connected(struct tevent_req *subreq)
2891 struct tevent_req *req = tevent_req_callback_data(
2892 subreq, struct tevent_req);
2893 struct cli_start_connection_state *state = tevent_req_data(
2894 req, struct cli_start_connection_state);
2895 NTSTATUS status;
2897 status = cli_connect_nb_recv(subreq, &state->cli);
2898 TALLOC_FREE(subreq);
2899 if (tevent_req_nterror(req, status)) {
2900 return;
2903 subreq = smbXcli_negprot_send(
2904 state,
2905 state->ev,
2906 state->cli->conn,
2907 state->cli->timeout,
2908 state->min_protocol,
2909 state->max_protocol,
2910 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK,
2911 state->negotiate_contexts);
2912 if (tevent_req_nomem(subreq, req)) {
2913 return;
2915 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2918 static void cli_start_connection_done(struct tevent_req *subreq)
2920 struct tevent_req *req = tevent_req_callback_data(
2921 subreq, struct tevent_req);
2922 struct cli_start_connection_state *state = tevent_req_data(
2923 req, struct cli_start_connection_state);
2924 NTSTATUS status;
2926 status = smbXcli_negprot_recv(subreq, NULL, NULL);
2927 TALLOC_FREE(subreq);
2928 if (tevent_req_nterror(req, status)) {
2929 return;
2932 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2933 /* Ensure we ask for some initial credits. */
2934 smb2cli_conn_set_max_credits(state->cli->conn,
2935 DEFAULT_SMB2_MAX_CREDITS);
2938 tevent_req_done(req);
2941 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2942 struct cli_state **output_cli)
2944 struct cli_start_connection_state *state = tevent_req_data(
2945 req, struct cli_start_connection_state);
2946 NTSTATUS status;
2948 if (tevent_req_is_nterror(req, &status)) {
2949 return status;
2951 *output_cli = state->cli;
2953 return NT_STATUS_OK;
2956 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2957 const char *my_name,
2958 const char *dest_host,
2959 const struct sockaddr_storage *dest_ss, int port,
2960 enum smb_signing_setting signing_state, int flags)
2962 struct tevent_context *ev;
2963 struct tevent_req *req;
2964 NTSTATUS status = NT_STATUS_NO_MEMORY;
2966 ev = samba_tevent_context_init(talloc_tos());
2967 if (ev == NULL) {
2968 goto fail;
2970 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2971 port, signing_state, flags, NULL);
2972 if (req == NULL) {
2973 goto fail;
2975 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2976 goto fail;
2978 status = cli_start_connection_recv(req, output_cli);
2979 fail:
2980 TALLOC_FREE(ev);
2981 return status;
2984 struct cli_smb1_setup_encryption_blob_state {
2985 uint16_t setup[1];
2986 uint8_t param[4];
2987 NTSTATUS status;
2988 DATA_BLOB out;
2989 uint16_t enc_ctx_id;
2992 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2994 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2995 struct tevent_context *ev,
2996 struct cli_state *cli,
2997 const DATA_BLOB in)
2999 struct tevent_req *req = NULL;
3000 struct cli_smb1_setup_encryption_blob_state *state = NULL;
3001 struct tevent_req *subreq = NULL;
3003 req = tevent_req_create(mem_ctx, &state,
3004 struct cli_smb1_setup_encryption_blob_state);
3005 if (req == NULL) {
3006 return NULL;
3009 if (in.length > CLI_BUFFER_SIZE) {
3010 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3011 return tevent_req_post(req, ev);
3014 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
3015 SSVAL(state->param, 0, 0);
3016 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
3018 subreq = smb1cli_trans_send(state, ev, cli->conn,
3019 SMBtrans2,
3020 0, 0, /* _flags */
3021 0, 0, /* _flags2 */
3022 cli->timeout,
3023 cli->smb1.pid,
3024 cli->smb1.tcon,
3025 cli->smb1.session,
3026 NULL, /* pipe_name */
3027 0, /* fid */
3028 0, /* function */
3029 0, /* flags */
3030 state->setup, 1, 0,
3031 state->param, 4, 2,
3032 in.data, in.length, CLI_BUFFER_SIZE);
3033 if (tevent_req_nomem(subreq, req)) {
3034 return tevent_req_post(req, ev);
3036 tevent_req_set_callback(subreq,
3037 cli_smb1_setup_encryption_blob_done,
3038 req);
3040 return req;
3043 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
3045 struct tevent_req *req =
3046 tevent_req_callback_data(subreq,
3047 struct tevent_req);
3048 struct cli_smb1_setup_encryption_blob_state *state =
3049 tevent_req_data(req,
3050 struct cli_smb1_setup_encryption_blob_state);
3051 uint8_t *rparam=NULL, *rdata=NULL;
3052 uint32_t num_rparam, num_rdata;
3053 NTSTATUS status;
3055 status = smb1cli_trans_recv(subreq, state,
3056 NULL, /* recv_flags */
3057 NULL, 0, NULL, /* rsetup */
3058 &rparam, 0, &num_rparam,
3059 &rdata, 0, &num_rdata);
3060 TALLOC_FREE(subreq);
3061 state->status = status;
3062 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
3063 status = NT_STATUS_OK;
3065 if (tevent_req_nterror(req, status)) {
3066 return;
3069 if (num_rparam == 2) {
3070 state->enc_ctx_id = SVAL(rparam, 0);
3072 TALLOC_FREE(rparam);
3074 state->out = data_blob_const(rdata, num_rdata);
3076 tevent_req_done(req);
3079 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
3080 TALLOC_CTX *mem_ctx,
3081 DATA_BLOB *out,
3082 uint16_t *enc_ctx_id)
3084 struct cli_smb1_setup_encryption_blob_state *state =
3085 tevent_req_data(req,
3086 struct cli_smb1_setup_encryption_blob_state);
3087 NTSTATUS status;
3089 if (tevent_req_is_nterror(req, &status)) {
3090 tevent_req_received(req);
3091 return status;
3094 status = state->status;
3096 *out = state->out;
3097 talloc_steal(mem_ctx, out->data);
3099 *enc_ctx_id = state->enc_ctx_id;
3101 tevent_req_received(req);
3102 return status;
3105 struct cli_smb1_setup_encryption_state {
3106 struct tevent_context *ev;
3107 struct cli_state *cli;
3108 struct smb_trans_enc_state *es;
3109 DATA_BLOB blob_in;
3110 DATA_BLOB blob_out;
3111 bool local_ready;
3112 bool remote_ready;
3115 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
3116 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
3117 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
3118 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
3119 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
3121 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
3122 struct tevent_context *ev,
3123 struct cli_state *cli,
3124 struct cli_credentials *creds)
3126 struct tevent_req *req = NULL;
3127 struct cli_smb1_setup_encryption_state *state = NULL;
3128 struct auth_generic_state *ags = NULL;
3129 const DATA_BLOB *b = NULL;
3130 bool auth_requested = false;
3131 const char *target_service = NULL;
3132 const char *target_hostname = NULL;
3133 NTSTATUS status;
3135 req = tevent_req_create(mem_ctx, &state,
3136 struct cli_smb1_setup_encryption_state);
3137 if (req == NULL) {
3138 return NULL;
3140 state->ev = ev;
3141 state->cli = cli;
3143 auth_requested = cli_credentials_authentication_requested(creds);
3144 if (!auth_requested) {
3145 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3146 return tevent_req_post(req, ev);
3149 target_service = "cifs";
3150 target_hostname = smbXcli_conn_remote_name(cli->conn);
3152 status = cli_session_creds_prepare_krb5(cli, creds);
3153 if (tevent_req_nterror(req, status)) {
3154 return tevent_req_post(req, ev);
3157 state->es = talloc_zero(state, struct smb_trans_enc_state);
3158 if (tevent_req_nomem(state->es, req)) {
3159 return tevent_req_post(req, ev);
3162 status = auth_generic_client_prepare(state->es, &ags);
3163 if (tevent_req_nterror(req, status)) {
3164 return tevent_req_post(req, ev);
3167 gensec_want_feature(ags->gensec_security,
3168 GENSEC_FEATURE_SIGN);
3169 gensec_want_feature(ags->gensec_security,
3170 GENSEC_FEATURE_SEAL);
3172 status = auth_generic_set_creds(ags, creds);
3173 if (tevent_req_nterror(req, status)) {
3174 return tevent_req_post(req, ev);
3177 if (target_service != NULL) {
3178 status = gensec_set_target_service(ags->gensec_security,
3179 target_service);
3180 if (tevent_req_nterror(req, status)) {
3181 return tevent_req_post(req, ev);
3185 if (target_hostname != NULL) {
3186 status = gensec_set_target_hostname(ags->gensec_security,
3187 target_hostname);
3188 if (tevent_req_nterror(req, status)) {
3189 return tevent_req_post(req, ev);
3193 gensec_set_max_update_size(ags->gensec_security,
3194 CLI_BUFFER_SIZE);
3196 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3197 if (b != NULL) {
3198 state->blob_in = *b;
3201 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3202 if (tevent_req_nterror(req, status)) {
3203 return tevent_req_post(req, ev);
3207 * We only need the gensec_security part from here.
3209 state->es->gensec_security = talloc_move(state->es,
3210 &ags->gensec_security);
3211 TALLOC_FREE(ags);
3213 cli_smb1_setup_encryption_local_next(req);
3214 if (!tevent_req_is_in_progress(req)) {
3215 return tevent_req_post(req, ev);
3218 return req;
3221 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3223 struct cli_smb1_setup_encryption_state *state =
3224 tevent_req_data(req,
3225 struct cli_smb1_setup_encryption_state);
3226 struct tevent_req *subreq = NULL;
3228 if (state->local_ready) {
3229 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3230 return;
3233 subreq = gensec_update_send(state, state->ev,
3234 state->es->gensec_security,
3235 state->blob_in);
3236 if (tevent_req_nomem(subreq, req)) {
3237 return;
3239 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3242 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3244 struct tevent_req *req =
3245 tevent_req_callback_data(subreq,
3246 struct tevent_req);
3247 struct cli_smb1_setup_encryption_state *state =
3248 tevent_req_data(req,
3249 struct cli_smb1_setup_encryption_state);
3250 NTSTATUS status;
3252 status = gensec_update_recv(subreq, state, &state->blob_out);
3253 TALLOC_FREE(subreq);
3254 state->blob_in = data_blob_null;
3255 if (!NT_STATUS_IS_OK(status) &&
3256 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3258 tevent_req_nterror(req, status);
3259 return;
3262 if (NT_STATUS_IS_OK(status)) {
3263 state->local_ready = true;
3267 * We always get NT_STATUS_OK from the server even if it is not ready.
3268 * So guess the server is ready when we are ready and already sent
3269 * our last blob to the server.
3271 if (state->local_ready && state->blob_out.length == 0) {
3272 state->remote_ready = true;
3275 if (state->local_ready && state->remote_ready) {
3276 cli_smb1_setup_encryption_ready(req);
3277 return;
3280 cli_smb1_setup_encryption_remote_next(req);
3283 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3285 struct cli_smb1_setup_encryption_state *state =
3286 tevent_req_data(req,
3287 struct cli_smb1_setup_encryption_state);
3288 struct tevent_req *subreq = NULL;
3290 if (state->remote_ready) {
3291 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3292 return;
3295 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3296 state->cli, state->blob_out);
3297 if (tevent_req_nomem(subreq, req)) {
3298 return;
3300 tevent_req_set_callback(subreq,
3301 cli_smb1_setup_encryption_remote_done,
3302 req);
3305 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3307 struct tevent_req *req =
3308 tevent_req_callback_data(subreq,
3309 struct tevent_req);
3310 struct cli_smb1_setup_encryption_state *state =
3311 tevent_req_data(req,
3312 struct cli_smb1_setup_encryption_state);
3313 NTSTATUS status;
3315 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3316 &state->blob_in,
3317 &state->es->enc_ctx_num);
3318 TALLOC_FREE(subreq);
3319 data_blob_free(&state->blob_out);
3320 if (!NT_STATUS_IS_OK(status) &&
3321 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3323 tevent_req_nterror(req, status);
3324 return;
3328 * We always get NT_STATUS_OK even if the server is not ready.
3329 * So guess the server is ready when we are ready and sent
3330 * our last blob to the server.
3332 if (state->local_ready) {
3333 state->remote_ready = true;
3336 if (state->local_ready && state->remote_ready) {
3337 cli_smb1_setup_encryption_ready(req);
3338 return;
3341 cli_smb1_setup_encryption_local_next(req);
3344 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3346 struct cli_smb1_setup_encryption_state *state =
3347 tevent_req_data(req,
3348 struct cli_smb1_setup_encryption_state);
3349 struct smb_trans_enc_state *es = NULL;
3351 if (state->blob_in.length != 0) {
3352 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3353 return;
3356 if (state->blob_out.length != 0) {
3357 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3358 return;
3361 es = talloc_move(state->cli->conn, &state->es);
3362 es->enc_on = true;
3363 smb1cli_conn_set_encryption(state->cli->conn, es);
3364 es = NULL;
3366 tevent_req_done(req);
3369 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3371 return tevent_req_simple_recv_ntstatus(req);
3374 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3375 struct cli_credentials *creds)
3377 struct tevent_context *ev = NULL;
3378 struct tevent_req *req = NULL;
3379 NTSTATUS status = NT_STATUS_NO_MEMORY;
3381 ev = samba_tevent_context_init(talloc_tos());
3382 if (ev == NULL) {
3383 goto fail;
3385 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3386 if (req == NULL) {
3387 goto fail;
3389 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3390 goto fail;
3392 status = cli_smb1_setup_encryption_recv(req);
3393 fail:
3394 TALLOC_FREE(ev);
3395 return status;
3399 establishes a connection right up to doing tconX, password specified.
3400 @param output_cli A fully initialised cli structure, non-null only on success
3401 @param dest_host The netbios name of the remote host
3402 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3403 @param port (optional) The destination port (0 for default)
3404 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3405 @param service_type The 'type' of service.
3406 @param creds The used user credentials
3409 struct cli_full_connection_creds_state {
3410 struct tevent_context *ev;
3411 const char *service;
3412 const char *service_type;
3413 struct cli_credentials *creds;
3414 int flags;
3415 struct cli_state *cli;
3418 static int cli_full_connection_creds_state_destructor(
3419 struct cli_full_connection_creds_state *s)
3421 if (s->cli != NULL) {
3422 cli_shutdown(s->cli);
3423 s->cli = NULL;
3425 return 0;
3428 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3429 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3430 static void cli_full_connection_creds_enc_start(struct tevent_req *req);
3431 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq);
3432 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq);
3433 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq);
3434 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req);
3435 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq);
3436 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3437 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3439 struct tevent_req *cli_full_connection_creds_send(
3440 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3441 const char *my_name, const char *dest_host,
3442 const struct sockaddr_storage *dest_ss, int port,
3443 const char *service, const char *service_type,
3444 struct cli_credentials *creds,
3445 int flags,
3446 struct smb2_negotiate_contexts *negotiate_contexts)
3448 struct tevent_req *req, *subreq;
3449 struct cli_full_connection_creds_state *state;
3450 enum smb_signing_setting signing_state;
3451 enum smb_encryption_setting encryption_state =
3452 cli_credentials_get_smb_encryption(creds);
3454 req = tevent_req_create(mem_ctx, &state,
3455 struct cli_full_connection_creds_state);
3456 if (req == NULL) {
3457 return NULL;
3459 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3461 state->ev = ev;
3462 state->service = service;
3463 state->service_type = service_type;
3464 state->creds = creds;
3465 state->flags = flags;
3467 if (flags & CLI_FULL_CONNECTION_IPC) {
3468 signing_state = cli_credentials_get_smb_ipc_signing(creds);
3469 } else {
3470 signing_state = cli_credentials_get_smb_signing(creds);
3473 if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
3474 if (flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK) {
3475 encryption_state = SMB_ENCRYPTION_DESIRED;
3479 if (encryption_state >= SMB_ENCRYPTION_DESIRED) {
3480 signing_state = SMB_SIGNING_REQUIRED;
3483 subreq = cli_start_connection_send(
3484 state, ev, my_name, dest_host, dest_ss, port,
3485 signing_state, flags,
3486 negotiate_contexts);
3487 if (tevent_req_nomem(subreq, req)) {
3488 return tevent_req_post(req, ev);
3490 tevent_req_set_callback(subreq,
3491 cli_full_connection_creds_conn_done,
3492 req);
3493 return req;
3496 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3498 struct tevent_req *req = tevent_req_callback_data(
3499 subreq, struct tevent_req);
3500 struct cli_full_connection_creds_state *state = tevent_req_data(
3501 req, struct cli_full_connection_creds_state);
3502 NTSTATUS status;
3504 status = cli_start_connection_recv(subreq, &state->cli);
3505 TALLOC_FREE(subreq);
3506 if (tevent_req_nterror(req, status)) {
3507 return;
3510 subreq = cli_session_setup_creds_send(
3511 state, state->ev, state->cli, state->creds);
3512 if (tevent_req_nomem(subreq, req)) {
3513 return;
3515 tevent_req_set_callback(subreq,
3516 cli_full_connection_creds_sess_done,
3517 req);
3520 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3522 struct tevent_req *req = tevent_req_callback_data(
3523 subreq, struct tevent_req);
3524 struct cli_full_connection_creds_state *state = tevent_req_data(
3525 req, struct cli_full_connection_creds_state);
3526 NTSTATUS status;
3528 status = cli_session_setup_creds_recv(subreq);
3529 TALLOC_FREE(subreq);
3531 if (!NT_STATUS_IS_OK(status) &&
3532 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3534 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3536 state->creds = cli_credentials_init_anon(state);
3537 if (tevent_req_nomem(state->creds, req)) {
3538 return;
3541 subreq = cli_session_setup_creds_send(
3542 state, state->ev, state->cli, state->creds);
3543 if (tevent_req_nomem(subreq, req)) {
3544 return;
3546 tevent_req_set_callback(subreq,
3547 cli_full_connection_creds_sess_done,
3548 req);
3549 return;
3552 if (tevent_req_nterror(req, status)) {
3553 return;
3556 cli_full_connection_creds_enc_start(req);
3559 static void cli_full_connection_creds_enc_start(struct tevent_req *req)
3561 struct cli_full_connection_creds_state *state = tevent_req_data(
3562 req, struct cli_full_connection_creds_state);
3563 enum smb_encryption_setting encryption_state =
3564 cli_credentials_get_smb_encryption(state->creds);
3565 struct tevent_req *subreq = NULL;
3566 NTSTATUS status;
3568 if (encryption_state < SMB_ENCRYPTION_DESIRED) {
3569 cli_full_connection_creds_tcon_start(req);
3570 return;
3573 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3574 status = smb2cli_session_encryption_on(state->cli->smb2.session);
3575 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
3576 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3577 cli_full_connection_creds_tcon_start(req);
3578 return;
3580 d_printf("Encryption required and "
3581 "server doesn't support "
3582 "SMB3 encryption - failing connect\n");
3583 tevent_req_nterror(req, status);
3584 return;
3585 } else if (!NT_STATUS_IS_OK(status)) {
3586 d_printf("Encryption required and "
3587 "setup failed with error %s.\n",
3588 nt_errstr(status));
3589 tevent_req_nterror(req, status);
3590 return;
3593 cli_full_connection_creds_tcon_start(req);
3594 return;
3597 if (!SERVER_HAS_UNIX_CIFS(state->cli)) {
3598 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3599 cli_full_connection_creds_tcon_start(req);
3600 return;
3603 status = NT_STATUS_NOT_SUPPORTED;
3604 d_printf("Encryption required and "
3605 "server doesn't support "
3606 "SMB1 Unix Extensions - failing connect\n");
3607 tevent_req_nterror(req, status);
3608 return;
3612 * We do a tcon on IPC$ just to setup the encryption,
3613 * the real tcon will be encrypted then.
3615 subreq = cli_tree_connect_send(state, state->ev, state->cli,
3616 "IPC$", "IPC", NULL);
3617 if (tevent_req_nomem(subreq, req)) {
3618 return;
3620 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_tcon, req);
3623 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq)
3625 struct tevent_req *req = tevent_req_callback_data(
3626 subreq, struct tevent_req);
3627 struct cli_full_connection_creds_state *state = tevent_req_data(
3628 req, struct cli_full_connection_creds_state);
3629 NTSTATUS status;
3631 status = cli_tree_connect_recv(subreq);
3632 TALLOC_FREE(subreq);
3633 if (tevent_req_nterror(req, status)) {
3634 return;
3637 subreq = cli_unix_extensions_version_send(state, state->ev, state->cli);
3638 if (tevent_req_nomem(subreq, req)) {
3639 return;
3641 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_ver, req);
3644 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq)
3646 struct tevent_req *req = tevent_req_callback_data(
3647 subreq, struct tevent_req);
3648 struct cli_full_connection_creds_state *state = tevent_req_data(
3649 req, struct cli_full_connection_creds_state);
3650 enum smb_encryption_setting encryption_state =
3651 cli_credentials_get_smb_encryption(state->creds);
3652 uint16_t major, minor;
3653 uint32_t caplow, caphigh;
3654 NTSTATUS status;
3656 status = cli_unix_extensions_version_recv(subreq,
3657 &major, &minor,
3658 &caplow,
3659 &caphigh);
3660 TALLOC_FREE(subreq);
3661 if (!NT_STATUS_IS_OK(status)) {
3662 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3663 /* disconnect ipc$ followed by the real tree connect */
3664 cli_full_connection_creds_enc_tdis(req);
3665 return;
3667 DEBUG(10, ("%s: cli_unix_extensions_version "
3668 "returned %s\n", __func__, nt_errstr(status)));
3669 tevent_req_nterror(req, NT_STATUS_UNKNOWN_REVISION);
3670 return;
3673 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
3674 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3675 /* disconnect ipc$ followed by the real tree connect */
3676 cli_full_connection_creds_enc_tdis(req);
3677 return;
3679 DEBUG(10, ("%s: CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP "
3680 "not supported\n", __func__));
3681 tevent_req_nterror(req, NT_STATUS_UNSUPPORTED_COMPRESSION);
3682 return;
3685 subreq = cli_smb1_setup_encryption_send(state, state->ev,
3686 state->cli,
3687 state->creds);
3688 if (tevent_req_nomem(subreq, req)) {
3689 return;
3691 tevent_req_set_callback(subreq,
3692 cli_full_connection_creds_enc_done,
3693 req);
3696 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq)
3698 struct tevent_req *req = tevent_req_callback_data(
3699 subreq, struct tevent_req);
3700 NTSTATUS status;
3702 status = cli_smb1_setup_encryption_recv(subreq);
3703 TALLOC_FREE(subreq);
3704 if (tevent_req_nterror(req, status)) {
3705 return;
3708 /* disconnect ipc$ followed by the real tree connect */
3709 cli_full_connection_creds_enc_tdis(req);
3712 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req)
3714 struct cli_full_connection_creds_state *state = tevent_req_data(
3715 req, struct cli_full_connection_creds_state);
3716 struct tevent_req *subreq = NULL;
3718 subreq = cli_tdis_send(state, state->ev, state->cli);
3719 if (tevent_req_nomem(subreq, req)) {
3720 return;
3722 tevent_req_set_callback(subreq,
3723 cli_full_connection_creds_enc_finished,
3724 req);
3727 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq)
3729 struct tevent_req *req = tevent_req_callback_data(
3730 subreq, struct tevent_req);
3731 NTSTATUS status;
3733 status = cli_tdis_recv(subreq);
3734 TALLOC_FREE(subreq);
3735 if (tevent_req_nterror(req, status)) {
3736 return;
3739 cli_full_connection_creds_tcon_start(req);
3742 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3744 struct cli_full_connection_creds_state *state = tevent_req_data(
3745 req, struct cli_full_connection_creds_state);
3746 struct tevent_req *subreq = NULL;
3747 const char *password = NULL;
3749 if (state->service == NULL) {
3750 tevent_req_done(req);
3751 return;
3754 password = cli_credentials_get_password(state->creds);
3756 subreq = cli_tree_connect_send(state, state->ev,
3757 state->cli,
3758 state->service,
3759 state->service_type,
3760 password);
3761 if (tevent_req_nomem(subreq, req)) {
3762 return;
3764 tevent_req_set_callback(subreq,
3765 cli_full_connection_creds_tcon_done,
3766 req);
3769 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3771 struct tevent_req *req = tevent_req_callback_data(
3772 subreq, struct tevent_req);
3773 NTSTATUS status;
3775 status = cli_tree_connect_recv(subreq);
3776 TALLOC_FREE(subreq);
3777 if (tevent_req_nterror(req, status)) {
3778 return;
3781 tevent_req_done(req);
3784 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3785 struct cli_state **output_cli)
3787 struct cli_full_connection_creds_state *state = tevent_req_data(
3788 req, struct cli_full_connection_creds_state);
3789 NTSTATUS status;
3791 if (tevent_req_is_nterror(req, &status)) {
3792 return status;
3794 *output_cli = state->cli;
3795 talloc_set_destructor(state, NULL);
3796 return NT_STATUS_OK;
3799 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3800 const char *my_name,
3801 const char *dest_host,
3802 const struct sockaddr_storage *dest_ss, int port,
3803 const char *service, const char *service_type,
3804 struct cli_credentials *creds,
3805 int flags)
3807 struct tevent_context *ev;
3808 struct tevent_req *req;
3809 NTSTATUS status = NT_STATUS_NO_MEMORY;
3811 ev = samba_tevent_context_init(talloc_tos());
3812 if (ev == NULL) {
3813 goto fail;
3815 req = cli_full_connection_creds_send(
3816 ev, ev, my_name, dest_host, dest_ss, port, service,
3817 service_type, creds, flags,
3818 NULL);
3819 if (req == NULL) {
3820 goto fail;
3822 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3823 goto fail;
3825 status = cli_full_connection_creds_recv(req, output_cli);
3826 fail:
3827 TALLOC_FREE(ev);
3828 return status;
3831 /****************************************************************************
3832 Send an old style tcon.
3833 ****************************************************************************/
3834 struct cli_raw_tcon_state {
3835 uint16_t *ret_vwv;
3838 static void cli_raw_tcon_done(struct tevent_req *subreq);
3840 static struct tevent_req *cli_raw_tcon_send(
3841 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3842 const char *service, const char *pass, const char *dev)
3844 struct tevent_req *req, *subreq;
3845 struct cli_raw_tcon_state *state;
3846 uint8_t *bytes;
3848 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3849 if (req == NULL) {
3850 return NULL;
3853 if (!lp_client_plaintext_auth() && (*pass)) {
3854 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3855 " or 'client ntlmv2 auth = yes'\n"));
3856 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3857 return tevent_req_post(req, ev);
3860 TALLOC_FREE(cli->smb1.tcon);
3861 cli->smb1.tcon = smbXcli_tcon_create(cli);
3862 if (tevent_req_nomem(cli->smb1.tcon, req)) {
3863 return tevent_req_post(req, ev);
3865 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
3867 bytes = talloc_array(state, uint8_t, 0);
3868 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3869 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3870 service, strlen(service)+1, NULL);
3871 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3872 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3873 pass, strlen(pass)+1, NULL);
3874 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3875 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3876 dev, strlen(dev)+1, NULL);
3878 if (tevent_req_nomem(bytes, req)) {
3879 return tevent_req_post(req, ev);
3882 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3883 talloc_get_size(bytes), bytes);
3884 if (tevent_req_nomem(subreq, req)) {
3885 return tevent_req_post(req, ev);
3887 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3888 return req;
3891 static void cli_raw_tcon_done(struct tevent_req *subreq)
3893 struct tevent_req *req = tevent_req_callback_data(
3894 subreq, struct tevent_req);
3895 struct cli_raw_tcon_state *state = tevent_req_data(
3896 req, struct cli_raw_tcon_state);
3897 NTSTATUS status;
3899 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3900 NULL, NULL);
3901 TALLOC_FREE(subreq);
3902 if (tevent_req_nterror(req, status)) {
3903 return;
3905 tevent_req_done(req);
3908 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3909 uint16_t *max_xmit, uint16_t *tid)
3911 struct cli_raw_tcon_state *state = tevent_req_data(
3912 req, struct cli_raw_tcon_state);
3913 NTSTATUS status;
3915 if (tevent_req_is_nterror(req, &status)) {
3916 return status;
3918 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3919 *tid = SVAL(state->ret_vwv + 1, 0);
3920 return NT_STATUS_OK;
3923 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3924 const char *service, const char *pass, const char *dev,
3925 uint16_t *max_xmit, uint16_t *tid)
3927 struct tevent_context *ev;
3928 struct tevent_req *req;
3929 NTSTATUS status = NT_STATUS_NO_MEMORY;
3931 ev = samba_tevent_context_init(talloc_tos());
3932 if (ev == NULL) {
3933 goto fail;
3935 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3936 if (req == NULL) {
3937 goto fail;
3939 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3940 goto fail;
3942 status = cli_raw_tcon_recv(req, max_xmit, tid);
3943 fail:
3944 TALLOC_FREE(ev);
3945 return status;
3948 /* Return a cli_state pointing at the IPC$ share for the given server */
3950 struct cli_state *get_ipc_connect(char *server,
3951 struct sockaddr_storage *server_ss,
3952 struct cli_credentials *creds)
3954 struct cli_state *cli;
3955 NTSTATUS nt_status;
3956 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3958 flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
3959 flags |= CLI_FULL_CONNECTION_IPC;
3961 nt_status = cli_full_connection_creds(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3962 creds,
3963 flags);
3965 if (NT_STATUS_IS_OK(nt_status)) {
3966 return cli;
3968 if (is_ipaddress(server)) {
3969 /* windows 9* needs a correct NMB name for connections */
3970 fstring remote_name;
3972 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3973 cli = get_ipc_connect(remote_name, server_ss, creds);
3974 if (cli)
3975 return cli;
3978 return NULL;
3982 * Given the IP address of a master browser on the network, return its
3983 * workgroup and connect to it.
3985 * This function is provided to allow additional processing beyond what
3986 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3987 * browsers and obtain each master browsers' list of domains (in case the
3988 * first master browser is recently on the network and has not yet
3989 * synchronized with other master browsers and therefore does not yet have the
3990 * entire network browse list)
3993 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3994 struct sockaddr_storage *mb_ip,
3995 struct cli_credentials *creds,
3996 char **pp_workgroup_out)
3998 char addr[INET6_ADDRSTRLEN];
3999 fstring name;
4000 struct cli_state *cli;
4001 struct sockaddr_storage server_ss;
4003 *pp_workgroup_out = NULL;
4005 print_sockaddr(addr, sizeof(addr), mb_ip);
4006 DEBUG(99, ("Looking up name of master browser %s\n",
4007 addr));
4010 * Do a name status query to find out the name of the master browser.
4011 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
4012 * master browser will not respond to a wildcard query (or, at least,
4013 * an NT4 server acting as the domain master browser will not).
4015 * We might be able to use ONLY the query on MSBROWSE, but that's not
4016 * yet been tested with all Windows versions, so until it is, leave
4017 * the original wildcard query as the first choice and fall back to
4018 * MSBROWSE if the wildcard query fails.
4020 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
4021 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
4023 DEBUG(99, ("Could not retrieve name status for %s\n",
4024 addr));
4025 return NULL;
4028 if (!find_master_ip(name, &server_ss)) {
4029 DEBUG(99, ("Could not find master ip for %s\n", name));
4030 return NULL;
4033 *pp_workgroup_out = talloc_strdup(ctx, name);
4035 DEBUG(4, ("found master browser %s, %s\n", name, addr));
4037 print_sockaddr(addr, sizeof(addr), &server_ss);
4038 cli = get_ipc_connect(addr, &server_ss, creds);
4040 return cli;