drsuapi.idl: fix source_dsa spelling
[samba4-gss.git] / source3 / libsmb / cliconnect.c
blobbd75393ac076483cd0c1fcf62b9649fd399b79fd
1 /*
2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
6 Copyright (C) Volker Lendecke 2011
7 Copyright (C) Jeremy Allison 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "libsmb/libsmb.h"
25 #include "libsmb/namequery.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "auth/credentials/credentials.h"
28 #include "auth/gensec/gensec.h"
29 #include "auth/ntlmssp/ntlmssp.h"
30 #include "auth_generic.h"
31 #include "../lib/util/tevent_ntstatus.h"
32 #include "async_smb.h"
33 #include "libsmb/nmblib.h"
34 #include "librpc/ndr/libndr.h"
35 #include "../libcli/smb/smbXcli_base.h"
36 #include "../libcli/smb/smb_seal.h"
37 #include "lib/param/param.h"
38 #include "../libcli/smb/smb2_negotiate_context.h"
40 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
41 const char *principal);
43 struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
44 const char *username,
45 const char *domain,
46 const char *realm,
47 const char *password,
48 bool use_kerberos,
49 bool fallback_after_kerberos,
50 bool use_ccache,
51 bool password_is_nt_hash)
53 struct loadparm_context *lp_ctx = NULL;
54 struct cli_credentials *creds = NULL;
55 const char *principal = NULL;
56 enum credentials_use_kerberos creds_use_krb;
57 char *tmp = NULL;
58 char *p = NULL;
59 bool ok;
61 creds = cli_credentials_init(mem_ctx);
62 if (creds == NULL) {
63 return NULL;
66 lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
67 if (lp_ctx == NULL) {
68 goto fail;
70 ok = cli_credentials_set_conf(creds, lp_ctx);
71 if (!ok) {
72 goto fail;
75 if (username == NULL) {
76 username = "";
79 if (strlen(username) == 0) {
80 if (password != NULL && strlen(password) == 0) {
82 * some callers pass "" as no password
84 * gensec only handles NULL as no password.
86 password = NULL;
88 if (password == NULL) {
89 cli_credentials_set_anonymous(creds);
90 return creds;
94 tmp = talloc_strdup(creds, username);
95 if (tmp == NULL) {
96 goto fail;
98 username = tmp;
100 /* allow for workgroups as part of the username */
101 if ((p = strchr_m(tmp, '\\')) ||
102 (p = strchr_m(tmp, '/')) ||
103 (p = strchr_m(tmp, *lp_winbind_separator()))) {
104 *p = 0;
105 username = p + 1;
106 domain = tmp;
109 principal = username;
110 username = cli_session_setup_get_account(creds, principal);
111 if (username == NULL) {
112 goto fail;
114 ok = strequal(username, principal);
115 if (ok) {
117 * Ok still the same, so it's not a principal
119 principal = NULL;
122 if (use_kerberos) {
123 if (fallback_after_kerberos) {
125 * Keep what we learned from the
126 * "client use kerberos" option.
128 creds_use_krb = cli_credentials_get_kerberos_state(
129 creds);
130 } else {
131 creds_use_krb = CRED_USE_KERBEROS_REQUIRED;
133 } else {
134 creds_use_krb = CRED_USE_KERBEROS_DISABLED;
137 cli_credentials_set_kerberos_state(creds,
138 creds_use_krb,
139 CRED_SPECIFIED);
141 if (use_ccache) {
142 cli_credentials_add_gensec_features(creds,
143 GENSEC_FEATURE_NTLM_CCACHE,
144 CRED_SPECIFIED);
146 if (password != NULL && strlen(password) == 0) {
148 * some callers pass "" as no password
150 * GENSEC_FEATURE_NTLM_CCACHE only handles
151 * NULL as no password.
153 password = NULL;
157 ok = cli_credentials_set_username(creds,
158 username,
159 CRED_SPECIFIED);
160 if (!ok) {
161 goto fail;
164 if (domain != NULL) {
165 ok = cli_credentials_set_domain(creds,
166 domain,
167 CRED_SPECIFIED);
168 if (!ok) {
169 goto fail;
173 if (principal != NULL) {
174 ok = cli_credentials_set_principal(creds,
175 principal,
176 CRED_SPECIFIED);
177 if (!ok) {
178 goto fail;
182 if (realm != NULL) {
183 ok = cli_credentials_set_realm(creds,
184 realm,
185 CRED_SPECIFIED);
186 if (!ok) {
187 goto fail;
191 if (password != NULL && strlen(password) > 0) {
192 if (password_is_nt_hash) {
193 struct samr_Password nt_hash;
194 size_t converted;
196 converted = strhex_to_str((char *)nt_hash.hash,
197 sizeof(nt_hash.hash),
198 password,
199 strlen(password));
200 if (converted != sizeof(nt_hash.hash)) {
201 goto fail;
204 ok = cli_credentials_set_nt_hash(creds,
205 &nt_hash,
206 CRED_SPECIFIED);
207 if (!ok) {
208 goto fail;
210 } else {
211 ok = cli_credentials_set_password(creds,
212 password,
213 CRED_SPECIFIED);
214 if (!ok) {
215 goto fail;
218 } else if (use_kerberos && !fallback_after_kerberos) {
219 const char *error_string = NULL;
220 int rc;
222 rc = cli_credentials_set_ccache(creds,
223 lp_ctx,
224 NULL,
225 CRED_SPECIFIED,
226 &error_string);
227 if (rc != 0) {
228 fprintf(stderr,
229 "Warning reading default "
230 "krb5 credentials cache: %s\n",
231 error_string);
235 return creds;
236 fail:
237 TALLOC_FREE(creds);
238 return NULL;
241 static NTSTATUS cli_state_update_after_sesssetup(struct cli_state *cli,
242 const char *native_os,
243 const char *native_lm,
244 const char *primary_domain)
246 #define _VALID_STR(p) ((p) != NULL && (p)[0] != '\0')
248 if (!_VALID_STR(cli->server_os) && _VALID_STR(native_os)) {
249 cli->server_os = talloc_strdup(cli, native_os);
250 if (cli->server_os == NULL) {
251 return NT_STATUS_NO_MEMORY;
255 if (!_VALID_STR(cli->server_type) && _VALID_STR(native_lm)) {
256 cli->server_type = talloc_strdup(cli, native_lm);
257 if (cli->server_type == NULL) {
258 return NT_STATUS_NO_MEMORY;
262 if (!_VALID_STR(cli->server_domain) && _VALID_STR(primary_domain)) {
263 cli->server_domain = talloc_strdup(cli, primary_domain);
264 if (cli->server_domain == NULL) {
265 return NT_STATUS_NO_MEMORY;
269 #undef _VALID_STRING
270 return NT_STATUS_OK;
273 /********************************************************
274 Utility function to ensure we always return at least
275 a valid char * pointer to an empty string for the
276 cli->server_os, cli->server_type and cli->server_domain
277 strings.
278 *******************************************************/
280 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
281 const uint8_t *hdr,
282 char **dest,
283 uint8_t *src,
284 size_t srclen,
285 ssize_t *destlen)
287 *destlen = pull_string_talloc(mem_ctx,
288 (const char *)hdr,
289 SVAL(hdr, HDR_FLG2),
290 dest,
291 (char *)src,
292 srclen,
293 STR_TERMINATE);
294 if (*destlen == -1) {
295 return NT_STATUS_NO_MEMORY;
298 if (*dest == NULL) {
299 *dest = talloc_strdup(mem_ctx, "");
300 if (*dest == NULL) {
301 return NT_STATUS_NO_MEMORY;
304 return NT_STATUS_OK;
307 /****************************************************************************
308 Work out suitable capabilities to offer the server.
309 ****************************************************************************/
311 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
312 uint32_t sesssetup_capabilities)
314 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
317 * We only send capabilities based on the mask for:
318 * - client only flags
319 * - flags used in both directions
321 * We do not echo the server only flags, except some legacy flags.
323 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
324 * CAP_LARGE_WRITEX in order to allow us to do large reads
325 * against old Samba releases (<= 3.6.x).
327 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
330 * Session Setup specific flags CAP_DYNAMIC_REAUTH
331 * and CAP_EXTENDED_SECURITY are passed by the caller.
332 * We need that in order to do guest logins even if
333 * CAP_EXTENDED_SECURITY is negotiated.
335 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
336 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
337 client_capabilities |= sesssetup_capabilities;
339 return client_capabilities;
342 /****************************************************************************
343 Do a NT1 guest session setup.
344 ****************************************************************************/
346 struct cli_session_setup_guest_state {
347 struct cli_state *cli;
348 uint16_t vwv[13];
349 struct iovec bytes;
352 static void cli_session_setup_guest_done(struct tevent_req *subreq);
354 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
355 struct tevent_context *ev,
356 struct cli_state *cli,
357 struct tevent_req **psmbreq)
359 struct tevent_req *req, *subreq;
360 struct cli_session_setup_guest_state *state;
361 uint16_t *vwv;
362 uint8_t *bytes;
364 req = tevent_req_create(mem_ctx, &state,
365 struct cli_session_setup_guest_state);
366 if (req == NULL) {
367 return NULL;
369 state->cli = cli;
370 vwv = state->vwv;
372 SCVAL(vwv+0, 0, 0xFF);
373 SCVAL(vwv+0, 1, 0);
374 SSVAL(vwv+1, 0, 0);
375 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
376 SSVAL(vwv+3, 0, 2);
377 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
378 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
379 SSVAL(vwv+7, 0, 0);
380 SSVAL(vwv+8, 0, 0);
381 SSVAL(vwv+9, 0, 0);
382 SSVAL(vwv+10, 0, 0);
383 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
385 bytes = talloc_array(state, uint8_t, 0);
387 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
388 NULL);
389 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
390 NULL);
391 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
392 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
394 if (bytes == NULL) {
395 TALLOC_FREE(req);
396 return NULL;
399 state->bytes.iov_base = (void *)bytes;
400 state->bytes.iov_len = talloc_get_size(bytes);
402 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
403 vwv, 1, &state->bytes);
404 if (subreq == NULL) {
405 TALLOC_FREE(req);
406 return NULL;
408 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
409 *psmbreq = subreq;
410 return req;
413 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
414 struct tevent_context *ev,
415 struct cli_state *cli)
417 struct tevent_req *req, *subreq;
418 NTSTATUS status;
420 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
421 if (req == NULL) {
422 return NULL;
425 status = smb1cli_req_chain_submit(&subreq, 1);
426 if (!NT_STATUS_IS_OK(status)) {
427 tevent_req_nterror(req, status);
428 return tevent_req_post(req, ev);
430 return req;
433 static void cli_session_setup_guest_done(struct tevent_req *subreq)
435 struct tevent_req *req = tevent_req_callback_data(
436 subreq, struct tevent_req);
437 struct cli_session_setup_guest_state *state = tevent_req_data(
438 req, struct cli_session_setup_guest_state);
439 struct cli_state *cli = state->cli;
440 uint32_t num_bytes;
441 uint8_t *in;
442 uint8_t *inhdr;
443 uint8_t *bytes;
444 uint8_t *p;
445 NTSTATUS status;
446 ssize_t ret;
447 uint8_t wct;
448 uint16_t *vwv;
450 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
451 &num_bytes, &bytes);
452 TALLOC_FREE(subreq);
453 if (!NT_STATUS_IS_OK(status)) {
454 tevent_req_nterror(req, status);
455 return;
458 inhdr = in + NBT_HDR_SIZE;
459 p = bytes;
461 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
462 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
464 status = smb_bytes_talloc_string(cli,
465 inhdr,
466 &cli->server_os,
468 bytes+num_bytes-p,
469 &ret);
471 if (!NT_STATUS_IS_OK(status)) {
472 tevent_req_nterror(req, status);
473 return;
475 p += ret;
477 status = smb_bytes_talloc_string(cli,
478 inhdr,
479 &cli->server_type,
481 bytes+num_bytes-p,
482 &ret);
484 if (!NT_STATUS_IS_OK(status)) {
485 tevent_req_nterror(req, status);
486 return;
488 p += ret;
490 status = smb_bytes_talloc_string(cli,
491 inhdr,
492 &cli->server_domain,
494 bytes+num_bytes-p,
495 &ret);
497 if (!NT_STATUS_IS_OK(status)) {
498 tevent_req_nterror(req, status);
499 return;
502 tevent_req_done(req);
505 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
507 return tevent_req_simple_recv_ntstatus(req);
510 /* The following is calculated from :
511 * (smb_size-4) = 35
512 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
513 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
514 * end of packet.
517 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
519 struct cli_sesssetup_blob_state {
520 struct tevent_context *ev;
521 struct cli_state *cli;
522 DATA_BLOB blob;
523 uint16_t max_blob_size;
525 DATA_BLOB this_blob;
526 struct iovec *recv_iov;
528 NTSTATUS status;
529 const uint8_t *inbuf;
530 DATA_BLOB ret_blob;
532 char *out_native_os;
533 char *out_native_lm;
536 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
537 struct tevent_req **psubreq);
538 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
540 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
541 struct tevent_context *ev,
542 struct cli_state *cli,
543 DATA_BLOB blob)
545 struct tevent_req *req, *subreq;
546 struct cli_sesssetup_blob_state *state;
547 uint32_t usable_space;
549 req = tevent_req_create(mem_ctx, &state,
550 struct cli_sesssetup_blob_state);
551 if (req == NULL) {
552 return NULL;
554 state->ev = ev;
555 state->blob = blob;
556 state->cli = cli;
558 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
559 usable_space = UINT16_MAX;
560 } else {
561 usable_space = cli_state_available_size(cli,
562 BASE_SESSSETUP_BLOB_PACKET_SIZE);
565 if (usable_space == 0) {
566 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
567 "(not possible to send %u bytes)\n",
568 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
569 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
570 return tevent_req_post(req, ev);
572 state->max_blob_size = MIN(usable_space, 0xFFFF);
574 if (!cli_sesssetup_blob_next(state, &subreq)) {
575 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
576 return tevent_req_post(req, ev);
578 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
579 return req;
582 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
583 struct tevent_req **psubreq)
585 struct tevent_req *subreq;
586 uint16_t thistime;
588 thistime = MIN(state->blob.length, state->max_blob_size);
590 state->this_blob.data = state->blob.data;
591 state->this_blob.length = thistime;
593 state->blob.data += thistime;
594 state->blob.length -= thistime;
596 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
597 subreq = smb2cli_session_setup_send(state, state->ev,
598 state->cli->conn,
599 state->cli->timeout,
600 state->cli->smb2.session,
601 0, /* in_flags */
602 SMB2_CAP_DFS, /* in_capabilities */
603 0, /* in_channel */
604 0, /* in_previous_session_id */
605 &state->this_blob);
606 if (subreq == NULL) {
607 return false;
609 } else {
610 uint16_t in_buf_size = 0;
611 uint16_t in_mpx_max = 0;
612 uint16_t in_vc_num = 0;
613 uint32_t in_sess_key = 0;
614 uint32_t in_capabilities = 0;
615 const char *in_native_os = NULL;
616 const char *in_native_lm = NULL;
618 in_buf_size = CLI_BUFFER_SIZE;
619 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
620 in_vc_num = cli_state_get_vc_num(state->cli);
621 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
622 in_capabilities = cli_session_setup_capabilities(state->cli,
623 CAP_EXTENDED_SECURITY);
624 in_native_os = "Unix";
625 in_native_lm = "Samba";
628 * For now we keep the same values as before,
629 * we may remove these in a separate commit later.
631 in_mpx_max = 2;
632 in_vc_num = 1;
633 in_sess_key = 0;
635 subreq = smb1cli_session_setup_ext_send(state, state->ev,
636 state->cli->conn,
637 state->cli->timeout,
638 state->cli->smb1.pid,
639 state->cli->smb1.session,
640 in_buf_size,
641 in_mpx_max,
642 in_vc_num,
643 in_sess_key,
644 state->this_blob,
645 in_capabilities,
646 in_native_os,
647 in_native_lm);
648 if (subreq == NULL) {
649 return false;
652 *psubreq = subreq;
653 return true;
656 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
658 struct tevent_req *req = tevent_req_callback_data(
659 subreq, struct tevent_req);
660 struct cli_sesssetup_blob_state *state = tevent_req_data(
661 req, struct cli_sesssetup_blob_state);
662 NTSTATUS status;
664 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
665 status = smb2cli_session_setup_recv(subreq, state,
666 &state->recv_iov,
667 &state->ret_blob);
668 } else {
669 status = smb1cli_session_setup_ext_recv(subreq, state,
670 &state->recv_iov,
671 &state->inbuf,
672 &state->ret_blob,
673 &state->out_native_os,
674 &state->out_native_lm);
676 TALLOC_FREE(subreq);
677 if (!NT_STATUS_IS_OK(status)
678 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
679 tevent_req_nterror(req, status);
680 return;
683 state->status = status;
685 status = cli_state_update_after_sesssetup(state->cli,
686 state->out_native_os,
687 state->out_native_lm,
688 NULL);
689 if (tevent_req_nterror(req, status)) {
690 return;
693 if (state->blob.length != 0) {
695 * More to send
697 if (!cli_sesssetup_blob_next(state, &subreq)) {
698 tevent_req_oom(req);
699 return;
701 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
702 return;
704 tevent_req_done(req);
707 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
708 TALLOC_CTX *mem_ctx,
709 DATA_BLOB *pblob,
710 const uint8_t **pinbuf,
711 struct iovec **precv_iov)
713 struct cli_sesssetup_blob_state *state = tevent_req_data(
714 req, struct cli_sesssetup_blob_state);
715 NTSTATUS status;
716 struct iovec *recv_iov;
718 if (tevent_req_is_nterror(req, &status)) {
719 TALLOC_FREE(state->cli->smb2.session);
720 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
721 tevent_req_received(req);
722 return status;
725 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
726 if (pblob != NULL) {
727 *pblob = state->ret_blob;
729 if (pinbuf != NULL) {
730 *pinbuf = state->inbuf;
732 if (precv_iov != NULL) {
733 *precv_iov = recv_iov;
735 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
736 status = state->status;
737 tevent_req_received(req);
738 return status;
741 /****************************************************************************
742 Do a spnego/NTLMSSP encrypted session setup.
743 ****************************************************************************/
745 struct cli_session_setup_gensec_state {
746 struct tevent_context *ev;
747 struct cli_state *cli;
748 struct auth_generic_state *auth_generic;
749 bool is_anonymous;
750 DATA_BLOB blob_in;
751 const uint8_t *inbuf;
752 struct iovec *recv_iov;
753 DATA_BLOB blob_out;
754 bool local_ready;
755 bool remote_ready;
756 DATA_BLOB session_key;
759 static int cli_session_setup_gensec_state_destructor(
760 struct cli_session_setup_gensec_state *state)
762 TALLOC_FREE(state->auth_generic);
763 data_blob_clear_free(&state->session_key);
764 return 0;
767 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
768 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
769 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
770 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
771 static void cli_session_setup_gensec_ready(struct tevent_req *req);
773 static struct tevent_req *cli_session_setup_gensec_send(
774 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
775 struct cli_credentials *creds,
776 const char *target_service,
777 const char *target_hostname)
779 struct tevent_req *req;
780 struct cli_session_setup_gensec_state *state;
781 NTSTATUS status;
782 const DATA_BLOB *b = NULL;
784 req = tevent_req_create(mem_ctx, &state,
785 struct cli_session_setup_gensec_state);
786 if (req == NULL) {
787 return NULL;
789 state->ev = ev;
790 state->cli = cli;
792 talloc_set_destructor(
793 state, cli_session_setup_gensec_state_destructor);
795 status = auth_generic_client_prepare(state, &state->auth_generic);
796 if (tevent_req_nterror(req, status)) {
797 return tevent_req_post(req, ev);
800 status = auth_generic_set_creds(state->auth_generic, creds);
801 if (tevent_req_nterror(req, status)) {
802 return tevent_req_post(req, ev);
805 gensec_want_feature(state->auth_generic->gensec_security,
806 GENSEC_FEATURE_SESSION_KEY);
808 if (target_service != NULL) {
809 status = gensec_set_target_service(
810 state->auth_generic->gensec_security,
811 target_service);
812 if (tevent_req_nterror(req, status)) {
813 return tevent_req_post(req, ev);
817 if (target_hostname != NULL) {
818 status = gensec_set_target_hostname(
819 state->auth_generic->gensec_security,
820 target_hostname);
821 if (tevent_req_nterror(req, status)) {
822 return tevent_req_post(req, ev);
826 b = smbXcli_conn_server_gss_blob(cli->conn);
827 if (b != NULL) {
828 state->blob_in = *b;
831 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
833 status = auth_generic_client_start(state->auth_generic,
834 GENSEC_OID_SPNEGO);
835 if (tevent_req_nterror(req, status)) {
836 return tevent_req_post(req, ev);
839 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
840 state->cli->smb2.session = smbXcli_session_create(cli,
841 cli->conn);
842 if (tevent_req_nomem(state->cli->smb2.session, req)) {
843 return tevent_req_post(req, ev);
847 cli_session_setup_gensec_local_next(req);
848 if (!tevent_req_is_in_progress(req)) {
849 return tevent_req_post(req, ev);
852 return req;
855 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
857 struct cli_session_setup_gensec_state *state =
858 tevent_req_data(req,
859 struct cli_session_setup_gensec_state);
860 struct tevent_req *subreq = NULL;
862 if (state->local_ready) {
863 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
864 return;
867 subreq = gensec_update_send(state, state->ev,
868 state->auth_generic->gensec_security,
869 state->blob_in);
870 if (tevent_req_nomem(subreq, req)) {
871 return;
873 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
876 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
878 struct tevent_req *req =
879 tevent_req_callback_data(subreq,
880 struct tevent_req);
881 struct cli_session_setup_gensec_state *state =
882 tevent_req_data(req,
883 struct cli_session_setup_gensec_state);
884 NTSTATUS status;
886 status = gensec_update_recv(subreq, state, &state->blob_out);
887 TALLOC_FREE(subreq);
888 state->blob_in = data_blob_null;
889 if (!NT_STATUS_IS_OK(status) &&
890 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
892 tevent_req_nterror(req, status);
893 return;
896 if (NT_STATUS_IS_OK(status)) {
897 state->local_ready = true;
900 if (state->local_ready && state->remote_ready) {
901 cli_session_setup_gensec_ready(req);
902 return;
905 cli_session_setup_gensec_remote_next(req);
908 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
910 struct cli_session_setup_gensec_state *state =
911 tevent_req_data(req,
912 struct cli_session_setup_gensec_state);
913 struct tevent_req *subreq = NULL;
915 if (state->remote_ready) {
916 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
917 return;
920 subreq = cli_sesssetup_blob_send(state, state->ev,
921 state->cli, state->blob_out);
922 if (tevent_req_nomem(subreq, req)) {
923 return;
925 tevent_req_set_callback(subreq,
926 cli_session_setup_gensec_remote_done,
927 req);
930 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
932 struct tevent_req *req =
933 tevent_req_callback_data(subreq,
934 struct tevent_req);
935 struct cli_session_setup_gensec_state *state =
936 tevent_req_data(req,
937 struct cli_session_setup_gensec_state);
938 NTSTATUS status;
940 state->inbuf = NULL;
941 TALLOC_FREE(state->recv_iov);
943 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
944 &state->inbuf, &state->recv_iov);
945 TALLOC_FREE(subreq);
946 data_blob_free(&state->blob_out);
947 if (!NT_STATUS_IS_OK(status) &&
948 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
950 tevent_req_nterror(req, status);
951 return;
954 if (NT_STATUS_IS_OK(status)) {
955 struct smbXcli_session *session = NULL;
956 bool is_guest = false;
958 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
959 session = state->cli->smb2.session;
960 } else {
961 session = state->cli->smb1.session;
964 is_guest = smbXcli_session_is_guest(session);
965 if (is_guest) {
967 * We can't finish the gensec handshake, we don't
968 * have a negotiated session key.
970 * So just pretend we are completely done,
971 * we need to continue as anonymous from this point,
972 * as we can't get a session key.
974 * Note that smbXcli_session_is_guest()
975 * always returns false if we require signing.
977 state->blob_in = data_blob_null;
978 state->local_ready = true;
979 state->is_anonymous = true;
982 state->remote_ready = true;
985 if (state->local_ready && state->remote_ready) {
986 cli_session_setup_gensec_ready(req);
987 return;
990 cli_session_setup_gensec_local_next(req);
993 static void cli_session_dump_keys(TALLOC_CTX *mem_ctx,
994 struct smbXcli_session *session,
995 DATA_BLOB session_key)
997 NTSTATUS status;
998 DATA_BLOB sig = data_blob_null;
999 DATA_BLOB app = data_blob_null;
1000 DATA_BLOB enc = data_blob_null;
1001 DATA_BLOB dec = data_blob_null;
1002 uint64_t sid = smb2cli_session_current_id(session);
1004 status = smb2cli_session_signing_key(session, mem_ctx, &sig);
1005 if (!NT_STATUS_IS_OK(status)) {
1006 goto out;
1008 status = smbXcli_session_application_key(session, mem_ctx, &app);
1009 if (!NT_STATUS_IS_OK(status)) {
1010 goto out;
1012 status = smb2cli_session_encryption_key(session, mem_ctx, &enc);
1013 if (!NT_STATUS_IS_OK(status)) {
1014 goto out;
1016 status = smb2cli_session_decryption_key(session, mem_ctx, &dec);
1017 if (!NT_STATUS_IS_OK(status)) {
1018 goto out;
1021 DEBUG(0, ("debug encryption: dumping generated session keys\n"));
1022 DEBUGADD(0, ("Session Id "));
1023 dump_data(0, (uint8_t*)&sid, sizeof(sid));
1024 DEBUGADD(0, ("Session Key "));
1025 dump_data(0, session_key.data, session_key.length);
1026 DEBUGADD(0, ("Signing Key "));
1027 dump_data(0, sig.data, sig.length);
1028 DEBUGADD(0, ("App Key "));
1029 dump_data(0, app.data, app.length);
1031 /* In client code, ServerIn is the encryption key */
1033 DEBUGADD(0, ("ServerIn Key "));
1034 dump_data(0, enc.data, enc.length);
1035 DEBUGADD(0, ("ServerOut Key "));
1036 dump_data(0, dec.data, dec.length);
1038 out:
1039 data_blob_clear_free(&sig);
1040 data_blob_clear_free(&app);
1041 data_blob_clear_free(&enc);
1042 data_blob_clear_free(&dec);
1045 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1047 struct cli_session_setup_gensec_state *state =
1048 tevent_req_data(req,
1049 struct cli_session_setup_gensec_state);
1050 const char *server_domain = NULL;
1051 NTSTATUS status;
1053 if (state->blob_in.length != 0) {
1054 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1055 return;
1058 if (state->blob_out.length != 0) {
1059 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1060 return;
1064 * gensec_ntlmssp_server_domain() returns NULL
1065 * if NTLMSSP is not used.
1067 * We can remove this later
1068 * and leave the server domain empty for SMB2 and above
1069 * in future releases.
1071 server_domain = gensec_ntlmssp_server_domain(
1072 state->auth_generic->gensec_security);
1074 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1075 TALLOC_FREE(state->cli->server_domain);
1076 state->cli->server_domain = talloc_strdup(state->cli,
1077 server_domain);
1078 if (state->cli->server_domain == NULL) {
1079 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1080 return;
1084 if (state->is_anonymous) {
1086 * Windows server does not set the
1087 * SMB2_SESSION_FLAG_IS_NULL flag.
1089 * This fix makes sure we do not try
1090 * to verify a signature on the final
1091 * session setup response.
1093 tevent_req_done(req);
1094 return;
1097 status = gensec_session_key(state->auth_generic->gensec_security,
1098 state, &state->session_key);
1099 if (tevent_req_nterror(req, status)) {
1100 return;
1103 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1104 struct smbXcli_session *session = state->cli->smb2.session;
1106 status = smb2cli_session_set_session_key(session,
1107 state->session_key,
1108 state->recv_iov);
1109 if (tevent_req_nterror(req, status)) {
1110 return;
1112 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB3_00
1113 && lp_debug_encryption())
1115 cli_session_dump_keys(state, session, state->session_key);
1117 } else {
1118 struct smbXcli_session *session = state->cli->smb1.session;
1119 bool active;
1121 status = smb1cli_session_set_session_key(session,
1122 state->session_key);
1123 if (tevent_req_nterror(req, status)) {
1124 return;
1127 active = smb1cli_conn_activate_signing(state->cli->conn,
1128 state->session_key,
1129 data_blob_null);
1130 if (active) {
1131 bool ok;
1133 ok = smb1cli_conn_check_signing(state->cli->conn,
1134 state->inbuf, 1);
1135 if (!ok) {
1136 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1137 return;
1142 tevent_req_done(req);
1145 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1147 struct cli_session_setup_gensec_state *state =
1148 tevent_req_data(req,
1149 struct cli_session_setup_gensec_state);
1150 NTSTATUS status;
1152 if (tevent_req_is_nterror(req, &status)) {
1153 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1154 return status;
1156 return NT_STATUS_OK;
1159 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1160 const char *principal)
1162 char *account, *p;
1164 account = talloc_strdup(mem_ctx, principal);
1165 if (account == NULL) {
1166 return NULL;
1168 p = strchr_m(account, '@');
1169 if (p != NULL) {
1170 *p = '\0';
1172 return account;
1175 /****************************************************************************
1176 Do a spnego encrypted session setup.
1178 user_domain: The shortname of the domain the user/machine is a member of.
1179 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1180 ****************************************************************************/
1182 struct cli_session_setup_spnego_state {
1183 ADS_STATUS result;
1186 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1188 static struct tevent_req *cli_session_setup_spnego_send(
1189 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1190 struct cli_credentials *creds)
1192 struct tevent_req *req, *subreq;
1193 struct cli_session_setup_spnego_state *state;
1194 const char *target_service = NULL;
1195 const char *target_hostname = NULL;
1197 req = tevent_req_create(mem_ctx, &state,
1198 struct cli_session_setup_spnego_state);
1199 if (req == NULL) {
1200 return NULL;
1203 target_service = "cifs";
1204 target_hostname = smbXcli_conn_remote_name(cli->conn);
1206 DBG_INFO("Connect to %s as %s using SPNEGO\n",
1207 target_hostname,
1208 cli_credentials_get_principal(creds, talloc_tos()));
1210 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1211 target_service, target_hostname);
1212 if (tevent_req_nomem(subreq, req)) {
1213 return tevent_req_post(req, ev);
1215 tevent_req_set_callback(
1216 subreq, cli_session_setup_spnego_done, req);
1217 return req;
1220 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1222 struct tevent_req *req = tevent_req_callback_data(
1223 subreq, struct tevent_req);
1224 NTSTATUS status;
1226 status = cli_session_setup_gensec_recv(subreq);
1227 TALLOC_FREE(subreq);
1228 if (tevent_req_nterror(req, status)) {
1229 return;
1232 tevent_req_done(req);
1235 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1237 struct cli_session_setup_spnego_state *state = tevent_req_data(
1238 req, struct cli_session_setup_spnego_state);
1239 NTSTATUS status;
1241 if (tevent_req_is_nterror(req, &status)) {
1242 state->result = ADS_ERROR_NT(status);
1245 return state->result;
1248 struct cli_session_setup_creds_state {
1249 struct cli_state *cli;
1250 DATA_BLOB apassword_blob;
1251 DATA_BLOB upassword_blob;
1252 DATA_BLOB lm_session_key;
1253 DATA_BLOB session_key;
1254 char *out_native_os;
1255 char *out_native_lm;
1256 char *out_primary_domain;
1259 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1260 enum tevent_req_state req_state)
1262 struct cli_session_setup_creds_state *state = tevent_req_data(
1263 req, struct cli_session_setup_creds_state);
1265 if (req_state != TEVENT_REQ_RECEIVED) {
1266 return;
1270 * We only call data_blob_clear() as
1271 * some of the blobs point to the same memory.
1273 * We let the talloc hierarchy free the memory.
1275 data_blob_clear(&state->apassword_blob);
1276 data_blob_clear(&state->upassword_blob);
1277 data_blob_clear(&state->lm_session_key);
1278 data_blob_clear(&state->session_key);
1279 ZERO_STRUCTP(state);
1282 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1283 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1284 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1286 /****************************************************************************
1287 Send a session setup. The username and workgroup is in UNIX character
1288 format and must be converted to DOS codepage format before sending. If the
1289 password is in plaintext, the same should be done.
1290 ****************************************************************************/
1292 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1293 struct tevent_context *ev,
1294 struct cli_state *cli,
1295 struct cli_credentials *creds)
1297 struct tevent_req *req, *subreq;
1298 struct cli_session_setup_creds_state *state;
1299 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1300 bool use_spnego = false;
1301 int flags = 0;
1302 const char *username = "";
1303 const char *domain = "";
1304 DATA_BLOB target_info = data_blob_null;
1305 DATA_BLOB challenge = data_blob_null;
1306 uint16_t in_buf_size = 0;
1307 uint16_t in_mpx_max = 0;
1308 uint16_t in_vc_num = 0;
1309 uint32_t in_sess_key = 0;
1310 const char *in_native_os = NULL;
1311 const char *in_native_lm = NULL;
1312 enum credentials_use_kerberos krb5_state =
1313 cli_credentials_get_kerberos_state(creds);
1314 NTSTATUS status;
1316 req = tevent_req_create(mem_ctx, &state,
1317 struct cli_session_setup_creds_state);
1318 if (req == NULL) {
1319 return NULL;
1321 state->cli = cli;
1323 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1326 * Now work out what sort of session setup we are going to
1327 * do. I have split this into separate functions to make the flow a bit
1328 * easier to understand (tridge).
1330 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1331 use_spnego = false;
1332 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1333 use_spnego = true;
1334 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1336 * if the server supports extended security then use SPNEGO
1337 * even for anonymous connections.
1339 use_spnego = true;
1340 } else {
1341 use_spnego = false;
1344 if (use_spnego) {
1345 subreq = cli_session_setup_spnego_send(
1346 state, ev, cli, creds);
1347 if (tevent_req_nomem(subreq, req)) {
1348 return tevent_req_post(req, ev);
1350 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1351 req);
1352 return req;
1355 if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
1356 DBG_WARNING("Kerberos authentication requested, but "
1357 "the server does not support SPNEGO authentication\n");
1358 tevent_req_nterror(req, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT);
1359 return tevent_req_post(req, ev);
1362 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1364 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1365 * this step against older servers.
1367 tevent_req_done(req);
1368 return tevent_req_post(req, ev);
1371 if (cli_credentials_is_anonymous(creds)) {
1373 * Do an anonymous session setup
1375 goto non_spnego_creds_done;
1378 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1380 * Do an anonymous session setup,
1381 * the password is passed via the tree connect.
1383 goto non_spnego_creds_done;
1386 cli_credentials_get_ntlm_username_domain(creds, state,
1387 &username,
1388 &domain);
1389 if (tevent_req_nomem(username, req)) {
1390 return tevent_req_post(req, ev);
1392 if (tevent_req_nomem(domain, req)) {
1393 return tevent_req_post(req, ev);
1396 DBG_INFO("Connect to %s as %s using NTLM\n", domain, username);
1398 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1399 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1400 uint8_t *bytes = NULL;
1401 size_t bytes_len = 0;
1402 const char *pw = cli_credentials_get_password(creds);
1403 size_t pw_len = 0;
1405 if (pw == NULL) {
1406 pw = "";
1408 pw_len = strlen(pw) + 1;
1410 if (!lp_client_plaintext_auth()) {
1411 DEBUG(1, ("Server requested PLAINTEXT password but "
1412 "'client plaintext auth = no'\n"));
1413 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1414 return tevent_req_post(req, ev);
1417 bytes = talloc_array(state, uint8_t, 0);
1418 bytes = trans2_bytes_push_str(bytes, use_unicode,
1419 pw, pw_len, &bytes_len);
1420 if (tevent_req_nomem(bytes, req)) {
1421 return tevent_req_post(req, ev);
1424 if (use_unicode) {
1426 * CAP_UNICODE, can only be negotiated by NT1.
1428 state->upassword_blob = data_blob_const(bytes,
1429 bytes_len);
1430 } else {
1431 state->apassword_blob = data_blob_const(bytes,
1432 bytes_len);
1435 goto non_spnego_creds_done;
1438 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1440 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1441 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1443 * Don't send an NTLMv2 response without NTLMSSP if we
1444 * want to use spnego support.
1446 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1447 " but 'client use spnego = yes'"
1448 " and 'client ntlmv2 auth = yes' is set\n"));
1449 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1450 return tevent_req_post(req, ev);
1453 if (lp_client_ntlmv2_auth()) {
1454 flags |= CLI_CRED_NTLMv2_AUTH;
1457 * note that the 'domain' here is a best
1458 * guess - we don't know the server's domain
1459 * at this point. Windows clients also don't
1460 * use hostname...
1462 target_info = NTLMv2_generate_names_blob(state,
1463 NULL,
1464 domain);
1465 if (tevent_req_nomem(target_info.data, req)) {
1466 return tevent_req_post(req, ev);
1468 } else {
1469 flags |= CLI_CRED_NTLM_AUTH;
1470 if (lp_client_lanman_auth()) {
1471 flags |= CLI_CRED_LANMAN_AUTH;
1474 } else {
1475 if (!lp_client_lanman_auth()) {
1476 DEBUG(1, ("Server requested user level LM password but "
1477 "'client lanman auth = no' is set.\n"));
1478 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1479 return tevent_req_post(req, ev);
1482 flags |= CLI_CRED_LANMAN_AUTH;
1485 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1486 challenge, NULL,
1487 target_info,
1488 &state->apassword_blob,
1489 &state->upassword_blob,
1490 &state->lm_session_key,
1491 &state->session_key);
1492 if (tevent_req_nterror(req, status)) {
1493 return tevent_req_post(req, ev);
1496 non_spnego_creds_done:
1498 in_buf_size = CLI_BUFFER_SIZE;
1499 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1500 in_vc_num = cli_state_get_vc_num(cli);
1501 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1502 in_native_os = "Unix";
1503 in_native_lm = "Samba";
1505 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1506 uint32_t in_capabilities = 0;
1508 in_capabilities = cli_session_setup_capabilities(cli, 0);
1511 * For now we keep the same values as before,
1512 * we may remove these in a separate commit later.
1514 in_mpx_max = 2;
1516 subreq = smb1cli_session_setup_nt1_send(state, ev,
1517 cli->conn,
1518 cli->timeout,
1519 cli->smb1.pid,
1520 cli->smb1.session,
1521 in_buf_size,
1522 in_mpx_max,
1523 in_vc_num,
1524 in_sess_key,
1525 username,
1526 domain,
1527 state->apassword_blob,
1528 state->upassword_blob,
1529 in_capabilities,
1530 in_native_os,
1531 in_native_lm);
1532 if (tevent_req_nomem(subreq, req)) {
1533 return tevent_req_post(req, ev);
1535 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1536 req);
1537 return req;
1541 * For now we keep the same values as before,
1542 * we may remove these in a separate commit later.
1544 in_mpx_max = 2;
1545 in_vc_num = 1;
1547 subreq = smb1cli_session_setup_lm21_send(state, ev,
1548 cli->conn,
1549 cli->timeout,
1550 cli->smb1.pid,
1551 cli->smb1.session,
1552 in_buf_size,
1553 in_mpx_max,
1554 in_vc_num,
1555 in_sess_key,
1556 username,
1557 domain,
1558 state->apassword_blob,
1559 in_native_os,
1560 in_native_lm);
1561 if (tevent_req_nomem(subreq, req)) {
1562 return tevent_req_post(req, ev);
1564 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1565 req);
1566 return req;
1569 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1571 struct tevent_req *req = tevent_req_callback_data(
1572 subreq, struct tevent_req);
1573 ADS_STATUS status;
1575 status = cli_session_setup_spnego_recv(subreq);
1576 TALLOC_FREE(subreq);
1577 if (!ADS_ERR_OK(status)) {
1578 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1579 tevent_req_nterror(req, ads_ntstatus(status));
1580 return;
1582 tevent_req_done(req);
1585 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1587 struct tevent_req *req = tevent_req_callback_data(
1588 subreq, struct tevent_req);
1589 struct cli_session_setup_creds_state *state = tevent_req_data(
1590 req, struct cli_session_setup_creds_state);
1591 struct cli_state *cli = state->cli;
1592 NTSTATUS status;
1593 struct iovec *recv_iov = NULL;
1594 const uint8_t *inbuf = NULL;
1595 bool ok;
1597 status = smb1cli_session_setup_nt1_recv(subreq, state,
1598 &recv_iov,
1599 &inbuf,
1600 &state->out_native_os,
1601 &state->out_native_lm,
1602 &state->out_primary_domain);
1603 TALLOC_FREE(subreq);
1604 if (tevent_req_nterror(req, status)) {
1605 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1606 return;
1609 status = cli_state_update_after_sesssetup(state->cli,
1610 state->out_native_os,
1611 state->out_native_lm,
1612 state->out_primary_domain);
1613 if (tevent_req_nterror(req, status)) {
1614 return;
1617 ok = smb1cli_conn_activate_signing(cli->conn,
1618 state->session_key,
1619 state->upassword_blob);
1620 if (ok) {
1621 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1622 if (!ok) {
1623 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1624 return;
1628 if (state->session_key.data) {
1629 struct smbXcli_session *session = cli->smb1.session;
1631 status = smb1cli_session_set_session_key(session,
1632 state->session_key);
1633 if (tevent_req_nterror(req, status)) {
1634 return;
1638 tevent_req_done(req);
1641 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1643 struct tevent_req *req = tevent_req_callback_data(
1644 subreq, struct tevent_req);
1645 struct cli_session_setup_creds_state *state = tevent_req_data(
1646 req, struct cli_session_setup_creds_state);
1647 NTSTATUS status;
1649 status = smb1cli_session_setup_lm21_recv(subreq, state,
1650 &state->out_native_os,
1651 &state->out_native_lm);
1652 TALLOC_FREE(subreq);
1653 if (tevent_req_nterror(req, status)) {
1654 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1655 return;
1658 status = cli_state_update_after_sesssetup(state->cli,
1659 state->out_native_os,
1660 state->out_native_lm,
1661 NULL);
1662 if (tevent_req_nterror(req, status)) {
1663 return;
1666 tevent_req_done(req);
1669 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1671 return tevent_req_simple_recv_ntstatus(req);
1674 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1675 struct cli_credentials *creds)
1677 struct tevent_context *ev;
1678 struct tevent_req *req;
1679 NTSTATUS status = NT_STATUS_NO_MEMORY;
1681 if (smbXcli_conn_has_async_calls(cli->conn)) {
1682 return NT_STATUS_INVALID_PARAMETER;
1684 ev = samba_tevent_context_init(talloc_tos());
1685 if (ev == NULL) {
1686 goto fail;
1688 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1689 if (req == NULL) {
1690 goto fail;
1692 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1693 goto fail;
1695 status = cli_session_setup_creds_recv(req);
1696 fail:
1697 TALLOC_FREE(ev);
1698 return status;
1701 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1703 NTSTATUS status;
1704 struct cli_credentials *creds = NULL;
1706 creds = cli_credentials_init_anon(cli);
1707 if (creds == NULL) {
1708 return NT_STATUS_NO_MEMORY;
1711 status = cli_session_setup_creds(cli, creds);
1712 TALLOC_FREE(creds);
1713 if (!NT_STATUS_IS_OK(status)) {
1714 return status;
1717 return NT_STATUS_OK;
1720 /****************************************************************************
1721 Send a uloggoff.
1722 *****************************************************************************/
1724 struct cli_ulogoff_state {
1725 struct cli_state *cli;
1726 uint16_t vwv[3];
1729 static void cli_ulogoff_done(struct tevent_req *subreq);
1731 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1732 struct tevent_context *ev,
1733 struct cli_state *cli)
1735 struct tevent_req *req, *subreq;
1736 struct cli_ulogoff_state *state;
1738 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1739 if (req == NULL) {
1740 return NULL;
1742 state->cli = cli;
1744 SCVAL(state->vwv+0, 0, 0xFF);
1745 SCVAL(state->vwv+1, 0, 0);
1746 SSVAL(state->vwv+2, 0, 0);
1748 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1749 0, NULL);
1750 if (tevent_req_nomem(subreq, req)) {
1751 return tevent_req_post(req, ev);
1753 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1754 return req;
1757 static void cli_ulogoff_done(struct tevent_req *subreq)
1759 struct tevent_req *req = tevent_req_callback_data(
1760 subreq, struct tevent_req);
1761 struct cli_ulogoff_state *state = tevent_req_data(
1762 req, struct cli_ulogoff_state);
1763 NTSTATUS status;
1765 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1766 if (tevent_req_nterror(req, status)) {
1767 return;
1769 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1770 tevent_req_done(req);
1773 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1775 return tevent_req_simple_recv_ntstatus(req);
1778 NTSTATUS cli_ulogoff(struct cli_state *cli)
1780 struct tevent_context *ev;
1781 struct tevent_req *req;
1782 NTSTATUS status = NT_STATUS_NO_MEMORY;
1784 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1785 status = smb2cli_logoff(cli->conn,
1786 cli->timeout,
1787 cli->smb2.session);
1788 if (!NT_STATUS_IS_OK(status)) {
1789 return status;
1791 smb2cli_session_set_id_and_flags(cli->smb2.session,
1792 UINT64_MAX, 0);
1793 return NT_STATUS_OK;
1796 if (smbXcli_conn_has_async_calls(cli->conn)) {
1797 return NT_STATUS_INVALID_PARAMETER;
1799 ev = samba_tevent_context_init(talloc_tos());
1800 if (ev == NULL) {
1801 goto fail;
1803 req = cli_ulogoff_send(ev, ev, cli);
1804 if (req == NULL) {
1805 goto fail;
1807 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1808 goto fail;
1810 status = cli_ulogoff_recv(req);
1811 fail:
1812 TALLOC_FREE(ev);
1813 return status;
1816 /****************************************************************************
1817 Send a tconX.
1818 ****************************************************************************/
1820 struct cli_tcon_andx_state {
1821 struct cli_state *cli;
1822 uint16_t vwv[4];
1823 struct iovec bytes;
1826 static void cli_tcon_andx_done(struct tevent_req *subreq);
1828 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1829 struct tevent_context *ev,
1830 struct cli_state *cli,
1831 const char *share, const char *dev,
1832 const char *pass, int passlen,
1833 struct tevent_req **psmbreq)
1835 struct tevent_req *req, *subreq;
1836 struct cli_tcon_andx_state *state;
1837 uint8_t p24[24];
1838 uint16_t *vwv;
1839 char *tmp = NULL;
1840 uint8_t *bytes;
1841 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1842 uint16_t tcon_flags = 0;
1844 *psmbreq = NULL;
1846 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1847 if (req == NULL) {
1848 return NULL;
1850 state->cli = cli;
1851 vwv = state->vwv;
1853 TALLOC_FREE(cli->smb1.tcon);
1854 cli->smb1.tcon = smbXcli_tcon_create(cli);
1855 if (tevent_req_nomem(cli->smb1.tcon, req)) {
1856 return tevent_req_post(req, ev);
1858 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
1860 cli->share = talloc_strdup(cli, share);
1861 if (!cli->share) {
1862 return NULL;
1865 /* in user level security don't send a password now */
1866 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1867 passlen = 1;
1868 pass = "";
1869 } else if (pass == NULL) {
1870 DEBUG(1, ("Server not using user level security and no "
1871 "password supplied.\n"));
1872 goto access_denied;
1875 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1876 *pass && passlen != 24) {
1877 if (!lp_client_lanman_auth()) {
1878 DEBUG(1, ("Server requested LANMAN password "
1879 "(share-level security) but "
1880 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1881 goto access_denied;
1885 * Non-encrypted passwords - convert to DOS codepage before
1886 * encryption.
1888 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1889 passlen = 24;
1890 pass = (const char *)p24;
1891 } else {
1892 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1893 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1894 == 0) {
1895 uint8_t *tmp_pass;
1897 if (!lp_client_plaintext_auth() && (*pass)) {
1898 DEBUG(1, ("Server requested PLAINTEXT "
1899 "password but "
1900 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
1901 goto access_denied;
1905 * Non-encrypted passwords - convert to DOS codepage
1906 * before using.
1908 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
1909 if (tevent_req_nomem(tmp_pass, req)) {
1910 return tevent_req_post(req, ev);
1912 tmp_pass = trans2_bytes_push_str(tmp_pass,
1913 false, /* always DOS */
1914 pass,
1915 passlen,
1916 NULL);
1917 if (tevent_req_nomem(tmp_pass, req)) {
1918 return tevent_req_post(req, ev);
1920 pass = (const char *)tmp_pass;
1921 passlen = talloc_get_size(tmp_pass);
1925 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
1926 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
1928 SCVAL(vwv+0, 0, 0xFF);
1929 SCVAL(vwv+0, 1, 0);
1930 SSVAL(vwv+1, 0, 0);
1931 SSVAL(vwv+2, 0, tcon_flags);
1932 SSVAL(vwv+3, 0, passlen);
1934 if (passlen && pass) {
1935 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
1936 } else {
1937 bytes = talloc_array(state, uint8_t, 0);
1941 * Add the sharename
1943 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1944 smbXcli_conn_remote_name(cli->conn), share);
1945 if (tmp == NULL) {
1946 TALLOC_FREE(req);
1947 return NULL;
1949 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
1950 NULL);
1951 TALLOC_FREE(tmp);
1954 * Add the devicetype
1956 tmp = talloc_strdup_upper(talloc_tos(), dev);
1957 if (tmp == NULL) {
1958 TALLOC_FREE(req);
1959 return NULL;
1961 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1962 TALLOC_FREE(tmp);
1964 if (bytes == NULL) {
1965 TALLOC_FREE(req);
1966 return NULL;
1969 state->bytes.iov_base = (void *)bytes;
1970 state->bytes.iov_len = talloc_get_size(bytes);
1972 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
1973 1, &state->bytes);
1974 if (subreq == NULL) {
1975 TALLOC_FREE(req);
1976 return NULL;
1978 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1979 *psmbreq = subreq;
1980 return req;
1982 access_denied:
1983 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1984 return tevent_req_post(req, ev);
1987 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1988 struct tevent_context *ev,
1989 struct cli_state *cli,
1990 const char *share, const char *dev,
1991 const char *pass, int passlen)
1993 struct tevent_req *req, *subreq;
1994 NTSTATUS status;
1996 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1997 &subreq);
1998 if (req == NULL) {
1999 return NULL;
2001 if (subreq == NULL) {
2002 return req;
2004 status = smb1cli_req_chain_submit(&subreq, 1);
2005 if (tevent_req_nterror(req, status)) {
2006 return tevent_req_post(req, ev);
2008 return req;
2011 static void cli_tcon_andx_done(struct tevent_req *subreq)
2013 struct tevent_req *req = tevent_req_callback_data(
2014 subreq, struct tevent_req);
2015 struct cli_tcon_andx_state *state = tevent_req_data(
2016 req, struct cli_tcon_andx_state);
2017 struct cli_state *cli = state->cli;
2018 uint8_t *in;
2019 uint8_t *inhdr;
2020 uint8_t wct;
2021 uint16_t *vwv;
2022 uint32_t num_bytes;
2023 uint8_t *bytes;
2024 NTSTATUS status;
2025 uint16_t optional_support = 0;
2027 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2028 &num_bytes, &bytes);
2029 TALLOC_FREE(subreq);
2030 if (tevent_req_nterror(req, status)) {
2031 return;
2034 inhdr = in + NBT_HDR_SIZE;
2036 if (num_bytes) {
2037 if (pull_string_talloc(cli,
2038 (const char *)inhdr,
2039 SVAL(inhdr, HDR_FLG2),
2040 &cli->dev,
2041 bytes,
2042 num_bytes,
2043 STR_TERMINATE|STR_ASCII) == -1) {
2044 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2045 return;
2047 } else {
2048 cli->dev = talloc_strdup(cli, "");
2049 if (cli->dev == NULL) {
2050 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2051 return;
2055 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2056 /* almost certainly win95 - enable bug fixes */
2057 cli->win95 = True;
2061 * Make sure that we have the optional support 16-bit field. WCT > 2.
2062 * Avoids issues when connecting to Win9x boxes sharing files
2065 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2066 optional_support = SVAL(vwv+2, 0);
2069 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2070 smb1cli_session_protect_session_key(cli->smb1.session);
2073 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2074 SVAL(inhdr, HDR_TID),
2075 optional_support,
2076 0, /* maximal_access */
2077 0, /* guest_maximal_access */
2078 NULL, /* service */
2079 NULL); /* fs_type */
2081 tevent_req_done(req);
2084 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2086 return tevent_req_simple_recv_ntstatus(req);
2089 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2090 const char *dev, const char *pass, int passlen)
2092 TALLOC_CTX *frame = talloc_stackframe();
2093 struct tevent_context *ev;
2094 struct tevent_req *req;
2095 NTSTATUS status = NT_STATUS_NO_MEMORY;
2097 if (smbXcli_conn_has_async_calls(cli->conn)) {
2099 * Can't use sync call while an async call is in flight
2101 status = NT_STATUS_INVALID_PARAMETER;
2102 goto fail;
2105 ev = samba_tevent_context_init(frame);
2106 if (ev == NULL) {
2107 goto fail;
2110 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2111 if (req == NULL) {
2112 goto fail;
2115 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2116 goto fail;
2119 status = cli_tcon_andx_recv(req);
2120 fail:
2121 TALLOC_FREE(frame);
2122 return status;
2125 struct cli_tree_connect_state {
2126 struct cli_state *cli;
2129 static struct tevent_req *cli_raw_tcon_send(
2130 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2131 const char *service, const char *pass, const char *dev);
2132 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2133 uint16_t *max_xmit, uint16_t *tid);
2135 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2136 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2137 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2139 static struct tevent_req *cli_tree_connect_send(
2140 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2141 const char *share, const char *dev, const char *pass)
2143 struct tevent_req *req, *subreq;
2144 struct cli_tree_connect_state *state;
2145 int passlen;
2147 if (pass == NULL) {
2148 pass = "";
2150 passlen = strlen(pass) + 1;
2152 req = tevent_req_create(mem_ctx, &state,
2153 struct cli_tree_connect_state);
2154 if (req == NULL) {
2155 return NULL;
2157 state->cli = cli;
2159 cli->share = talloc_strdup(cli, share);
2160 if (tevent_req_nomem(cli->share, req)) {
2161 return tevent_req_post(req, ev);
2164 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2165 char *unc;
2167 TALLOC_FREE(cli->smb2.tcon);
2168 cli->smb2.tcon = smbXcli_tcon_create(cli);
2169 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2170 return tevent_req_post(req, ev);
2173 unc = talloc_asprintf(state, "\\\\%s\\%s",
2174 smbXcli_conn_remote_name(cli->conn),
2175 share);
2176 if (tevent_req_nomem(unc, req)) {
2177 return tevent_req_post(req, ev);
2180 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2181 cli->smb2.session, cli->smb2.tcon,
2182 0, /* flags */
2183 unc);
2184 if (tevent_req_nomem(subreq, req)) {
2185 return tevent_req_post(req, ev);
2187 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2188 req);
2189 return req;
2192 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2193 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2194 pass, passlen);
2195 if (tevent_req_nomem(subreq, req)) {
2196 return tevent_req_post(req, ev);
2198 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2199 req);
2200 return req;
2203 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2204 if (tevent_req_nomem(subreq, req)) {
2205 return tevent_req_post(req, ev);
2207 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2209 return req;
2212 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2214 NTSTATUS status = smb2cli_tcon_recv(subreq);
2215 tevent_req_simple_finish_ntstatus(subreq, status);
2218 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2220 NTSTATUS status = cli_tcon_andx_recv(subreq);
2221 tevent_req_simple_finish_ntstatus(subreq, status);
2224 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2226 struct tevent_req *req = tevent_req_callback_data(
2227 subreq, struct tevent_req);
2228 struct cli_tree_connect_state *state = tevent_req_data(
2229 req, struct cli_tree_connect_state);
2230 NTSTATUS status;
2231 uint16_t max_xmit = 0;
2232 uint16_t tid = 0;
2234 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2235 if (tevent_req_nterror(req, status)) {
2236 return;
2239 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2240 tid,
2241 0, /* optional_support */
2242 0, /* maximal_access */
2243 0, /* guest_maximal_access */
2244 NULL, /* service */
2245 NULL); /* fs_type */
2247 tevent_req_done(req);
2250 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2252 return tevent_req_simple_recv_ntstatus(req);
2255 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2256 const char *dev, const char *pass)
2258 struct tevent_context *ev;
2259 struct tevent_req *req;
2260 NTSTATUS status = NT_STATUS_NO_MEMORY;
2262 if (smbXcli_conn_has_async_calls(cli->conn)) {
2263 return NT_STATUS_INVALID_PARAMETER;
2265 ev = samba_tevent_context_init(talloc_tos());
2266 if (ev == NULL) {
2267 goto fail;
2269 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2270 if (req == NULL) {
2271 goto fail;
2273 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2274 goto fail;
2276 status = cli_tree_connect_recv(req);
2277 fail:
2278 TALLOC_FREE(ev);
2279 return status;
2282 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2283 const char *share, const char *dev,
2284 struct cli_credentials *creds)
2286 bool need_pass = false;
2287 const char *pw = NULL;
2290 * We should work out if the protocol
2291 * will make use of a password for share level
2292 * authentication before we may cause
2293 * the password prompt to be called.
2295 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2296 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2298 /* in user level security don't send a password now */
2299 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
2300 need_pass = true;
2304 if (need_pass && creds != NULL) {
2305 pw = cli_credentials_get_password(creds);
2308 return cli_tree_connect(cli, share, dev, pw);
2311 /****************************************************************************
2312 Send a tree disconnect.
2313 ****************************************************************************/
2315 struct cli_tdis_state {
2316 struct cli_state *cli;
2319 static void cli_tdis_done(struct tevent_req *subreq);
2321 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2322 struct tevent_context *ev,
2323 struct cli_state *cli)
2325 struct tevent_req *req, *subreq;
2326 struct cli_tdis_state *state;
2328 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2329 if (req == NULL) {
2330 return NULL;
2332 state->cli = cli;
2334 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2335 if (tevent_req_nomem(subreq, req)) {
2336 return tevent_req_post(req, ev);
2338 tevent_req_set_callback(subreq, cli_tdis_done, req);
2339 return req;
2342 static void cli_tdis_done(struct tevent_req *subreq)
2344 struct tevent_req *req = tevent_req_callback_data(
2345 subreq, struct tevent_req);
2346 struct cli_tdis_state *state = tevent_req_data(
2347 req, struct cli_tdis_state);
2348 NTSTATUS status;
2350 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2351 TALLOC_FREE(subreq);
2352 if (tevent_req_nterror(req, status)) {
2353 return;
2355 TALLOC_FREE(state->cli->smb1.tcon);
2356 tevent_req_done(req);
2359 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2361 return tevent_req_simple_recv_ntstatus(req);
2364 NTSTATUS cli_tdis(struct cli_state *cli)
2366 struct tevent_context *ev;
2367 struct tevent_req *req;
2368 NTSTATUS status = NT_STATUS_NO_MEMORY;
2370 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2371 status = smb2cli_tdis(cli->conn,
2372 cli->timeout,
2373 cli->smb2.session,
2374 cli->smb2.tcon);
2375 if (NT_STATUS_IS_OK(status)) {
2376 TALLOC_FREE(cli->smb2.tcon);
2378 return status;
2381 if (smbXcli_conn_has_async_calls(cli->conn)) {
2382 return NT_STATUS_INVALID_PARAMETER;
2384 ev = samba_tevent_context_init(talloc_tos());
2385 if (ev == NULL) {
2386 goto fail;
2388 req = cli_tdis_send(ev, ev, cli);
2389 if (req == NULL) {
2390 goto fail;
2392 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2393 goto fail;
2395 status = cli_tdis_recv(req);
2396 fail:
2397 TALLOC_FREE(ev);
2398 return status;
2401 struct cli_connect_sock_state {
2402 const char **called_names;
2403 const char **calling_names;
2404 int *called_types;
2405 int fd;
2406 uint16_t port;
2409 static void cli_connect_sock_done(struct tevent_req *subreq);
2412 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2413 * nonzero address.
2416 static struct tevent_req *cli_connect_sock_send(
2417 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2418 const char *host, int name_type, const struct sockaddr_storage *pss,
2419 const char *myname, uint16_t port)
2421 struct tevent_req *req, *subreq;
2422 struct cli_connect_sock_state *state;
2423 struct sockaddr_storage *addrs = NULL;
2424 unsigned i;
2425 unsigned num_addrs = 0;
2426 NTSTATUS status;
2428 req = tevent_req_create(mem_ctx, &state,
2429 struct cli_connect_sock_state);
2430 if (req == NULL) {
2431 return NULL;
2434 if ((pss == NULL) || is_zero_addr(pss)) {
2437 * Here we cheat. resolve_name_list is not async at all. So
2438 * this call will only be really async if the name lookup has
2439 * been done externally.
2442 status = resolve_name_list(state, host, name_type,
2443 &addrs, &num_addrs);
2444 if (tevent_req_nterror(req, status)) {
2445 return tevent_req_post(req, ev);
2447 } else {
2448 addrs = talloc_array(state, struct sockaddr_storage, 1);
2449 if (tevent_req_nomem(addrs, req)) {
2450 return tevent_req_post(req, ev);
2452 addrs[0] = *pss;
2453 num_addrs = 1;
2456 state->called_names = talloc_array(state, const char *, num_addrs);
2457 if (tevent_req_nomem(state->called_names, req)) {
2458 return tevent_req_post(req, ev);
2460 state->called_types = talloc_array(state, int, num_addrs);
2461 if (tevent_req_nomem(state->called_types, req)) {
2462 return tevent_req_post(req, ev);
2464 state->calling_names = talloc_array(state, const char *, num_addrs);
2465 if (tevent_req_nomem(state->calling_names, req)) {
2466 return tevent_req_post(req, ev);
2468 for (i=0; i<num_addrs; i++) {
2469 state->called_names[i] = host;
2470 state->called_types[i] = name_type;
2471 state->calling_names[i] = myname;
2474 subreq = smbsock_any_connect_send(
2475 state, ev, addrs, state->called_names, state->called_types,
2476 state->calling_names, NULL, num_addrs, port);
2477 if (tevent_req_nomem(subreq, req)) {
2478 return tevent_req_post(req, ev);
2480 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2481 return req;
2484 static void cli_connect_sock_done(struct tevent_req *subreq)
2486 struct tevent_req *req = tevent_req_callback_data(
2487 subreq, struct tevent_req);
2488 struct cli_connect_sock_state *state = tevent_req_data(
2489 req, struct cli_connect_sock_state);
2490 NTSTATUS status;
2492 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2493 &state->port);
2494 TALLOC_FREE(subreq);
2495 if (tevent_req_nterror(req, status)) {
2496 return;
2498 set_socket_options(state->fd, lp_socket_options());
2499 tevent_req_done(req);
2502 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2503 int *pfd, uint16_t *pport)
2505 struct cli_connect_sock_state *state = tevent_req_data(
2506 req, struct cli_connect_sock_state);
2507 NTSTATUS status;
2509 if (tevent_req_is_nterror(req, &status)) {
2510 return status;
2512 *pfd = state->fd;
2513 *pport = state->port;
2514 return NT_STATUS_OK;
2517 struct cli_connect_nb_state {
2518 const char *desthost;
2519 enum smb_signing_setting signing_state;
2520 int flags;
2521 struct cli_state *cli;
2524 static void cli_connect_nb_done(struct tevent_req *subreq);
2526 static struct tevent_req *cli_connect_nb_send(
2527 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2528 const char *host, const struct sockaddr_storage *dest_ss,
2529 uint16_t port, int name_type, const char *myname,
2530 enum smb_signing_setting signing_state, int flags)
2532 struct tevent_req *req, *subreq;
2533 struct cli_connect_nb_state *state;
2535 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2536 if (req == NULL) {
2537 return NULL;
2539 state->signing_state = signing_state;
2540 state->flags = flags;
2542 if (host != NULL) {
2543 char *p = strchr(host, '#');
2545 if (p != NULL) {
2546 name_type = strtol(p+1, NULL, 16);
2547 host = talloc_strndup(state, host, p - host);
2548 if (tevent_req_nomem(host, req)) {
2549 return tevent_req_post(req, ev);
2553 state->desthost = host;
2554 } else if (dest_ss != NULL) {
2555 state->desthost = print_canonical_sockaddr(state, dest_ss);
2556 if (tevent_req_nomem(state->desthost, req)) {
2557 return tevent_req_post(req, ev);
2559 } else {
2560 /* No host or dest_ss given. Error out. */
2561 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2562 return tevent_req_post(req, ev);
2565 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2566 myname, port);
2567 if (tevent_req_nomem(subreq, req)) {
2568 return tevent_req_post(req, ev);
2570 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2571 return req;
2574 static void cli_connect_nb_done(struct tevent_req *subreq)
2576 struct tevent_req *req = tevent_req_callback_data(
2577 subreq, struct tevent_req);
2578 struct cli_connect_nb_state *state = tevent_req_data(
2579 req, struct cli_connect_nb_state);
2580 NTSTATUS status;
2581 int fd = 0;
2582 uint16_t port;
2584 status = cli_connect_sock_recv(subreq, &fd, &port);
2585 TALLOC_FREE(subreq);
2586 if (tevent_req_nterror(req, status)) {
2587 return;
2590 state->cli = cli_state_create(state, fd, state->desthost,
2591 state->signing_state, state->flags);
2592 if (tevent_req_nomem(state->cli, req)) {
2593 close(fd);
2594 return;
2596 tevent_req_done(req);
2599 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2600 TALLOC_CTX *mem_ctx,
2601 struct cli_state **pcli)
2603 struct cli_connect_nb_state *state = tevent_req_data(
2604 req, struct cli_connect_nb_state);
2605 NTSTATUS status;
2607 if (tevent_req_is_nterror(req, &status)) {
2608 return status;
2610 *pcli = talloc_move(mem_ctx, &state->cli);
2611 return NT_STATUS_OK;
2614 NTSTATUS cli_connect_nb(TALLOC_CTX *mem_ctx,
2615 const char *host,
2616 const struct sockaddr_storage *dest_ss,
2617 uint16_t port,
2618 int name_type,
2619 const char *myname,
2620 enum smb_signing_setting signing_state,
2621 int flags,
2622 struct cli_state **pcli)
2624 struct tevent_context *ev;
2625 struct tevent_req *req;
2626 NTSTATUS status = NT_STATUS_NO_MEMORY;
2628 ev = samba_tevent_context_init(mem_ctx);
2629 if (ev == NULL) {
2630 goto fail;
2632 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2633 myname, signing_state, flags);
2634 if (req == NULL) {
2635 goto fail;
2637 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2638 goto fail;
2640 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2641 goto fail;
2643 status = cli_connect_nb_recv(req, mem_ctx, pcli);
2644 fail:
2645 TALLOC_FREE(ev);
2646 return status;
2649 struct cli_start_connection_state {
2650 struct tevent_context *ev;
2651 struct cli_state *cli;
2652 int min_protocol;
2653 int max_protocol;
2654 struct smb2_negotiate_contexts *negotiate_contexts;
2657 static void cli_start_connection_connected(struct tevent_req *subreq);
2658 static void cli_start_connection_done(struct tevent_req *subreq);
2661 establishes a connection to after the negprot.
2662 @param output_cli A fully initialised cli structure, non-null only on success
2663 @param dest_host The netbios name of the remote host
2664 @param dest_ss (optional) The destination IP, NULL for name based lookup
2665 @param port (optional) The destination port (0 for default)
2668 static struct tevent_req *cli_start_connection_send(
2669 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2670 const char *my_name, const char *dest_host,
2671 const struct sockaddr_storage *dest_ss, int port,
2672 enum smb_signing_setting signing_state, int flags,
2673 struct smb2_negotiate_contexts *negotiate_contexts)
2675 struct tevent_req *req, *subreq;
2676 struct cli_start_connection_state *state;
2678 req = tevent_req_create(mem_ctx, &state,
2679 struct cli_start_connection_state);
2680 if (req == NULL) {
2681 return NULL;
2683 state->ev = ev;
2685 if (flags & CLI_FULL_CONNECTION_IPC) {
2686 state->min_protocol = lp_client_ipc_min_protocol();
2687 state->max_protocol = lp_client_ipc_max_protocol();
2688 } else {
2689 state->min_protocol = lp_client_min_protocol();
2690 state->max_protocol = lp_client_max_protocol();
2693 if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
2694 state->max_protocol = MIN(state->max_protocol,
2695 PROTOCOL_NT1);
2696 state->min_protocol = MIN(state->min_protocol,
2697 state->max_protocol);
2700 if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
2701 state->min_protocol = MAX(state->min_protocol,
2702 PROTOCOL_SMB2_02);
2703 state->max_protocol = MAX(state->max_protocol,
2704 state->min_protocol);
2707 state->negotiate_contexts = talloc_zero(
2708 state, struct smb2_negotiate_contexts);
2709 if (tevent_req_nomem(state->negotiate_contexts, req)) {
2710 return tevent_req_post(req, ev);
2713 if (flags & CLI_FULL_CONNECTION_REQUEST_POSIX) {
2714 NTSTATUS status;
2716 status = smb2_negotiate_context_add(
2717 state->negotiate_contexts,
2718 state->negotiate_contexts,
2719 SMB2_POSIX_EXTENSIONS_AVAILABLE,
2720 (const uint8_t *)SMB2_CREATE_TAG_POSIX,
2721 strlen(SMB2_CREATE_TAG_POSIX));
2722 if (tevent_req_nterror(req, status)) {
2723 return tevent_req_post(req, ev);
2727 if (negotiate_contexts != NULL) {
2728 uint16_t i;
2730 for (i=0; i<negotiate_contexts->num_contexts; i++) {
2731 struct smb2_negotiate_context *ctx =
2732 &negotiate_contexts->contexts[i];
2733 NTSTATUS status;
2735 status = smb2_negotiate_context_add(
2736 state->negotiate_contexts,
2737 state->negotiate_contexts,
2738 ctx->type,
2739 ctx->data.data,
2740 ctx->data.length);
2741 if (tevent_req_nterror(req, status)) {
2742 return tevent_req_post(req, ev);
2747 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2748 0x20, my_name, signing_state, flags);
2749 if (tevent_req_nomem(subreq, req)) {
2750 return tevent_req_post(req, ev);
2752 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2753 return req;
2756 static void cli_start_connection_connected(struct tevent_req *subreq)
2758 struct tevent_req *req = tevent_req_callback_data(
2759 subreq, struct tevent_req);
2760 struct cli_start_connection_state *state = tevent_req_data(
2761 req, struct cli_start_connection_state);
2762 NTSTATUS status;
2764 status = cli_connect_nb_recv(subreq, state, &state->cli);
2765 TALLOC_FREE(subreq);
2766 if (tevent_req_nterror(req, status)) {
2767 return;
2770 subreq = smbXcli_negprot_send(
2771 state,
2772 state->ev,
2773 state->cli->conn,
2774 state->cli->timeout,
2775 state->min_protocol,
2776 state->max_protocol,
2777 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK,
2778 state->negotiate_contexts);
2779 if (tevent_req_nomem(subreq, req)) {
2780 return;
2782 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2785 static void cli_start_connection_done(struct tevent_req *subreq)
2787 struct tevent_req *req = tevent_req_callback_data(
2788 subreq, struct tevent_req);
2789 struct cli_start_connection_state *state = tevent_req_data(
2790 req, struct cli_start_connection_state);
2791 NTSTATUS status;
2793 status = smbXcli_negprot_recv(subreq, NULL, NULL);
2794 TALLOC_FREE(subreq);
2795 if (tevent_req_nterror(req, status)) {
2796 return;
2799 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2800 /* Ensure we ask for some initial credits. */
2801 smb2cli_conn_set_max_credits(state->cli->conn,
2802 DEFAULT_SMB2_MAX_CREDITS);
2805 tevent_req_done(req);
2808 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2809 TALLOC_CTX *mem_ctx,
2810 struct cli_state **output_cli)
2812 struct cli_start_connection_state *state = tevent_req_data(
2813 req, struct cli_start_connection_state);
2814 NTSTATUS status;
2816 if (tevent_req_is_nterror(req, &status)) {
2817 return status;
2819 *output_cli = talloc_move(mem_ctx, &state->cli);
2821 return NT_STATUS_OK;
2824 NTSTATUS cli_start_connection(TALLOC_CTX *mem_ctx,
2825 struct cli_state **output_cli,
2826 const char *my_name,
2827 const char *dest_host,
2828 const struct sockaddr_storage *dest_ss, int port,
2829 enum smb_signing_setting signing_state, int flags)
2831 struct tevent_context *ev;
2832 struct tevent_req *req;
2833 NTSTATUS status = NT_STATUS_NO_MEMORY;
2835 ev = samba_tevent_context_init(mem_ctx);
2836 if (ev == NULL) {
2837 goto fail;
2839 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2840 port, signing_state, flags, NULL);
2841 if (req == NULL) {
2842 goto fail;
2844 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2845 goto fail;
2847 status = cli_start_connection_recv(req, mem_ctx, output_cli);
2848 fail:
2849 TALLOC_FREE(ev);
2850 return status;
2853 struct cli_smb1_setup_encryption_blob_state {
2854 uint16_t setup[1];
2855 uint8_t param[4];
2856 NTSTATUS status;
2857 DATA_BLOB out;
2858 uint16_t enc_ctx_id;
2861 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2863 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2864 struct tevent_context *ev,
2865 struct cli_state *cli,
2866 const DATA_BLOB in)
2868 struct tevent_req *req = NULL;
2869 struct cli_smb1_setup_encryption_blob_state *state = NULL;
2870 struct tevent_req *subreq = NULL;
2872 req = tevent_req_create(mem_ctx, &state,
2873 struct cli_smb1_setup_encryption_blob_state);
2874 if (req == NULL) {
2875 return NULL;
2878 if (in.length > CLI_BUFFER_SIZE) {
2879 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2880 return tevent_req_post(req, ev);
2883 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
2884 SSVAL(state->param, 0, 0);
2885 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
2887 subreq = smb1cli_trans_send(state, ev, cli->conn,
2888 SMBtrans2,
2889 0, 0, /* _flags */
2890 0, 0, /* _flags2 */
2891 cli->timeout,
2892 cli->smb1.pid,
2893 cli->smb1.tcon,
2894 cli->smb1.session,
2895 NULL, /* pipe_name */
2896 0, /* fid */
2897 0, /* function */
2898 0, /* flags */
2899 state->setup, 1, 0,
2900 state->param, 4, 2,
2901 in.data, in.length, CLI_BUFFER_SIZE);
2902 if (tevent_req_nomem(subreq, req)) {
2903 return tevent_req_post(req, ev);
2905 tevent_req_set_callback(subreq,
2906 cli_smb1_setup_encryption_blob_done,
2907 req);
2909 return req;
2912 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
2914 struct tevent_req *req =
2915 tevent_req_callback_data(subreq,
2916 struct tevent_req);
2917 struct cli_smb1_setup_encryption_blob_state *state =
2918 tevent_req_data(req,
2919 struct cli_smb1_setup_encryption_blob_state);
2920 uint8_t *rparam=NULL, *rdata=NULL;
2921 uint32_t num_rparam, num_rdata;
2922 NTSTATUS status;
2924 status = smb1cli_trans_recv(subreq, state,
2925 NULL, /* recv_flags */
2926 NULL, 0, NULL, /* rsetup */
2927 &rparam, 0, &num_rparam,
2928 &rdata, 0, &num_rdata);
2929 TALLOC_FREE(subreq);
2930 state->status = status;
2931 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2932 status = NT_STATUS_OK;
2934 if (tevent_req_nterror(req, status)) {
2935 return;
2938 if (num_rparam == 2) {
2939 state->enc_ctx_id = SVAL(rparam, 0);
2941 TALLOC_FREE(rparam);
2943 state->out = data_blob_const(rdata, num_rdata);
2945 tevent_req_done(req);
2948 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
2949 TALLOC_CTX *mem_ctx,
2950 DATA_BLOB *out,
2951 uint16_t *enc_ctx_id)
2953 struct cli_smb1_setup_encryption_blob_state *state =
2954 tevent_req_data(req,
2955 struct cli_smb1_setup_encryption_blob_state);
2956 NTSTATUS status;
2958 if (tevent_req_is_nterror(req, &status)) {
2959 tevent_req_received(req);
2960 return status;
2963 status = state->status;
2965 *out = state->out;
2966 talloc_steal(mem_ctx, out->data);
2968 *enc_ctx_id = state->enc_ctx_id;
2970 tevent_req_received(req);
2971 return status;
2974 struct cli_smb1_setup_encryption_state {
2975 struct tevent_context *ev;
2976 struct cli_state *cli;
2977 struct smb_trans_enc_state *es;
2978 DATA_BLOB blob_in;
2979 DATA_BLOB blob_out;
2980 bool local_ready;
2981 bool remote_ready;
2984 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
2985 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
2986 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
2987 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
2988 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
2990 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
2991 struct tevent_context *ev,
2992 struct cli_state *cli,
2993 struct cli_credentials *creds)
2995 struct tevent_req *req = NULL;
2996 struct cli_smb1_setup_encryption_state *state = NULL;
2997 struct auth_generic_state *ags = NULL;
2998 const DATA_BLOB *b = NULL;
2999 bool auth_requested = false;
3000 const char *target_service = NULL;
3001 const char *target_hostname = NULL;
3002 NTSTATUS status;
3004 req = tevent_req_create(mem_ctx, &state,
3005 struct cli_smb1_setup_encryption_state);
3006 if (req == NULL) {
3007 return NULL;
3009 state->ev = ev;
3010 state->cli = cli;
3012 auth_requested = cli_credentials_authentication_requested(creds);
3013 if (!auth_requested) {
3014 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3015 return tevent_req_post(req, ev);
3018 target_service = "cifs";
3019 target_hostname = smbXcli_conn_remote_name(cli->conn);
3021 state->es = talloc_zero(state, struct smb_trans_enc_state);
3022 if (tevent_req_nomem(state->es, req)) {
3023 return tevent_req_post(req, ev);
3026 status = auth_generic_client_prepare(state->es, &ags);
3027 if (tevent_req_nterror(req, status)) {
3028 return tevent_req_post(req, ev);
3031 gensec_want_feature(ags->gensec_security,
3032 GENSEC_FEATURE_SIGN);
3033 gensec_want_feature(ags->gensec_security,
3034 GENSEC_FEATURE_SEAL);
3036 status = auth_generic_set_creds(ags, creds);
3037 if (tevent_req_nterror(req, status)) {
3038 return tevent_req_post(req, ev);
3041 if (target_service != NULL) {
3042 status = gensec_set_target_service(ags->gensec_security,
3043 target_service);
3044 if (tevent_req_nterror(req, status)) {
3045 return tevent_req_post(req, ev);
3049 if (target_hostname != NULL) {
3050 status = gensec_set_target_hostname(ags->gensec_security,
3051 target_hostname);
3052 if (tevent_req_nterror(req, status)) {
3053 return tevent_req_post(req, ev);
3057 gensec_set_max_update_size(ags->gensec_security,
3058 CLI_BUFFER_SIZE);
3060 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3061 if (b != NULL) {
3062 state->blob_in = *b;
3065 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3066 if (tevent_req_nterror(req, status)) {
3067 return tevent_req_post(req, ev);
3071 * We only need the gensec_security part from here.
3073 state->es->gensec_security = talloc_move(state->es,
3074 &ags->gensec_security);
3075 TALLOC_FREE(ags);
3077 cli_smb1_setup_encryption_local_next(req);
3078 if (!tevent_req_is_in_progress(req)) {
3079 return tevent_req_post(req, ev);
3082 return req;
3085 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3087 struct cli_smb1_setup_encryption_state *state =
3088 tevent_req_data(req,
3089 struct cli_smb1_setup_encryption_state);
3090 struct tevent_req *subreq = NULL;
3092 if (state->local_ready) {
3093 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3094 return;
3097 subreq = gensec_update_send(state, state->ev,
3098 state->es->gensec_security,
3099 state->blob_in);
3100 if (tevent_req_nomem(subreq, req)) {
3101 return;
3103 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3106 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3108 struct tevent_req *req =
3109 tevent_req_callback_data(subreq,
3110 struct tevent_req);
3111 struct cli_smb1_setup_encryption_state *state =
3112 tevent_req_data(req,
3113 struct cli_smb1_setup_encryption_state);
3114 NTSTATUS status;
3116 status = gensec_update_recv(subreq, state, &state->blob_out);
3117 TALLOC_FREE(subreq);
3118 state->blob_in = data_blob_null;
3119 if (!NT_STATUS_IS_OK(status) &&
3120 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3122 tevent_req_nterror(req, status);
3123 return;
3126 if (NT_STATUS_IS_OK(status)) {
3127 state->local_ready = true;
3131 * We always get NT_STATUS_OK from the server even if it is not ready.
3132 * So guess the server is ready when we are ready and already sent
3133 * our last blob to the server.
3135 if (state->local_ready && state->blob_out.length == 0) {
3136 state->remote_ready = true;
3139 if (state->local_ready && state->remote_ready) {
3140 cli_smb1_setup_encryption_ready(req);
3141 return;
3144 cli_smb1_setup_encryption_remote_next(req);
3147 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3149 struct cli_smb1_setup_encryption_state *state =
3150 tevent_req_data(req,
3151 struct cli_smb1_setup_encryption_state);
3152 struct tevent_req *subreq = NULL;
3154 if (state->remote_ready) {
3155 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3156 return;
3159 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3160 state->cli, state->blob_out);
3161 if (tevent_req_nomem(subreq, req)) {
3162 return;
3164 tevent_req_set_callback(subreq,
3165 cli_smb1_setup_encryption_remote_done,
3166 req);
3169 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3171 struct tevent_req *req =
3172 tevent_req_callback_data(subreq,
3173 struct tevent_req);
3174 struct cli_smb1_setup_encryption_state *state =
3175 tevent_req_data(req,
3176 struct cli_smb1_setup_encryption_state);
3177 NTSTATUS status;
3179 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3180 &state->blob_in,
3181 &state->es->enc_ctx_num);
3182 TALLOC_FREE(subreq);
3183 data_blob_free(&state->blob_out);
3184 if (!NT_STATUS_IS_OK(status) &&
3185 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3187 tevent_req_nterror(req, status);
3188 return;
3192 * We always get NT_STATUS_OK even if the server is not ready.
3193 * So guess the server is ready when we are ready and sent
3194 * our last blob to the server.
3196 if (state->local_ready) {
3197 state->remote_ready = true;
3200 if (state->local_ready && state->remote_ready) {
3201 cli_smb1_setup_encryption_ready(req);
3202 return;
3205 cli_smb1_setup_encryption_local_next(req);
3208 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3210 struct cli_smb1_setup_encryption_state *state =
3211 tevent_req_data(req,
3212 struct cli_smb1_setup_encryption_state);
3213 struct smb_trans_enc_state *es = NULL;
3215 if (state->blob_in.length != 0) {
3216 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3217 return;
3220 if (state->blob_out.length != 0) {
3221 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3222 return;
3225 es = talloc_move(state->cli->conn, &state->es);
3226 es->enc_on = true;
3227 smb1cli_conn_set_encryption(state->cli->conn, es);
3228 es = NULL;
3230 tevent_req_done(req);
3233 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3235 return tevent_req_simple_recv_ntstatus(req);
3238 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3239 struct cli_credentials *creds)
3241 struct tevent_context *ev = NULL;
3242 struct tevent_req *req = NULL;
3243 NTSTATUS status = NT_STATUS_NO_MEMORY;
3245 ev = samba_tevent_context_init(talloc_tos());
3246 if (ev == NULL) {
3247 goto fail;
3249 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3250 if (req == NULL) {
3251 goto fail;
3253 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3254 goto fail;
3256 status = cli_smb1_setup_encryption_recv(req);
3257 fail:
3258 TALLOC_FREE(ev);
3259 return status;
3263 establishes a connection right up to doing tconX, password specified.
3264 @param output_cli A fully initialised cli structure, non-null only on success
3265 @param dest_host The netbios name of the remote host
3266 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3267 @param port (optional) The destination port (0 for default)
3268 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3269 @param service_type The 'type' of service.
3270 @param creds The used user credentials
3273 struct cli_full_connection_creds_state {
3274 struct tevent_context *ev;
3275 const char *service;
3276 const char *service_type;
3277 struct cli_credentials *creds;
3278 int flags;
3279 struct cli_state *cli;
3282 static int cli_full_connection_creds_state_destructor(
3283 struct cli_full_connection_creds_state *s)
3285 if (s->cli != NULL) {
3286 cli_shutdown(s->cli);
3287 s->cli = NULL;
3289 return 0;
3292 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3293 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3294 static void cli_full_connection_creds_enc_start(struct tevent_req *req);
3295 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq);
3296 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq);
3297 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq);
3298 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req);
3299 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq);
3300 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3301 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3303 struct tevent_req *cli_full_connection_creds_send(
3304 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3305 const char *my_name, const char *dest_host,
3306 const struct sockaddr_storage *dest_ss, int port,
3307 const char *service, const char *service_type,
3308 struct cli_credentials *creds,
3309 int flags,
3310 struct smb2_negotiate_contexts *negotiate_contexts)
3312 struct tevent_req *req, *subreq;
3313 struct cli_full_connection_creds_state *state;
3314 enum smb_signing_setting signing_state;
3315 enum smb_encryption_setting encryption_state =
3316 cli_credentials_get_smb_encryption(creds);
3318 req = tevent_req_create(mem_ctx, &state,
3319 struct cli_full_connection_creds_state);
3320 if (req == NULL) {
3321 return NULL;
3323 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3325 state->ev = ev;
3326 state->service = service;
3327 state->service_type = service_type;
3328 state->creds = creds;
3329 state->flags = flags;
3331 if (flags & CLI_FULL_CONNECTION_IPC) {
3332 signing_state = cli_credentials_get_smb_ipc_signing(creds);
3333 } else {
3334 signing_state = cli_credentials_get_smb_signing(creds);
3337 if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
3338 if (flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK) {
3339 encryption_state = SMB_ENCRYPTION_DESIRED;
3343 if (encryption_state >= SMB_ENCRYPTION_DESIRED) {
3344 signing_state = SMB_SIGNING_REQUIRED;
3347 subreq = cli_start_connection_send(
3348 state, ev, my_name, dest_host, dest_ss, port,
3349 signing_state, flags,
3350 negotiate_contexts);
3351 if (tevent_req_nomem(subreq, req)) {
3352 return tevent_req_post(req, ev);
3354 tevent_req_set_callback(subreq,
3355 cli_full_connection_creds_conn_done,
3356 req);
3357 return req;
3360 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3362 struct tevent_req *req = tevent_req_callback_data(
3363 subreq, struct tevent_req);
3364 struct cli_full_connection_creds_state *state = tevent_req_data(
3365 req, struct cli_full_connection_creds_state);
3366 NTSTATUS status;
3368 status = cli_start_connection_recv(subreq, state, &state->cli);
3369 TALLOC_FREE(subreq);
3370 if (tevent_req_nterror(req, status)) {
3371 return;
3374 subreq = cli_session_setup_creds_send(
3375 state, state->ev, state->cli, state->creds);
3376 if (tevent_req_nomem(subreq, req)) {
3377 return;
3379 tevent_req_set_callback(subreq,
3380 cli_full_connection_creds_sess_done,
3381 req);
3384 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3386 struct tevent_req *req = tevent_req_callback_data(
3387 subreq, struct tevent_req);
3388 struct cli_full_connection_creds_state *state = tevent_req_data(
3389 req, struct cli_full_connection_creds_state);
3390 NTSTATUS status;
3392 status = cli_session_setup_creds_recv(subreq);
3393 TALLOC_FREE(subreq);
3395 if (!NT_STATUS_IS_OK(status) &&
3396 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3398 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3400 state->creds = cli_credentials_init_anon(state);
3401 if (tevent_req_nomem(state->creds, req)) {
3402 return;
3405 subreq = cli_session_setup_creds_send(
3406 state, state->ev, state->cli, state->creds);
3407 if (tevent_req_nomem(subreq, req)) {
3408 return;
3410 tevent_req_set_callback(subreq,
3411 cli_full_connection_creds_sess_done,
3412 req);
3413 return;
3416 if (tevent_req_nterror(req, status)) {
3417 return;
3420 cli_full_connection_creds_enc_start(req);
3423 static void cli_full_connection_creds_enc_start(struct tevent_req *req)
3425 struct cli_full_connection_creds_state *state = tevent_req_data(
3426 req, struct cli_full_connection_creds_state);
3427 enum smb_encryption_setting encryption_state =
3428 cli_credentials_get_smb_encryption(state->creds);
3429 struct tevent_req *subreq = NULL;
3430 NTSTATUS status;
3432 if (encryption_state < SMB_ENCRYPTION_DESIRED) {
3433 cli_full_connection_creds_tcon_start(req);
3434 return;
3437 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3438 status = smb2cli_session_encryption_on(state->cli->smb2.session);
3439 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
3440 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3441 cli_full_connection_creds_tcon_start(req);
3442 return;
3444 d_printf("Encryption required and "
3445 "server doesn't support "
3446 "SMB3 encryption - failing connect\n");
3447 tevent_req_nterror(req, status);
3448 return;
3449 } else if (!NT_STATUS_IS_OK(status)) {
3450 d_printf("Encryption required and "
3451 "setup failed with error %s.\n",
3452 nt_errstr(status));
3453 tevent_req_nterror(req, status);
3454 return;
3457 cli_full_connection_creds_tcon_start(req);
3458 return;
3461 if (!SERVER_HAS_UNIX_CIFS(state->cli)) {
3462 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3463 cli_full_connection_creds_tcon_start(req);
3464 return;
3467 status = NT_STATUS_NOT_SUPPORTED;
3468 d_printf("Encryption required and "
3469 "server doesn't support "
3470 "SMB1 Unix Extensions - failing connect\n");
3471 tevent_req_nterror(req, status);
3472 return;
3476 * We do a tcon on IPC$ just to setup the encryption,
3477 * the real tcon will be encrypted then.
3479 subreq = cli_tree_connect_send(state, state->ev, state->cli,
3480 "IPC$", "IPC", NULL);
3481 if (tevent_req_nomem(subreq, req)) {
3482 return;
3484 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_tcon, req);
3487 static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq)
3489 struct tevent_req *req = tevent_req_callback_data(
3490 subreq, struct tevent_req);
3491 struct cli_full_connection_creds_state *state = tevent_req_data(
3492 req, struct cli_full_connection_creds_state);
3493 NTSTATUS status;
3495 status = cli_tree_connect_recv(subreq);
3496 TALLOC_FREE(subreq);
3497 if (tevent_req_nterror(req, status)) {
3498 return;
3501 subreq = cli_unix_extensions_version_send(state, state->ev, state->cli);
3502 if (tevent_req_nomem(subreq, req)) {
3503 return;
3505 tevent_req_set_callback(subreq, cli_full_connection_creds_enc_ver, req);
3508 static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq)
3510 struct tevent_req *req = tevent_req_callback_data(
3511 subreq, struct tevent_req);
3512 struct cli_full_connection_creds_state *state = tevent_req_data(
3513 req, struct cli_full_connection_creds_state);
3514 enum smb_encryption_setting encryption_state =
3515 cli_credentials_get_smb_encryption(state->creds);
3516 uint16_t major, minor;
3517 uint32_t caplow, caphigh;
3518 NTSTATUS status;
3520 status = cli_unix_extensions_version_recv(subreq,
3521 &major, &minor,
3522 &caplow,
3523 &caphigh);
3524 TALLOC_FREE(subreq);
3525 if (!NT_STATUS_IS_OK(status)) {
3526 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3527 /* disconnect ipc$ followed by the real tree connect */
3528 cli_full_connection_creds_enc_tdis(req);
3529 return;
3531 DEBUG(10, ("%s: cli_unix_extensions_version "
3532 "returned %s\n", __func__, nt_errstr(status)));
3533 tevent_req_nterror(req, NT_STATUS_UNKNOWN_REVISION);
3534 return;
3537 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
3538 if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
3539 /* disconnect ipc$ followed by the real tree connect */
3540 cli_full_connection_creds_enc_tdis(req);
3541 return;
3543 DEBUG(10, ("%s: CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP "
3544 "not supported\n", __func__));
3545 tevent_req_nterror(req, NT_STATUS_UNSUPPORTED_COMPRESSION);
3546 return;
3549 subreq = cli_smb1_setup_encryption_send(state, state->ev,
3550 state->cli,
3551 state->creds);
3552 if (tevent_req_nomem(subreq, req)) {
3553 return;
3555 tevent_req_set_callback(subreq,
3556 cli_full_connection_creds_enc_done,
3557 req);
3560 static void cli_full_connection_creds_enc_done(struct tevent_req *subreq)
3562 struct tevent_req *req = tevent_req_callback_data(
3563 subreq, struct tevent_req);
3564 NTSTATUS status;
3566 status = cli_smb1_setup_encryption_recv(subreq);
3567 TALLOC_FREE(subreq);
3568 if (tevent_req_nterror(req, status)) {
3569 return;
3572 /* disconnect ipc$ followed by the real tree connect */
3573 cli_full_connection_creds_enc_tdis(req);
3576 static void cli_full_connection_creds_enc_tdis(struct tevent_req *req)
3578 struct cli_full_connection_creds_state *state = tevent_req_data(
3579 req, struct cli_full_connection_creds_state);
3580 struct tevent_req *subreq = NULL;
3582 subreq = cli_tdis_send(state, state->ev, state->cli);
3583 if (tevent_req_nomem(subreq, req)) {
3584 return;
3586 tevent_req_set_callback(subreq,
3587 cli_full_connection_creds_enc_finished,
3588 req);
3591 static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq)
3593 struct tevent_req *req = tevent_req_callback_data(
3594 subreq, struct tevent_req);
3595 NTSTATUS status;
3597 status = cli_tdis_recv(subreq);
3598 TALLOC_FREE(subreq);
3599 if (tevent_req_nterror(req, status)) {
3600 return;
3603 cli_full_connection_creds_tcon_start(req);
3606 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3608 struct cli_full_connection_creds_state *state = tevent_req_data(
3609 req, struct cli_full_connection_creds_state);
3610 struct tevent_req *subreq = NULL;
3611 const char *password = NULL;
3613 if (state->service == NULL) {
3614 tevent_req_done(req);
3615 return;
3618 password = cli_credentials_get_password(state->creds);
3620 subreq = cli_tree_connect_send(state, state->ev,
3621 state->cli,
3622 state->service,
3623 state->service_type,
3624 password);
3625 if (tevent_req_nomem(subreq, req)) {
3626 return;
3628 tevent_req_set_callback(subreq,
3629 cli_full_connection_creds_tcon_done,
3630 req);
3633 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3635 struct tevent_req *req = tevent_req_callback_data(
3636 subreq, struct tevent_req);
3637 NTSTATUS status;
3639 status = cli_tree_connect_recv(subreq);
3640 TALLOC_FREE(subreq);
3641 if (tevent_req_nterror(req, status)) {
3642 return;
3645 tevent_req_done(req);
3648 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3649 TALLOC_CTX *mem_ctx,
3650 struct cli_state **output_cli)
3652 struct cli_full_connection_creds_state *state = tevent_req_data(
3653 req, struct cli_full_connection_creds_state);
3654 NTSTATUS status;
3656 if (tevent_req_is_nterror(req, &status)) {
3657 return status;
3659 *output_cli = talloc_move(mem_ctx, &state->cli);
3660 talloc_set_destructor(state, NULL);
3661 return NT_STATUS_OK;
3664 NTSTATUS cli_full_connection_creds(TALLOC_CTX *mem_ctx,
3665 struct cli_state **output_cli,
3666 const char *my_name,
3667 const char *dest_host,
3668 const struct sockaddr_storage *dest_ss, int port,
3669 const char *service, const char *service_type,
3670 struct cli_credentials *creds,
3671 int flags)
3673 struct tevent_context *ev;
3674 struct tevent_req *req;
3675 NTSTATUS status = NT_STATUS_NO_MEMORY;
3677 ev = samba_tevent_context_init(mem_ctx);
3678 if (ev == NULL) {
3679 goto fail;
3681 req = cli_full_connection_creds_send(
3682 ev, ev, my_name, dest_host, dest_ss, port, service,
3683 service_type, creds, flags,
3684 NULL);
3685 if (req == NULL) {
3686 goto fail;
3688 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3689 goto fail;
3691 status = cli_full_connection_creds_recv(req, mem_ctx, output_cli);
3692 fail:
3693 TALLOC_FREE(ev);
3694 return status;
3697 /****************************************************************************
3698 Send an old style tcon.
3699 ****************************************************************************/
3700 struct cli_raw_tcon_state {
3701 uint16_t *ret_vwv;
3704 static void cli_raw_tcon_done(struct tevent_req *subreq);
3706 static struct tevent_req *cli_raw_tcon_send(
3707 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3708 const char *service, const char *pass, const char *dev)
3710 struct tevent_req *req, *subreq;
3711 struct cli_raw_tcon_state *state;
3712 uint8_t *bytes;
3714 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3715 if (req == NULL) {
3716 return NULL;
3719 if (!lp_client_plaintext_auth() && (*pass)) {
3720 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3721 " or 'client ntlmv2 auth = yes'\n"));
3722 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3723 return tevent_req_post(req, ev);
3726 TALLOC_FREE(cli->smb1.tcon);
3727 cli->smb1.tcon = smbXcli_tcon_create(cli);
3728 if (tevent_req_nomem(cli->smb1.tcon, req)) {
3729 return tevent_req_post(req, ev);
3731 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
3733 bytes = talloc_array(state, uint8_t, 0);
3734 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3735 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3736 service, strlen(service)+1, NULL);
3737 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3738 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3739 pass, strlen(pass)+1, NULL);
3740 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3741 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3742 dev, strlen(dev)+1, NULL);
3744 if (tevent_req_nomem(bytes, req)) {
3745 return tevent_req_post(req, ev);
3748 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3749 talloc_get_size(bytes), bytes);
3750 if (tevent_req_nomem(subreq, req)) {
3751 return tevent_req_post(req, ev);
3753 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3754 return req;
3757 static void cli_raw_tcon_done(struct tevent_req *subreq)
3759 struct tevent_req *req = tevent_req_callback_data(
3760 subreq, struct tevent_req);
3761 struct cli_raw_tcon_state *state = tevent_req_data(
3762 req, struct cli_raw_tcon_state);
3763 NTSTATUS status;
3765 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3766 NULL, NULL);
3767 TALLOC_FREE(subreq);
3768 if (tevent_req_nterror(req, status)) {
3769 return;
3771 tevent_req_done(req);
3774 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3775 uint16_t *max_xmit, uint16_t *tid)
3777 struct cli_raw_tcon_state *state = tevent_req_data(
3778 req, struct cli_raw_tcon_state);
3779 NTSTATUS status;
3781 if (tevent_req_is_nterror(req, &status)) {
3782 return status;
3784 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3785 *tid = SVAL(state->ret_vwv + 1, 0);
3786 return NT_STATUS_OK;
3789 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3790 const char *service, const char *pass, const char *dev,
3791 uint16_t *max_xmit, uint16_t *tid)
3793 struct tevent_context *ev;
3794 struct tevent_req *req;
3795 NTSTATUS status = NT_STATUS_NO_MEMORY;
3797 ev = samba_tevent_context_init(talloc_tos());
3798 if (ev == NULL) {
3799 goto fail;
3801 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3802 if (req == NULL) {
3803 goto fail;
3805 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3806 goto fail;
3808 status = cli_raw_tcon_recv(req, max_xmit, tid);
3809 fail:
3810 TALLOC_FREE(ev);
3811 return status;
3814 /* Return a cli_state pointing at the IPC$ share for the given server */
3816 static struct cli_state *get_ipc_connect(TALLOC_CTX *mem_ctx,
3817 char *server,
3818 struct sockaddr_storage *server_ss,
3819 struct cli_credentials *creds)
3821 struct cli_state *cli;
3822 NTSTATUS nt_status;
3823 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3825 flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
3826 flags |= CLI_FULL_CONNECTION_IPC;
3828 nt_status = cli_full_connection_creds(mem_ctx,
3829 &cli,
3830 NULL,
3831 server,
3832 server_ss,
3834 "IPC$",
3835 "IPC",
3836 creds,
3837 flags);
3839 if (NT_STATUS_IS_OK(nt_status)) {
3840 return cli;
3842 if (is_ipaddress(server)) {
3843 /* windows 9* needs a correct NMB name for connections */
3844 fstring remote_name;
3846 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3847 cli = get_ipc_connect(mem_ctx, remote_name, server_ss, creds);
3848 if (cli)
3849 return cli;
3852 return NULL;
3856 * Given the IP address of a master browser on the network, return its
3857 * workgroup and connect to it.
3859 * This function is provided to allow additional processing beyond what
3860 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3861 * browsers and obtain each master browsers' list of domains (in case the
3862 * first master browser is recently on the network and has not yet
3863 * synchronized with other master browsers and therefore does not yet have the
3864 * entire network browse list)
3867 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3868 struct sockaddr_storage *mb_ip,
3869 struct cli_credentials *creds,
3870 char **pp_workgroup_out)
3872 char addr[INET6_ADDRSTRLEN];
3873 fstring name;
3874 struct cli_state *cli;
3875 struct sockaddr_storage server_ss;
3877 *pp_workgroup_out = NULL;
3879 print_sockaddr(addr, sizeof(addr), mb_ip);
3880 DEBUG(99, ("Looking up name of master browser %s\n",
3881 addr));
3884 * Do a name status query to find out the name of the master browser.
3885 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3886 * master browser will not respond to a wildcard query (or, at least,
3887 * an NT4 server acting as the domain master browser will not).
3889 * We might be able to use ONLY the query on MSBROWSE, but that's not
3890 * yet been tested with all Windows versions, so until it is, leave
3891 * the original wildcard query as the first choice and fall back to
3892 * MSBROWSE if the wildcard query fails.
3894 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3895 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3897 DEBUG(99, ("Could not retrieve name status for %s\n",
3898 addr));
3899 return NULL;
3902 if (!find_master_ip(name, &server_ss)) {
3903 DEBUG(99, ("Could not find master ip for %s\n", name));
3904 return NULL;
3907 *pp_workgroup_out = talloc_strdup(ctx, name);
3909 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3911 print_sockaddr(addr, sizeof(addr), &server_ss);
3912 cli = get_ipc_connect(ctx, addr, &server_ss, creds);
3914 return cli;