VERSION: Disable GIT_SNAPSHOT for the 4.11.8 release.
[Samba.git] / source3 / libsmb / cliconnect.c
blob3df35931bb651becbfb6d6f53c5d77f1b867c1e4
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;
630 p += ret;
632 tevent_req_done(req);
635 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
637 return tevent_req_simple_recv_ntstatus(req);
640 /* The following is calculated from :
641 * (smb_size-4) = 35
642 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
643 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
644 * end of packet.
647 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
649 struct cli_sesssetup_blob_state {
650 struct tevent_context *ev;
651 struct cli_state *cli;
652 DATA_BLOB blob;
653 uint16_t max_blob_size;
655 DATA_BLOB this_blob;
656 struct iovec *recv_iov;
658 NTSTATUS status;
659 const uint8_t *inbuf;
660 DATA_BLOB ret_blob;
662 char *out_native_os;
663 char *out_native_lm;
666 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
667 struct tevent_req **psubreq);
668 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
670 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
671 struct tevent_context *ev,
672 struct cli_state *cli,
673 DATA_BLOB blob)
675 struct tevent_req *req, *subreq;
676 struct cli_sesssetup_blob_state *state;
677 uint32_t usable_space;
679 req = tevent_req_create(mem_ctx, &state,
680 struct cli_sesssetup_blob_state);
681 if (req == NULL) {
682 return NULL;
684 state->ev = ev;
685 state->blob = blob;
686 state->cli = cli;
688 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
689 usable_space = UINT16_MAX;
690 } else {
691 usable_space = cli_state_available_size(cli,
692 BASE_SESSSETUP_BLOB_PACKET_SIZE);
695 if (usable_space == 0) {
696 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
697 "(not possible to send %u bytes)\n",
698 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
699 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
700 return tevent_req_post(req, ev);
702 state->max_blob_size = MIN(usable_space, 0xFFFF);
704 if (!cli_sesssetup_blob_next(state, &subreq)) {
705 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
706 return tevent_req_post(req, ev);
708 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
709 return req;
712 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
713 struct tevent_req **psubreq)
715 struct tevent_req *subreq;
716 uint16_t thistime;
718 thistime = MIN(state->blob.length, state->max_blob_size);
720 state->this_blob.data = state->blob.data;
721 state->this_blob.length = thistime;
723 state->blob.data += thistime;
724 state->blob.length -= thistime;
726 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
727 subreq = smb2cli_session_setup_send(state, state->ev,
728 state->cli->conn,
729 state->cli->timeout,
730 state->cli->smb2.session,
731 0, /* in_flags */
732 SMB2_CAP_DFS, /* in_capabilities */
733 0, /* in_channel */
734 0, /* in_previous_session_id */
735 &state->this_blob);
736 if (subreq == NULL) {
737 return false;
739 } else {
740 uint16_t in_buf_size = 0;
741 uint16_t in_mpx_max = 0;
742 uint16_t in_vc_num = 0;
743 uint32_t in_sess_key = 0;
744 uint32_t in_capabilities = 0;
745 const char *in_native_os = NULL;
746 const char *in_native_lm = NULL;
748 in_buf_size = CLI_BUFFER_SIZE;
749 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
750 in_vc_num = cli_state_get_vc_num(state->cli);
751 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
752 in_capabilities = cli_session_setup_capabilities(state->cli,
753 CAP_EXTENDED_SECURITY);
754 in_native_os = "Unix";
755 in_native_lm = "Samba";
758 * For now we keep the same values as before,
759 * we may remove these in a separate commit later.
761 in_mpx_max = 2;
762 in_vc_num = 1;
763 in_sess_key = 0;
765 subreq = smb1cli_session_setup_ext_send(state, state->ev,
766 state->cli->conn,
767 state->cli->timeout,
768 state->cli->smb1.pid,
769 state->cli->smb1.session,
770 in_buf_size,
771 in_mpx_max,
772 in_vc_num,
773 in_sess_key,
774 state->this_blob,
775 in_capabilities,
776 in_native_os,
777 in_native_lm);
778 if (subreq == NULL) {
779 return false;
782 *psubreq = subreq;
783 return true;
786 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
788 struct tevent_req *req = tevent_req_callback_data(
789 subreq, struct tevent_req);
790 struct cli_sesssetup_blob_state *state = tevent_req_data(
791 req, struct cli_sesssetup_blob_state);
792 NTSTATUS status;
794 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
795 status = smb2cli_session_setup_recv(subreq, state,
796 &state->recv_iov,
797 &state->ret_blob);
798 } else {
799 status = smb1cli_session_setup_ext_recv(subreq, state,
800 &state->recv_iov,
801 &state->inbuf,
802 &state->ret_blob,
803 &state->out_native_os,
804 &state->out_native_lm);
806 TALLOC_FREE(subreq);
807 if (!NT_STATUS_IS_OK(status)
808 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
809 tevent_req_nterror(req, status);
810 return;
813 state->status = status;
815 status = cli_state_update_after_sesssetup(state->cli,
816 state->out_native_os,
817 state->out_native_lm,
818 NULL);
819 if (tevent_req_nterror(req, status)) {
820 return;
823 if (state->blob.length != 0) {
825 * More to send
827 if (!cli_sesssetup_blob_next(state, &subreq)) {
828 tevent_req_oom(req);
829 return;
831 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
832 return;
834 tevent_req_done(req);
837 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
838 TALLOC_CTX *mem_ctx,
839 DATA_BLOB *pblob,
840 const uint8_t **pinbuf,
841 struct iovec **precv_iov)
843 struct cli_sesssetup_blob_state *state = tevent_req_data(
844 req, struct cli_sesssetup_blob_state);
845 NTSTATUS status;
846 struct iovec *recv_iov;
848 if (tevent_req_is_nterror(req, &status)) {
849 TALLOC_FREE(state->cli->smb2.session);
850 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
851 tevent_req_received(req);
852 return status;
855 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
856 if (pblob != NULL) {
857 *pblob = state->ret_blob;
859 if (pinbuf != NULL) {
860 *pinbuf = state->inbuf;
862 if (precv_iov != NULL) {
863 *precv_iov = recv_iov;
865 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
866 status = state->status;
867 tevent_req_received(req);
868 return status;
871 /****************************************************************************
872 Do a spnego/NTLMSSP encrypted session setup.
873 ****************************************************************************/
875 struct cli_session_setup_gensec_state {
876 struct tevent_context *ev;
877 struct cli_state *cli;
878 struct auth_generic_state *auth_generic;
879 bool is_anonymous;
880 DATA_BLOB blob_in;
881 const uint8_t *inbuf;
882 struct iovec *recv_iov;
883 DATA_BLOB blob_out;
884 bool local_ready;
885 bool remote_ready;
886 DATA_BLOB session_key;
889 static int cli_session_setup_gensec_state_destructor(
890 struct cli_session_setup_gensec_state *state)
892 TALLOC_FREE(state->auth_generic);
893 data_blob_clear_free(&state->session_key);
894 return 0;
897 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
898 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
899 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
900 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
901 static void cli_session_setup_gensec_ready(struct tevent_req *req);
903 static struct tevent_req *cli_session_setup_gensec_send(
904 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
905 struct cli_credentials *creds,
906 const char *target_service,
907 const char *target_hostname)
909 struct tevent_req *req;
910 struct cli_session_setup_gensec_state *state;
911 NTSTATUS status;
912 const DATA_BLOB *b = NULL;
914 req = tevent_req_create(mem_ctx, &state,
915 struct cli_session_setup_gensec_state);
916 if (req == NULL) {
917 return NULL;
919 state->ev = ev;
920 state->cli = cli;
922 talloc_set_destructor(
923 state, cli_session_setup_gensec_state_destructor);
925 status = auth_generic_client_prepare(state, &state->auth_generic);
926 if (tevent_req_nterror(req, status)) {
927 return tevent_req_post(req, ev);
930 status = auth_generic_set_creds(state->auth_generic, creds);
931 if (tevent_req_nterror(req, status)) {
932 return tevent_req_post(req, ev);
935 gensec_want_feature(state->auth_generic->gensec_security,
936 GENSEC_FEATURE_SESSION_KEY);
938 if (target_service != NULL) {
939 status = gensec_set_target_service(
940 state->auth_generic->gensec_security,
941 target_service);
942 if (tevent_req_nterror(req, status)) {
943 return tevent_req_post(req, ev);
947 if (target_hostname != NULL) {
948 status = gensec_set_target_hostname(
949 state->auth_generic->gensec_security,
950 target_hostname);
951 if (tevent_req_nterror(req, status)) {
952 return tevent_req_post(req, ev);
956 b = smbXcli_conn_server_gss_blob(cli->conn);
957 if (b != NULL) {
958 state->blob_in = *b;
961 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
963 status = auth_generic_client_start(state->auth_generic,
964 GENSEC_OID_SPNEGO);
965 if (tevent_req_nterror(req, status)) {
966 return tevent_req_post(req, ev);
969 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
970 state->cli->smb2.session = smbXcli_session_create(cli,
971 cli->conn);
972 if (tevent_req_nomem(state->cli->smb2.session, req)) {
973 return tevent_req_post(req, ev);
977 cli_session_setup_gensec_local_next(req);
978 if (!tevent_req_is_in_progress(req)) {
979 return tevent_req_post(req, ev);
982 return req;
985 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
987 struct cli_session_setup_gensec_state *state =
988 tevent_req_data(req,
989 struct cli_session_setup_gensec_state);
990 struct tevent_req *subreq = NULL;
992 if (state->local_ready) {
993 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
994 return;
997 subreq = gensec_update_send(state, state->ev,
998 state->auth_generic->gensec_security,
999 state->blob_in);
1000 if (tevent_req_nomem(subreq, req)) {
1001 return;
1003 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1006 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1008 struct tevent_req *req =
1009 tevent_req_callback_data(subreq,
1010 struct tevent_req);
1011 struct cli_session_setup_gensec_state *state =
1012 tevent_req_data(req,
1013 struct cli_session_setup_gensec_state);
1014 NTSTATUS status;
1016 status = gensec_update_recv(subreq, state, &state->blob_out);
1017 TALLOC_FREE(subreq);
1018 state->blob_in = data_blob_null;
1019 if (!NT_STATUS_IS_OK(status) &&
1020 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1022 tevent_req_nterror(req, status);
1023 return;
1026 if (NT_STATUS_IS_OK(status)) {
1027 state->local_ready = true;
1030 if (state->local_ready && state->remote_ready) {
1031 cli_session_setup_gensec_ready(req);
1032 return;
1035 cli_session_setup_gensec_remote_next(req);
1038 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1040 struct cli_session_setup_gensec_state *state =
1041 tevent_req_data(req,
1042 struct cli_session_setup_gensec_state);
1043 struct tevent_req *subreq = NULL;
1045 if (state->remote_ready) {
1046 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1047 return;
1050 subreq = cli_sesssetup_blob_send(state, state->ev,
1051 state->cli, state->blob_out);
1052 if (tevent_req_nomem(subreq, req)) {
1053 return;
1055 tevent_req_set_callback(subreq,
1056 cli_session_setup_gensec_remote_done,
1057 req);
1060 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1062 struct tevent_req *req =
1063 tevent_req_callback_data(subreq,
1064 struct tevent_req);
1065 struct cli_session_setup_gensec_state *state =
1066 tevent_req_data(req,
1067 struct cli_session_setup_gensec_state);
1068 NTSTATUS status;
1070 state->inbuf = NULL;
1071 TALLOC_FREE(state->recv_iov);
1073 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1074 &state->inbuf, &state->recv_iov);
1075 TALLOC_FREE(subreq);
1076 data_blob_free(&state->blob_out);
1077 if (!NT_STATUS_IS_OK(status) &&
1078 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1080 tevent_req_nterror(req, status);
1081 return;
1084 if (NT_STATUS_IS_OK(status)) {
1085 struct smbXcli_session *session = NULL;
1086 bool is_guest = false;
1088 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1089 session = state->cli->smb2.session;
1090 } else {
1091 session = state->cli->smb1.session;
1094 is_guest = smbXcli_session_is_guest(session);
1095 if (is_guest) {
1097 * We can't finish the gensec handshake, we don't
1098 * have a negotiated session key.
1100 * So just pretend we are completely done,
1101 * we need to continue as anonymous from this point,
1102 * as we can't get a session key.
1104 * Note that smbXcli_session_is_guest()
1105 * always returns false if we require signing.
1107 state->blob_in = data_blob_null;
1108 state->local_ready = true;
1109 state->is_anonymous = true;
1112 state->remote_ready = true;
1115 if (state->local_ready && state->remote_ready) {
1116 cli_session_setup_gensec_ready(req);
1117 return;
1120 cli_session_setup_gensec_local_next(req);
1123 static void cli_session_dump_keys(TALLOC_CTX *mem_ctx,
1124 struct smbXcli_session *session,
1125 DATA_BLOB session_key)
1127 NTSTATUS status;
1128 DATA_BLOB sig = data_blob_null;
1129 DATA_BLOB app = data_blob_null;
1130 DATA_BLOB enc = data_blob_null;
1131 DATA_BLOB dec = data_blob_null;
1132 uint64_t sid = smb2cli_session_current_id(session);
1134 status = smb2cli_session_signing_key(session, mem_ctx, &sig);
1135 if (!NT_STATUS_IS_OK(status)) {
1136 goto out;
1138 status = smbXcli_session_application_key(session, mem_ctx, &app);
1139 if (!NT_STATUS_IS_OK(status)) {
1140 goto out;
1142 status = smb2cli_session_encryption_key(session, mem_ctx, &enc);
1143 if (!NT_STATUS_IS_OK(status)) {
1144 goto out;
1146 status = smb2cli_session_decryption_key(session, mem_ctx, &dec);
1147 if (!NT_STATUS_IS_OK(status)) {
1148 goto out;
1151 DEBUG(0, ("debug encryption: dumping generated session keys\n"));
1152 DEBUGADD(0, ("Session Id "));
1153 dump_data(0, (uint8_t*)&sid, sizeof(sid));
1154 DEBUGADD(0, ("Session Key "));
1155 dump_data(0, session_key.data, session_key.length);
1156 DEBUGADD(0, ("Signing Key "));
1157 dump_data(0, sig.data, sig.length);
1158 DEBUGADD(0, ("App Key "));
1159 dump_data(0, app.data, app.length);
1161 /* In client code, ServerIn is the encryption key */
1163 DEBUGADD(0, ("ServerIn Key "));
1164 dump_data(0, enc.data, enc.length);
1165 DEBUGADD(0, ("ServerOut Key "));
1166 dump_data(0, dec.data, dec.length);
1168 out:
1169 data_blob_clear_free(&sig);
1170 data_blob_clear_free(&app);
1171 data_blob_clear_free(&enc);
1172 data_blob_clear_free(&dec);
1175 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1177 struct cli_session_setup_gensec_state *state =
1178 tevent_req_data(req,
1179 struct cli_session_setup_gensec_state);
1180 const char *server_domain = NULL;
1181 NTSTATUS status;
1183 if (state->blob_in.length != 0) {
1184 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1185 return;
1188 if (state->blob_out.length != 0) {
1189 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1190 return;
1194 * gensec_ntlmssp_server_domain() returns NULL
1195 * if NTLMSSP is not used.
1197 * We can remove this later
1198 * and leave the server domain empty for SMB2 and above
1199 * in future releases.
1201 server_domain = gensec_ntlmssp_server_domain(
1202 state->auth_generic->gensec_security);
1204 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1205 TALLOC_FREE(state->cli->server_domain);
1206 state->cli->server_domain = talloc_strdup(state->cli,
1207 server_domain);
1208 if (state->cli->server_domain == NULL) {
1209 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1210 return;
1214 if (state->is_anonymous) {
1216 * Windows server does not set the
1217 * SMB2_SESSION_FLAG_IS_NULL flag.
1219 * This fix makes sure we do not try
1220 * to verify a signature on the final
1221 * session setup response.
1223 tevent_req_done(req);
1224 return;
1227 status = gensec_session_key(state->auth_generic->gensec_security,
1228 state, &state->session_key);
1229 if (tevent_req_nterror(req, status)) {
1230 return;
1233 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1234 struct smbXcli_session *session = state->cli->smb2.session;
1236 status = smb2cli_session_set_session_key(session,
1237 state->session_key,
1238 state->recv_iov);
1239 if (tevent_req_nterror(req, status)) {
1240 return;
1242 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB3_00
1243 && lp_debug_encryption())
1245 cli_session_dump_keys(state, session, state->session_key);
1247 } else {
1248 struct smbXcli_session *session = state->cli->smb1.session;
1249 bool active;
1251 status = smb1cli_session_set_session_key(session,
1252 state->session_key);
1253 if (tevent_req_nterror(req, status)) {
1254 return;
1257 active = smb1cli_conn_activate_signing(state->cli->conn,
1258 state->session_key,
1259 data_blob_null);
1260 if (active) {
1261 bool ok;
1263 ok = smb1cli_conn_check_signing(state->cli->conn,
1264 state->inbuf, 1);
1265 if (!ok) {
1266 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1267 return;
1272 tevent_req_done(req);
1275 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1277 struct cli_session_setup_gensec_state *state =
1278 tevent_req_data(req,
1279 struct cli_session_setup_gensec_state);
1280 NTSTATUS status;
1282 if (tevent_req_is_nterror(req, &status)) {
1283 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1284 return status;
1286 return NT_STATUS_OK;
1289 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1290 const char *principal)
1292 char *account, *p;
1294 account = talloc_strdup(mem_ctx, principal);
1295 if (account == NULL) {
1296 return NULL;
1298 p = strchr_m(account, '@');
1299 if (p != NULL) {
1300 *p = '\0';
1302 return account;
1305 /****************************************************************************
1306 Do a spnego encrypted session setup.
1308 user_domain: The shortname of the domain the user/machine is a member of.
1309 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1310 ****************************************************************************/
1312 struct cli_session_setup_spnego_state {
1313 ADS_STATUS result;
1316 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1318 static struct tevent_req *cli_session_setup_spnego_send(
1319 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1320 struct cli_credentials *creds)
1322 struct tevent_req *req, *subreq;
1323 struct cli_session_setup_spnego_state *state;
1324 const char *target_service = NULL;
1325 const char *target_hostname = NULL;
1326 NTSTATUS status;
1328 req = tevent_req_create(mem_ctx, &state,
1329 struct cli_session_setup_spnego_state);
1330 if (req == NULL) {
1331 return NULL;
1334 target_service = "cifs";
1335 target_hostname = smbXcli_conn_remote_name(cli->conn);
1337 status = cli_session_creds_prepare_krb5(cli, creds);
1338 if (tevent_req_nterror(req, status)) {
1339 return tevent_req_post(req, ev);
1342 DBG_INFO("Connect to %s as %s using SPNEGO\n",
1343 target_hostname,
1344 cli_credentials_get_principal(creds, talloc_tos()));
1346 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1347 target_service, target_hostname);
1348 if (tevent_req_nomem(subreq, req)) {
1349 return tevent_req_post(req, ev);
1351 tevent_req_set_callback(
1352 subreq, cli_session_setup_spnego_done, req);
1353 return req;
1356 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1358 struct tevent_req *req = tevent_req_callback_data(
1359 subreq, struct tevent_req);
1360 NTSTATUS status;
1362 status = cli_session_setup_gensec_recv(subreq);
1363 TALLOC_FREE(subreq);
1364 if (tevent_req_nterror(req, status)) {
1365 return;
1368 tevent_req_done(req);
1371 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1373 struct cli_session_setup_spnego_state *state = tevent_req_data(
1374 req, struct cli_session_setup_spnego_state);
1375 NTSTATUS status;
1377 if (tevent_req_is_nterror(req, &status)) {
1378 state->result = ADS_ERROR_NT(status);
1381 return state->result;
1384 struct cli_session_setup_creds_state {
1385 struct cli_state *cli;
1386 DATA_BLOB apassword_blob;
1387 DATA_BLOB upassword_blob;
1388 DATA_BLOB lm_session_key;
1389 DATA_BLOB session_key;
1390 char *out_native_os;
1391 char *out_native_lm;
1392 char *out_primary_domain;
1395 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1396 enum tevent_req_state req_state)
1398 struct cli_session_setup_creds_state *state = tevent_req_data(
1399 req, struct cli_session_setup_creds_state);
1401 if (req_state != TEVENT_REQ_RECEIVED) {
1402 return;
1406 * We only call data_blob_clear() as
1407 * some of the blobs point to the same memory.
1409 * We let the talloc hierachy free the memory.
1411 data_blob_clear(&state->apassword_blob);
1412 data_blob_clear(&state->upassword_blob);
1413 data_blob_clear(&state->lm_session_key);
1414 data_blob_clear(&state->session_key);
1415 ZERO_STRUCTP(state);
1418 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1419 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1420 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1422 /****************************************************************************
1423 Send a session setup. The username and workgroup is in UNIX character
1424 format and must be converted to DOS codepage format before sending. If the
1425 password is in plaintext, the same should be done.
1426 ****************************************************************************/
1428 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1429 struct tevent_context *ev,
1430 struct cli_state *cli,
1431 struct cli_credentials *creds)
1433 struct tevent_req *req, *subreq;
1434 struct cli_session_setup_creds_state *state;
1435 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1436 bool use_spnego = false;
1437 int flags = 0;
1438 enum credentials_use_kerberos krb5_state;
1439 uint32_t gensec_features;
1440 const char *username = "";
1441 const char *domain = "";
1442 DATA_BLOB target_info = data_blob_null;
1443 DATA_BLOB challenge = data_blob_null;
1444 uint16_t in_buf_size = 0;
1445 uint16_t in_mpx_max = 0;
1446 uint16_t in_vc_num = 0;
1447 uint32_t in_sess_key = 0;
1448 const char *in_native_os = NULL;
1449 const char *in_native_lm = NULL;
1450 NTSTATUS status;
1452 req = tevent_req_create(mem_ctx, &state,
1453 struct cli_session_setup_creds_state);
1454 if (req == NULL) {
1455 return NULL;
1457 state->cli = cli;
1459 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1461 krb5_state = cli_credentials_get_kerberos_state(creds);
1462 gensec_features = cli_credentials_get_gensec_features(creds);
1464 switch (krb5_state) {
1465 case CRED_MUST_USE_KERBEROS:
1466 cli->use_kerberos = true;
1467 cli->fallback_after_kerberos = false;
1468 break;
1469 case CRED_AUTO_USE_KERBEROS:
1470 cli->use_kerberos = true;
1471 cli->fallback_after_kerberos = true;
1472 break;
1473 case CRED_DONT_USE_KERBEROS:
1474 cli->use_kerberos = false;
1475 cli->fallback_after_kerberos = false;
1476 break;
1479 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
1480 cli->use_ccache = true;
1481 } else {
1482 cli->use_ccache = false;
1486 * Now work out what sort of session setup we are going to
1487 * do. I have split this into separate functions to make the flow a bit
1488 * easier to understand (tridge).
1490 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1491 use_spnego = false;
1492 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1493 use_spnego = true;
1494 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1496 * if the server supports extended security then use SPNEGO
1497 * even for anonymous connections.
1499 use_spnego = true;
1500 } else {
1501 use_spnego = false;
1504 if (use_spnego) {
1505 subreq = cli_session_setup_spnego_send(
1506 state, ev, cli, creds);
1507 if (tevent_req_nomem(subreq, req)) {
1508 return tevent_req_post(req, ev);
1510 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1511 req);
1512 return req;
1515 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1517 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1518 * this step against older servers.
1520 tevent_req_done(req);
1521 return tevent_req_post(req, ev);
1524 if (cli_credentials_is_anonymous(creds)) {
1526 * Do an anonymous session setup
1528 goto non_spnego_creds_done;
1531 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1533 * Do an anonymous session setup,
1534 * the password is passed via the tree connect.
1536 goto non_spnego_creds_done;
1539 cli_credentials_get_ntlm_username_domain(creds, state,
1540 &username,
1541 &domain);
1542 if (tevent_req_nomem(username, req)) {
1543 return tevent_req_post(req, ev);
1545 if (tevent_req_nomem(domain, req)) {
1546 return tevent_req_post(req, ev);
1549 DBG_INFO("Connect to %s as %s using NTLM\n", domain, username);
1551 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1552 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1553 uint8_t *bytes = NULL;
1554 size_t bytes_len = 0;
1555 const char *pw = cli_credentials_get_password(creds);
1556 size_t pw_len = 0;
1558 if (pw == NULL) {
1559 pw = "";
1561 pw_len = strlen(pw) + 1;
1563 if (!lp_client_plaintext_auth()) {
1564 DEBUG(1, ("Server requested PLAINTEXT password but "
1565 "'client plaintext auth = no'\n"));
1566 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1567 return tevent_req_post(req, ev);
1570 bytes = talloc_array(state, uint8_t, 0);
1571 bytes = trans2_bytes_push_str(bytes, use_unicode,
1572 pw, pw_len, &bytes_len);
1573 if (tevent_req_nomem(bytes, req)) {
1574 return tevent_req_post(req, ev);
1577 if (use_unicode) {
1579 * CAP_UNICODE, can only be negotiated by NT1.
1581 state->upassword_blob = data_blob_const(bytes,
1582 bytes_len);
1583 } else {
1584 state->apassword_blob = data_blob_const(bytes,
1585 bytes_len);
1588 goto non_spnego_creds_done;
1591 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1593 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1594 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1596 * Don't send an NTLMv2 response without NTLMSSP if we
1597 * want to use spnego support.
1599 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1600 " but 'client use spnego = yes'"
1601 " and 'client ntlmv2 auth = yes' is set\n"));
1602 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1603 return tevent_req_post(req, ev);
1606 if (lp_client_ntlmv2_auth()) {
1607 flags |= CLI_CRED_NTLMv2_AUTH;
1610 * note that the 'domain' here is a best
1611 * guess - we don't know the server's domain
1612 * at this point. Windows clients also don't
1613 * use hostname...
1615 target_info = NTLMv2_generate_names_blob(state,
1616 NULL,
1617 domain);
1618 if (tevent_req_nomem(target_info.data, req)) {
1619 return tevent_req_post(req, ev);
1621 } else {
1622 flags |= CLI_CRED_NTLM_AUTH;
1623 if (lp_client_lanman_auth()) {
1624 flags |= CLI_CRED_LANMAN_AUTH;
1627 } else {
1628 if (!lp_client_lanman_auth()) {
1629 DEBUG(1, ("Server requested user level LM password but "
1630 "'client lanman auth = no' is set.\n"));
1631 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1632 return tevent_req_post(req, ev);
1635 flags |= CLI_CRED_LANMAN_AUTH;
1638 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1639 challenge, NULL,
1640 target_info,
1641 &state->apassword_blob,
1642 &state->upassword_blob,
1643 &state->lm_session_key,
1644 &state->session_key);
1645 if (tevent_req_nterror(req, status)) {
1646 return tevent_req_post(req, ev);
1649 non_spnego_creds_done:
1651 in_buf_size = CLI_BUFFER_SIZE;
1652 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1653 in_vc_num = cli_state_get_vc_num(cli);
1654 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1655 in_native_os = "Unix";
1656 in_native_lm = "Samba";
1658 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1659 uint32_t in_capabilities = 0;
1661 in_capabilities = cli_session_setup_capabilities(cli, 0);
1664 * For now we keep the same values as before,
1665 * we may remove these in a separate commit later.
1667 in_mpx_max = 2;
1669 subreq = smb1cli_session_setup_nt1_send(state, ev,
1670 cli->conn,
1671 cli->timeout,
1672 cli->smb1.pid,
1673 cli->smb1.session,
1674 in_buf_size,
1675 in_mpx_max,
1676 in_vc_num,
1677 in_sess_key,
1678 username,
1679 domain,
1680 state->apassword_blob,
1681 state->upassword_blob,
1682 in_capabilities,
1683 in_native_os,
1684 in_native_lm);
1685 if (tevent_req_nomem(subreq, req)) {
1686 return tevent_req_post(req, ev);
1688 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1689 req);
1690 return req;
1694 * For now we keep the same values as before,
1695 * we may remove these in a separate commit later.
1697 in_mpx_max = 2;
1698 in_vc_num = 1;
1700 subreq = smb1cli_session_setup_lm21_send(state, ev,
1701 cli->conn,
1702 cli->timeout,
1703 cli->smb1.pid,
1704 cli->smb1.session,
1705 in_buf_size,
1706 in_mpx_max,
1707 in_vc_num,
1708 in_sess_key,
1709 username,
1710 domain,
1711 state->apassword_blob,
1712 in_native_os,
1713 in_native_lm);
1714 if (tevent_req_nomem(subreq, req)) {
1715 return tevent_req_post(req, ev);
1717 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1718 req);
1719 return req;
1722 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1724 struct tevent_req *req = tevent_req_callback_data(
1725 subreq, struct tevent_req);
1726 ADS_STATUS status;
1728 status = cli_session_setup_spnego_recv(subreq);
1729 TALLOC_FREE(subreq);
1730 if (!ADS_ERR_OK(status)) {
1731 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1732 tevent_req_nterror(req, ads_ntstatus(status));
1733 return;
1735 tevent_req_done(req);
1738 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1740 struct tevent_req *req = tevent_req_callback_data(
1741 subreq, struct tevent_req);
1742 struct cli_session_setup_creds_state *state = tevent_req_data(
1743 req, struct cli_session_setup_creds_state);
1744 struct cli_state *cli = state->cli;
1745 NTSTATUS status;
1746 struct iovec *recv_iov = NULL;
1747 const uint8_t *inbuf = NULL;
1748 bool ok;
1750 status = smb1cli_session_setup_nt1_recv(subreq, state,
1751 &recv_iov,
1752 &inbuf,
1753 &state->out_native_os,
1754 &state->out_native_lm,
1755 &state->out_primary_domain);
1756 TALLOC_FREE(subreq);
1757 if (!NT_STATUS_IS_OK(status)) {
1758 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1759 tevent_req_nterror(req, status);
1760 return;
1763 status = cli_state_update_after_sesssetup(state->cli,
1764 state->out_native_os,
1765 state->out_native_lm,
1766 state->out_primary_domain);
1767 if (tevent_req_nterror(req, status)) {
1768 return;
1771 ok = smb1cli_conn_activate_signing(cli->conn,
1772 state->session_key,
1773 state->upassword_blob);
1774 if (ok) {
1775 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1776 if (!ok) {
1777 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1778 return;
1782 if (state->session_key.data) {
1783 struct smbXcli_session *session = cli->smb1.session;
1785 status = smb1cli_session_set_session_key(session,
1786 state->session_key);
1787 if (tevent_req_nterror(req, status)) {
1788 return;
1792 tevent_req_done(req);
1795 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1797 struct tevent_req *req = tevent_req_callback_data(
1798 subreq, struct tevent_req);
1799 struct cli_session_setup_creds_state *state = tevent_req_data(
1800 req, struct cli_session_setup_creds_state);
1801 NTSTATUS status;
1803 status = smb1cli_session_setup_lm21_recv(subreq, state,
1804 &state->out_native_os,
1805 &state->out_native_lm);
1806 TALLOC_FREE(subreq);
1807 if (!NT_STATUS_IS_OK(status)) {
1808 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1809 tevent_req_nterror(req, status);
1810 return;
1813 status = cli_state_update_after_sesssetup(state->cli,
1814 state->out_native_os,
1815 state->out_native_lm,
1816 NULL);
1817 if (tevent_req_nterror(req, status)) {
1818 return;
1821 tevent_req_done(req);
1824 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1826 return tevent_req_simple_recv_ntstatus(req);
1829 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1830 struct cli_credentials *creds)
1832 struct tevent_context *ev;
1833 struct tevent_req *req;
1834 NTSTATUS status = NT_STATUS_NO_MEMORY;
1836 if (smbXcli_conn_has_async_calls(cli->conn)) {
1837 return NT_STATUS_INVALID_PARAMETER;
1839 ev = samba_tevent_context_init(talloc_tos());
1840 if (ev == NULL) {
1841 goto fail;
1843 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1844 if (req == NULL) {
1845 goto fail;
1847 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1848 goto fail;
1850 status = cli_session_setup_creds_recv(req);
1851 fail:
1852 TALLOC_FREE(ev);
1853 return status;
1856 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1858 NTSTATUS status = NT_STATUS_NO_MEMORY;
1859 struct cli_credentials *creds = NULL;
1861 creds = cli_credentials_init_anon(cli);
1862 if (creds == NULL) {
1863 return NT_STATUS_NO_MEMORY;
1866 status = cli_session_setup_creds(cli, creds);
1867 TALLOC_FREE(creds);
1868 if (!NT_STATUS_IS_OK(status)) {
1869 return status;
1872 return NT_STATUS_OK;
1875 /****************************************************************************
1876 Send a uloggoff.
1877 *****************************************************************************/
1879 struct cli_ulogoff_state {
1880 struct cli_state *cli;
1881 uint16_t vwv[3];
1884 static void cli_ulogoff_done(struct tevent_req *subreq);
1886 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1887 struct tevent_context *ev,
1888 struct cli_state *cli)
1890 struct tevent_req *req, *subreq;
1891 struct cli_ulogoff_state *state;
1893 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1894 if (req == NULL) {
1895 return NULL;
1897 state->cli = cli;
1899 SCVAL(state->vwv+0, 0, 0xFF);
1900 SCVAL(state->vwv+1, 0, 0);
1901 SSVAL(state->vwv+2, 0, 0);
1903 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1904 0, NULL);
1905 if (tevent_req_nomem(subreq, req)) {
1906 return tevent_req_post(req, ev);
1908 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1909 return req;
1912 static void cli_ulogoff_done(struct tevent_req *subreq)
1914 struct tevent_req *req = tevent_req_callback_data(
1915 subreq, struct tevent_req);
1916 struct cli_ulogoff_state *state = tevent_req_data(
1917 req, struct cli_ulogoff_state);
1918 NTSTATUS status;
1920 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1921 if (!NT_STATUS_IS_OK(status)) {
1922 tevent_req_nterror(req, status);
1923 return;
1925 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1926 tevent_req_done(req);
1929 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1931 return tevent_req_simple_recv_ntstatus(req);
1934 NTSTATUS cli_ulogoff(struct cli_state *cli)
1936 struct tevent_context *ev;
1937 struct tevent_req *req;
1938 NTSTATUS status = NT_STATUS_NO_MEMORY;
1940 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1941 status = smb2cli_logoff(cli->conn,
1942 cli->timeout,
1943 cli->smb2.session);
1944 if (!NT_STATUS_IS_OK(status)) {
1945 return status;
1947 smb2cli_session_set_id_and_flags(cli->smb2.session,
1948 UINT64_MAX, 0);
1949 return NT_STATUS_OK;
1952 if (smbXcli_conn_has_async_calls(cli->conn)) {
1953 return NT_STATUS_INVALID_PARAMETER;
1955 ev = samba_tevent_context_init(talloc_tos());
1956 if (ev == NULL) {
1957 goto fail;
1959 req = cli_ulogoff_send(ev, ev, cli);
1960 if (req == NULL) {
1961 goto fail;
1963 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1964 goto fail;
1966 status = cli_ulogoff_recv(req);
1967 fail:
1968 TALLOC_FREE(ev);
1969 return status;
1972 /****************************************************************************
1973 Send a tconX.
1974 ****************************************************************************/
1976 struct cli_tcon_andx_state {
1977 struct cli_state *cli;
1978 uint16_t vwv[4];
1979 struct iovec bytes;
1982 static void cli_tcon_andx_done(struct tevent_req *subreq);
1984 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1985 struct tevent_context *ev,
1986 struct cli_state *cli,
1987 const char *share, const char *dev,
1988 const char *pass, int passlen,
1989 struct tevent_req **psmbreq)
1991 struct tevent_req *req, *subreq;
1992 struct cli_tcon_andx_state *state;
1993 uint8_t p24[24];
1994 uint16_t *vwv;
1995 char *tmp = NULL;
1996 uint8_t *bytes;
1997 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1998 uint16_t tcon_flags = 0;
2000 *psmbreq = NULL;
2002 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2003 if (req == NULL) {
2004 return NULL;
2006 state->cli = cli;
2007 vwv = state->vwv;
2009 TALLOC_FREE(cli->smb1.tcon);
2010 cli->smb1.tcon = smbXcli_tcon_create(cli);
2011 if (tevent_req_nomem(cli->smb1.tcon, req)) {
2012 return tevent_req_post(req, ev);
2014 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
2016 cli->share = talloc_strdup(cli, share);
2017 if (!cli->share) {
2018 return NULL;
2021 /* in user level security don't send a password now */
2022 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2023 passlen = 1;
2024 pass = "";
2025 } else if (pass == NULL) {
2026 DEBUG(1, ("Server not using user level security and no "
2027 "password supplied.\n"));
2028 goto access_denied;
2031 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2032 *pass && passlen != 24) {
2033 if (!lp_client_lanman_auth()) {
2034 DEBUG(1, ("Server requested LANMAN password "
2035 "(share-level security) but "
2036 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2037 goto access_denied;
2041 * Non-encrypted passwords - convert to DOS codepage before
2042 * encryption.
2044 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2045 passlen = 24;
2046 pass = (const char *)p24;
2047 } else {
2048 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2049 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2050 == 0) {
2051 uint8_t *tmp_pass;
2053 if (!lp_client_plaintext_auth() && (*pass)) {
2054 DEBUG(1, ("Server requested PLAINTEXT "
2055 "password but "
2056 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2057 goto access_denied;
2061 * Non-encrypted passwords - convert to DOS codepage
2062 * before using.
2064 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2065 if (tevent_req_nomem(tmp_pass, req)) {
2066 return tevent_req_post(req, ev);
2068 tmp_pass = trans2_bytes_push_str(tmp_pass,
2069 false, /* always DOS */
2070 pass,
2071 passlen,
2072 NULL);
2073 if (tevent_req_nomem(tmp_pass, req)) {
2074 return tevent_req_post(req, ev);
2076 pass = (const char *)tmp_pass;
2077 passlen = talloc_get_size(tmp_pass);
2081 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2082 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2084 SCVAL(vwv+0, 0, 0xFF);
2085 SCVAL(vwv+0, 1, 0);
2086 SSVAL(vwv+1, 0, 0);
2087 SSVAL(vwv+2, 0, tcon_flags);
2088 SSVAL(vwv+3, 0, passlen);
2090 if (passlen && pass) {
2091 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2092 } else {
2093 bytes = talloc_array(state, uint8_t, 0);
2097 * Add the sharename
2099 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2100 smbXcli_conn_remote_name(cli->conn), share);
2101 if (tmp == NULL) {
2102 TALLOC_FREE(req);
2103 return NULL;
2105 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2106 NULL);
2107 TALLOC_FREE(tmp);
2110 * Add the devicetype
2112 tmp = talloc_strdup_upper(talloc_tos(), dev);
2113 if (tmp == NULL) {
2114 TALLOC_FREE(req);
2115 return NULL;
2117 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2118 TALLOC_FREE(tmp);
2120 if (bytes == NULL) {
2121 TALLOC_FREE(req);
2122 return NULL;
2125 state->bytes.iov_base = (void *)bytes;
2126 state->bytes.iov_len = talloc_get_size(bytes);
2128 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2129 1, &state->bytes);
2130 if (subreq == NULL) {
2131 TALLOC_FREE(req);
2132 return NULL;
2134 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2135 *psmbreq = subreq;
2136 return req;
2138 access_denied:
2139 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2140 return tevent_req_post(req, ev);
2143 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2144 struct tevent_context *ev,
2145 struct cli_state *cli,
2146 const char *share, const char *dev,
2147 const char *pass, int passlen)
2149 struct tevent_req *req, *subreq;
2150 NTSTATUS status;
2152 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2153 &subreq);
2154 if (req == NULL) {
2155 return NULL;
2157 if (subreq == NULL) {
2158 return req;
2160 status = smb1cli_req_chain_submit(&subreq, 1);
2161 if (!NT_STATUS_IS_OK(status)) {
2162 tevent_req_nterror(req, status);
2163 return tevent_req_post(req, ev);
2165 return req;
2168 static void cli_tcon_andx_done(struct tevent_req *subreq)
2170 struct tevent_req *req = tevent_req_callback_data(
2171 subreq, struct tevent_req);
2172 struct cli_tcon_andx_state *state = tevent_req_data(
2173 req, struct cli_tcon_andx_state);
2174 struct cli_state *cli = state->cli;
2175 uint8_t *in;
2176 uint8_t *inhdr;
2177 uint8_t wct;
2178 uint16_t *vwv;
2179 uint32_t num_bytes;
2180 uint8_t *bytes;
2181 NTSTATUS status;
2182 uint16_t optional_support = 0;
2184 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2185 &num_bytes, &bytes);
2186 TALLOC_FREE(subreq);
2187 if (!NT_STATUS_IS_OK(status)) {
2188 tevent_req_nterror(req, status);
2189 return;
2192 inhdr = in + NBT_HDR_SIZE;
2194 if (num_bytes) {
2195 if (clistr_pull_talloc(cli,
2196 (const char *)inhdr,
2197 SVAL(inhdr, HDR_FLG2),
2198 &cli->dev,
2199 bytes,
2200 num_bytes,
2201 STR_TERMINATE|STR_ASCII) == -1) {
2202 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2203 return;
2205 } else {
2206 cli->dev = talloc_strdup(cli, "");
2207 if (cli->dev == NULL) {
2208 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2209 return;
2213 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2214 /* almost certainly win95 - enable bug fixes */
2215 cli->win95 = True;
2219 * Make sure that we have the optional support 16-bit field. WCT > 2.
2220 * Avoids issues when connecting to Win9x boxes sharing files
2223 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2224 optional_support = SVAL(vwv+2, 0);
2227 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2228 smb1cli_session_protect_session_key(cli->smb1.session);
2231 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2232 SVAL(inhdr, HDR_TID),
2233 optional_support,
2234 0, /* maximal_access */
2235 0, /* guest_maximal_access */
2236 NULL, /* service */
2237 NULL); /* fs_type */
2239 tevent_req_done(req);
2242 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2244 return tevent_req_simple_recv_ntstatus(req);
2247 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2248 const char *dev, const char *pass, int passlen)
2250 TALLOC_CTX *frame = talloc_stackframe();
2251 struct tevent_context *ev;
2252 struct tevent_req *req;
2253 NTSTATUS status = NT_STATUS_NO_MEMORY;
2255 if (smbXcli_conn_has_async_calls(cli->conn)) {
2257 * Can't use sync call while an async call is in flight
2259 status = NT_STATUS_INVALID_PARAMETER;
2260 goto fail;
2263 ev = samba_tevent_context_init(frame);
2264 if (ev == NULL) {
2265 goto fail;
2268 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2269 if (req == NULL) {
2270 goto fail;
2273 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2274 goto fail;
2277 status = cli_tcon_andx_recv(req);
2278 fail:
2279 TALLOC_FREE(frame);
2280 return status;
2283 struct cli_tree_connect_state {
2284 struct cli_state *cli;
2287 static struct tevent_req *cli_raw_tcon_send(
2288 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2289 const char *service, const char *pass, const char *dev);
2290 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2291 uint16_t *max_xmit, uint16_t *tid);
2293 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2294 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2295 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2297 static struct tevent_req *cli_tree_connect_send(
2298 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2299 const char *share, const char *dev, const char *pass)
2301 struct tevent_req *req, *subreq;
2302 struct cli_tree_connect_state *state;
2303 int passlen;
2305 if (pass == NULL) {
2306 pass = "";
2308 passlen = strlen(pass) + 1;
2310 req = tevent_req_create(mem_ctx, &state,
2311 struct cli_tree_connect_state);
2312 if (req == NULL) {
2313 return NULL;
2315 state->cli = cli;
2317 cli->share = talloc_strdup(cli, share);
2318 if (tevent_req_nomem(cli->share, req)) {
2319 return tevent_req_post(req, ev);
2322 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2323 char *unc;
2325 TALLOC_FREE(cli->smb2.tcon);
2326 cli->smb2.tcon = smbXcli_tcon_create(cli);
2327 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2328 return tevent_req_post(req, ev);
2331 unc = talloc_asprintf(state, "\\\\%s\\%s",
2332 smbXcli_conn_remote_name(cli->conn),
2333 share);
2334 if (tevent_req_nomem(unc, req)) {
2335 return tevent_req_post(req, ev);
2338 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2339 cli->smb2.session, cli->smb2.tcon,
2340 0, /* flags */
2341 unc);
2342 if (tevent_req_nomem(subreq, req)) {
2343 return tevent_req_post(req, ev);
2345 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2346 req);
2347 return req;
2350 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2351 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2352 pass, passlen);
2353 if (tevent_req_nomem(subreq, req)) {
2354 return tevent_req_post(req, ev);
2356 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2357 req);
2358 return req;
2361 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2362 if (tevent_req_nomem(subreq, req)) {
2363 return tevent_req_post(req, ev);
2365 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2367 return req;
2370 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2372 tevent_req_simple_finish_ntstatus(
2373 subreq, smb2cli_tcon_recv(subreq));
2376 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2378 tevent_req_simple_finish_ntstatus(
2379 subreq, cli_tcon_andx_recv(subreq));
2382 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2384 struct tevent_req *req = tevent_req_callback_data(
2385 subreq, struct tevent_req);
2386 struct cli_tree_connect_state *state = tevent_req_data(
2387 req, struct cli_tree_connect_state);
2388 NTSTATUS status;
2389 uint16_t max_xmit = 0;
2390 uint16_t tid = 0;
2392 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2393 if (tevent_req_nterror(req, status)) {
2394 return;
2397 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2398 tid,
2399 0, /* optional_support */
2400 0, /* maximal_access */
2401 0, /* guest_maximal_access */
2402 NULL, /* service */
2403 NULL); /* fs_type */
2405 tevent_req_done(req);
2408 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2410 return tevent_req_simple_recv_ntstatus(req);
2413 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2414 const char *dev, const char *pass)
2416 struct tevent_context *ev;
2417 struct tevent_req *req;
2418 NTSTATUS status = NT_STATUS_NO_MEMORY;
2420 if (smbXcli_conn_has_async_calls(cli->conn)) {
2421 return NT_STATUS_INVALID_PARAMETER;
2423 ev = samba_tevent_context_init(talloc_tos());
2424 if (ev == NULL) {
2425 goto fail;
2427 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2428 if (req == NULL) {
2429 goto fail;
2431 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2432 goto fail;
2434 status = cli_tree_connect_recv(req);
2435 fail:
2436 TALLOC_FREE(ev);
2437 return status;
2440 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2441 const char *share, const char *dev,
2442 struct cli_credentials *creds)
2444 const char *pw = NULL;
2446 if (creds != NULL) {
2447 pw = cli_credentials_get_password(creds);
2450 return cli_tree_connect(cli, share, dev, pw);
2453 /****************************************************************************
2454 Send a tree disconnect.
2455 ****************************************************************************/
2457 struct cli_tdis_state {
2458 struct cli_state *cli;
2461 static void cli_tdis_done(struct tevent_req *subreq);
2463 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2464 struct tevent_context *ev,
2465 struct cli_state *cli)
2467 struct tevent_req *req, *subreq;
2468 struct cli_tdis_state *state;
2470 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2471 if (req == NULL) {
2472 return NULL;
2474 state->cli = cli;
2476 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2477 if (tevent_req_nomem(subreq, req)) {
2478 return tevent_req_post(req, ev);
2480 tevent_req_set_callback(subreq, cli_tdis_done, req);
2481 return req;
2484 static void cli_tdis_done(struct tevent_req *subreq)
2486 struct tevent_req *req = tevent_req_callback_data(
2487 subreq, struct tevent_req);
2488 struct cli_tdis_state *state = tevent_req_data(
2489 req, struct cli_tdis_state);
2490 NTSTATUS status;
2492 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2493 TALLOC_FREE(subreq);
2494 if (!NT_STATUS_IS_OK(status)) {
2495 tevent_req_nterror(req, status);
2496 return;
2498 TALLOC_FREE(state->cli->smb1.tcon);
2499 tevent_req_done(req);
2502 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2504 return tevent_req_simple_recv_ntstatus(req);
2507 NTSTATUS cli_tdis(struct cli_state *cli)
2509 struct tevent_context *ev;
2510 struct tevent_req *req;
2511 NTSTATUS status = NT_STATUS_NO_MEMORY;
2513 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2514 status = smb2cli_tdis(cli->conn,
2515 cli->timeout,
2516 cli->smb2.session,
2517 cli->smb2.tcon);
2518 if (NT_STATUS_IS_OK(status)) {
2519 TALLOC_FREE(cli->smb2.tcon);
2521 return status;
2524 if (smbXcli_conn_has_async_calls(cli->conn)) {
2525 return NT_STATUS_INVALID_PARAMETER;
2527 ev = samba_tevent_context_init(talloc_tos());
2528 if (ev == NULL) {
2529 goto fail;
2531 req = cli_tdis_send(ev, ev, cli);
2532 if (req == NULL) {
2533 goto fail;
2535 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2536 goto fail;
2538 status = cli_tdis_recv(req);
2539 fail:
2540 TALLOC_FREE(ev);
2541 return status;
2544 struct cli_connect_sock_state {
2545 const char **called_names;
2546 const char **calling_names;
2547 int *called_types;
2548 int fd;
2549 uint16_t port;
2552 static void cli_connect_sock_done(struct tevent_req *subreq);
2555 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2556 * nonzero address.
2559 static struct tevent_req *cli_connect_sock_send(
2560 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2561 const char *host, int name_type, const struct sockaddr_storage *pss,
2562 const char *myname, uint16_t port)
2564 struct tevent_req *req, *subreq;
2565 struct cli_connect_sock_state *state;
2566 struct sockaddr_storage *addrs;
2567 unsigned i, num_addrs;
2568 NTSTATUS status;
2570 req = tevent_req_create(mem_ctx, &state,
2571 struct cli_connect_sock_state);
2572 if (req == NULL) {
2573 return NULL;
2576 if ((pss == NULL) || is_zero_addr(pss)) {
2579 * Here we cheat. resolve_name_list is not async at all. So
2580 * this call will only be really async if the name lookup has
2581 * been done externally.
2584 status = resolve_name_list(state, host, name_type,
2585 &addrs, &num_addrs);
2586 if (!NT_STATUS_IS_OK(status)) {
2587 tevent_req_nterror(req, status);
2588 return tevent_req_post(req, ev);
2590 } else {
2591 addrs = talloc_array(state, struct sockaddr_storage, 1);
2592 if (tevent_req_nomem(addrs, req)) {
2593 return tevent_req_post(req, ev);
2595 addrs[0] = *pss;
2596 num_addrs = 1;
2599 state->called_names = talloc_array(state, const char *, num_addrs);
2600 if (tevent_req_nomem(state->called_names, req)) {
2601 return tevent_req_post(req, ev);
2603 state->called_types = talloc_array(state, int, num_addrs);
2604 if (tevent_req_nomem(state->called_types, req)) {
2605 return tevent_req_post(req, ev);
2607 state->calling_names = talloc_array(state, const char *, num_addrs);
2608 if (tevent_req_nomem(state->calling_names, req)) {
2609 return tevent_req_post(req, ev);
2611 for (i=0; i<num_addrs; i++) {
2612 state->called_names[i] = host;
2613 state->called_types[i] = name_type;
2614 state->calling_names[i] = myname;
2617 subreq = smbsock_any_connect_send(
2618 state, ev, addrs, state->called_names, state->called_types,
2619 state->calling_names, NULL, num_addrs, port);
2620 if (tevent_req_nomem(subreq, req)) {
2621 return tevent_req_post(req, ev);
2623 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2624 return req;
2627 static void cli_connect_sock_done(struct tevent_req *subreq)
2629 struct tevent_req *req = tevent_req_callback_data(
2630 subreq, struct tevent_req);
2631 struct cli_connect_sock_state *state = tevent_req_data(
2632 req, struct cli_connect_sock_state);
2633 NTSTATUS status;
2635 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2636 &state->port);
2637 TALLOC_FREE(subreq);
2638 if (tevent_req_nterror(req, status)) {
2639 return;
2641 set_socket_options(state->fd, lp_socket_options());
2642 tevent_req_done(req);
2645 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2646 int *pfd, uint16_t *pport)
2648 struct cli_connect_sock_state *state = tevent_req_data(
2649 req, struct cli_connect_sock_state);
2650 NTSTATUS status;
2652 if (tevent_req_is_nterror(req, &status)) {
2653 return status;
2655 *pfd = state->fd;
2656 *pport = state->port;
2657 return NT_STATUS_OK;
2660 struct cli_connect_nb_state {
2661 const char *desthost;
2662 int signing_state;
2663 int flags;
2664 struct cli_state *cli;
2667 static void cli_connect_nb_done(struct tevent_req *subreq);
2669 static struct tevent_req *cli_connect_nb_send(
2670 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2671 const char *host, const struct sockaddr_storage *dest_ss,
2672 uint16_t port, int name_type, const char *myname,
2673 int signing_state, int flags)
2675 struct tevent_req *req, *subreq;
2676 struct cli_connect_nb_state *state;
2678 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2679 if (req == NULL) {
2680 return NULL;
2682 state->signing_state = signing_state;
2683 state->flags = flags;
2685 if (host != NULL) {
2686 char *p = strchr(host, '#');
2688 if (p != NULL) {
2689 name_type = strtol(p+1, NULL, 16);
2690 host = talloc_strndup(state, host, p - host);
2691 if (tevent_req_nomem(host, req)) {
2692 return tevent_req_post(req, ev);
2696 state->desthost = host;
2697 } else if (dest_ss != NULL) {
2698 state->desthost = print_canonical_sockaddr(state, dest_ss);
2699 if (tevent_req_nomem(state->desthost, req)) {
2700 return tevent_req_post(req, ev);
2702 } else {
2703 /* No host or dest_ss given. Error out. */
2704 tevent_req_error(req, EINVAL);
2705 return tevent_req_post(req, ev);
2708 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2709 myname, port);
2710 if (tevent_req_nomem(subreq, req)) {
2711 return tevent_req_post(req, ev);
2713 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2714 return req;
2717 static void cli_connect_nb_done(struct tevent_req *subreq)
2719 struct tevent_req *req = tevent_req_callback_data(
2720 subreq, struct tevent_req);
2721 struct cli_connect_nb_state *state = tevent_req_data(
2722 req, struct cli_connect_nb_state);
2723 NTSTATUS status;
2724 int fd = 0;
2725 uint16_t port;
2727 status = cli_connect_sock_recv(subreq, &fd, &port);
2728 TALLOC_FREE(subreq);
2729 if (tevent_req_nterror(req, status)) {
2730 return;
2733 state->cli = cli_state_create(state, fd, state->desthost,
2734 state->signing_state, state->flags);
2735 if (tevent_req_nomem(state->cli, req)) {
2736 close(fd);
2737 return;
2739 tevent_req_done(req);
2742 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2743 struct cli_state **pcli)
2745 struct cli_connect_nb_state *state = tevent_req_data(
2746 req, struct cli_connect_nb_state);
2747 NTSTATUS status;
2749 if (tevent_req_is_nterror(req, &status)) {
2750 return status;
2752 *pcli = talloc_move(NULL, &state->cli);
2753 return NT_STATUS_OK;
2756 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2757 uint16_t port, int name_type, const char *myname,
2758 int signing_state, int flags, struct cli_state **pcli)
2760 struct tevent_context *ev;
2761 struct tevent_req *req;
2762 NTSTATUS status = NT_STATUS_NO_MEMORY;
2764 ev = samba_tevent_context_init(talloc_tos());
2765 if (ev == NULL) {
2766 goto fail;
2768 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2769 myname, signing_state, flags);
2770 if (req == NULL) {
2771 goto fail;
2773 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2774 goto fail;
2776 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2777 goto fail;
2779 status = cli_connect_nb_recv(req, pcli);
2780 fail:
2781 TALLOC_FREE(ev);
2782 return status;
2785 struct cli_start_connection_state {
2786 struct tevent_context *ev;
2787 struct cli_state *cli;
2788 int min_protocol;
2789 int max_protocol;
2792 static void cli_start_connection_connected(struct tevent_req *subreq);
2793 static void cli_start_connection_done(struct tevent_req *subreq);
2796 establishes a connection to after the negprot.
2797 @param output_cli A fully initialised cli structure, non-null only on success
2798 @param dest_host The netbios name of the remote host
2799 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2800 @param port (optional) The destination port (0 for default)
2803 static struct tevent_req *cli_start_connection_send(
2804 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2805 const char *my_name, const char *dest_host,
2806 const struct sockaddr_storage *dest_ss, int port,
2807 int signing_state, int flags)
2809 struct tevent_req *req, *subreq;
2810 struct cli_start_connection_state *state;
2812 req = tevent_req_create(mem_ctx, &state,
2813 struct cli_start_connection_state);
2814 if (req == NULL) {
2815 return NULL;
2817 state->ev = ev;
2819 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
2820 state->min_protocol = lp_client_ipc_min_protocol();
2821 state->max_protocol = lp_client_ipc_max_protocol();
2822 } else {
2823 state->min_protocol = lp_client_min_protocol();
2824 state->max_protocol = lp_client_max_protocol();
2827 if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
2828 state->max_protocol = MIN(state->max_protocol, PROTOCOL_NT1);
2831 if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
2832 state->min_protocol = MAX(state->max_protocol, PROTOCOL_SMB2_02);
2833 state->max_protocol = MAX(state->max_protocol, PROTOCOL_LATEST);
2836 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2837 0x20, my_name, signing_state, flags);
2838 if (tevent_req_nomem(subreq, req)) {
2839 return tevent_req_post(req, ev);
2841 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2842 return req;
2845 static void cli_start_connection_connected(struct tevent_req *subreq)
2847 struct tevent_req *req = tevent_req_callback_data(
2848 subreq, struct tevent_req);
2849 struct cli_start_connection_state *state = tevent_req_data(
2850 req, struct cli_start_connection_state);
2851 NTSTATUS status;
2853 status = cli_connect_nb_recv(subreq, &state->cli);
2854 TALLOC_FREE(subreq);
2855 if (tevent_req_nterror(req, status)) {
2856 return;
2859 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2860 state->cli->timeout,
2861 state->min_protocol,
2862 state->max_protocol,
2863 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK);
2864 if (tevent_req_nomem(subreq, req)) {
2865 return;
2867 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2870 static void cli_start_connection_done(struct tevent_req *subreq)
2872 struct tevent_req *req = tevent_req_callback_data(
2873 subreq, struct tevent_req);
2874 struct cli_start_connection_state *state = tevent_req_data(
2875 req, struct cli_start_connection_state);
2876 NTSTATUS status;
2878 status = smbXcli_negprot_recv(subreq);
2879 TALLOC_FREE(subreq);
2880 if (tevent_req_nterror(req, status)) {
2881 return;
2884 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2885 /* Ensure we ask for some initial credits. */
2886 smb2cli_conn_set_max_credits(state->cli->conn,
2887 DEFAULT_SMB2_MAX_CREDITS);
2890 tevent_req_done(req);
2893 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2894 struct cli_state **output_cli)
2896 struct cli_start_connection_state *state = tevent_req_data(
2897 req, struct cli_start_connection_state);
2898 NTSTATUS status;
2900 if (tevent_req_is_nterror(req, &status)) {
2901 return status;
2903 *output_cli = state->cli;
2905 return NT_STATUS_OK;
2908 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2909 const char *my_name,
2910 const char *dest_host,
2911 const struct sockaddr_storage *dest_ss, int port,
2912 int signing_state, int flags)
2914 struct tevent_context *ev;
2915 struct tevent_req *req;
2916 NTSTATUS status = NT_STATUS_NO_MEMORY;
2918 ev = samba_tevent_context_init(talloc_tos());
2919 if (ev == NULL) {
2920 goto fail;
2922 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2923 port, signing_state, flags);
2924 if (req == NULL) {
2925 goto fail;
2927 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2928 goto fail;
2930 status = cli_start_connection_recv(req, output_cli);
2931 fail:
2932 TALLOC_FREE(ev);
2933 return status;
2936 struct cli_smb1_setup_encryption_blob_state {
2937 uint16_t setup[1];
2938 uint8_t param[4];
2939 NTSTATUS status;
2940 DATA_BLOB out;
2941 uint16_t enc_ctx_id;
2944 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2946 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2947 struct tevent_context *ev,
2948 struct cli_state *cli,
2949 const DATA_BLOB in)
2951 struct tevent_req *req = NULL;
2952 struct cli_smb1_setup_encryption_blob_state *state = NULL;
2953 struct tevent_req *subreq = NULL;
2955 req = tevent_req_create(mem_ctx, &state,
2956 struct cli_smb1_setup_encryption_blob_state);
2957 if (req == NULL) {
2958 return NULL;
2961 if (in.length > CLI_BUFFER_SIZE) {
2962 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2963 return tevent_req_post(req, ev);
2966 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
2967 SSVAL(state->param, 0, 0);
2968 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
2970 subreq = smb1cli_trans_send(state, ev, cli->conn,
2971 SMBtrans2,
2972 0, 0, /* _flags */
2973 0, 0, /* _flags2 */
2974 cli->timeout,
2975 cli->smb1.pid,
2976 cli->smb1.tcon,
2977 cli->smb1.session,
2978 NULL, /* pipe_name */
2979 0, /* fid */
2980 0, /* function */
2981 0, /* flags */
2982 state->setup, 1, 0,
2983 state->param, 4, 2,
2984 in.data, in.length, CLI_BUFFER_SIZE);
2985 if (tevent_req_nomem(subreq, req)) {
2986 return tevent_req_post(req, ev);
2988 tevent_req_set_callback(subreq,
2989 cli_smb1_setup_encryption_blob_done,
2990 req);
2992 return req;
2995 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
2997 struct tevent_req *req =
2998 tevent_req_callback_data(subreq,
2999 struct tevent_req);
3000 struct cli_smb1_setup_encryption_blob_state *state =
3001 tevent_req_data(req,
3002 struct cli_smb1_setup_encryption_blob_state);
3003 uint8_t *rparam=NULL, *rdata=NULL;
3004 uint32_t num_rparam, num_rdata;
3005 NTSTATUS status;
3007 status = smb1cli_trans_recv(subreq, state,
3008 NULL, /* recv_flags */
3009 NULL, 0, NULL, /* rsetup */
3010 &rparam, 0, &num_rparam,
3011 &rdata, 0, &num_rdata);
3012 TALLOC_FREE(subreq);
3013 state->status = status;
3014 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
3015 status = NT_STATUS_OK;
3017 if (tevent_req_nterror(req, status)) {
3018 return;
3021 if (num_rparam == 2) {
3022 state->enc_ctx_id = SVAL(rparam, 0);
3024 TALLOC_FREE(rparam);
3026 state->out = data_blob_const(rdata, num_rdata);
3028 tevent_req_done(req);
3031 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
3032 TALLOC_CTX *mem_ctx,
3033 DATA_BLOB *out,
3034 uint16_t *enc_ctx_id)
3036 struct cli_smb1_setup_encryption_blob_state *state =
3037 tevent_req_data(req,
3038 struct cli_smb1_setup_encryption_blob_state);
3039 NTSTATUS status;
3041 if (tevent_req_is_nterror(req, &status)) {
3042 tevent_req_received(req);
3043 return status;
3046 status = state->status;
3048 *out = state->out;
3049 talloc_steal(mem_ctx, out->data);
3051 *enc_ctx_id = state->enc_ctx_id;
3053 tevent_req_received(req);
3054 return status;
3057 struct cli_smb1_setup_encryption_state {
3058 struct tevent_context *ev;
3059 struct cli_state *cli;
3060 struct smb_trans_enc_state *es;
3061 DATA_BLOB blob_in;
3062 DATA_BLOB blob_out;
3063 bool local_ready;
3064 bool remote_ready;
3067 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
3068 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
3069 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
3070 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
3071 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
3073 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
3074 struct tevent_context *ev,
3075 struct cli_state *cli,
3076 struct cli_credentials *creds)
3078 struct tevent_req *req = NULL;
3079 struct cli_smb1_setup_encryption_state *state = NULL;
3080 struct auth_generic_state *ags = NULL;
3081 const DATA_BLOB *b = NULL;
3082 bool auth_requested = false;
3083 const char *target_service = NULL;
3084 const char *target_hostname = NULL;
3085 NTSTATUS status;
3087 req = tevent_req_create(mem_ctx, &state,
3088 struct cli_smb1_setup_encryption_state);
3089 if (req == NULL) {
3090 return NULL;
3092 state->ev = ev;
3093 state->cli = cli;
3095 auth_requested = cli_credentials_authentication_requested(creds);
3096 if (!auth_requested) {
3097 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3098 return tevent_req_post(req, ev);
3101 target_service = "cifs";
3102 target_hostname = smbXcli_conn_remote_name(cli->conn);
3104 status = cli_session_creds_prepare_krb5(cli, creds);
3105 if (tevent_req_nterror(req, status)) {
3106 return tevent_req_post(req, ev);
3109 state->es = talloc_zero(state, struct smb_trans_enc_state);
3110 if (tevent_req_nomem(state->es, req)) {
3111 return tevent_req_post(req, ev);
3114 status = auth_generic_client_prepare(state->es, &ags);
3115 if (tevent_req_nterror(req, status)) {
3116 return tevent_req_post(req, ev);
3119 gensec_want_feature(ags->gensec_security,
3120 GENSEC_FEATURE_SIGN);
3121 gensec_want_feature(ags->gensec_security,
3122 GENSEC_FEATURE_SEAL);
3124 status = auth_generic_set_creds(ags, creds);
3125 if (tevent_req_nterror(req, status)) {
3126 return tevent_req_post(req, ev);
3129 if (target_service != NULL) {
3130 status = gensec_set_target_service(ags->gensec_security,
3131 target_service);
3132 if (tevent_req_nterror(req, status)) {
3133 return tevent_req_post(req, ev);
3137 if (target_hostname != NULL) {
3138 status = gensec_set_target_hostname(ags->gensec_security,
3139 target_hostname);
3140 if (tevent_req_nterror(req, status)) {
3141 return tevent_req_post(req, ev);
3145 gensec_set_max_update_size(ags->gensec_security,
3146 CLI_BUFFER_SIZE);
3148 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3149 if (b != NULL) {
3150 state->blob_in = *b;
3153 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3154 if (tevent_req_nterror(req, status)) {
3155 return tevent_req_post(req, ev);
3159 * We only need the gensec_security part from here.
3161 state->es->gensec_security = talloc_move(state->es,
3162 &ags->gensec_security);
3163 TALLOC_FREE(ags);
3165 cli_smb1_setup_encryption_local_next(req);
3166 if (!tevent_req_is_in_progress(req)) {
3167 return tevent_req_post(req, ev);
3170 return req;
3173 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3175 struct cli_smb1_setup_encryption_state *state =
3176 tevent_req_data(req,
3177 struct cli_smb1_setup_encryption_state);
3178 struct tevent_req *subreq = NULL;
3180 if (state->local_ready) {
3181 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3182 return;
3185 subreq = gensec_update_send(state, state->ev,
3186 state->es->gensec_security,
3187 state->blob_in);
3188 if (tevent_req_nomem(subreq, req)) {
3189 return;
3191 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3194 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3196 struct tevent_req *req =
3197 tevent_req_callback_data(subreq,
3198 struct tevent_req);
3199 struct cli_smb1_setup_encryption_state *state =
3200 tevent_req_data(req,
3201 struct cli_smb1_setup_encryption_state);
3202 NTSTATUS status;
3204 status = gensec_update_recv(subreq, state, &state->blob_out);
3205 TALLOC_FREE(subreq);
3206 state->blob_in = data_blob_null;
3207 if (!NT_STATUS_IS_OK(status) &&
3208 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3210 tevent_req_nterror(req, status);
3211 return;
3214 if (NT_STATUS_IS_OK(status)) {
3215 state->local_ready = true;
3219 * We always get NT_STATUS_OK from the server even if it is not ready.
3220 * So guess the server is ready when we are ready and already sent
3221 * our last blob to the server.
3223 if (state->local_ready && state->blob_out.length == 0) {
3224 state->remote_ready = true;
3227 if (state->local_ready && state->remote_ready) {
3228 cli_smb1_setup_encryption_ready(req);
3229 return;
3232 cli_smb1_setup_encryption_remote_next(req);
3235 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3237 struct cli_smb1_setup_encryption_state *state =
3238 tevent_req_data(req,
3239 struct cli_smb1_setup_encryption_state);
3240 struct tevent_req *subreq = NULL;
3242 if (state->remote_ready) {
3243 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3244 return;
3247 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3248 state->cli, state->blob_out);
3249 if (tevent_req_nomem(subreq, req)) {
3250 return;
3252 tevent_req_set_callback(subreq,
3253 cli_smb1_setup_encryption_remote_done,
3254 req);
3257 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3259 struct tevent_req *req =
3260 tevent_req_callback_data(subreq,
3261 struct tevent_req);
3262 struct cli_smb1_setup_encryption_state *state =
3263 tevent_req_data(req,
3264 struct cli_smb1_setup_encryption_state);
3265 NTSTATUS status;
3267 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3268 &state->blob_in,
3269 &state->es->enc_ctx_num);
3270 TALLOC_FREE(subreq);
3271 data_blob_free(&state->blob_out);
3272 if (!NT_STATUS_IS_OK(status) &&
3273 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3275 tevent_req_nterror(req, status);
3276 return;
3280 * We always get NT_STATUS_OK even if the server is not ready.
3281 * So guess the server is ready when we are ready and sent
3282 * our last blob to the server.
3284 if (state->local_ready) {
3285 state->remote_ready = true;
3288 if (state->local_ready && state->remote_ready) {
3289 cli_smb1_setup_encryption_ready(req);
3290 return;
3293 cli_smb1_setup_encryption_local_next(req);
3296 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3298 struct cli_smb1_setup_encryption_state *state =
3299 tevent_req_data(req,
3300 struct cli_smb1_setup_encryption_state);
3301 struct smb_trans_enc_state *es = NULL;
3303 if (state->blob_in.length != 0) {
3304 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3305 return;
3308 if (state->blob_out.length != 0) {
3309 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3310 return;
3313 es = talloc_move(state->cli->conn, &state->es);
3314 es->enc_on = true;
3315 smb1cli_conn_set_encryption(state->cli->conn, es);
3316 es = NULL;
3318 tevent_req_done(req);
3321 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3323 return tevent_req_simple_recv_ntstatus(req);
3326 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3327 struct cli_credentials *creds)
3329 struct tevent_context *ev = NULL;
3330 struct tevent_req *req = NULL;
3331 NTSTATUS status = NT_STATUS_NO_MEMORY;
3333 ev = samba_tevent_context_init(talloc_tos());
3334 if (ev == NULL) {
3335 goto fail;
3337 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3338 if (req == NULL) {
3339 goto fail;
3341 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3342 goto fail;
3344 status = cli_smb1_setup_encryption_recv(req);
3345 fail:
3346 TALLOC_FREE(ev);
3347 return status;
3351 establishes a connection right up to doing tconX, password specified.
3352 @param output_cli A fully initialised cli structure, non-null only on success
3353 @param dest_host The netbios name of the remote host
3354 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3355 @param port (optional) The destination port (0 for default)
3356 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3357 @param service_type The 'type' of serivice.
3358 @param creds The used user credentials
3361 struct cli_full_connection_creds_state {
3362 struct tevent_context *ev;
3363 const char *service;
3364 const char *service_type;
3365 struct cli_credentials *creds;
3366 int flags;
3367 struct cli_state *cli;
3370 static int cli_full_connection_creds_state_destructor(
3371 struct cli_full_connection_creds_state *s)
3373 if (s->cli != NULL) {
3374 cli_shutdown(s->cli);
3375 s->cli = NULL;
3377 return 0;
3380 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3381 static void cli_full_connection_creds_sess_start(struct tevent_req *req);
3382 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3383 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3384 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3386 struct tevent_req *cli_full_connection_creds_send(
3387 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3388 const char *my_name, const char *dest_host,
3389 const struct sockaddr_storage *dest_ss, int port,
3390 const char *service, const char *service_type,
3391 struct cli_credentials *creds,
3392 int flags, int signing_state)
3394 struct tevent_req *req, *subreq;
3395 struct cli_full_connection_creds_state *state;
3396 enum credentials_use_kerberos krb5_state;
3397 uint32_t gensec_features = 0;
3399 req = tevent_req_create(mem_ctx, &state,
3400 struct cli_full_connection_creds_state);
3401 if (req == NULL) {
3402 return NULL;
3404 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3406 flags &= ~CLI_FULL_CONNECTION_USE_KERBEROS;
3407 flags &= ~CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3408 flags &= ~CLI_FULL_CONNECTION_USE_CCACHE;
3409 flags &= ~CLI_FULL_CONNECTION_USE_NT_HASH;
3411 krb5_state = cli_credentials_get_kerberos_state(creds);
3412 switch (krb5_state) {
3413 case CRED_MUST_USE_KERBEROS:
3414 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3415 flags &= ~CLI_FULL_CONNECTION_DONT_SPNEGO;
3416 break;
3417 case CRED_AUTO_USE_KERBEROS:
3418 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3419 flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3420 break;
3421 case CRED_DONT_USE_KERBEROS:
3422 break;
3425 gensec_features = cli_credentials_get_gensec_features(creds);
3426 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
3427 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
3430 state->ev = ev;
3431 state->service = service;
3432 state->service_type = service_type;
3433 state->creds = creds;
3434 state->flags = flags;
3436 subreq = cli_start_connection_send(
3437 state, ev, my_name, dest_host, dest_ss, port,
3438 signing_state, flags);
3439 if (tevent_req_nomem(subreq, req)) {
3440 return tevent_req_post(req, ev);
3442 tevent_req_set_callback(subreq,
3443 cli_full_connection_creds_conn_done,
3444 req);
3445 return req;
3448 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3450 struct tevent_req *req = tevent_req_callback_data(
3451 subreq, struct tevent_req);
3452 struct cli_full_connection_creds_state *state = tevent_req_data(
3453 req, struct cli_full_connection_creds_state);
3454 NTSTATUS status;
3456 status = cli_start_connection_recv(subreq, &state->cli);
3457 TALLOC_FREE(subreq);
3458 if (tevent_req_nterror(req, status)) {
3459 return;
3462 cli_full_connection_creds_sess_start(req);
3465 static void cli_full_connection_creds_sess_start(struct tevent_req *req)
3467 struct cli_full_connection_creds_state *state = tevent_req_data(
3468 req, struct cli_full_connection_creds_state);
3469 struct tevent_req *subreq = NULL;
3471 subreq = cli_session_setup_creds_send(
3472 state, state->ev, state->cli, state->creds);
3473 if (tevent_req_nomem(subreq, req)) {
3474 return;
3476 tevent_req_set_callback(subreq,
3477 cli_full_connection_creds_sess_done,
3478 req);
3481 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3483 struct tevent_req *req = tevent_req_callback_data(
3484 subreq, struct tevent_req);
3485 struct cli_full_connection_creds_state *state = tevent_req_data(
3486 req, struct cli_full_connection_creds_state);
3487 NTSTATUS status;
3489 status = cli_session_setup_creds_recv(subreq);
3490 TALLOC_FREE(subreq);
3492 if (!NT_STATUS_IS_OK(status) &&
3493 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3495 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3497 state->creds = cli_credentials_init_anon(state);
3498 if (tevent_req_nomem(state->creds, req)) {
3499 return;
3502 cli_full_connection_creds_sess_start(req);
3503 return;
3506 if (tevent_req_nterror(req, status)) {
3507 return;
3510 cli_full_connection_creds_tcon_start(req);
3513 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3515 struct cli_full_connection_creds_state *state = tevent_req_data(
3516 req, struct cli_full_connection_creds_state);
3517 struct tevent_req *subreq = NULL;
3518 const char *password = NULL;
3520 if (state->service == NULL) {
3521 tevent_req_done(req);
3522 return;
3525 password = cli_credentials_get_password(state->creds);
3527 subreq = cli_tree_connect_send(state, state->ev,
3528 state->cli,
3529 state->service,
3530 state->service_type,
3531 password);
3532 if (tevent_req_nomem(subreq, req)) {
3533 return;
3535 tevent_req_set_callback(subreq,
3536 cli_full_connection_creds_tcon_done,
3537 req);
3540 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3542 struct tevent_req *req = tevent_req_callback_data(
3543 subreq, struct tevent_req);
3544 NTSTATUS status;
3546 status = cli_tree_connect_recv(subreq);
3547 TALLOC_FREE(subreq);
3548 if (tevent_req_nterror(req, status)) {
3549 return;
3552 tevent_req_done(req);
3555 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3556 struct cli_state **output_cli)
3558 struct cli_full_connection_creds_state *state = tevent_req_data(
3559 req, struct cli_full_connection_creds_state);
3560 NTSTATUS status;
3562 if (tevent_req_is_nterror(req, &status)) {
3563 return status;
3565 *output_cli = state->cli;
3566 talloc_set_destructor(state, NULL);
3567 return NT_STATUS_OK;
3570 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3571 const char *my_name,
3572 const char *dest_host,
3573 const struct sockaddr_storage *dest_ss, int port,
3574 const char *service, const char *service_type,
3575 struct cli_credentials *creds,
3576 int flags,
3577 int signing_state)
3579 struct tevent_context *ev;
3580 struct tevent_req *req;
3581 NTSTATUS status = NT_STATUS_NO_MEMORY;
3583 ev = samba_tevent_context_init(talloc_tos());
3584 if (ev == NULL) {
3585 goto fail;
3587 req = cli_full_connection_creds_send(
3588 ev, ev, my_name, dest_host, dest_ss, port, service,
3589 service_type, creds, flags, signing_state);
3590 if (req == NULL) {
3591 goto fail;
3593 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3594 goto fail;
3596 status = cli_full_connection_creds_recv(req, output_cli);
3597 fail:
3598 TALLOC_FREE(ev);
3599 return status;
3602 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3603 const char *my_name,
3604 const char *dest_host,
3605 const struct sockaddr_storage *dest_ss, int port,
3606 const char *service, const char *service_type,
3607 const char *user, const char *domain,
3608 const char *password, int flags,
3609 int signing_state)
3611 TALLOC_CTX *frame = talloc_stackframe();
3612 NTSTATUS status;
3613 bool use_kerberos = false;
3614 bool fallback_after_kerberos = false;
3615 bool use_ccache = false;
3616 bool pw_nt_hash = false;
3617 struct cli_credentials *creds = NULL;
3619 if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
3620 use_kerberos = true;
3623 if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) {
3624 fallback_after_kerberos = true;
3627 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3628 use_ccache = true;
3631 if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) {
3632 pw_nt_hash = true;
3635 creds = cli_session_creds_init(frame,
3636 user,
3637 domain,
3638 NULL, /* realm (use default) */
3639 password,
3640 use_kerberos,
3641 fallback_after_kerberos,
3642 use_ccache,
3643 pw_nt_hash);
3644 if (creds == NULL) {
3645 TALLOC_FREE(frame);
3646 return NT_STATUS_NO_MEMORY;
3649 status = cli_full_connection_creds(output_cli, my_name,
3650 dest_host, dest_ss, port,
3651 service, service_type,
3652 creds, flags, signing_state);
3653 if (!NT_STATUS_IS_OK(status)) {
3654 TALLOC_FREE(frame);
3655 return status;
3658 TALLOC_FREE(frame);
3659 return NT_STATUS_OK;
3662 /****************************************************************************
3663 Send an old style tcon.
3664 ****************************************************************************/
3665 struct cli_raw_tcon_state {
3666 uint16_t *ret_vwv;
3669 static void cli_raw_tcon_done(struct tevent_req *subreq);
3671 static struct tevent_req *cli_raw_tcon_send(
3672 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3673 const char *service, const char *pass, const char *dev)
3675 struct tevent_req *req, *subreq;
3676 struct cli_raw_tcon_state *state;
3677 uint8_t *bytes;
3679 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3680 if (req == NULL) {
3681 return NULL;
3684 if (!lp_client_plaintext_auth() && (*pass)) {
3685 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3686 " or 'client ntlmv2 auth = yes'\n"));
3687 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3688 return tevent_req_post(req, ev);
3691 TALLOC_FREE(cli->smb1.tcon);
3692 cli->smb1.tcon = smbXcli_tcon_create(cli);
3693 if (tevent_req_nomem(cli->smb1.tcon, req)) {
3694 return tevent_req_post(req, ev);
3696 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
3698 bytes = talloc_array(state, uint8_t, 0);
3699 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3700 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3701 service, strlen(service)+1, NULL);
3702 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3703 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3704 pass, strlen(pass)+1, NULL);
3705 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3706 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3707 dev, strlen(dev)+1, NULL);
3709 if (tevent_req_nomem(bytes, req)) {
3710 return tevent_req_post(req, ev);
3713 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3714 talloc_get_size(bytes), bytes);
3715 if (tevent_req_nomem(subreq, req)) {
3716 return tevent_req_post(req, ev);
3718 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3719 return req;
3722 static void cli_raw_tcon_done(struct tevent_req *subreq)
3724 struct tevent_req *req = tevent_req_callback_data(
3725 subreq, struct tevent_req);
3726 struct cli_raw_tcon_state *state = tevent_req_data(
3727 req, struct cli_raw_tcon_state);
3728 NTSTATUS status;
3730 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3731 NULL, NULL);
3732 TALLOC_FREE(subreq);
3733 if (tevent_req_nterror(req, status)) {
3734 return;
3736 tevent_req_done(req);
3739 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3740 uint16_t *max_xmit, uint16_t *tid)
3742 struct cli_raw_tcon_state *state = tevent_req_data(
3743 req, struct cli_raw_tcon_state);
3744 NTSTATUS status;
3746 if (tevent_req_is_nterror(req, &status)) {
3747 return status;
3749 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3750 *tid = SVAL(state->ret_vwv + 1, 0);
3751 return NT_STATUS_OK;
3754 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3755 const char *service, const char *pass, const char *dev,
3756 uint16_t *max_xmit, uint16_t *tid)
3758 struct tevent_context *ev;
3759 struct tevent_req *req;
3760 NTSTATUS status = NT_STATUS_NO_MEMORY;
3762 ev = samba_tevent_context_init(talloc_tos());
3763 if (ev == NULL) {
3764 goto fail;
3766 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3767 if (req == NULL) {
3768 goto fail;
3770 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3771 goto fail;
3773 status = cli_raw_tcon_recv(req, max_xmit, tid);
3774 fail:
3775 TALLOC_FREE(ev);
3776 return status;
3779 /* Return a cli_state pointing at the IPC$ share for the given server */
3781 struct cli_state *get_ipc_connect(char *server,
3782 struct sockaddr_storage *server_ss,
3783 const struct user_auth_info *user_info)
3785 struct cli_state *cli;
3786 NTSTATUS nt_status;
3787 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3789 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3790 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3793 flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
3795 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3796 get_cmdline_auth_info_username(user_info),
3797 lp_workgroup(),
3798 get_cmdline_auth_info_password(user_info),
3799 flags,
3800 SMB_SIGNING_DEFAULT);
3802 if (NT_STATUS_IS_OK(nt_status)) {
3803 return cli;
3804 } else if (is_ipaddress(server)) {
3805 /* windows 9* needs a correct NMB name for connections */
3806 fstring remote_name;
3808 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3809 cli = get_ipc_connect(remote_name, server_ss, user_info);
3810 if (cli)
3811 return cli;
3814 return NULL;
3818 * Given the IP address of a master browser on the network, return its
3819 * workgroup and connect to it.
3821 * This function is provided to allow additional processing beyond what
3822 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3823 * browsers and obtain each master browsers' list of domains (in case the
3824 * first master browser is recently on the network and has not yet
3825 * synchronized with other master browsers and therefore does not yet have the
3826 * entire network browse list)
3829 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3830 struct sockaddr_storage *mb_ip,
3831 const struct user_auth_info *user_info,
3832 char **pp_workgroup_out)
3834 char addr[INET6_ADDRSTRLEN];
3835 fstring name;
3836 struct cli_state *cli;
3837 struct sockaddr_storage server_ss;
3839 *pp_workgroup_out = NULL;
3841 print_sockaddr(addr, sizeof(addr), mb_ip);
3842 DEBUG(99, ("Looking up name of master browser %s\n",
3843 addr));
3846 * Do a name status query to find out the name of the master browser.
3847 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3848 * master browser will not respond to a wildcard query (or, at least,
3849 * an NT4 server acting as the domain master browser will not).
3851 * We might be able to use ONLY the query on MSBROWSE, but that's not
3852 * yet been tested with all Windows versions, so until it is, leave
3853 * the original wildcard query as the first choice and fall back to
3854 * MSBROWSE if the wildcard query fails.
3856 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3857 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3859 DEBUG(99, ("Could not retrieve name status for %s\n",
3860 addr));
3861 return NULL;
3864 if (!find_master_ip(name, &server_ss)) {
3865 DEBUG(99, ("Could not find master ip for %s\n", name));
3866 return NULL;
3869 *pp_workgroup_out = talloc_strdup(ctx, name);
3871 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3873 print_sockaddr(addr, sizeof(addr), &server_ss);
3874 cli = get_ipc_connect(addr, &server_ss, user_info);
3876 return cli;
3880 * Return the IP address and workgroup of a master browser on the network, and
3881 * connect to it.
3884 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3885 const struct user_auth_info *user_info,
3886 char **pp_workgroup_out)
3888 struct sockaddr_storage *ip_list;
3889 struct cli_state *cli;
3890 int i, count;
3891 NTSTATUS status;
3893 *pp_workgroup_out = NULL;
3895 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3897 /* Go looking for workgroups by broadcasting on the local network */
3899 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3900 &ip_list, &count);
3901 if (!NT_STATUS_IS_OK(status)) {
3902 DEBUG(99, ("No master browsers responded: %s\n",
3903 nt_errstr(status)));
3904 return NULL;
3907 for (i = 0; i < count; i++) {
3908 char addr[INET6_ADDRSTRLEN];
3909 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3910 DEBUG(99, ("Found master browser %s\n", addr));
3912 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3913 user_info, pp_workgroup_out);
3914 if (cli)
3915 return(cli);
3918 return NULL;