ctdb-tcp: Make error handling for outbound connection consistent
[Samba.git] / source3 / libsmb / cliconnect.c
blob82d8384e91c6867a8fd5ad050c86bc2d2de4f37a
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 "auth_info.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "../libcli/auth/spnego.h"
29 #include "smb_krb5.h"
30 #include "auth/credentials/credentials.h"
31 #include "auth/gensec/gensec.h"
32 #include "auth/ntlmssp/ntlmssp.h"
33 #include "auth_generic.h"
34 #include "libads/kerberos_proto.h"
35 #include "krb5_env.h"
36 #include "../lib/util/tevent_ntstatus.h"
37 #include "async_smb.h"
38 #include "libsmb/nmblib.h"
39 #include "librpc/ndr/libndr.h"
40 #include "../libcli/smb/smbXcli_base.h"
41 #include "../libcli/smb/smb_seal.h"
42 #include "lib/param/param.h"
43 #include "../libcli/smb/smb2_negotiate_context.h"
44 #include "libads/krb5_errs.h"
46 #define STAR_SMBSERVER "*SMBSERVER"
48 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
49 const char *principal);
51 struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
52 const char *username,
53 const char *domain,
54 const char *realm,
55 const char *password,
56 bool use_kerberos,
57 bool fallback_after_kerberos,
58 bool use_ccache,
59 bool password_is_nt_hash)
61 struct loadparm_context *lp_ctx = NULL;
62 struct cli_credentials *creds = NULL;
63 const char *principal = NULL;
64 char *tmp = NULL;
65 char *p = NULL;
66 bool ok;
68 creds = cli_credentials_init(mem_ctx);
69 if (creds == NULL) {
70 return NULL;
73 lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
74 if (lp_ctx == NULL) {
75 goto fail;
77 cli_credentials_set_conf(creds, lp_ctx);
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_AUTO_USE_KERBEROS);
129 } else if (use_kerberos) {
130 cli_credentials_set_kerberos_state(creds,
131 CRED_MUST_USE_KERBEROS);
132 } else {
133 cli_credentials_set_kerberos_state(creds,
134 CRED_DONT_USE_KERBEROS);
137 if (use_ccache) {
138 uint32_t features;
140 features = cli_credentials_get_gensec_features(creds);
141 features |= GENSEC_FEATURE_NTLM_CCACHE;
142 cli_credentials_set_gensec_features(creds, features);
144 if (password != NULL && strlen(password) == 0) {
146 * some callers pass "" as no password
148 * GENSEC_FEATURE_NTLM_CCACHE only handles
149 * NULL as no password.
151 password = NULL;
155 ok = cli_credentials_set_username(creds,
156 username,
157 CRED_SPECIFIED);
158 if (!ok) {
159 goto fail;
162 if (domain != NULL) {
163 ok = cli_credentials_set_domain(creds,
164 domain,
165 CRED_SPECIFIED);
166 if (!ok) {
167 goto fail;
171 if (principal != NULL) {
172 ok = cli_credentials_set_principal(creds,
173 principal,
174 CRED_SPECIFIED);
175 if (!ok) {
176 goto fail;
180 if (realm != NULL) {
181 ok = cli_credentials_set_realm(creds,
182 realm,
183 CRED_SPECIFIED);
184 if (!ok) {
185 goto fail;
189 if (password != NULL && strlen(password) > 0) {
190 if (password_is_nt_hash) {
191 struct samr_Password nt_hash;
192 size_t converted;
194 converted = strhex_to_str((char *)nt_hash.hash,
195 sizeof(nt_hash.hash),
196 password,
197 strlen(password));
198 if (converted != sizeof(nt_hash.hash)) {
199 goto fail;
202 ok = cli_credentials_set_nt_hash(creds,
203 &nt_hash,
204 CRED_SPECIFIED);
205 if (!ok) {
206 goto fail;
208 } else {
209 ok = cli_credentials_set_password(creds,
210 password,
211 CRED_SPECIFIED);
212 if (!ok) {
213 goto fail;
218 return creds;
219 fail:
220 TALLOC_FREE(creds);
221 return NULL;
224 NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
225 struct cli_credentials *creds)
227 TALLOC_CTX *frame = talloc_stackframe();
228 const char *user_principal = NULL;
229 const char *user_account = NULL;
230 const char *user_domain = NULL;
231 const char *pass = NULL;
232 char *canon_principal = NULL;
233 char *canon_realm = NULL;
234 const char *target_hostname = NULL;
235 enum credentials_use_kerberos krb5_state;
236 bool try_kerberos = false;
237 bool need_kinit = false;
238 bool auth_requested = true;
239 int ret;
240 bool ok;
242 target_hostname = smbXcli_conn_remote_name(cli->conn);
244 auth_requested = cli_credentials_authentication_requested(creds);
245 if (auth_requested) {
246 errno = 0;
247 user_principal = cli_credentials_get_principal(creds, frame);
248 if (errno != 0) {
249 TALLOC_FREE(frame);
250 return NT_STATUS_NO_MEMORY;
253 user_account = cli_credentials_get_username(creds);
254 user_domain = cli_credentials_get_domain(creds);
255 pass = cli_credentials_get_password(creds);
257 krb5_state = cli_credentials_get_kerberos_state(creds);
259 if (krb5_state != CRED_DONT_USE_KERBEROS) {
260 try_kerberos = true;
263 if (user_principal == NULL) {
264 try_kerberos = false;
267 if (target_hostname == NULL) {
268 try_kerberos = false;
269 } else if (is_ipaddress(target_hostname)) {
270 try_kerberos = false;
271 } else if (strequal(target_hostname, "localhost")) {
272 try_kerberos = false;
273 } else if (strequal(target_hostname, STAR_SMBSERVER)) {
274 try_kerberos = false;
275 } else if (!auth_requested) {
276 try_kerberos = false;
279 if (krb5_state == CRED_MUST_USE_KERBEROS && !try_kerberos) {
280 DEBUG(0, ("Kerberos auth with '%s' (%s\\%s) to access "
281 "'%s' not possible\n",
282 user_principal, user_domain, user_account,
283 target_hostname));
284 TALLOC_FREE(frame);
285 return NT_STATUS_ACCESS_DENIED;
288 if (pass == NULL || strlen(pass) == 0) {
289 need_kinit = false;
290 } else if (krb5_state == CRED_MUST_USE_KERBEROS) {
291 need_kinit = try_kerberos;
292 } else {
293 need_kinit = try_kerberos;
296 if (!need_kinit) {
297 TALLOC_FREE(frame);
298 return NT_STATUS_OK;
301 DBG_INFO("Doing kinit for %s to access %s\n",
302 user_principal, target_hostname);
305 * TODO: This should be done within the gensec layer
306 * only if required!
308 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
309 ret = kerberos_kinit_password_ext(user_principal,
310 pass,
314 NULL,
315 false,
316 false,
318 frame,
319 &canon_principal,
320 &canon_realm,
321 NULL);
322 if (ret != 0) {
323 int dbglvl = DBGLVL_NOTICE;
325 if (krb5_state == CRED_MUST_USE_KERBEROS) {
326 dbglvl = DBGLVL_ERR;
329 DEBUG(dbglvl, ("Kinit for %s to access %s failed: %s\n",
330 user_principal, target_hostname,
331 error_message(ret)));
332 if (krb5_state == CRED_MUST_USE_KERBEROS) {
333 TALLOC_FREE(frame);
334 return krb5_to_nt_status(ret);
338 * Ignore the error and hope that NTLM will work
340 TALLOC_FREE(frame);
341 return NT_STATUS_OK;
344 ok = cli_credentials_set_principal(creds,
345 canon_principal,
346 CRED_SPECIFIED);
347 if (!ok) {
348 TALLOC_FREE(frame);
349 return NT_STATUS_NO_MEMORY;
352 ok = cli_credentials_set_realm(creds,
353 canon_realm,
354 CRED_SPECIFIED);
355 if (!ok) {
356 TALLOC_FREE(frame);
357 return NT_STATUS_NO_MEMORY;
360 DBG_DEBUG("Successfully authenticated as %s (%s) to access %s using "
361 "Kerberos\n",
362 user_principal,
363 canon_principal,
364 target_hostname);
366 TALLOC_FREE(frame);
367 return NT_STATUS_OK;
370 static NTSTATUS cli_state_update_after_sesssetup(struct cli_state *cli,
371 const char *native_os,
372 const char *native_lm,
373 const char *primary_domain)
375 #define _VALID_STR(p) ((p) != NULL && (p)[0] != '\0')
377 if (!_VALID_STR(cli->server_os) && _VALID_STR(native_os)) {
378 cli->server_os = talloc_strdup(cli, native_os);
379 if (cli->server_os == NULL) {
380 return NT_STATUS_NO_MEMORY;
384 if (!_VALID_STR(cli->server_type) && _VALID_STR(native_lm)) {
385 cli->server_type = talloc_strdup(cli, native_lm);
386 if (cli->server_type == NULL) {
387 return NT_STATUS_NO_MEMORY;
391 if (!_VALID_STR(cli->server_domain) && _VALID_STR(primary_domain)) {
392 cli->server_domain = talloc_strdup(cli, primary_domain);
393 if (cli->server_domain == NULL) {
394 return NT_STATUS_NO_MEMORY;
398 #undef _VALID_STRING
399 return NT_STATUS_OK;
402 /********************************************************
403 Utility function to ensure we always return at least
404 a valid char * pointer to an empty string for the
405 cli->server_os, cli->server_type and cli->server_domain
406 strings.
407 *******************************************************/
409 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
410 const uint8_t *hdr,
411 char **dest,
412 uint8_t *src,
413 size_t srclen,
414 ssize_t *destlen)
416 *destlen = clistr_pull_talloc(mem_ctx,
417 (const char *)hdr,
418 SVAL(hdr, HDR_FLG2),
419 dest,
420 (char *)src,
421 srclen,
422 STR_TERMINATE);
423 if (*destlen == -1) {
424 return NT_STATUS_NO_MEMORY;
427 if (*dest == NULL) {
428 *dest = talloc_strdup(mem_ctx, "");
429 if (*dest == NULL) {
430 return NT_STATUS_NO_MEMORY;
433 return NT_STATUS_OK;
436 /****************************************************************************
437 Work out suitable capabilities to offer the server.
438 ****************************************************************************/
440 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
441 uint32_t sesssetup_capabilities)
443 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
446 * We only send capabilities based on the mask for:
447 * - client only flags
448 * - flags used in both directions
450 * We do not echo the server only flags, except some legacy flags.
452 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
453 * CAP_LARGE_WRITEX in order to allow us to do large reads
454 * against old Samba releases (<= 3.6.x).
456 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
459 * Session Setup specific flags CAP_DYNAMIC_REAUTH
460 * and CAP_EXTENDED_SECURITY are passed by the caller.
461 * We need that in order to do guest logins even if
462 * CAP_EXTENDED_SECURITY is negotiated.
464 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
465 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
466 client_capabilities |= sesssetup_capabilities;
468 return client_capabilities;
471 /****************************************************************************
472 Do a NT1 guest session setup.
473 ****************************************************************************/
475 struct cli_session_setup_guest_state {
476 struct cli_state *cli;
477 uint16_t vwv[13];
478 struct iovec bytes;
481 static void cli_session_setup_guest_done(struct tevent_req *subreq);
483 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
484 struct tevent_context *ev,
485 struct cli_state *cli,
486 struct tevent_req **psmbreq)
488 struct tevent_req *req, *subreq;
489 struct cli_session_setup_guest_state *state;
490 uint16_t *vwv;
491 uint8_t *bytes;
493 req = tevent_req_create(mem_ctx, &state,
494 struct cli_session_setup_guest_state);
495 if (req == NULL) {
496 return NULL;
498 state->cli = cli;
499 vwv = state->vwv;
501 SCVAL(vwv+0, 0, 0xFF);
502 SCVAL(vwv+0, 1, 0);
503 SSVAL(vwv+1, 0, 0);
504 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
505 SSVAL(vwv+3, 0, 2);
506 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
507 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
508 SSVAL(vwv+7, 0, 0);
509 SSVAL(vwv+8, 0, 0);
510 SSVAL(vwv+9, 0, 0);
511 SSVAL(vwv+10, 0, 0);
512 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
514 bytes = talloc_array(state, uint8_t, 0);
516 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
517 NULL);
518 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
519 NULL);
520 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
521 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
523 if (bytes == NULL) {
524 TALLOC_FREE(req);
525 return NULL;
528 state->bytes.iov_base = (void *)bytes;
529 state->bytes.iov_len = talloc_get_size(bytes);
531 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
532 vwv, 1, &state->bytes);
533 if (subreq == NULL) {
534 TALLOC_FREE(req);
535 return NULL;
537 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
538 *psmbreq = subreq;
539 return req;
542 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
543 struct tevent_context *ev,
544 struct cli_state *cli)
546 struct tevent_req *req, *subreq;
547 NTSTATUS status;
549 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
550 if (req == NULL) {
551 return NULL;
554 status = smb1cli_req_chain_submit(&subreq, 1);
555 if (!NT_STATUS_IS_OK(status)) {
556 tevent_req_nterror(req, status);
557 return tevent_req_post(req, ev);
559 return req;
562 static void cli_session_setup_guest_done(struct tevent_req *subreq)
564 struct tevent_req *req = tevent_req_callback_data(
565 subreq, struct tevent_req);
566 struct cli_session_setup_guest_state *state = tevent_req_data(
567 req, struct cli_session_setup_guest_state);
568 struct cli_state *cli = state->cli;
569 uint32_t num_bytes;
570 uint8_t *in;
571 uint8_t *inhdr;
572 uint8_t *bytes;
573 uint8_t *p;
574 NTSTATUS status;
575 ssize_t ret;
576 uint8_t wct;
577 uint16_t *vwv;
579 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
580 &num_bytes, &bytes);
581 TALLOC_FREE(subreq);
582 if (!NT_STATUS_IS_OK(status)) {
583 tevent_req_nterror(req, status);
584 return;
587 inhdr = in + NBT_HDR_SIZE;
588 p = bytes;
590 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
591 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
593 status = smb_bytes_talloc_string(cli,
594 inhdr,
595 &cli->server_os,
597 bytes+num_bytes-p,
598 &ret);
600 if (!NT_STATUS_IS_OK(status)) {
601 tevent_req_nterror(req, status);
602 return;
604 p += ret;
606 status = smb_bytes_talloc_string(cli,
607 inhdr,
608 &cli->server_type,
610 bytes+num_bytes-p,
611 &ret);
613 if (!NT_STATUS_IS_OK(status)) {
614 tevent_req_nterror(req, status);
615 return;
617 p += ret;
619 status = smb_bytes_talloc_string(cli,
620 inhdr,
621 &cli->server_domain,
623 bytes+num_bytes-p,
624 &ret);
626 if (!NT_STATUS_IS_OK(status)) {
627 tevent_req_nterror(req, status);
628 return;
631 tevent_req_done(req);
634 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
636 return tevent_req_simple_recv_ntstatus(req);
639 /* The following is calculated from :
640 * (smb_size-4) = 35
641 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
642 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
643 * end of packet.
646 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
648 struct cli_sesssetup_blob_state {
649 struct tevent_context *ev;
650 struct cli_state *cli;
651 DATA_BLOB blob;
652 uint16_t max_blob_size;
654 DATA_BLOB this_blob;
655 struct iovec *recv_iov;
657 NTSTATUS status;
658 const uint8_t *inbuf;
659 DATA_BLOB ret_blob;
661 char *out_native_os;
662 char *out_native_lm;
665 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
666 struct tevent_req **psubreq);
667 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
669 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
670 struct tevent_context *ev,
671 struct cli_state *cli,
672 DATA_BLOB blob)
674 struct tevent_req *req, *subreq;
675 struct cli_sesssetup_blob_state *state;
676 uint32_t usable_space;
678 req = tevent_req_create(mem_ctx, &state,
679 struct cli_sesssetup_blob_state);
680 if (req == NULL) {
681 return NULL;
683 state->ev = ev;
684 state->blob = blob;
685 state->cli = cli;
687 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
688 usable_space = UINT16_MAX;
689 } else {
690 usable_space = cli_state_available_size(cli,
691 BASE_SESSSETUP_BLOB_PACKET_SIZE);
694 if (usable_space == 0) {
695 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
696 "(not possible to send %u bytes)\n",
697 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
698 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
699 return tevent_req_post(req, ev);
701 state->max_blob_size = MIN(usable_space, 0xFFFF);
703 if (!cli_sesssetup_blob_next(state, &subreq)) {
704 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
705 return tevent_req_post(req, ev);
707 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
708 return req;
711 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
712 struct tevent_req **psubreq)
714 struct tevent_req *subreq;
715 uint16_t thistime;
717 thistime = MIN(state->blob.length, state->max_blob_size);
719 state->this_blob.data = state->blob.data;
720 state->this_blob.length = thistime;
722 state->blob.data += thistime;
723 state->blob.length -= thistime;
725 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
726 subreq = smb2cli_session_setup_send(state, state->ev,
727 state->cli->conn,
728 state->cli->timeout,
729 state->cli->smb2.session,
730 0, /* in_flags */
731 SMB2_CAP_DFS, /* in_capabilities */
732 0, /* in_channel */
733 0, /* in_previous_session_id */
734 &state->this_blob);
735 if (subreq == NULL) {
736 return false;
738 } else {
739 uint16_t in_buf_size = 0;
740 uint16_t in_mpx_max = 0;
741 uint16_t in_vc_num = 0;
742 uint32_t in_sess_key = 0;
743 uint32_t in_capabilities = 0;
744 const char *in_native_os = NULL;
745 const char *in_native_lm = NULL;
747 in_buf_size = CLI_BUFFER_SIZE;
748 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
749 in_vc_num = cli_state_get_vc_num(state->cli);
750 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
751 in_capabilities = cli_session_setup_capabilities(state->cli,
752 CAP_EXTENDED_SECURITY);
753 in_native_os = "Unix";
754 in_native_lm = "Samba";
757 * For now we keep the same values as before,
758 * we may remove these in a separate commit later.
760 in_mpx_max = 2;
761 in_vc_num = 1;
762 in_sess_key = 0;
764 subreq = smb1cli_session_setup_ext_send(state, state->ev,
765 state->cli->conn,
766 state->cli->timeout,
767 state->cli->smb1.pid,
768 state->cli->smb1.session,
769 in_buf_size,
770 in_mpx_max,
771 in_vc_num,
772 in_sess_key,
773 state->this_blob,
774 in_capabilities,
775 in_native_os,
776 in_native_lm);
777 if (subreq == NULL) {
778 return false;
781 *psubreq = subreq;
782 return true;
785 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
787 struct tevent_req *req = tevent_req_callback_data(
788 subreq, struct tevent_req);
789 struct cli_sesssetup_blob_state *state = tevent_req_data(
790 req, struct cli_sesssetup_blob_state);
791 NTSTATUS status;
793 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
794 status = smb2cli_session_setup_recv(subreq, state,
795 &state->recv_iov,
796 &state->ret_blob);
797 } else {
798 status = smb1cli_session_setup_ext_recv(subreq, state,
799 &state->recv_iov,
800 &state->inbuf,
801 &state->ret_blob,
802 &state->out_native_os,
803 &state->out_native_lm);
805 TALLOC_FREE(subreq);
806 if (!NT_STATUS_IS_OK(status)
807 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
808 tevent_req_nterror(req, status);
809 return;
812 state->status = status;
814 status = cli_state_update_after_sesssetup(state->cli,
815 state->out_native_os,
816 state->out_native_lm,
817 NULL);
818 if (tevent_req_nterror(req, status)) {
819 return;
822 if (state->blob.length != 0) {
824 * More to send
826 if (!cli_sesssetup_blob_next(state, &subreq)) {
827 tevent_req_oom(req);
828 return;
830 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
831 return;
833 tevent_req_done(req);
836 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
837 TALLOC_CTX *mem_ctx,
838 DATA_BLOB *pblob,
839 const uint8_t **pinbuf,
840 struct iovec **precv_iov)
842 struct cli_sesssetup_blob_state *state = tevent_req_data(
843 req, struct cli_sesssetup_blob_state);
844 NTSTATUS status;
845 struct iovec *recv_iov;
847 if (tevent_req_is_nterror(req, &status)) {
848 TALLOC_FREE(state->cli->smb2.session);
849 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
850 tevent_req_received(req);
851 return status;
854 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
855 if (pblob != NULL) {
856 *pblob = state->ret_blob;
858 if (pinbuf != NULL) {
859 *pinbuf = state->inbuf;
861 if (precv_iov != NULL) {
862 *precv_iov = recv_iov;
864 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
865 status = state->status;
866 tevent_req_received(req);
867 return status;
870 /****************************************************************************
871 Do a spnego/NTLMSSP encrypted session setup.
872 ****************************************************************************/
874 struct cli_session_setup_gensec_state {
875 struct tevent_context *ev;
876 struct cli_state *cli;
877 struct auth_generic_state *auth_generic;
878 bool is_anonymous;
879 DATA_BLOB blob_in;
880 const uint8_t *inbuf;
881 struct iovec *recv_iov;
882 DATA_BLOB blob_out;
883 bool local_ready;
884 bool remote_ready;
885 DATA_BLOB session_key;
888 static int cli_session_setup_gensec_state_destructor(
889 struct cli_session_setup_gensec_state *state)
891 TALLOC_FREE(state->auth_generic);
892 data_blob_clear_free(&state->session_key);
893 return 0;
896 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
897 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
898 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
899 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
900 static void cli_session_setup_gensec_ready(struct tevent_req *req);
902 static struct tevent_req *cli_session_setup_gensec_send(
903 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
904 struct cli_credentials *creds,
905 const char *target_service,
906 const char *target_hostname)
908 struct tevent_req *req;
909 struct cli_session_setup_gensec_state *state;
910 NTSTATUS status;
911 const DATA_BLOB *b = NULL;
913 req = tevent_req_create(mem_ctx, &state,
914 struct cli_session_setup_gensec_state);
915 if (req == NULL) {
916 return NULL;
918 state->ev = ev;
919 state->cli = cli;
921 talloc_set_destructor(
922 state, cli_session_setup_gensec_state_destructor);
924 status = auth_generic_client_prepare(state, &state->auth_generic);
925 if (tevent_req_nterror(req, status)) {
926 return tevent_req_post(req, ev);
929 status = auth_generic_set_creds(state->auth_generic, creds);
930 if (tevent_req_nterror(req, status)) {
931 return tevent_req_post(req, ev);
934 gensec_want_feature(state->auth_generic->gensec_security,
935 GENSEC_FEATURE_SESSION_KEY);
937 if (target_service != NULL) {
938 status = gensec_set_target_service(
939 state->auth_generic->gensec_security,
940 target_service);
941 if (tevent_req_nterror(req, status)) {
942 return tevent_req_post(req, ev);
946 if (target_hostname != NULL) {
947 status = gensec_set_target_hostname(
948 state->auth_generic->gensec_security,
949 target_hostname);
950 if (tevent_req_nterror(req, status)) {
951 return tevent_req_post(req, ev);
955 b = smbXcli_conn_server_gss_blob(cli->conn);
956 if (b != NULL) {
957 state->blob_in = *b;
960 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
962 status = auth_generic_client_start(state->auth_generic,
963 GENSEC_OID_SPNEGO);
964 if (tevent_req_nterror(req, status)) {
965 return tevent_req_post(req, ev);
968 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
969 state->cli->smb2.session = smbXcli_session_create(cli,
970 cli->conn);
971 if (tevent_req_nomem(state->cli->smb2.session, req)) {
972 return tevent_req_post(req, ev);
976 cli_session_setup_gensec_local_next(req);
977 if (!tevent_req_is_in_progress(req)) {
978 return tevent_req_post(req, ev);
981 return req;
984 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
986 struct cli_session_setup_gensec_state *state =
987 tevent_req_data(req,
988 struct cli_session_setup_gensec_state);
989 struct tevent_req *subreq = NULL;
991 if (state->local_ready) {
992 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
993 return;
996 subreq = gensec_update_send(state, state->ev,
997 state->auth_generic->gensec_security,
998 state->blob_in);
999 if (tevent_req_nomem(subreq, req)) {
1000 return;
1002 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1005 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1007 struct tevent_req *req =
1008 tevent_req_callback_data(subreq,
1009 struct tevent_req);
1010 struct cli_session_setup_gensec_state *state =
1011 tevent_req_data(req,
1012 struct cli_session_setup_gensec_state);
1013 NTSTATUS status;
1015 status = gensec_update_recv(subreq, state, &state->blob_out);
1016 TALLOC_FREE(subreq);
1017 state->blob_in = data_blob_null;
1018 if (!NT_STATUS_IS_OK(status) &&
1019 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1021 tevent_req_nterror(req, status);
1022 return;
1025 if (NT_STATUS_IS_OK(status)) {
1026 state->local_ready = true;
1029 if (state->local_ready && state->remote_ready) {
1030 cli_session_setup_gensec_ready(req);
1031 return;
1034 cli_session_setup_gensec_remote_next(req);
1037 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1039 struct cli_session_setup_gensec_state *state =
1040 tevent_req_data(req,
1041 struct cli_session_setup_gensec_state);
1042 struct tevent_req *subreq = NULL;
1044 if (state->remote_ready) {
1045 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1046 return;
1049 subreq = cli_sesssetup_blob_send(state, state->ev,
1050 state->cli, state->blob_out);
1051 if (tevent_req_nomem(subreq, req)) {
1052 return;
1054 tevent_req_set_callback(subreq,
1055 cli_session_setup_gensec_remote_done,
1056 req);
1059 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1061 struct tevent_req *req =
1062 tevent_req_callback_data(subreq,
1063 struct tevent_req);
1064 struct cli_session_setup_gensec_state *state =
1065 tevent_req_data(req,
1066 struct cli_session_setup_gensec_state);
1067 NTSTATUS status;
1069 state->inbuf = NULL;
1070 TALLOC_FREE(state->recv_iov);
1072 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1073 &state->inbuf, &state->recv_iov);
1074 TALLOC_FREE(subreq);
1075 data_blob_free(&state->blob_out);
1076 if (!NT_STATUS_IS_OK(status) &&
1077 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1079 tevent_req_nterror(req, status);
1080 return;
1083 if (NT_STATUS_IS_OK(status)) {
1084 struct smbXcli_session *session = NULL;
1085 bool is_guest = false;
1087 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1088 session = state->cli->smb2.session;
1089 } else {
1090 session = state->cli->smb1.session;
1093 is_guest = smbXcli_session_is_guest(session);
1094 if (is_guest) {
1096 * We can't finish the gensec handshake, we don't
1097 * have a negotiated session key.
1099 * So just pretend we are completely done,
1100 * we need to continue as anonymous from this point,
1101 * as we can't get a session key.
1103 * Note that smbXcli_session_is_guest()
1104 * always returns false if we require signing.
1106 state->blob_in = data_blob_null;
1107 state->local_ready = true;
1108 state->is_anonymous = true;
1111 state->remote_ready = true;
1114 if (state->local_ready && state->remote_ready) {
1115 cli_session_setup_gensec_ready(req);
1116 return;
1119 cli_session_setup_gensec_local_next(req);
1122 static void cli_session_dump_keys(TALLOC_CTX *mem_ctx,
1123 struct smbXcli_session *session,
1124 DATA_BLOB session_key)
1126 NTSTATUS status;
1127 DATA_BLOB sig = data_blob_null;
1128 DATA_BLOB app = data_blob_null;
1129 DATA_BLOB enc = data_blob_null;
1130 DATA_BLOB dec = data_blob_null;
1131 uint64_t sid = smb2cli_session_current_id(session);
1133 status = smb2cli_session_signing_key(session, mem_ctx, &sig);
1134 if (!NT_STATUS_IS_OK(status)) {
1135 goto out;
1137 status = smbXcli_session_application_key(session, mem_ctx, &app);
1138 if (!NT_STATUS_IS_OK(status)) {
1139 goto out;
1141 status = smb2cli_session_encryption_key(session, mem_ctx, &enc);
1142 if (!NT_STATUS_IS_OK(status)) {
1143 goto out;
1145 status = smb2cli_session_decryption_key(session, mem_ctx, &dec);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 goto out;
1150 DEBUG(0, ("debug encryption: dumping generated session keys\n"));
1151 DEBUGADD(0, ("Session Id "));
1152 dump_data(0, (uint8_t*)&sid, sizeof(sid));
1153 DEBUGADD(0, ("Session Key "));
1154 dump_data(0, session_key.data, session_key.length);
1155 DEBUGADD(0, ("Signing Key "));
1156 dump_data(0, sig.data, sig.length);
1157 DEBUGADD(0, ("App Key "));
1158 dump_data(0, app.data, app.length);
1160 /* In client code, ServerIn is the encryption key */
1162 DEBUGADD(0, ("ServerIn Key "));
1163 dump_data(0, enc.data, enc.length);
1164 DEBUGADD(0, ("ServerOut Key "));
1165 dump_data(0, dec.data, dec.length);
1167 out:
1168 data_blob_clear_free(&sig);
1169 data_blob_clear_free(&app);
1170 data_blob_clear_free(&enc);
1171 data_blob_clear_free(&dec);
1174 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1176 struct cli_session_setup_gensec_state *state =
1177 tevent_req_data(req,
1178 struct cli_session_setup_gensec_state);
1179 const char *server_domain = NULL;
1180 NTSTATUS status;
1182 if (state->blob_in.length != 0) {
1183 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1184 return;
1187 if (state->blob_out.length != 0) {
1188 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1189 return;
1193 * gensec_ntlmssp_server_domain() returns NULL
1194 * if NTLMSSP is not used.
1196 * We can remove this later
1197 * and leave the server domain empty for SMB2 and above
1198 * in future releases.
1200 server_domain = gensec_ntlmssp_server_domain(
1201 state->auth_generic->gensec_security);
1203 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1204 TALLOC_FREE(state->cli->server_domain);
1205 state->cli->server_domain = talloc_strdup(state->cli,
1206 server_domain);
1207 if (state->cli->server_domain == NULL) {
1208 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1209 return;
1213 if (state->is_anonymous) {
1215 * Windows server does not set the
1216 * SMB2_SESSION_FLAG_IS_NULL flag.
1218 * This fix makes sure we do not try
1219 * to verify a signature on the final
1220 * session setup response.
1222 tevent_req_done(req);
1223 return;
1226 status = gensec_session_key(state->auth_generic->gensec_security,
1227 state, &state->session_key);
1228 if (tevent_req_nterror(req, status)) {
1229 return;
1232 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1233 struct smbXcli_session *session = state->cli->smb2.session;
1235 status = smb2cli_session_set_session_key(session,
1236 state->session_key,
1237 state->recv_iov);
1238 if (tevent_req_nterror(req, status)) {
1239 return;
1241 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB3_00
1242 && lp_debug_encryption())
1244 cli_session_dump_keys(state, session, state->session_key);
1246 } else {
1247 struct smbXcli_session *session = state->cli->smb1.session;
1248 bool active;
1250 status = smb1cli_session_set_session_key(session,
1251 state->session_key);
1252 if (tevent_req_nterror(req, status)) {
1253 return;
1256 active = smb1cli_conn_activate_signing(state->cli->conn,
1257 state->session_key,
1258 data_blob_null);
1259 if (active) {
1260 bool ok;
1262 ok = smb1cli_conn_check_signing(state->cli->conn,
1263 state->inbuf, 1);
1264 if (!ok) {
1265 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1266 return;
1271 tevent_req_done(req);
1274 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1276 struct cli_session_setup_gensec_state *state =
1277 tevent_req_data(req,
1278 struct cli_session_setup_gensec_state);
1279 NTSTATUS status;
1281 if (tevent_req_is_nterror(req, &status)) {
1282 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1283 return status;
1285 return NT_STATUS_OK;
1288 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1289 const char *principal)
1291 char *account, *p;
1293 account = talloc_strdup(mem_ctx, principal);
1294 if (account == NULL) {
1295 return NULL;
1297 p = strchr_m(account, '@');
1298 if (p != NULL) {
1299 *p = '\0';
1301 return account;
1304 /****************************************************************************
1305 Do a spnego encrypted session setup.
1307 user_domain: The shortname of the domain the user/machine is a member of.
1308 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1309 ****************************************************************************/
1311 struct cli_session_setup_spnego_state {
1312 ADS_STATUS result;
1315 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1317 static struct tevent_req *cli_session_setup_spnego_send(
1318 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1319 struct cli_credentials *creds)
1321 struct tevent_req *req, *subreq;
1322 struct cli_session_setup_spnego_state *state;
1323 const char *target_service = NULL;
1324 const char *target_hostname = NULL;
1325 NTSTATUS status;
1327 req = tevent_req_create(mem_ctx, &state,
1328 struct cli_session_setup_spnego_state);
1329 if (req == NULL) {
1330 return NULL;
1333 target_service = "cifs";
1334 target_hostname = smbXcli_conn_remote_name(cli->conn);
1336 status = cli_session_creds_prepare_krb5(cli, creds);
1337 if (tevent_req_nterror(req, status)) {
1338 return tevent_req_post(req, ev);
1341 DBG_INFO("Connect to %s as %s using SPNEGO\n",
1342 target_hostname,
1343 cli_credentials_get_principal(creds, talloc_tos()));
1345 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1346 target_service, target_hostname);
1347 if (tevent_req_nomem(subreq, req)) {
1348 return tevent_req_post(req, ev);
1350 tevent_req_set_callback(
1351 subreq, cli_session_setup_spnego_done, req);
1352 return req;
1355 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1357 struct tevent_req *req = tevent_req_callback_data(
1358 subreq, struct tevent_req);
1359 NTSTATUS status;
1361 status = cli_session_setup_gensec_recv(subreq);
1362 TALLOC_FREE(subreq);
1363 if (tevent_req_nterror(req, status)) {
1364 return;
1367 tevent_req_done(req);
1370 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1372 struct cli_session_setup_spnego_state *state = tevent_req_data(
1373 req, struct cli_session_setup_spnego_state);
1374 NTSTATUS status;
1376 if (tevent_req_is_nterror(req, &status)) {
1377 state->result = ADS_ERROR_NT(status);
1380 return state->result;
1383 struct cli_session_setup_creds_state {
1384 struct cli_state *cli;
1385 DATA_BLOB apassword_blob;
1386 DATA_BLOB upassword_blob;
1387 DATA_BLOB lm_session_key;
1388 DATA_BLOB session_key;
1389 char *out_native_os;
1390 char *out_native_lm;
1391 char *out_primary_domain;
1394 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1395 enum tevent_req_state req_state)
1397 struct cli_session_setup_creds_state *state = tevent_req_data(
1398 req, struct cli_session_setup_creds_state);
1400 if (req_state != TEVENT_REQ_RECEIVED) {
1401 return;
1405 * We only call data_blob_clear() as
1406 * some of the blobs point to the same memory.
1408 * We let the talloc hierarchy free the memory.
1410 data_blob_clear(&state->apassword_blob);
1411 data_blob_clear(&state->upassword_blob);
1412 data_blob_clear(&state->lm_session_key);
1413 data_blob_clear(&state->session_key);
1414 ZERO_STRUCTP(state);
1417 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1418 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1419 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1421 /****************************************************************************
1422 Send a session setup. The username and workgroup is in UNIX character
1423 format and must be converted to DOS codepage format before sending. If the
1424 password is in plaintext, the same should be done.
1425 ****************************************************************************/
1427 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1428 struct tevent_context *ev,
1429 struct cli_state *cli,
1430 struct cli_credentials *creds)
1432 struct tevent_req *req, *subreq;
1433 struct cli_session_setup_creds_state *state;
1434 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1435 bool use_spnego = false;
1436 int flags = 0;
1437 enum credentials_use_kerberos krb5_state;
1438 uint32_t gensec_features;
1439 const char *username = "";
1440 const char *domain = "";
1441 DATA_BLOB target_info = data_blob_null;
1442 DATA_BLOB challenge = data_blob_null;
1443 uint16_t in_buf_size = 0;
1444 uint16_t in_mpx_max = 0;
1445 uint16_t in_vc_num = 0;
1446 uint32_t in_sess_key = 0;
1447 const char *in_native_os = NULL;
1448 const char *in_native_lm = NULL;
1449 NTSTATUS status;
1451 req = tevent_req_create(mem_ctx, &state,
1452 struct cli_session_setup_creds_state);
1453 if (req == NULL) {
1454 return NULL;
1456 state->cli = cli;
1458 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1460 krb5_state = cli_credentials_get_kerberos_state(creds);
1461 gensec_features = cli_credentials_get_gensec_features(creds);
1463 switch (krb5_state) {
1464 case CRED_MUST_USE_KERBEROS:
1465 cli->use_kerberos = true;
1466 cli->fallback_after_kerberos = false;
1467 break;
1468 case CRED_AUTO_USE_KERBEROS:
1469 cli->use_kerberos = true;
1470 cli->fallback_after_kerberos = true;
1471 break;
1472 case CRED_DONT_USE_KERBEROS:
1473 cli->use_kerberos = false;
1474 cli->fallback_after_kerberos = false;
1475 break;
1478 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
1479 cli->use_ccache = true;
1480 } else {
1481 cli->use_ccache = false;
1485 * Now work out what sort of session setup we are going to
1486 * do. I have split this into separate functions to make the flow a bit
1487 * easier to understand (tridge).
1489 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1490 use_spnego = false;
1491 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1492 use_spnego = true;
1493 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1495 * if the server supports extended security then use SPNEGO
1496 * even for anonymous connections.
1498 use_spnego = true;
1499 } else {
1500 use_spnego = false;
1503 if (use_spnego) {
1504 subreq = cli_session_setup_spnego_send(
1505 state, ev, cli, creds);
1506 if (tevent_req_nomem(subreq, req)) {
1507 return tevent_req_post(req, ev);
1509 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1510 req);
1511 return req;
1514 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1516 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1517 * this step against older servers.
1519 tevent_req_done(req);
1520 return tevent_req_post(req, ev);
1523 if (cli_credentials_is_anonymous(creds)) {
1525 * Do an anonymous session setup
1527 goto non_spnego_creds_done;
1530 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1532 * Do an anonymous session setup,
1533 * the password is passed via the tree connect.
1535 goto non_spnego_creds_done;
1538 cli_credentials_get_ntlm_username_domain(creds, state,
1539 &username,
1540 &domain);
1541 if (tevent_req_nomem(username, req)) {
1542 return tevent_req_post(req, ev);
1544 if (tevent_req_nomem(domain, req)) {
1545 return tevent_req_post(req, ev);
1548 DBG_INFO("Connect to %s as %s using NTLM\n", domain, username);
1550 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1551 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1552 uint8_t *bytes = NULL;
1553 size_t bytes_len = 0;
1554 const char *pw = cli_credentials_get_password(creds);
1555 size_t pw_len = 0;
1557 if (pw == NULL) {
1558 pw = "";
1560 pw_len = strlen(pw) + 1;
1562 if (!lp_client_plaintext_auth()) {
1563 DEBUG(1, ("Server requested PLAINTEXT password but "
1564 "'client plaintext auth = no'\n"));
1565 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1566 return tevent_req_post(req, ev);
1569 bytes = talloc_array(state, uint8_t, 0);
1570 bytes = trans2_bytes_push_str(bytes, use_unicode,
1571 pw, pw_len, &bytes_len);
1572 if (tevent_req_nomem(bytes, req)) {
1573 return tevent_req_post(req, ev);
1576 if (use_unicode) {
1578 * CAP_UNICODE, can only be negotiated by NT1.
1580 state->upassword_blob = data_blob_const(bytes,
1581 bytes_len);
1582 } else {
1583 state->apassword_blob = data_blob_const(bytes,
1584 bytes_len);
1587 goto non_spnego_creds_done;
1590 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1592 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1593 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1595 * Don't send an NTLMv2 response without NTLMSSP if we
1596 * want to use spnego support.
1598 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1599 " but 'client use spnego = yes'"
1600 " and 'client ntlmv2 auth = yes' is set\n"));
1601 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1602 return tevent_req_post(req, ev);
1605 if (lp_client_ntlmv2_auth()) {
1606 flags |= CLI_CRED_NTLMv2_AUTH;
1609 * note that the 'domain' here is a best
1610 * guess - we don't know the server's domain
1611 * at this point. Windows clients also don't
1612 * use hostname...
1614 target_info = NTLMv2_generate_names_blob(state,
1615 NULL,
1616 domain);
1617 if (tevent_req_nomem(target_info.data, req)) {
1618 return tevent_req_post(req, ev);
1620 } else {
1621 flags |= CLI_CRED_NTLM_AUTH;
1622 if (lp_client_lanman_auth()) {
1623 flags |= CLI_CRED_LANMAN_AUTH;
1626 } else {
1627 if (!lp_client_lanman_auth()) {
1628 DEBUG(1, ("Server requested user level LM password but "
1629 "'client lanman auth = no' is set.\n"));
1630 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1631 return tevent_req_post(req, ev);
1634 flags |= CLI_CRED_LANMAN_AUTH;
1637 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1638 challenge, NULL,
1639 target_info,
1640 &state->apassword_blob,
1641 &state->upassword_blob,
1642 &state->lm_session_key,
1643 &state->session_key);
1644 if (tevent_req_nterror(req, status)) {
1645 return tevent_req_post(req, ev);
1648 non_spnego_creds_done:
1650 in_buf_size = CLI_BUFFER_SIZE;
1651 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1652 in_vc_num = cli_state_get_vc_num(cli);
1653 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1654 in_native_os = "Unix";
1655 in_native_lm = "Samba";
1657 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1658 uint32_t in_capabilities = 0;
1660 in_capabilities = cli_session_setup_capabilities(cli, 0);
1663 * For now we keep the same values as before,
1664 * we may remove these in a separate commit later.
1666 in_mpx_max = 2;
1668 subreq = smb1cli_session_setup_nt1_send(state, ev,
1669 cli->conn,
1670 cli->timeout,
1671 cli->smb1.pid,
1672 cli->smb1.session,
1673 in_buf_size,
1674 in_mpx_max,
1675 in_vc_num,
1676 in_sess_key,
1677 username,
1678 domain,
1679 state->apassword_blob,
1680 state->upassword_blob,
1681 in_capabilities,
1682 in_native_os,
1683 in_native_lm);
1684 if (tevent_req_nomem(subreq, req)) {
1685 return tevent_req_post(req, ev);
1687 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1688 req);
1689 return req;
1693 * For now we keep the same values as before,
1694 * we may remove these in a separate commit later.
1696 in_mpx_max = 2;
1697 in_vc_num = 1;
1699 subreq = smb1cli_session_setup_lm21_send(state, ev,
1700 cli->conn,
1701 cli->timeout,
1702 cli->smb1.pid,
1703 cli->smb1.session,
1704 in_buf_size,
1705 in_mpx_max,
1706 in_vc_num,
1707 in_sess_key,
1708 username,
1709 domain,
1710 state->apassword_blob,
1711 in_native_os,
1712 in_native_lm);
1713 if (tevent_req_nomem(subreq, req)) {
1714 return tevent_req_post(req, ev);
1716 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1717 req);
1718 return req;
1721 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1723 struct tevent_req *req = tevent_req_callback_data(
1724 subreq, struct tevent_req);
1725 ADS_STATUS status;
1727 status = cli_session_setup_spnego_recv(subreq);
1728 TALLOC_FREE(subreq);
1729 if (!ADS_ERR_OK(status)) {
1730 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1731 tevent_req_nterror(req, ads_ntstatus(status));
1732 return;
1734 tevent_req_done(req);
1737 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1739 struct tevent_req *req = tevent_req_callback_data(
1740 subreq, struct tevent_req);
1741 struct cli_session_setup_creds_state *state = tevent_req_data(
1742 req, struct cli_session_setup_creds_state);
1743 struct cli_state *cli = state->cli;
1744 NTSTATUS status;
1745 struct iovec *recv_iov = NULL;
1746 const uint8_t *inbuf = NULL;
1747 bool ok;
1749 status = smb1cli_session_setup_nt1_recv(subreq, state,
1750 &recv_iov,
1751 &inbuf,
1752 &state->out_native_os,
1753 &state->out_native_lm,
1754 &state->out_primary_domain);
1755 TALLOC_FREE(subreq);
1756 if (!NT_STATUS_IS_OK(status)) {
1757 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1758 tevent_req_nterror(req, status);
1759 return;
1762 status = cli_state_update_after_sesssetup(state->cli,
1763 state->out_native_os,
1764 state->out_native_lm,
1765 state->out_primary_domain);
1766 if (tevent_req_nterror(req, status)) {
1767 return;
1770 ok = smb1cli_conn_activate_signing(cli->conn,
1771 state->session_key,
1772 state->upassword_blob);
1773 if (ok) {
1774 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1775 if (!ok) {
1776 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1777 return;
1781 if (state->session_key.data) {
1782 struct smbXcli_session *session = cli->smb1.session;
1784 status = smb1cli_session_set_session_key(session,
1785 state->session_key);
1786 if (tevent_req_nterror(req, status)) {
1787 return;
1791 tevent_req_done(req);
1794 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1796 struct tevent_req *req = tevent_req_callback_data(
1797 subreq, struct tevent_req);
1798 struct cli_session_setup_creds_state *state = tevent_req_data(
1799 req, struct cli_session_setup_creds_state);
1800 NTSTATUS status;
1802 status = smb1cli_session_setup_lm21_recv(subreq, state,
1803 &state->out_native_os,
1804 &state->out_native_lm);
1805 TALLOC_FREE(subreq);
1806 if (!NT_STATUS_IS_OK(status)) {
1807 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1808 tevent_req_nterror(req, status);
1809 return;
1812 status = cli_state_update_after_sesssetup(state->cli,
1813 state->out_native_os,
1814 state->out_native_lm,
1815 NULL);
1816 if (tevent_req_nterror(req, status)) {
1817 return;
1820 tevent_req_done(req);
1823 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1825 return tevent_req_simple_recv_ntstatus(req);
1828 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1829 struct cli_credentials *creds)
1831 struct tevent_context *ev;
1832 struct tevent_req *req;
1833 NTSTATUS status = NT_STATUS_NO_MEMORY;
1835 if (smbXcli_conn_has_async_calls(cli->conn)) {
1836 return NT_STATUS_INVALID_PARAMETER;
1838 ev = samba_tevent_context_init(talloc_tos());
1839 if (ev == NULL) {
1840 goto fail;
1842 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1843 if (req == NULL) {
1844 goto fail;
1846 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1847 goto fail;
1849 status = cli_session_setup_creds_recv(req);
1850 fail:
1851 TALLOC_FREE(ev);
1852 return status;
1855 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1857 NTSTATUS status;
1858 struct cli_credentials *creds = NULL;
1860 creds = cli_credentials_init_anon(cli);
1861 if (creds == NULL) {
1862 return NT_STATUS_NO_MEMORY;
1865 status = cli_session_setup_creds(cli, creds);
1866 TALLOC_FREE(creds);
1867 if (!NT_STATUS_IS_OK(status)) {
1868 return status;
1871 return NT_STATUS_OK;
1874 /****************************************************************************
1875 Send a uloggoff.
1876 *****************************************************************************/
1878 struct cli_ulogoff_state {
1879 struct cli_state *cli;
1880 uint16_t vwv[3];
1883 static void cli_ulogoff_done(struct tevent_req *subreq);
1885 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1886 struct tevent_context *ev,
1887 struct cli_state *cli)
1889 struct tevent_req *req, *subreq;
1890 struct cli_ulogoff_state *state;
1892 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1893 if (req == NULL) {
1894 return NULL;
1896 state->cli = cli;
1898 SCVAL(state->vwv+0, 0, 0xFF);
1899 SCVAL(state->vwv+1, 0, 0);
1900 SSVAL(state->vwv+2, 0, 0);
1902 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1903 0, NULL);
1904 if (tevent_req_nomem(subreq, req)) {
1905 return tevent_req_post(req, ev);
1907 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1908 return req;
1911 static void cli_ulogoff_done(struct tevent_req *subreq)
1913 struct tevent_req *req = tevent_req_callback_data(
1914 subreq, struct tevent_req);
1915 struct cli_ulogoff_state *state = tevent_req_data(
1916 req, struct cli_ulogoff_state);
1917 NTSTATUS status;
1919 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1920 if (!NT_STATUS_IS_OK(status)) {
1921 tevent_req_nterror(req, status);
1922 return;
1924 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1925 tevent_req_done(req);
1928 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1930 return tevent_req_simple_recv_ntstatus(req);
1933 NTSTATUS cli_ulogoff(struct cli_state *cli)
1935 struct tevent_context *ev;
1936 struct tevent_req *req;
1937 NTSTATUS status = NT_STATUS_NO_MEMORY;
1939 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1940 status = smb2cli_logoff(cli->conn,
1941 cli->timeout,
1942 cli->smb2.session);
1943 if (!NT_STATUS_IS_OK(status)) {
1944 return status;
1946 smb2cli_session_set_id_and_flags(cli->smb2.session,
1947 UINT64_MAX, 0);
1948 return NT_STATUS_OK;
1951 if (smbXcli_conn_has_async_calls(cli->conn)) {
1952 return NT_STATUS_INVALID_PARAMETER;
1954 ev = samba_tevent_context_init(talloc_tos());
1955 if (ev == NULL) {
1956 goto fail;
1958 req = cli_ulogoff_send(ev, ev, cli);
1959 if (req == NULL) {
1960 goto fail;
1962 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1963 goto fail;
1965 status = cli_ulogoff_recv(req);
1966 fail:
1967 TALLOC_FREE(ev);
1968 return status;
1971 /****************************************************************************
1972 Send a tconX.
1973 ****************************************************************************/
1975 struct cli_tcon_andx_state {
1976 struct cli_state *cli;
1977 uint16_t vwv[4];
1978 struct iovec bytes;
1981 static void cli_tcon_andx_done(struct tevent_req *subreq);
1983 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1984 struct tevent_context *ev,
1985 struct cli_state *cli,
1986 const char *share, const char *dev,
1987 const char *pass, int passlen,
1988 struct tevent_req **psmbreq)
1990 struct tevent_req *req, *subreq;
1991 struct cli_tcon_andx_state *state;
1992 uint8_t p24[24];
1993 uint16_t *vwv;
1994 char *tmp = NULL;
1995 uint8_t *bytes;
1996 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1997 uint16_t tcon_flags = 0;
1999 *psmbreq = NULL;
2001 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2002 if (req == NULL) {
2003 return NULL;
2005 state->cli = cli;
2006 vwv = state->vwv;
2008 TALLOC_FREE(cli->smb1.tcon);
2009 cli->smb1.tcon = smbXcli_tcon_create(cli);
2010 if (tevent_req_nomem(cli->smb1.tcon, req)) {
2011 return tevent_req_post(req, ev);
2013 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
2015 cli->share = talloc_strdup(cli, share);
2016 if (!cli->share) {
2017 return NULL;
2020 /* in user level security don't send a password now */
2021 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2022 passlen = 1;
2023 pass = "";
2024 } else if (pass == NULL) {
2025 DEBUG(1, ("Server not using user level security and no "
2026 "password supplied.\n"));
2027 goto access_denied;
2030 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2031 *pass && passlen != 24) {
2032 if (!lp_client_lanman_auth()) {
2033 DEBUG(1, ("Server requested LANMAN password "
2034 "(share-level security) but "
2035 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2036 goto access_denied;
2040 * Non-encrypted passwords - convert to DOS codepage before
2041 * encryption.
2043 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2044 passlen = 24;
2045 pass = (const char *)p24;
2046 } else {
2047 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2048 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2049 == 0) {
2050 uint8_t *tmp_pass;
2052 if (!lp_client_plaintext_auth() && (*pass)) {
2053 DEBUG(1, ("Server requested PLAINTEXT "
2054 "password but "
2055 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2056 goto access_denied;
2060 * Non-encrypted passwords - convert to DOS codepage
2061 * before using.
2063 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2064 if (tevent_req_nomem(tmp_pass, req)) {
2065 return tevent_req_post(req, ev);
2067 tmp_pass = trans2_bytes_push_str(tmp_pass,
2068 false, /* always DOS */
2069 pass,
2070 passlen,
2071 NULL);
2072 if (tevent_req_nomem(tmp_pass, req)) {
2073 return tevent_req_post(req, ev);
2075 pass = (const char *)tmp_pass;
2076 passlen = talloc_get_size(tmp_pass);
2080 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2081 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2083 SCVAL(vwv+0, 0, 0xFF);
2084 SCVAL(vwv+0, 1, 0);
2085 SSVAL(vwv+1, 0, 0);
2086 SSVAL(vwv+2, 0, tcon_flags);
2087 SSVAL(vwv+3, 0, passlen);
2089 if (passlen && pass) {
2090 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2091 } else {
2092 bytes = talloc_array(state, uint8_t, 0);
2096 * Add the sharename
2098 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2099 smbXcli_conn_remote_name(cli->conn), share);
2100 if (tmp == NULL) {
2101 TALLOC_FREE(req);
2102 return NULL;
2104 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2105 NULL);
2106 TALLOC_FREE(tmp);
2109 * Add the devicetype
2111 tmp = talloc_strdup_upper(talloc_tos(), dev);
2112 if (tmp == NULL) {
2113 TALLOC_FREE(req);
2114 return NULL;
2116 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2117 TALLOC_FREE(tmp);
2119 if (bytes == NULL) {
2120 TALLOC_FREE(req);
2121 return NULL;
2124 state->bytes.iov_base = (void *)bytes;
2125 state->bytes.iov_len = talloc_get_size(bytes);
2127 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2128 1, &state->bytes);
2129 if (subreq == NULL) {
2130 TALLOC_FREE(req);
2131 return NULL;
2133 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2134 *psmbreq = subreq;
2135 return req;
2137 access_denied:
2138 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2139 return tevent_req_post(req, ev);
2142 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2143 struct tevent_context *ev,
2144 struct cli_state *cli,
2145 const char *share, const char *dev,
2146 const char *pass, int passlen)
2148 struct tevent_req *req, *subreq;
2149 NTSTATUS status;
2151 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2152 &subreq);
2153 if (req == NULL) {
2154 return NULL;
2156 if (subreq == NULL) {
2157 return req;
2159 status = smb1cli_req_chain_submit(&subreq, 1);
2160 if (!NT_STATUS_IS_OK(status)) {
2161 tevent_req_nterror(req, status);
2162 return tevent_req_post(req, ev);
2164 return req;
2167 static void cli_tcon_andx_done(struct tevent_req *subreq)
2169 struct tevent_req *req = tevent_req_callback_data(
2170 subreq, struct tevent_req);
2171 struct cli_tcon_andx_state *state = tevent_req_data(
2172 req, struct cli_tcon_andx_state);
2173 struct cli_state *cli = state->cli;
2174 uint8_t *in;
2175 uint8_t *inhdr;
2176 uint8_t wct;
2177 uint16_t *vwv;
2178 uint32_t num_bytes;
2179 uint8_t *bytes;
2180 NTSTATUS status;
2181 uint16_t optional_support = 0;
2183 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2184 &num_bytes, &bytes);
2185 TALLOC_FREE(subreq);
2186 if (!NT_STATUS_IS_OK(status)) {
2187 tevent_req_nterror(req, status);
2188 return;
2191 inhdr = in + NBT_HDR_SIZE;
2193 if (num_bytes) {
2194 if (clistr_pull_talloc(cli,
2195 (const char *)inhdr,
2196 SVAL(inhdr, HDR_FLG2),
2197 &cli->dev,
2198 bytes,
2199 num_bytes,
2200 STR_TERMINATE|STR_ASCII) == -1) {
2201 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2202 return;
2204 } else {
2205 cli->dev = talloc_strdup(cli, "");
2206 if (cli->dev == NULL) {
2207 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2208 return;
2212 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2213 /* almost certainly win95 - enable bug fixes */
2214 cli->win95 = True;
2218 * Make sure that we have the optional support 16-bit field. WCT > 2.
2219 * Avoids issues when connecting to Win9x boxes sharing files
2222 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2223 optional_support = SVAL(vwv+2, 0);
2226 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2227 smb1cli_session_protect_session_key(cli->smb1.session);
2230 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2231 SVAL(inhdr, HDR_TID),
2232 optional_support,
2233 0, /* maximal_access */
2234 0, /* guest_maximal_access */
2235 NULL, /* service */
2236 NULL); /* fs_type */
2238 tevent_req_done(req);
2241 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2243 return tevent_req_simple_recv_ntstatus(req);
2246 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2247 const char *dev, const char *pass, int passlen)
2249 TALLOC_CTX *frame = talloc_stackframe();
2250 struct tevent_context *ev;
2251 struct tevent_req *req;
2252 NTSTATUS status = NT_STATUS_NO_MEMORY;
2254 if (smbXcli_conn_has_async_calls(cli->conn)) {
2256 * Can't use sync call while an async call is in flight
2258 status = NT_STATUS_INVALID_PARAMETER;
2259 goto fail;
2262 ev = samba_tevent_context_init(frame);
2263 if (ev == NULL) {
2264 goto fail;
2267 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2268 if (req == NULL) {
2269 goto fail;
2272 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2273 goto fail;
2276 status = cli_tcon_andx_recv(req);
2277 fail:
2278 TALLOC_FREE(frame);
2279 return status;
2282 struct cli_tree_connect_state {
2283 struct cli_state *cli;
2286 static struct tevent_req *cli_raw_tcon_send(
2287 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2288 const char *service, const char *pass, const char *dev);
2289 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2290 uint16_t *max_xmit, uint16_t *tid);
2292 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2293 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2294 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2296 static struct tevent_req *cli_tree_connect_send(
2297 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2298 const char *share, const char *dev, const char *pass)
2300 struct tevent_req *req, *subreq;
2301 struct cli_tree_connect_state *state;
2302 int passlen;
2304 if (pass == NULL) {
2305 pass = "";
2307 passlen = strlen(pass) + 1;
2309 req = tevent_req_create(mem_ctx, &state,
2310 struct cli_tree_connect_state);
2311 if (req == NULL) {
2312 return NULL;
2314 state->cli = cli;
2316 cli->share = talloc_strdup(cli, share);
2317 if (tevent_req_nomem(cli->share, req)) {
2318 return tevent_req_post(req, ev);
2321 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2322 char *unc;
2324 TALLOC_FREE(cli->smb2.tcon);
2325 cli->smb2.tcon = smbXcli_tcon_create(cli);
2326 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2327 return tevent_req_post(req, ev);
2330 unc = talloc_asprintf(state, "\\\\%s\\%s",
2331 smbXcli_conn_remote_name(cli->conn),
2332 share);
2333 if (tevent_req_nomem(unc, req)) {
2334 return tevent_req_post(req, ev);
2337 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2338 cli->smb2.session, cli->smb2.tcon,
2339 0, /* flags */
2340 unc);
2341 if (tevent_req_nomem(subreq, req)) {
2342 return tevent_req_post(req, ev);
2344 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2345 req);
2346 return req;
2349 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2350 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2351 pass, passlen);
2352 if (tevent_req_nomem(subreq, req)) {
2353 return tevent_req_post(req, ev);
2355 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2356 req);
2357 return req;
2360 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2361 if (tevent_req_nomem(subreq, req)) {
2362 return tevent_req_post(req, ev);
2364 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2366 return req;
2369 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2371 tevent_req_simple_finish_ntstatus(
2372 subreq, smb2cli_tcon_recv(subreq));
2375 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2377 tevent_req_simple_finish_ntstatus(
2378 subreq, cli_tcon_andx_recv(subreq));
2381 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2383 struct tevent_req *req = tevent_req_callback_data(
2384 subreq, struct tevent_req);
2385 struct cli_tree_connect_state *state = tevent_req_data(
2386 req, struct cli_tree_connect_state);
2387 NTSTATUS status;
2388 uint16_t max_xmit = 0;
2389 uint16_t tid = 0;
2391 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2392 if (tevent_req_nterror(req, status)) {
2393 return;
2396 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2397 tid,
2398 0, /* optional_support */
2399 0, /* maximal_access */
2400 0, /* guest_maximal_access */
2401 NULL, /* service */
2402 NULL); /* fs_type */
2404 tevent_req_done(req);
2407 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2409 return tevent_req_simple_recv_ntstatus(req);
2412 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2413 const char *dev, const char *pass)
2415 struct tevent_context *ev;
2416 struct tevent_req *req;
2417 NTSTATUS status = NT_STATUS_NO_MEMORY;
2419 if (smbXcli_conn_has_async_calls(cli->conn)) {
2420 return NT_STATUS_INVALID_PARAMETER;
2422 ev = samba_tevent_context_init(talloc_tos());
2423 if (ev == NULL) {
2424 goto fail;
2426 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2427 if (req == NULL) {
2428 goto fail;
2430 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2431 goto fail;
2433 status = cli_tree_connect_recv(req);
2434 fail:
2435 TALLOC_FREE(ev);
2436 return status;
2439 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2440 const char *share, const char *dev,
2441 struct cli_credentials *creds)
2443 const char *pw = NULL;
2445 if (creds != NULL) {
2446 pw = cli_credentials_get_password(creds);
2449 return cli_tree_connect(cli, share, dev, pw);
2452 /****************************************************************************
2453 Send a tree disconnect.
2454 ****************************************************************************/
2456 struct cli_tdis_state {
2457 struct cli_state *cli;
2460 static void cli_tdis_done(struct tevent_req *subreq);
2462 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2463 struct tevent_context *ev,
2464 struct cli_state *cli)
2466 struct tevent_req *req, *subreq;
2467 struct cli_tdis_state *state;
2469 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2470 if (req == NULL) {
2471 return NULL;
2473 state->cli = cli;
2475 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2476 if (tevent_req_nomem(subreq, req)) {
2477 return tevent_req_post(req, ev);
2479 tevent_req_set_callback(subreq, cli_tdis_done, req);
2480 return req;
2483 static void cli_tdis_done(struct tevent_req *subreq)
2485 struct tevent_req *req = tevent_req_callback_data(
2486 subreq, struct tevent_req);
2487 struct cli_tdis_state *state = tevent_req_data(
2488 req, struct cli_tdis_state);
2489 NTSTATUS status;
2491 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2492 TALLOC_FREE(subreq);
2493 if (!NT_STATUS_IS_OK(status)) {
2494 tevent_req_nterror(req, status);
2495 return;
2497 TALLOC_FREE(state->cli->smb1.tcon);
2498 tevent_req_done(req);
2501 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2503 return tevent_req_simple_recv_ntstatus(req);
2506 NTSTATUS cli_tdis(struct cli_state *cli)
2508 struct tevent_context *ev;
2509 struct tevent_req *req;
2510 NTSTATUS status = NT_STATUS_NO_MEMORY;
2512 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2513 status = smb2cli_tdis(cli->conn,
2514 cli->timeout,
2515 cli->smb2.session,
2516 cli->smb2.tcon);
2517 if (NT_STATUS_IS_OK(status)) {
2518 TALLOC_FREE(cli->smb2.tcon);
2520 return status;
2523 if (smbXcli_conn_has_async_calls(cli->conn)) {
2524 return NT_STATUS_INVALID_PARAMETER;
2526 ev = samba_tevent_context_init(talloc_tos());
2527 if (ev == NULL) {
2528 goto fail;
2530 req = cli_tdis_send(ev, ev, cli);
2531 if (req == NULL) {
2532 goto fail;
2534 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2535 goto fail;
2537 status = cli_tdis_recv(req);
2538 fail:
2539 TALLOC_FREE(ev);
2540 return status;
2543 struct cli_connect_sock_state {
2544 const char **called_names;
2545 const char **calling_names;
2546 int *called_types;
2547 int fd;
2548 uint16_t port;
2551 static void cli_connect_sock_done(struct tevent_req *subreq);
2554 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2555 * nonzero address.
2558 static struct tevent_req *cli_connect_sock_send(
2559 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2560 const char *host, int name_type, const struct sockaddr_storage *pss,
2561 const char *myname, uint16_t port)
2563 struct tevent_req *req, *subreq;
2564 struct cli_connect_sock_state *state;
2565 struct sockaddr_storage *addrs;
2566 unsigned i, num_addrs;
2567 NTSTATUS status;
2569 req = tevent_req_create(mem_ctx, &state,
2570 struct cli_connect_sock_state);
2571 if (req == NULL) {
2572 return NULL;
2575 if ((pss == NULL) || is_zero_addr(pss)) {
2578 * Here we cheat. resolve_name_list is not async at all. So
2579 * this call will only be really async if the name lookup has
2580 * been done externally.
2583 status = resolve_name_list(state, host, name_type,
2584 &addrs, &num_addrs);
2585 if (!NT_STATUS_IS_OK(status)) {
2586 tevent_req_nterror(req, status);
2587 return tevent_req_post(req, ev);
2589 } else {
2590 addrs = talloc_array(state, struct sockaddr_storage, 1);
2591 if (tevent_req_nomem(addrs, req)) {
2592 return tevent_req_post(req, ev);
2594 addrs[0] = *pss;
2595 num_addrs = 1;
2598 state->called_names = talloc_array(state, const char *, num_addrs);
2599 if (tevent_req_nomem(state->called_names, req)) {
2600 return tevent_req_post(req, ev);
2602 state->called_types = talloc_array(state, int, num_addrs);
2603 if (tevent_req_nomem(state->called_types, req)) {
2604 return tevent_req_post(req, ev);
2606 state->calling_names = talloc_array(state, const char *, num_addrs);
2607 if (tevent_req_nomem(state->calling_names, req)) {
2608 return tevent_req_post(req, ev);
2610 for (i=0; i<num_addrs; i++) {
2611 state->called_names[i] = host;
2612 state->called_types[i] = name_type;
2613 state->calling_names[i] = myname;
2616 subreq = smbsock_any_connect_send(
2617 state, ev, addrs, state->called_names, state->called_types,
2618 state->calling_names, NULL, num_addrs, port);
2619 if (tevent_req_nomem(subreq, req)) {
2620 return tevent_req_post(req, ev);
2622 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2623 return req;
2626 static void cli_connect_sock_done(struct tevent_req *subreq)
2628 struct tevent_req *req = tevent_req_callback_data(
2629 subreq, struct tevent_req);
2630 struct cli_connect_sock_state *state = tevent_req_data(
2631 req, struct cli_connect_sock_state);
2632 NTSTATUS status;
2634 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2635 &state->port);
2636 TALLOC_FREE(subreq);
2637 if (tevent_req_nterror(req, status)) {
2638 return;
2640 set_socket_options(state->fd, lp_socket_options());
2641 tevent_req_done(req);
2644 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2645 int *pfd, uint16_t *pport)
2647 struct cli_connect_sock_state *state = tevent_req_data(
2648 req, struct cli_connect_sock_state);
2649 NTSTATUS status;
2651 if (tevent_req_is_nterror(req, &status)) {
2652 return status;
2654 *pfd = state->fd;
2655 *pport = state->port;
2656 return NT_STATUS_OK;
2659 struct cli_connect_nb_state {
2660 const char *desthost;
2661 int signing_state;
2662 int flags;
2663 struct cli_state *cli;
2666 static void cli_connect_nb_done(struct tevent_req *subreq);
2668 static struct tevent_req *cli_connect_nb_send(
2669 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2670 const char *host, const struct sockaddr_storage *dest_ss,
2671 uint16_t port, int name_type, const char *myname,
2672 int signing_state, int flags)
2674 struct tevent_req *req, *subreq;
2675 struct cli_connect_nb_state *state;
2677 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2678 if (req == NULL) {
2679 return NULL;
2681 state->signing_state = signing_state;
2682 state->flags = flags;
2684 if (host != NULL) {
2685 char *p = strchr(host, '#');
2687 if (p != NULL) {
2688 name_type = strtol(p+1, NULL, 16);
2689 host = talloc_strndup(state, host, p - host);
2690 if (tevent_req_nomem(host, req)) {
2691 return tevent_req_post(req, ev);
2695 state->desthost = host;
2696 } else if (dest_ss != NULL) {
2697 state->desthost = print_canonical_sockaddr(state, dest_ss);
2698 if (tevent_req_nomem(state->desthost, req)) {
2699 return tevent_req_post(req, ev);
2701 } else {
2702 /* No host or dest_ss given. Error out. */
2703 tevent_req_error(req, EINVAL);
2704 return tevent_req_post(req, ev);
2707 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2708 myname, port);
2709 if (tevent_req_nomem(subreq, req)) {
2710 return tevent_req_post(req, ev);
2712 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2713 return req;
2716 static void cli_connect_nb_done(struct tevent_req *subreq)
2718 struct tevent_req *req = tevent_req_callback_data(
2719 subreq, struct tevent_req);
2720 struct cli_connect_nb_state *state = tevent_req_data(
2721 req, struct cli_connect_nb_state);
2722 NTSTATUS status;
2723 int fd = 0;
2724 uint16_t port;
2726 status = cli_connect_sock_recv(subreq, &fd, &port);
2727 TALLOC_FREE(subreq);
2728 if (tevent_req_nterror(req, status)) {
2729 return;
2732 state->cli = cli_state_create(state, fd, state->desthost,
2733 state->signing_state, state->flags);
2734 if (tevent_req_nomem(state->cli, req)) {
2735 close(fd);
2736 return;
2738 tevent_req_done(req);
2741 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2742 struct cli_state **pcli)
2744 struct cli_connect_nb_state *state = tevent_req_data(
2745 req, struct cli_connect_nb_state);
2746 NTSTATUS status;
2748 if (tevent_req_is_nterror(req, &status)) {
2749 return status;
2751 *pcli = talloc_move(NULL, &state->cli);
2752 return NT_STATUS_OK;
2755 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2756 uint16_t port, int name_type, const char *myname,
2757 int signing_state, int flags, struct cli_state **pcli)
2759 struct tevent_context *ev;
2760 struct tevent_req *req;
2761 NTSTATUS status = NT_STATUS_NO_MEMORY;
2763 ev = samba_tevent_context_init(talloc_tos());
2764 if (ev == NULL) {
2765 goto fail;
2767 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2768 myname, signing_state, flags);
2769 if (req == NULL) {
2770 goto fail;
2772 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2773 goto fail;
2775 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2776 goto fail;
2778 status = cli_connect_nb_recv(req, pcli);
2779 fail:
2780 TALLOC_FREE(ev);
2781 return status;
2784 struct cli_start_connection_state {
2785 struct tevent_context *ev;
2786 struct cli_state *cli;
2787 int min_protocol;
2788 int max_protocol;
2791 static void cli_start_connection_connected(struct tevent_req *subreq);
2792 static void cli_start_connection_done(struct tevent_req *subreq);
2795 establishes a connection to after the negprot.
2796 @param output_cli A fully initialised cli structure, non-null only on success
2797 @param dest_host The netbios name of the remote host
2798 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2799 @param port (optional) The destination port (0 for default)
2802 static struct tevent_req *cli_start_connection_send(
2803 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2804 const char *my_name, const char *dest_host,
2805 const struct sockaddr_storage *dest_ss, int port,
2806 int signing_state, int flags)
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 (signing_state == SMB_SIGNING_IPC_DEFAULT) {
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, PROTOCOL_NT1);
2830 if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
2831 state->min_protocol = MAX(state->max_protocol, PROTOCOL_SMB2_02);
2832 state->max_protocol = MAX(state->max_protocol, PROTOCOL_LATEST);
2835 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2836 0x20, my_name, signing_state, flags);
2837 if (tevent_req_nomem(subreq, req)) {
2838 return tevent_req_post(req, ev);
2840 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2841 return req;
2844 static void cli_start_connection_connected(struct tevent_req *subreq)
2846 struct tevent_req *req = tevent_req_callback_data(
2847 subreq, struct tevent_req);
2848 struct cli_start_connection_state *state = tevent_req_data(
2849 req, struct cli_start_connection_state);
2850 NTSTATUS status;
2852 status = cli_connect_nb_recv(subreq, &state->cli);
2853 TALLOC_FREE(subreq);
2854 if (tevent_req_nterror(req, status)) {
2855 return;
2858 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2859 state->cli->timeout,
2860 state->min_protocol,
2861 state->max_protocol,
2862 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK);
2863 if (tevent_req_nomem(subreq, req)) {
2864 return;
2866 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2869 static void cli_start_connection_done(struct tevent_req *subreq)
2871 struct tevent_req *req = tevent_req_callback_data(
2872 subreq, struct tevent_req);
2873 struct cli_start_connection_state *state = tevent_req_data(
2874 req, struct cli_start_connection_state);
2875 NTSTATUS status;
2877 status = smbXcli_negprot_recv(subreq);
2878 TALLOC_FREE(subreq);
2879 if (tevent_req_nterror(req, status)) {
2880 return;
2883 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2884 /* Ensure we ask for some initial credits. */
2885 smb2cli_conn_set_max_credits(state->cli->conn,
2886 DEFAULT_SMB2_MAX_CREDITS);
2889 tevent_req_done(req);
2892 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2893 struct cli_state **output_cli)
2895 struct cli_start_connection_state *state = tevent_req_data(
2896 req, struct cli_start_connection_state);
2897 NTSTATUS status;
2899 if (tevent_req_is_nterror(req, &status)) {
2900 return status;
2902 *output_cli = state->cli;
2904 return NT_STATUS_OK;
2907 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2908 const char *my_name,
2909 const char *dest_host,
2910 const struct sockaddr_storage *dest_ss, int port,
2911 int signing_state, int flags)
2913 struct tevent_context *ev;
2914 struct tevent_req *req;
2915 NTSTATUS status = NT_STATUS_NO_MEMORY;
2917 ev = samba_tevent_context_init(talloc_tos());
2918 if (ev == NULL) {
2919 goto fail;
2921 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2922 port, signing_state, flags);
2923 if (req == NULL) {
2924 goto fail;
2926 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2927 goto fail;
2929 status = cli_start_connection_recv(req, output_cli);
2930 fail:
2931 TALLOC_FREE(ev);
2932 return status;
2935 struct cli_smb1_setup_encryption_blob_state {
2936 uint16_t setup[1];
2937 uint8_t param[4];
2938 NTSTATUS status;
2939 DATA_BLOB out;
2940 uint16_t enc_ctx_id;
2943 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2945 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2946 struct tevent_context *ev,
2947 struct cli_state *cli,
2948 const DATA_BLOB in)
2950 struct tevent_req *req = NULL;
2951 struct cli_smb1_setup_encryption_blob_state *state = NULL;
2952 struct tevent_req *subreq = NULL;
2954 req = tevent_req_create(mem_ctx, &state,
2955 struct cli_smb1_setup_encryption_blob_state);
2956 if (req == NULL) {
2957 return NULL;
2960 if (in.length > CLI_BUFFER_SIZE) {
2961 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2962 return tevent_req_post(req, ev);
2965 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
2966 SSVAL(state->param, 0, 0);
2967 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
2969 subreq = smb1cli_trans_send(state, ev, cli->conn,
2970 SMBtrans2,
2971 0, 0, /* _flags */
2972 0, 0, /* _flags2 */
2973 cli->timeout,
2974 cli->smb1.pid,
2975 cli->smb1.tcon,
2976 cli->smb1.session,
2977 NULL, /* pipe_name */
2978 0, /* fid */
2979 0, /* function */
2980 0, /* flags */
2981 state->setup, 1, 0,
2982 state->param, 4, 2,
2983 in.data, in.length, CLI_BUFFER_SIZE);
2984 if (tevent_req_nomem(subreq, req)) {
2985 return tevent_req_post(req, ev);
2987 tevent_req_set_callback(subreq,
2988 cli_smb1_setup_encryption_blob_done,
2989 req);
2991 return req;
2994 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
2996 struct tevent_req *req =
2997 tevent_req_callback_data(subreq,
2998 struct tevent_req);
2999 struct cli_smb1_setup_encryption_blob_state *state =
3000 tevent_req_data(req,
3001 struct cli_smb1_setup_encryption_blob_state);
3002 uint8_t *rparam=NULL, *rdata=NULL;
3003 uint32_t num_rparam, num_rdata;
3004 NTSTATUS status;
3006 status = smb1cli_trans_recv(subreq, state,
3007 NULL, /* recv_flags */
3008 NULL, 0, NULL, /* rsetup */
3009 &rparam, 0, &num_rparam,
3010 &rdata, 0, &num_rdata);
3011 TALLOC_FREE(subreq);
3012 state->status = status;
3013 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
3014 status = NT_STATUS_OK;
3016 if (tevent_req_nterror(req, status)) {
3017 return;
3020 if (num_rparam == 2) {
3021 state->enc_ctx_id = SVAL(rparam, 0);
3023 TALLOC_FREE(rparam);
3025 state->out = data_blob_const(rdata, num_rdata);
3027 tevent_req_done(req);
3030 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
3031 TALLOC_CTX *mem_ctx,
3032 DATA_BLOB *out,
3033 uint16_t *enc_ctx_id)
3035 struct cli_smb1_setup_encryption_blob_state *state =
3036 tevent_req_data(req,
3037 struct cli_smb1_setup_encryption_blob_state);
3038 NTSTATUS status;
3040 if (tevent_req_is_nterror(req, &status)) {
3041 tevent_req_received(req);
3042 return status;
3045 status = state->status;
3047 *out = state->out;
3048 talloc_steal(mem_ctx, out->data);
3050 *enc_ctx_id = state->enc_ctx_id;
3052 tevent_req_received(req);
3053 return status;
3056 struct cli_smb1_setup_encryption_state {
3057 struct tevent_context *ev;
3058 struct cli_state *cli;
3059 struct smb_trans_enc_state *es;
3060 DATA_BLOB blob_in;
3061 DATA_BLOB blob_out;
3062 bool local_ready;
3063 bool remote_ready;
3066 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
3067 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
3068 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
3069 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
3070 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
3072 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
3073 struct tevent_context *ev,
3074 struct cli_state *cli,
3075 struct cli_credentials *creds)
3077 struct tevent_req *req = NULL;
3078 struct cli_smb1_setup_encryption_state *state = NULL;
3079 struct auth_generic_state *ags = NULL;
3080 const DATA_BLOB *b = NULL;
3081 bool auth_requested = false;
3082 const char *target_service = NULL;
3083 const char *target_hostname = NULL;
3084 NTSTATUS status;
3086 req = tevent_req_create(mem_ctx, &state,
3087 struct cli_smb1_setup_encryption_state);
3088 if (req == NULL) {
3089 return NULL;
3091 state->ev = ev;
3092 state->cli = cli;
3094 auth_requested = cli_credentials_authentication_requested(creds);
3095 if (!auth_requested) {
3096 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3097 return tevent_req_post(req, ev);
3100 target_service = "cifs";
3101 target_hostname = smbXcli_conn_remote_name(cli->conn);
3103 status = cli_session_creds_prepare_krb5(cli, creds);
3104 if (tevent_req_nterror(req, status)) {
3105 return tevent_req_post(req, ev);
3108 state->es = talloc_zero(state, struct smb_trans_enc_state);
3109 if (tevent_req_nomem(state->es, req)) {
3110 return tevent_req_post(req, ev);
3113 status = auth_generic_client_prepare(state->es, &ags);
3114 if (tevent_req_nterror(req, status)) {
3115 return tevent_req_post(req, ev);
3118 gensec_want_feature(ags->gensec_security,
3119 GENSEC_FEATURE_SIGN);
3120 gensec_want_feature(ags->gensec_security,
3121 GENSEC_FEATURE_SEAL);
3123 status = auth_generic_set_creds(ags, creds);
3124 if (tevent_req_nterror(req, status)) {
3125 return tevent_req_post(req, ev);
3128 if (target_service != NULL) {
3129 status = gensec_set_target_service(ags->gensec_security,
3130 target_service);
3131 if (tevent_req_nterror(req, status)) {
3132 return tevent_req_post(req, ev);
3136 if (target_hostname != NULL) {
3137 status = gensec_set_target_hostname(ags->gensec_security,
3138 target_hostname);
3139 if (tevent_req_nterror(req, status)) {
3140 return tevent_req_post(req, ev);
3144 gensec_set_max_update_size(ags->gensec_security,
3145 CLI_BUFFER_SIZE);
3147 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3148 if (b != NULL) {
3149 state->blob_in = *b;
3152 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3153 if (tevent_req_nterror(req, status)) {
3154 return tevent_req_post(req, ev);
3158 * We only need the gensec_security part from here.
3160 state->es->gensec_security = talloc_move(state->es,
3161 &ags->gensec_security);
3162 TALLOC_FREE(ags);
3164 cli_smb1_setup_encryption_local_next(req);
3165 if (!tevent_req_is_in_progress(req)) {
3166 return tevent_req_post(req, ev);
3169 return req;
3172 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3174 struct cli_smb1_setup_encryption_state *state =
3175 tevent_req_data(req,
3176 struct cli_smb1_setup_encryption_state);
3177 struct tevent_req *subreq = NULL;
3179 if (state->local_ready) {
3180 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3181 return;
3184 subreq = gensec_update_send(state, state->ev,
3185 state->es->gensec_security,
3186 state->blob_in);
3187 if (tevent_req_nomem(subreq, req)) {
3188 return;
3190 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3193 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3195 struct tevent_req *req =
3196 tevent_req_callback_data(subreq,
3197 struct tevent_req);
3198 struct cli_smb1_setup_encryption_state *state =
3199 tevent_req_data(req,
3200 struct cli_smb1_setup_encryption_state);
3201 NTSTATUS status;
3203 status = gensec_update_recv(subreq, state, &state->blob_out);
3204 TALLOC_FREE(subreq);
3205 state->blob_in = data_blob_null;
3206 if (!NT_STATUS_IS_OK(status) &&
3207 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3209 tevent_req_nterror(req, status);
3210 return;
3213 if (NT_STATUS_IS_OK(status)) {
3214 state->local_ready = true;
3218 * We always get NT_STATUS_OK from the server even if it is not ready.
3219 * So guess the server is ready when we are ready and already sent
3220 * our last blob to the server.
3222 if (state->local_ready && state->blob_out.length == 0) {
3223 state->remote_ready = true;
3226 if (state->local_ready && state->remote_ready) {
3227 cli_smb1_setup_encryption_ready(req);
3228 return;
3231 cli_smb1_setup_encryption_remote_next(req);
3234 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3236 struct cli_smb1_setup_encryption_state *state =
3237 tevent_req_data(req,
3238 struct cli_smb1_setup_encryption_state);
3239 struct tevent_req *subreq = NULL;
3241 if (state->remote_ready) {
3242 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3243 return;
3246 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3247 state->cli, state->blob_out);
3248 if (tevent_req_nomem(subreq, req)) {
3249 return;
3251 tevent_req_set_callback(subreq,
3252 cli_smb1_setup_encryption_remote_done,
3253 req);
3256 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3258 struct tevent_req *req =
3259 tevent_req_callback_data(subreq,
3260 struct tevent_req);
3261 struct cli_smb1_setup_encryption_state *state =
3262 tevent_req_data(req,
3263 struct cli_smb1_setup_encryption_state);
3264 NTSTATUS status;
3266 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3267 &state->blob_in,
3268 &state->es->enc_ctx_num);
3269 TALLOC_FREE(subreq);
3270 data_blob_free(&state->blob_out);
3271 if (!NT_STATUS_IS_OK(status) &&
3272 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3274 tevent_req_nterror(req, status);
3275 return;
3279 * We always get NT_STATUS_OK even if the server is not ready.
3280 * So guess the server is ready when we are ready and sent
3281 * our last blob to the server.
3283 if (state->local_ready) {
3284 state->remote_ready = true;
3287 if (state->local_ready && state->remote_ready) {
3288 cli_smb1_setup_encryption_ready(req);
3289 return;
3292 cli_smb1_setup_encryption_local_next(req);
3295 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3297 struct cli_smb1_setup_encryption_state *state =
3298 tevent_req_data(req,
3299 struct cli_smb1_setup_encryption_state);
3300 struct smb_trans_enc_state *es = NULL;
3302 if (state->blob_in.length != 0) {
3303 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3304 return;
3307 if (state->blob_out.length != 0) {
3308 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3309 return;
3312 es = talloc_move(state->cli->conn, &state->es);
3313 es->enc_on = true;
3314 smb1cli_conn_set_encryption(state->cli->conn, es);
3315 es = NULL;
3317 tevent_req_done(req);
3320 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3322 return tevent_req_simple_recv_ntstatus(req);
3325 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3326 struct cli_credentials *creds)
3328 struct tevent_context *ev = NULL;
3329 struct tevent_req *req = NULL;
3330 NTSTATUS status = NT_STATUS_NO_MEMORY;
3332 ev = samba_tevent_context_init(talloc_tos());
3333 if (ev == NULL) {
3334 goto fail;
3336 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3337 if (req == NULL) {
3338 goto fail;
3340 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3341 goto fail;
3343 status = cli_smb1_setup_encryption_recv(req);
3344 fail:
3345 TALLOC_FREE(ev);
3346 return status;
3350 establishes a connection right up to doing tconX, password specified.
3351 @param output_cli A fully initialised cli structure, non-null only on success
3352 @param dest_host The netbios name of the remote host
3353 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3354 @param port (optional) The destination port (0 for default)
3355 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3356 @param service_type The 'type' of serivice.
3357 @param creds The used user credentials
3360 struct cli_full_connection_creds_state {
3361 struct tevent_context *ev;
3362 const char *service;
3363 const char *service_type;
3364 struct cli_credentials *creds;
3365 int flags;
3366 struct cli_state *cli;
3369 static int cli_full_connection_creds_state_destructor(
3370 struct cli_full_connection_creds_state *s)
3372 if (s->cli != NULL) {
3373 cli_shutdown(s->cli);
3374 s->cli = NULL;
3376 return 0;
3379 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3380 static void cli_full_connection_creds_sess_start(struct tevent_req *req);
3381 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3382 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3383 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3385 struct tevent_req *cli_full_connection_creds_send(
3386 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3387 const char *my_name, const char *dest_host,
3388 const struct sockaddr_storage *dest_ss, int port,
3389 const char *service, const char *service_type,
3390 struct cli_credentials *creds,
3391 int flags, int signing_state)
3393 struct tevent_req *req, *subreq;
3394 struct cli_full_connection_creds_state *state;
3395 enum credentials_use_kerberos krb5_state;
3396 uint32_t gensec_features = 0;
3398 req = tevent_req_create(mem_ctx, &state,
3399 struct cli_full_connection_creds_state);
3400 if (req == NULL) {
3401 return NULL;
3403 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3405 flags &= ~CLI_FULL_CONNECTION_USE_KERBEROS;
3406 flags &= ~CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3407 flags &= ~CLI_FULL_CONNECTION_USE_CCACHE;
3408 flags &= ~CLI_FULL_CONNECTION_USE_NT_HASH;
3410 krb5_state = cli_credentials_get_kerberos_state(creds);
3411 switch (krb5_state) {
3412 case CRED_MUST_USE_KERBEROS:
3413 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3414 flags &= ~CLI_FULL_CONNECTION_DONT_SPNEGO;
3415 break;
3416 case CRED_AUTO_USE_KERBEROS:
3417 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3418 flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3419 break;
3420 case CRED_DONT_USE_KERBEROS:
3421 break;
3424 gensec_features = cli_credentials_get_gensec_features(creds);
3425 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
3426 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
3429 state->ev = ev;
3430 state->service = service;
3431 state->service_type = service_type;
3432 state->creds = creds;
3433 state->flags = flags;
3435 subreq = cli_start_connection_send(
3436 state, ev, my_name, dest_host, dest_ss, port,
3437 signing_state, flags);
3438 if (tevent_req_nomem(subreq, req)) {
3439 return tevent_req_post(req, ev);
3441 tevent_req_set_callback(subreq,
3442 cli_full_connection_creds_conn_done,
3443 req);
3444 return req;
3447 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3449 struct tevent_req *req = tevent_req_callback_data(
3450 subreq, struct tevent_req);
3451 struct cli_full_connection_creds_state *state = tevent_req_data(
3452 req, struct cli_full_connection_creds_state);
3453 NTSTATUS status;
3455 status = cli_start_connection_recv(subreq, &state->cli);
3456 TALLOC_FREE(subreq);
3457 if (tevent_req_nterror(req, status)) {
3458 return;
3461 cli_full_connection_creds_sess_start(req);
3464 static void cli_full_connection_creds_sess_start(struct tevent_req *req)
3466 struct cli_full_connection_creds_state *state = tevent_req_data(
3467 req, struct cli_full_connection_creds_state);
3468 struct tevent_req *subreq = NULL;
3470 subreq = cli_session_setup_creds_send(
3471 state, state->ev, state->cli, state->creds);
3472 if (tevent_req_nomem(subreq, req)) {
3473 return;
3475 tevent_req_set_callback(subreq,
3476 cli_full_connection_creds_sess_done,
3477 req);
3480 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3482 struct tevent_req *req = tevent_req_callback_data(
3483 subreq, struct tevent_req);
3484 struct cli_full_connection_creds_state *state = tevent_req_data(
3485 req, struct cli_full_connection_creds_state);
3486 NTSTATUS status;
3488 status = cli_session_setup_creds_recv(subreq);
3489 TALLOC_FREE(subreq);
3491 if (!NT_STATUS_IS_OK(status) &&
3492 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3494 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3496 state->creds = cli_credentials_init_anon(state);
3497 if (tevent_req_nomem(state->creds, req)) {
3498 return;
3501 cli_full_connection_creds_sess_start(req);
3502 return;
3505 if (tevent_req_nterror(req, status)) {
3506 return;
3509 cli_full_connection_creds_tcon_start(req);
3512 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3514 struct cli_full_connection_creds_state *state = tevent_req_data(
3515 req, struct cli_full_connection_creds_state);
3516 struct tevent_req *subreq = NULL;
3517 const char *password = NULL;
3519 if (state->service == NULL) {
3520 tevent_req_done(req);
3521 return;
3524 password = cli_credentials_get_password(state->creds);
3526 subreq = cli_tree_connect_send(state, state->ev,
3527 state->cli,
3528 state->service,
3529 state->service_type,
3530 password);
3531 if (tevent_req_nomem(subreq, req)) {
3532 return;
3534 tevent_req_set_callback(subreq,
3535 cli_full_connection_creds_tcon_done,
3536 req);
3539 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3541 struct tevent_req *req = tevent_req_callback_data(
3542 subreq, struct tevent_req);
3543 NTSTATUS status;
3545 status = cli_tree_connect_recv(subreq);
3546 TALLOC_FREE(subreq);
3547 if (tevent_req_nterror(req, status)) {
3548 return;
3551 tevent_req_done(req);
3554 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3555 struct cli_state **output_cli)
3557 struct cli_full_connection_creds_state *state = tevent_req_data(
3558 req, struct cli_full_connection_creds_state);
3559 NTSTATUS status;
3561 if (tevent_req_is_nterror(req, &status)) {
3562 return status;
3564 *output_cli = state->cli;
3565 talloc_set_destructor(state, NULL);
3566 return NT_STATUS_OK;
3569 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3570 const char *my_name,
3571 const char *dest_host,
3572 const struct sockaddr_storage *dest_ss, int port,
3573 const char *service, const char *service_type,
3574 struct cli_credentials *creds,
3575 int flags,
3576 int signing_state)
3578 struct tevent_context *ev;
3579 struct tevent_req *req;
3580 NTSTATUS status = NT_STATUS_NO_MEMORY;
3582 ev = samba_tevent_context_init(talloc_tos());
3583 if (ev == NULL) {
3584 goto fail;
3586 req = cli_full_connection_creds_send(
3587 ev, ev, my_name, dest_host, dest_ss, port, service,
3588 service_type, creds, flags, signing_state);
3589 if (req == NULL) {
3590 goto fail;
3592 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3593 goto fail;
3595 status = cli_full_connection_creds_recv(req, output_cli);
3596 fail:
3597 TALLOC_FREE(ev);
3598 return status;
3601 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3602 const char *my_name,
3603 const char *dest_host,
3604 const struct sockaddr_storage *dest_ss, int port,
3605 const char *service, const char *service_type,
3606 const char *user, const char *domain,
3607 const char *password, int flags,
3608 int signing_state)
3610 TALLOC_CTX *frame = talloc_stackframe();
3611 NTSTATUS status;
3612 bool use_kerberos = false;
3613 bool fallback_after_kerberos = false;
3614 bool use_ccache = false;
3615 bool pw_nt_hash = false;
3616 struct cli_credentials *creds = NULL;
3618 if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
3619 use_kerberos = true;
3622 if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) {
3623 fallback_after_kerberos = true;
3626 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3627 use_ccache = true;
3630 if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) {
3631 pw_nt_hash = true;
3634 creds = cli_session_creds_init(frame,
3635 user,
3636 domain,
3637 NULL, /* realm (use default) */
3638 password,
3639 use_kerberos,
3640 fallback_after_kerberos,
3641 use_ccache,
3642 pw_nt_hash);
3643 if (creds == NULL) {
3644 TALLOC_FREE(frame);
3645 return NT_STATUS_NO_MEMORY;
3648 status = cli_full_connection_creds(output_cli, my_name,
3649 dest_host, dest_ss, port,
3650 service, service_type,
3651 creds, flags, signing_state);
3652 if (!NT_STATUS_IS_OK(status)) {
3653 TALLOC_FREE(frame);
3654 return status;
3657 TALLOC_FREE(frame);
3658 return NT_STATUS_OK;
3661 /****************************************************************************
3662 Send an old style tcon.
3663 ****************************************************************************/
3664 struct cli_raw_tcon_state {
3665 uint16_t *ret_vwv;
3668 static void cli_raw_tcon_done(struct tevent_req *subreq);
3670 static struct tevent_req *cli_raw_tcon_send(
3671 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3672 const char *service, const char *pass, const char *dev)
3674 struct tevent_req *req, *subreq;
3675 struct cli_raw_tcon_state *state;
3676 uint8_t *bytes;
3678 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3679 if (req == NULL) {
3680 return NULL;
3683 if (!lp_client_plaintext_auth() && (*pass)) {
3684 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3685 " or 'client ntlmv2 auth = yes'\n"));
3686 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3687 return tevent_req_post(req, ev);
3690 TALLOC_FREE(cli->smb1.tcon);
3691 cli->smb1.tcon = smbXcli_tcon_create(cli);
3692 if (tevent_req_nomem(cli->smb1.tcon, req)) {
3693 return tevent_req_post(req, ev);
3695 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
3697 bytes = talloc_array(state, uint8_t, 0);
3698 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3699 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3700 service, strlen(service)+1, NULL);
3701 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3702 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3703 pass, strlen(pass)+1, NULL);
3704 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3705 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3706 dev, strlen(dev)+1, NULL);
3708 if (tevent_req_nomem(bytes, req)) {
3709 return tevent_req_post(req, ev);
3712 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3713 talloc_get_size(bytes), bytes);
3714 if (tevent_req_nomem(subreq, req)) {
3715 return tevent_req_post(req, ev);
3717 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3718 return req;
3721 static void cli_raw_tcon_done(struct tevent_req *subreq)
3723 struct tevent_req *req = tevent_req_callback_data(
3724 subreq, struct tevent_req);
3725 struct cli_raw_tcon_state *state = tevent_req_data(
3726 req, struct cli_raw_tcon_state);
3727 NTSTATUS status;
3729 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3730 NULL, NULL);
3731 TALLOC_FREE(subreq);
3732 if (tevent_req_nterror(req, status)) {
3733 return;
3735 tevent_req_done(req);
3738 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3739 uint16_t *max_xmit, uint16_t *tid)
3741 struct cli_raw_tcon_state *state = tevent_req_data(
3742 req, struct cli_raw_tcon_state);
3743 NTSTATUS status;
3745 if (tevent_req_is_nterror(req, &status)) {
3746 return status;
3748 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3749 *tid = SVAL(state->ret_vwv + 1, 0);
3750 return NT_STATUS_OK;
3753 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3754 const char *service, const char *pass, const char *dev,
3755 uint16_t *max_xmit, uint16_t *tid)
3757 struct tevent_context *ev;
3758 struct tevent_req *req;
3759 NTSTATUS status = NT_STATUS_NO_MEMORY;
3761 ev = samba_tevent_context_init(talloc_tos());
3762 if (ev == NULL) {
3763 goto fail;
3765 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3766 if (req == NULL) {
3767 goto fail;
3769 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3770 goto fail;
3772 status = cli_raw_tcon_recv(req, max_xmit, tid);
3773 fail:
3774 TALLOC_FREE(ev);
3775 return status;
3778 /* Return a cli_state pointing at the IPC$ share for the given server */
3780 struct cli_state *get_ipc_connect(char *server,
3781 struct sockaddr_storage *server_ss,
3782 const struct user_auth_info *user_info)
3784 struct cli_state *cli;
3785 NTSTATUS nt_status;
3786 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3788 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3789 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3792 flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
3794 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3795 get_cmdline_auth_info_username(user_info),
3796 lp_workgroup(),
3797 get_cmdline_auth_info_password(user_info),
3798 flags,
3799 SMB_SIGNING_DEFAULT);
3801 if (NT_STATUS_IS_OK(nt_status)) {
3802 return cli;
3803 } else if (is_ipaddress(server)) {
3804 /* windows 9* needs a correct NMB name for connections */
3805 fstring remote_name;
3807 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3808 cli = get_ipc_connect(remote_name, server_ss, user_info);
3809 if (cli)
3810 return cli;
3813 return NULL;
3817 * Given the IP address of a master browser on the network, return its
3818 * workgroup and connect to it.
3820 * This function is provided to allow additional processing beyond what
3821 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3822 * browsers and obtain each master browsers' list of domains (in case the
3823 * first master browser is recently on the network and has not yet
3824 * synchronized with other master browsers and therefore does not yet have the
3825 * entire network browse list)
3828 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3829 struct sockaddr_storage *mb_ip,
3830 const struct user_auth_info *user_info,
3831 char **pp_workgroup_out)
3833 char addr[INET6_ADDRSTRLEN];
3834 fstring name;
3835 struct cli_state *cli;
3836 struct sockaddr_storage server_ss;
3838 *pp_workgroup_out = NULL;
3840 print_sockaddr(addr, sizeof(addr), mb_ip);
3841 DEBUG(99, ("Looking up name of master browser %s\n",
3842 addr));
3845 * Do a name status query to find out the name of the master browser.
3846 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3847 * master browser will not respond to a wildcard query (or, at least,
3848 * an NT4 server acting as the domain master browser will not).
3850 * We might be able to use ONLY the query on MSBROWSE, but that's not
3851 * yet been tested with all Windows versions, so until it is, leave
3852 * the original wildcard query as the first choice and fall back to
3853 * MSBROWSE if the wildcard query fails.
3855 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3856 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3858 DEBUG(99, ("Could not retrieve name status for %s\n",
3859 addr));
3860 return NULL;
3863 if (!find_master_ip(name, &server_ss)) {
3864 DEBUG(99, ("Could not find master ip for %s\n", name));
3865 return NULL;
3868 *pp_workgroup_out = talloc_strdup(ctx, name);
3870 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3872 print_sockaddr(addr, sizeof(addr), &server_ss);
3873 cli = get_ipc_connect(addr, &server_ss, user_info);
3875 return cli;
3879 * Return the IP address and workgroup of a master browser on the network, and
3880 * connect to it.
3883 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3884 const struct user_auth_info *user_info,
3885 char **pp_workgroup_out)
3887 struct sockaddr_storage *ip_list;
3888 struct cli_state *cli;
3889 int i, count;
3890 NTSTATUS status;
3892 *pp_workgroup_out = NULL;
3894 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3896 /* Go looking for workgroups by broadcasting on the local network */
3898 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3899 &ip_list, &count);
3900 if (!NT_STATUS_IS_OK(status)) {
3901 DEBUG(99, ("No master browsers responded: %s\n",
3902 nt_errstr(status)));
3903 return NULL;
3906 for (i = 0; i < count; i++) {
3907 char addr[INET6_ADDRSTRLEN];
3908 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3909 DEBUG(99, ("Found master browser %s\n", addr));
3911 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3912 user_info, pp_workgroup_out);
3913 if (cli)
3914 return(cli);
3917 return NULL;