s3:libsmb: change cli_session_setup_send/recv into cli_session_setup_creds_send/recv
[Samba.git] / source3 / libsmb / cliconnect.c
blob0583fa7a31cf6f88796d9894135c4b28c0594fa2
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 "auth_info.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
28 #include "smb_krb5.h"
29 #include "auth/credentials/credentials.h"
30 #include "auth/gensec/gensec.h"
31 #include "auth/ntlmssp/ntlmssp.h"
32 #include "auth_generic.h"
33 #include "libads/kerberos_proto.h"
34 #include "krb5_env.h"
35 #include "../lib/util/tevent_ntstatus.h"
36 #include "async_smb.h"
37 #include "libsmb/nmblib.h"
38 #include "librpc/ndr/libndr.h"
39 #include "../libcli/smb/smbXcli_base.h"
40 #include "lib/param/param.h"
42 #define STAR_SMBSERVER "*SMBSERVER"
44 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
45 const char *principal);
47 static struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
48 const char *username,
49 const char *domain,
50 const char *realm,
51 const char *password,
52 bool use_kerberos,
53 bool fallback_after_kerberos,
54 bool use_ccache,
55 bool password_is_nt_hash)
57 struct loadparm_context *lp_ctx = NULL;
58 struct cli_credentials *creds = NULL;
59 const char *principal = NULL;
60 char *tmp = NULL;
61 char *p = NULL;
62 bool ok;
64 creds = cli_credentials_init(mem_ctx);
65 if (creds == NULL) {
66 return NULL;
69 lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
70 if (lp_ctx == NULL) {
71 goto fail;
73 cli_credentials_set_conf(creds, lp_ctx);
75 if (domain == NULL) {
76 domain = "";
79 if (username == NULL) {
80 username = "";
83 if (strlen(username) == 0) {
84 if (password != NULL && strlen(password) == 0) {
86 * some callers pass "" as no password
88 * gensec only handles NULL as no password.
90 password = NULL;
92 if (password == NULL) {
93 cli_credentials_set_anonymous(creds);
94 return creds;
98 tmp = talloc_strdup(creds, username);
99 if (tmp == NULL) {
100 goto fail;
102 username = tmp;
104 /* allow for workgroups as part of the username */
105 if ((p = strchr_m(tmp, '\\')) ||
106 (p = strchr_m(tmp, '/')) ||
107 (p = strchr_m(tmp, *lp_winbind_separator()))) {
108 *p = 0;
109 username = p + 1;
110 domain = tmp;
113 principal = username;
114 username = cli_session_setup_get_account(creds, principal);
115 if (username == NULL) {
116 goto fail;
118 ok = strequal(username, principal);
119 if (ok) {
121 * Ok still the same, so it's not a principal
123 principal = NULL;
126 if (use_kerberos && fallback_after_kerberos) {
127 cli_credentials_set_kerberos_state(creds,
128 CRED_AUTO_USE_KERBEROS);
129 } else if (use_kerberos) {
130 cli_credentials_set_kerberos_state(creds,
131 CRED_MUST_USE_KERBEROS);
132 } else {
133 cli_credentials_set_kerberos_state(creds,
134 CRED_DONT_USE_KERBEROS);
137 if (use_ccache) {
138 uint32_t features;
140 features = cli_credentials_get_gensec_features(creds);
141 features |= GENSEC_FEATURE_NTLM_CCACHE;
142 cli_credentials_set_gensec_features(creds, features);
144 if (password != NULL && strlen(password) == 0) {
146 * some callers pass "" as no password
148 * GENSEC_FEATURE_NTLM_CCACHE only handles
149 * NULL as no password.
151 password = NULL;
155 ok = cli_credentials_set_username(creds,
156 username,
157 CRED_SPECIFIED);
158 if (!ok) {
159 goto fail;
162 ok = cli_credentials_set_domain(creds,
163 domain,
164 CRED_SPECIFIED);
165 if (!ok) {
166 goto fail;
169 if (principal != NULL) {
170 ok = cli_credentials_set_principal(creds,
171 principal,
172 CRED_SPECIFIED);
173 if (!ok) {
174 goto fail;
178 if (realm != NULL) {
179 ok = cli_credentials_set_realm(creds,
180 realm,
181 CRED_SPECIFIED);
182 if (!ok) {
183 goto fail;
187 if (password != NULL && strlen(password) > 0) {
188 if (password_is_nt_hash) {
189 struct samr_Password nt_hash;
190 size_t converted;
192 converted = strhex_to_str((char *)nt_hash.hash,
193 sizeof(nt_hash.hash),
194 password,
195 strlen(password));
196 if (converted != sizeof(nt_hash.hash)) {
197 goto fail;
200 ok = cli_credentials_set_nt_hash(creds,
201 &nt_hash,
202 CRED_SPECIFIED);
203 if (!ok) {
204 goto fail;
206 } else {
207 ok = cli_credentials_set_password(creds,
208 password,
209 CRED_SPECIFIED);
210 if (!ok) {
211 goto fail;
216 return creds;
217 fail:
218 TALLOC_FREE(creds);
219 return NULL;
222 /********************************************************
223 Utility function to ensure we always return at least
224 a valid char * pointer to an empty string for the
225 cli->server_os, cli->server_type and cli->server_domain
226 strings.
227 *******************************************************/
229 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
230 const uint8_t *hdr,
231 char **dest,
232 uint8_t *src,
233 size_t srclen,
234 ssize_t *destlen)
236 *destlen = clistr_pull_talloc(mem_ctx,
237 (const char *)hdr,
238 SVAL(hdr, HDR_FLG2),
239 dest,
240 (char *)src,
241 srclen,
242 STR_TERMINATE);
243 if (*destlen == -1) {
244 return NT_STATUS_NO_MEMORY;
247 if (*dest == NULL) {
248 *dest = talloc_strdup(mem_ctx, "");
249 if (*dest == NULL) {
250 return NT_STATUS_NO_MEMORY;
253 return NT_STATUS_OK;
256 /****************************************************************************
257 Work out suitable capabilities to offer the server.
258 ****************************************************************************/
260 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
261 uint32_t sesssetup_capabilities)
263 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
266 * We only send capabilities based on the mask for:
267 * - client only flags
268 * - flags used in both directions
270 * We do not echo the server only flags, except some legacy flags.
272 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
273 * CAP_LARGE_WRITEX in order to allow us to do large reads
274 * against old Samba releases (<= 3.6.x).
276 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
279 * Session Setup specific flags CAP_DYNAMIC_REAUTH
280 * and CAP_EXTENDED_SECURITY are passed by the caller.
281 * We need that in order to do guest logins even if
282 * CAP_EXTENDED_SECURITY is negotiated.
284 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
285 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
286 client_capabilities |= sesssetup_capabilities;
288 return client_capabilities;
291 /****************************************************************************
292 Do a NT1 guest session setup.
293 ****************************************************************************/
295 struct cli_session_setup_guest_state {
296 struct cli_state *cli;
297 uint16_t vwv[13];
298 struct iovec bytes;
301 static void cli_session_setup_guest_done(struct tevent_req *subreq);
303 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
304 struct tevent_context *ev,
305 struct cli_state *cli,
306 struct tevent_req **psmbreq)
308 struct tevent_req *req, *subreq;
309 struct cli_session_setup_guest_state *state;
310 uint16_t *vwv;
311 uint8_t *bytes;
313 req = tevent_req_create(mem_ctx, &state,
314 struct cli_session_setup_guest_state);
315 if (req == NULL) {
316 return NULL;
318 state->cli = cli;
319 vwv = state->vwv;
321 SCVAL(vwv+0, 0, 0xFF);
322 SCVAL(vwv+0, 1, 0);
323 SSVAL(vwv+1, 0, 0);
324 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
325 SSVAL(vwv+3, 0, 2);
326 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
327 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
328 SSVAL(vwv+7, 0, 0);
329 SSVAL(vwv+8, 0, 0);
330 SSVAL(vwv+9, 0, 0);
331 SSVAL(vwv+10, 0, 0);
332 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
334 bytes = talloc_array(state, uint8_t, 0);
336 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
337 NULL);
338 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
339 NULL);
340 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
341 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
343 if (bytes == NULL) {
344 TALLOC_FREE(req);
345 return NULL;
348 state->bytes.iov_base = (void *)bytes;
349 state->bytes.iov_len = talloc_get_size(bytes);
351 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
352 vwv, 1, &state->bytes);
353 if (subreq == NULL) {
354 TALLOC_FREE(req);
355 return NULL;
357 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
358 *psmbreq = subreq;
359 return req;
362 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
363 struct tevent_context *ev,
364 struct cli_state *cli)
366 struct tevent_req *req, *subreq;
367 NTSTATUS status;
369 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
370 if (req == NULL) {
371 return NULL;
374 status = smb1cli_req_chain_submit(&subreq, 1);
375 if (!NT_STATUS_IS_OK(status)) {
376 tevent_req_nterror(req, status);
377 return tevent_req_post(req, ev);
379 return req;
382 static void cli_session_setup_guest_done(struct tevent_req *subreq)
384 struct tevent_req *req = tevent_req_callback_data(
385 subreq, struct tevent_req);
386 struct cli_session_setup_guest_state *state = tevent_req_data(
387 req, struct cli_session_setup_guest_state);
388 struct cli_state *cli = state->cli;
389 uint32_t num_bytes;
390 uint8_t *in;
391 uint8_t *inhdr;
392 uint8_t *bytes;
393 uint8_t *p;
394 NTSTATUS status;
395 ssize_t ret;
396 uint8_t wct;
397 uint16_t *vwv;
399 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
400 &num_bytes, &bytes);
401 TALLOC_FREE(subreq);
402 if (!NT_STATUS_IS_OK(status)) {
403 tevent_req_nterror(req, status);
404 return;
407 inhdr = in + NBT_HDR_SIZE;
408 p = bytes;
410 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
411 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
413 status = smb_bytes_talloc_string(cli,
414 inhdr,
415 &cli->server_os,
417 bytes+num_bytes-p,
418 &ret);
420 if (!NT_STATUS_IS_OK(status)) {
421 tevent_req_nterror(req, status);
422 return;
424 p += ret;
426 status = smb_bytes_talloc_string(cli,
427 inhdr,
428 &cli->server_type,
430 bytes+num_bytes-p,
431 &ret);
433 if (!NT_STATUS_IS_OK(status)) {
434 tevent_req_nterror(req, status);
435 return;
437 p += ret;
439 status = smb_bytes_talloc_string(cli,
440 inhdr,
441 &cli->server_domain,
443 bytes+num_bytes-p,
444 &ret);
446 if (!NT_STATUS_IS_OK(status)) {
447 tevent_req_nterror(req, status);
448 return;
450 p += ret;
452 tevent_req_done(req);
455 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
457 return tevent_req_simple_recv_ntstatus(req);
460 /* The following is calculated from :
461 * (smb_size-4) = 35
462 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
463 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
464 * end of packet.
467 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
469 struct cli_sesssetup_blob_state {
470 struct tevent_context *ev;
471 struct cli_state *cli;
472 DATA_BLOB blob;
473 uint16_t max_blob_size;
475 DATA_BLOB this_blob;
476 struct iovec *recv_iov;
478 NTSTATUS status;
479 const uint8_t *inbuf;
480 DATA_BLOB ret_blob;
482 char *out_native_os;
483 char *out_native_lm;
486 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
487 struct tevent_req **psubreq);
488 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
490 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
491 struct tevent_context *ev,
492 struct cli_state *cli,
493 DATA_BLOB blob)
495 struct tevent_req *req, *subreq;
496 struct cli_sesssetup_blob_state *state;
497 uint32_t usable_space;
499 req = tevent_req_create(mem_ctx, &state,
500 struct cli_sesssetup_blob_state);
501 if (req == NULL) {
502 return NULL;
504 state->ev = ev;
505 state->blob = blob;
506 state->cli = cli;
508 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
509 usable_space = UINT16_MAX;
510 } else {
511 usable_space = cli_state_available_size(cli,
512 BASE_SESSSETUP_BLOB_PACKET_SIZE);
515 if (usable_space == 0) {
516 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
517 "(not possible to send %u bytes)\n",
518 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
519 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
520 return tevent_req_post(req, ev);
522 state->max_blob_size = MIN(usable_space, 0xFFFF);
524 if (!cli_sesssetup_blob_next(state, &subreq)) {
525 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
526 return tevent_req_post(req, ev);
528 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
529 return req;
532 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
533 struct tevent_req **psubreq)
535 struct tevent_req *subreq;
536 uint16_t thistime;
538 thistime = MIN(state->blob.length, state->max_blob_size);
540 state->this_blob.data = state->blob.data;
541 state->this_blob.length = thistime;
543 state->blob.data += thistime;
544 state->blob.length -= thistime;
546 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
547 subreq = smb2cli_session_setup_send(state, state->ev,
548 state->cli->conn,
549 state->cli->timeout,
550 state->cli->smb2.session,
551 0, /* in_flags */
552 SMB2_CAP_DFS, /* in_capabilities */
553 0, /* in_channel */
554 0, /* in_previous_session_id */
555 &state->this_blob);
556 if (subreq == NULL) {
557 return false;
559 } else {
560 uint16_t in_buf_size = 0;
561 uint16_t in_mpx_max = 0;
562 uint16_t in_vc_num = 0;
563 uint32_t in_sess_key = 0;
564 uint32_t in_capabilities = 0;
565 const char *in_native_os = NULL;
566 const char *in_native_lm = NULL;
568 in_buf_size = CLI_BUFFER_SIZE;
569 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
570 in_vc_num = cli_state_get_vc_num(state->cli);
571 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
572 in_capabilities = cli_session_setup_capabilities(state->cli,
573 CAP_EXTENDED_SECURITY);
574 in_native_os = "Unix";
575 in_native_lm = "Samba";
578 * For now we keep the same values as before,
579 * we may remove these in a separate commit later.
581 in_mpx_max = 2;
582 in_vc_num = 1;
583 in_sess_key = 0;
585 subreq = smb1cli_session_setup_ext_send(state, state->ev,
586 state->cli->conn,
587 state->cli->timeout,
588 state->cli->smb1.pid,
589 state->cli->smb1.session,
590 in_buf_size,
591 in_mpx_max,
592 in_vc_num,
593 in_sess_key,
594 state->this_blob,
595 in_capabilities,
596 in_native_os,
597 in_native_lm);
598 if (subreq == NULL) {
599 return false;
602 *psubreq = subreq;
603 return true;
606 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
608 struct tevent_req *req = tevent_req_callback_data(
609 subreq, struct tevent_req);
610 struct cli_sesssetup_blob_state *state = tevent_req_data(
611 req, struct cli_sesssetup_blob_state);
612 struct cli_state *cli = state->cli;
613 NTSTATUS status;
615 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
616 status = smb2cli_session_setup_recv(subreq, state,
617 &state->recv_iov,
618 &state->ret_blob);
619 } else {
620 status = smb1cli_session_setup_ext_recv(subreq, state,
621 &state->recv_iov,
622 &state->inbuf,
623 &state->ret_blob,
624 &state->out_native_os,
625 &state->out_native_lm);
627 TALLOC_FREE(subreq);
628 if (!NT_STATUS_IS_OK(status)
629 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
630 tevent_req_nterror(req, status);
631 return;
634 if (cli->server_os == NULL) {
635 cli->server_os = talloc_move(cli, &state->out_native_os);
637 if (cli->server_type == NULL) {
638 cli->server_type = talloc_move(cli, &state->out_native_lm);
641 state->status = status;
643 if (state->blob.length != 0) {
645 * More to send
647 if (!cli_sesssetup_blob_next(state, &subreq)) {
648 tevent_req_oom(req);
649 return;
651 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
652 return;
654 tevent_req_done(req);
657 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
658 TALLOC_CTX *mem_ctx,
659 DATA_BLOB *pblob,
660 const uint8_t **pinbuf,
661 struct iovec **precv_iov)
663 struct cli_sesssetup_blob_state *state = tevent_req_data(
664 req, struct cli_sesssetup_blob_state);
665 NTSTATUS status;
666 struct iovec *recv_iov;
668 if (tevent_req_is_nterror(req, &status)) {
669 TALLOC_FREE(state->cli->smb2.session);
670 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
671 tevent_req_received(req);
672 return status;
675 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
676 if (pblob != NULL) {
677 *pblob = state->ret_blob;
679 if (pinbuf != NULL) {
680 *pinbuf = state->inbuf;
682 if (precv_iov != NULL) {
683 *precv_iov = recv_iov;
685 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
686 status = state->status;
687 tevent_req_received(req);
688 return status;
691 /****************************************************************************
692 Use in-memory credentials cache
693 ****************************************************************************/
695 static void use_in_memory_ccache(void) {
696 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
699 /****************************************************************************
700 Do a spnego/NTLMSSP encrypted session setup.
701 ****************************************************************************/
703 struct cli_session_setup_gensec_state {
704 struct tevent_context *ev;
705 struct cli_state *cli;
706 struct auth_generic_state *auth_generic;
707 bool is_anonymous;
708 DATA_BLOB blob_in;
709 const uint8_t *inbuf;
710 struct iovec *recv_iov;
711 DATA_BLOB blob_out;
712 bool local_ready;
713 bool remote_ready;
714 DATA_BLOB session_key;
717 static int cli_session_setup_gensec_state_destructor(
718 struct cli_session_setup_gensec_state *state)
720 TALLOC_FREE(state->auth_generic);
721 data_blob_clear_free(&state->session_key);
722 return 0;
725 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
726 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
727 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
728 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
729 static void cli_session_setup_gensec_ready(struct tevent_req *req);
731 static struct tevent_req *cli_session_setup_gensec_send(
732 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
733 struct cli_credentials *creds,
734 const char *target_service,
735 const char *target_hostname)
737 struct tevent_req *req;
738 struct cli_session_setup_gensec_state *state;
739 NTSTATUS status;
740 const DATA_BLOB *b = NULL;
742 req = tevent_req_create(mem_ctx, &state,
743 struct cli_session_setup_gensec_state);
744 if (req == NULL) {
745 return NULL;
747 state->ev = ev;
748 state->cli = cli;
750 talloc_set_destructor(
751 state, cli_session_setup_gensec_state_destructor);
753 status = auth_generic_client_prepare(state, &state->auth_generic);
754 if (tevent_req_nterror(req, status)) {
755 return tevent_req_post(req, ev);
758 status = auth_generic_set_creds(state->auth_generic, creds);
759 if (tevent_req_nterror(req, status)) {
760 return tevent_req_post(req, ev);
763 gensec_want_feature(state->auth_generic->gensec_security,
764 GENSEC_FEATURE_SESSION_KEY);
766 if (target_service != NULL) {
767 status = gensec_set_target_service(
768 state->auth_generic->gensec_security,
769 target_service);
770 if (tevent_req_nterror(req, status)) {
771 return tevent_req_post(req, ev);
775 if (target_hostname != NULL) {
776 status = gensec_set_target_hostname(
777 state->auth_generic->gensec_security,
778 target_hostname);
779 if (tevent_req_nterror(req, status)) {
780 return tevent_req_post(req, ev);
784 b = smbXcli_conn_server_gss_blob(cli->conn);
785 if (b != NULL) {
786 state->blob_in = *b;
789 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
791 status = auth_generic_client_start(state->auth_generic,
792 GENSEC_OID_SPNEGO);
793 if (tevent_req_nterror(req, status)) {
794 return tevent_req_post(req, ev);
797 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
798 state->cli->smb2.session = smbXcli_session_create(cli,
799 cli->conn);
800 if (tevent_req_nomem(state->cli->smb2.session, req)) {
801 return tevent_req_post(req, ev);
805 cli_session_setup_gensec_local_next(req);
806 if (!tevent_req_is_in_progress(req)) {
807 return tevent_req_post(req, ev);
810 return req;
813 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
815 struct cli_session_setup_gensec_state *state =
816 tevent_req_data(req,
817 struct cli_session_setup_gensec_state);
818 struct tevent_req *subreq = NULL;
820 if (state->local_ready) {
821 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
822 return;
825 subreq = gensec_update_send(state, state->ev,
826 state->auth_generic->gensec_security,
827 state->blob_in);
828 if (tevent_req_nomem(subreq, req)) {
829 return;
831 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
834 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
836 struct tevent_req *req =
837 tevent_req_callback_data(subreq,
838 struct tevent_req);
839 struct cli_session_setup_gensec_state *state =
840 tevent_req_data(req,
841 struct cli_session_setup_gensec_state);
842 NTSTATUS status;
844 status = gensec_update_recv(subreq, state, &state->blob_out);
845 TALLOC_FREE(subreq);
846 state->blob_in = data_blob_null;
847 if (!NT_STATUS_IS_OK(status) &&
848 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
850 tevent_req_nterror(req, status);
851 return;
854 if (NT_STATUS_IS_OK(status)) {
855 state->local_ready = true;
858 if (state->local_ready && state->remote_ready) {
859 cli_session_setup_gensec_ready(req);
860 return;
863 cli_session_setup_gensec_remote_next(req);
866 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
868 struct cli_session_setup_gensec_state *state =
869 tevent_req_data(req,
870 struct cli_session_setup_gensec_state);
871 struct tevent_req *subreq = NULL;
873 if (state->remote_ready) {
874 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
875 return;
878 subreq = cli_sesssetup_blob_send(state, state->ev,
879 state->cli, state->blob_out);
880 if (tevent_req_nomem(subreq, req)) {
881 return;
883 tevent_req_set_callback(subreq,
884 cli_session_setup_gensec_remote_done,
885 req);
888 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
890 struct tevent_req *req =
891 tevent_req_callback_data(subreq,
892 struct tevent_req);
893 struct cli_session_setup_gensec_state *state =
894 tevent_req_data(req,
895 struct cli_session_setup_gensec_state);
896 NTSTATUS status;
898 state->inbuf = NULL;
899 TALLOC_FREE(state->recv_iov);
901 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
902 &state->inbuf, &state->recv_iov);
903 TALLOC_FREE(subreq);
904 data_blob_free(&state->blob_out);
905 if (!NT_STATUS_IS_OK(status) &&
906 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
908 tevent_req_nterror(req, status);
909 return;
912 if (NT_STATUS_IS_OK(status)) {
913 struct smbXcli_session *session = NULL;
914 bool is_guest = false;
916 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
917 session = state->cli->smb2.session;
918 } else {
919 session = state->cli->smb1.session;
922 is_guest = smbXcli_session_is_guest(session);
923 if (is_guest) {
925 * We can't finish the gensec handshake, we don't
926 * have a negotiated session key.
928 * So just pretend we are completely done.
930 * Note that smbXcli_session_is_guest()
931 * always returns false if we require signing.
933 state->blob_in = data_blob_null;
934 state->local_ready = true;
937 state->remote_ready = true;
940 if (state->local_ready && state->remote_ready) {
941 cli_session_setup_gensec_ready(req);
942 return;
945 cli_session_setup_gensec_local_next(req);
948 static void cli_session_setup_gensec_ready(struct tevent_req *req)
950 struct cli_session_setup_gensec_state *state =
951 tevent_req_data(req,
952 struct cli_session_setup_gensec_state);
953 const char *server_domain = NULL;
954 NTSTATUS status;
956 if (state->blob_in.length != 0) {
957 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
958 return;
961 if (state->blob_out.length != 0) {
962 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
963 return;
967 * gensec_ntlmssp_server_domain() returns NULL
968 * if NTLMSSP is not used.
970 * We can remove this later
971 * and leave the server domain empty for SMB2 and above
972 * in future releases.
974 server_domain = gensec_ntlmssp_server_domain(
975 state->auth_generic->gensec_security);
977 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
978 TALLOC_FREE(state->cli->server_domain);
979 state->cli->server_domain = talloc_strdup(state->cli,
980 server_domain);
981 if (state->cli->server_domain == NULL) {
982 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
983 return;
987 if (state->is_anonymous) {
989 * Windows server does not set the
990 * SMB2_SESSION_FLAG_IS_NULL flag.
992 * This fix makes sure we do not try
993 * to verify a signature on the final
994 * session setup response.
996 tevent_req_done(req);
997 return;
1000 status = gensec_session_key(state->auth_generic->gensec_security,
1001 state, &state->session_key);
1002 if (tevent_req_nterror(req, status)) {
1003 return;
1006 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1007 struct smbXcli_session *session = state->cli->smb2.session;
1009 status = smb2cli_session_set_session_key(session,
1010 state->session_key,
1011 state->recv_iov);
1012 if (tevent_req_nterror(req, status)) {
1013 return;
1015 } else {
1016 struct smbXcli_session *session = state->cli->smb1.session;
1017 bool active;
1019 status = smb1cli_session_set_session_key(session,
1020 state->session_key);
1021 if (tevent_req_nterror(req, status)) {
1022 return;
1025 active = smb1cli_conn_activate_signing(state->cli->conn,
1026 state->session_key,
1027 data_blob_null);
1028 if (active) {
1029 bool ok;
1031 ok = smb1cli_conn_check_signing(state->cli->conn,
1032 state->inbuf, 1);
1033 if (!ok) {
1034 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1035 return;
1040 tevent_req_done(req);
1043 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1045 struct cli_session_setup_gensec_state *state =
1046 tevent_req_data(req,
1047 struct cli_session_setup_gensec_state);
1048 NTSTATUS status;
1050 if (tevent_req_is_nterror(req, &status)) {
1051 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1052 return status;
1054 return NT_STATUS_OK;
1057 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1058 const char *principal)
1060 char *account, *p;
1062 account = talloc_strdup(mem_ctx, principal);
1063 if (account == NULL) {
1064 return NULL;
1066 p = strchr_m(account, '@');
1067 if (p != NULL) {
1068 *p = '\0';
1070 return account;
1073 /****************************************************************************
1074 Do a spnego encrypted session setup.
1076 user_domain: The shortname of the domain the user/machine is a member of.
1077 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1078 ****************************************************************************/
1080 struct cli_session_setup_spnego_state {
1081 ADS_STATUS result;
1084 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1086 static struct tevent_req *cli_session_setup_spnego_send(
1087 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1088 struct cli_credentials *creds)
1090 struct tevent_req *req, *subreq;
1091 struct cli_session_setup_spnego_state *state;
1092 const char *user_principal = NULL;
1093 const char *user_account = NULL;
1094 const char *user_domain = NULL;
1095 const char *pass = NULL;
1096 const char *target_hostname = NULL;
1097 const DATA_BLOB *server_blob = NULL;
1098 enum credentials_use_kerberos krb5_state;
1099 bool try_kerberos = false;
1100 bool need_kinit = false;
1101 bool auth_requested = true;
1103 req = tevent_req_create(mem_ctx, &state,
1104 struct cli_session_setup_spnego_state);
1105 if (req == NULL) {
1106 return NULL;
1109 target_hostname = smbXcli_conn_remote_name(cli->conn);
1110 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1112 /* the server might not even do spnego */
1113 if (server_blob != NULL && server_blob->length != 0) {
1114 char *principal = NULL;
1115 char *OIDs[ASN1_MAX_OIDS];
1116 int i;
1118 /* The server sent us the first part of the SPNEGO exchange in the
1119 * negprot reply. It is WRONG to depend on the principal sent in the
1120 * negprot reply, but right now we do it. If we don't receive one,
1121 * we try to best guess, then fall back to NTLM. */
1122 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1123 &principal, NULL) ||
1124 OIDs[0] == NULL) {
1125 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1126 tevent_req_done(req);
1127 return tevent_req_post(req, ev);
1129 TALLOC_FREE(principal);
1131 /* make sure the server understands kerberos */
1132 for (i = 0; OIDs[i] != NULL; i++) {
1133 if (i == 0) {
1134 DEBUG(3,("got OID=%s\n", OIDs[i]));
1135 } else {
1136 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1139 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1140 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1141 cli->got_kerberos_mechanism = True;
1143 talloc_free(OIDs[i]);
1147 auth_requested = cli_credentials_authentication_requested(creds);
1148 if (auth_requested) {
1149 user_principal = cli_credentials_get_principal(creds, state);
1150 if (tevent_req_nomem(user_principal, req)) {
1151 return tevent_req_post(req, ev);
1154 user_account = cli_credentials_get_username(creds);
1155 user_domain = cli_credentials_get_domain(creds);
1156 pass = cli_credentials_get_password(creds);
1158 krb5_state = cli_credentials_get_kerberos_state(creds);
1160 if (krb5_state != CRED_DONT_USE_KERBEROS) {
1161 try_kerberos = true;
1164 if (target_hostname == NULL) {
1165 try_kerberos = false;
1166 } else if (is_ipaddress(target_hostname)) {
1167 try_kerberos = false;
1168 } else if (strequal(target_hostname, "localhost")) {
1169 try_kerberos = false;
1170 } else if (strequal(target_hostname, STAR_SMBSERVER)) {
1171 try_kerberos = false;
1172 } else if (!auth_requested) {
1173 try_kerberos = false;
1176 if (krb5_state == CRED_MUST_USE_KERBEROS && !try_kerberos) {
1177 DEBUG(0, ("Kerberos auth with '%s' (%s\\%s) to access "
1178 "'%s' not possible\n",
1179 user_principal, user_domain, user_account,
1180 target_hostname));
1181 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1182 return tevent_req_post(req, ev);
1185 if (pass == NULL || strlen(pass) == 0) {
1186 need_kinit = false;
1187 } else if (krb5_state == CRED_MUST_USE_KERBEROS) {
1188 need_kinit = try_kerberos;
1189 } else if (!cli->got_kerberos_mechanism) {
1191 * Most likely the server doesn't support
1192 * Kerberos, don't waste time doing a kinit
1194 need_kinit = false;
1195 } else {
1196 need_kinit = try_kerberos;
1199 if (need_kinit) {
1200 int ret;
1202 use_in_memory_ccache();
1203 ret = kerberos_kinit_password(user_principal, pass,
1204 0 /* no time correction for now */,
1205 NULL);
1207 if (ret != 0) {
1208 DEBUG(0, ("Kinit for %s to access %s failed: %s\n",
1209 user_principal, target_hostname,
1210 error_message(ret)));
1211 if (krb5_state == CRED_MUST_USE_KERBEROS) {
1212 state->result = ADS_ERROR_KRB5(ret);
1213 tevent_req_done(req);
1214 return tevent_req_post(req, ev);
1218 * Ignore the error and hope that NTLM will work
1220 ret = 0;
1224 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1225 "cifs", target_hostname);
1226 if (tevent_req_nomem(subreq, req)) {
1227 return tevent_req_post(req, ev);
1229 tevent_req_set_callback(
1230 subreq, cli_session_setup_spnego_done, req);
1231 return req;
1234 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1236 struct tevent_req *req = tevent_req_callback_data(
1237 subreq, struct tevent_req);
1238 NTSTATUS status;
1240 status = cli_session_setup_gensec_recv(subreq);
1241 TALLOC_FREE(subreq);
1242 if (tevent_req_nterror(req, status)) {
1243 return;
1246 tevent_req_done(req);
1249 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1251 struct cli_session_setup_spnego_state *state = tevent_req_data(
1252 req, struct cli_session_setup_spnego_state);
1253 NTSTATUS status;
1255 if (tevent_req_is_nterror(req, &status)) {
1256 state->result = ADS_ERROR_NT(status);
1259 return state->result;
1262 struct cli_session_setup_creds_state {
1263 struct cli_state *cli;
1264 DATA_BLOB apassword_blob;
1265 DATA_BLOB upassword_blob;
1266 DATA_BLOB lm_session_key;
1267 DATA_BLOB session_key;
1268 char *out_native_os;
1269 char *out_native_lm;
1270 char *out_primary_domain;
1273 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1274 enum tevent_req_state req_state)
1276 struct cli_session_setup_creds_state *state = tevent_req_data(
1277 req, struct cli_session_setup_creds_state);
1279 if (req_state != TEVENT_REQ_RECEIVED) {
1280 return;
1284 * We only call data_blob_clear() as
1285 * some of the blobs point to the same memory.
1287 * We let the talloc hierachy free the memory.
1289 data_blob_clear(&state->apassword_blob);
1290 data_blob_clear(&state->upassword_blob);
1291 data_blob_clear(&state->lm_session_key);
1292 data_blob_clear(&state->session_key);
1293 ZERO_STRUCTP(state);
1296 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1297 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1298 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1300 /****************************************************************************
1301 Send a session setup. The username and workgroup is in UNIX character
1302 format and must be converted to DOS codepage format before sending. If the
1303 password is in plaintext, the same should be done.
1304 ****************************************************************************/
1306 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1307 struct tevent_context *ev,
1308 struct cli_state *cli,
1309 struct cli_credentials *creds)
1311 struct tevent_req *req, *subreq;
1312 struct cli_session_setup_creds_state *state;
1313 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1314 bool use_spnego = false;
1315 int flags = 0;
1316 enum credentials_use_kerberos krb5_state;
1317 uint32_t gensec_features;
1318 const char *username = "";
1319 const char *domain = "";
1320 DATA_BLOB target_info = data_blob_null;
1321 DATA_BLOB challenge = data_blob_null;
1322 uint16_t in_buf_size = 0;
1323 uint16_t in_mpx_max = 0;
1324 uint16_t in_vc_num = 0;
1325 uint32_t in_sess_key = 0;
1326 const char *in_native_os = NULL;
1327 const char *in_native_lm = NULL;
1328 NTSTATUS status;
1330 req = tevent_req_create(mem_ctx, &state,
1331 struct cli_session_setup_creds_state);
1332 if (req == NULL) {
1333 return NULL;
1335 state->cli = cli;
1337 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1339 krb5_state = cli_credentials_get_kerberos_state(creds);
1340 gensec_features = cli_credentials_get_gensec_features(creds);
1342 switch (krb5_state) {
1343 case CRED_MUST_USE_KERBEROS:
1344 cli->use_kerberos = true;
1345 cli->fallback_after_kerberos = false;
1346 break;
1347 case CRED_AUTO_USE_KERBEROS:
1348 cli->use_kerberos = true;
1349 cli->fallback_after_kerberos = true;
1350 break;
1351 case CRED_DONT_USE_KERBEROS:
1352 cli->use_kerberos = false;
1353 cli->fallback_after_kerberos = false;
1354 break;
1357 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
1358 cli->use_ccache = true;
1359 } else {
1360 cli->use_ccache = false;
1364 * Now work out what sort of session setup we are going to
1365 * do. I have split this into separate functions to make the flow a bit
1366 * easier to understand (tridge).
1368 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1369 use_spnego = false;
1370 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1371 use_spnego = true;
1372 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1374 * if the server supports extended security then use SPNEGO
1375 * even for anonymous connections.
1377 use_spnego = true;
1378 } else {
1379 use_spnego = false;
1382 if (use_spnego) {
1383 subreq = cli_session_setup_spnego_send(
1384 state, ev, cli, creds);
1385 if (tevent_req_nomem(subreq, req)) {
1386 return tevent_req_post(req, ev);
1388 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1389 req);
1390 return req;
1393 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1395 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1396 * this step against older servers.
1398 tevent_req_done(req);
1399 return tevent_req_post(req, ev);
1402 if (cli_credentials_is_anonymous(creds)) {
1404 * Do an anonymous session setup
1406 goto non_spnego_creds_done;
1409 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1411 * Do an anonymous session setup,
1412 * the password is passed via the tree connect.
1414 goto non_spnego_creds_done;
1417 cli_credentials_get_ntlm_username_domain(creds, state,
1418 &username,
1419 &domain);
1420 if (tevent_req_nomem(username, req)) {
1421 return tevent_req_post(req, ev);
1423 if (tevent_req_nomem(domain, req)) {
1424 return tevent_req_post(req, ev);
1427 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1428 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1429 uint8_t *bytes = NULL;
1430 size_t bytes_len = 0;
1431 const char *pw = cli_credentials_get_password(creds);
1432 size_t pw_len = 0;
1434 if (pw == NULL) {
1435 pw = "";
1437 pw_len = strlen(pw) + 1;
1439 if (!lp_client_plaintext_auth()) {
1440 DEBUG(1, ("Server requested PLAINTEXT password but "
1441 "'client plaintext auth = no'\n"));
1442 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1443 return tevent_req_post(req, ev);
1446 bytes = talloc_array(state, uint8_t, 0);
1447 bytes = trans2_bytes_push_str(bytes, use_unicode,
1448 pw, pw_len, &bytes_len);
1449 if (tevent_req_nomem(bytes, req)) {
1450 return tevent_req_post(req, ev);
1453 if (use_unicode) {
1455 * CAP_UNICODE, can only be negotiated by NT1.
1457 state->upassword_blob = data_blob_const(bytes,
1458 bytes_len);
1459 } else {
1460 state->apassword_blob = data_blob_const(bytes,
1461 bytes_len);
1464 goto non_spnego_creds_done;
1467 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1469 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1470 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1472 * Don't send an NTLMv2 response without NTLMSSP if we
1473 * want to use spnego support.
1475 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1476 " but 'client use spnego = yes'"
1477 " and 'client ntlmv2 auth = yes' is set\n"));
1478 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1479 return tevent_req_post(req, ev);
1482 if (lp_client_ntlmv2_auth()) {
1483 flags |= CLI_CRED_NTLMv2_AUTH;
1486 * note that the 'domain' here is a best
1487 * guess - we don't know the server's domain
1488 * at this point. Windows clients also don't
1489 * use hostname...
1491 target_info = NTLMv2_generate_names_blob(state,
1492 NULL,
1493 domain);
1494 if (tevent_req_nomem(target_info.data, req)) {
1495 return tevent_req_post(req, ev);
1497 } else {
1498 flags |= CLI_CRED_NTLM_AUTH;
1499 if (lp_client_lanman_auth()) {
1500 flags |= CLI_CRED_LANMAN_AUTH;
1503 } else {
1504 if (!lp_client_lanman_auth()) {
1505 DEBUG(1, ("Server requested LM password but "
1506 "'client lanman auth = no' "
1507 "or 'client ntlmv2 auth = yes' is set\n"));
1508 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1509 return tevent_req_post(req, ev);
1512 flags |= CLI_CRED_LANMAN_AUTH;
1515 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1516 challenge, NULL,
1517 target_info,
1518 &state->apassword_blob,
1519 &state->upassword_blob,
1520 &state->lm_session_key,
1521 &state->session_key);
1522 if (tevent_req_nterror(req, status)) {
1523 return tevent_req_post(req, ev);
1526 non_spnego_creds_done:
1528 in_buf_size = CLI_BUFFER_SIZE;
1529 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1530 in_vc_num = cli_state_get_vc_num(cli);
1531 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1532 in_native_os = "Unix";
1533 in_native_lm = "Samba";
1535 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1536 uint32_t in_capabilities = 0;
1538 in_capabilities = cli_session_setup_capabilities(cli, 0);
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;
1546 subreq = smb1cli_session_setup_nt1_send(state, ev,
1547 cli->conn,
1548 cli->timeout,
1549 cli->smb1.pid,
1550 cli->smb1.session,
1551 in_buf_size,
1552 in_mpx_max,
1553 in_vc_num,
1554 in_sess_key,
1555 username,
1556 domain,
1557 state->apassword_blob,
1558 state->upassword_blob,
1559 in_capabilities,
1560 in_native_os,
1561 in_native_lm);
1562 if (tevent_req_nomem(subreq, req)) {
1563 return tevent_req_post(req, ev);
1565 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1566 req);
1567 return req;
1571 * For now we keep the same values as before,
1572 * we may remove these in a separate commit later.
1574 in_mpx_max = 2;
1575 in_vc_num = 1;
1577 subreq = smb1cli_session_setup_lm21_send(state, ev,
1578 cli->conn,
1579 cli->timeout,
1580 cli->smb1.pid,
1581 cli->smb1.session,
1582 in_buf_size,
1583 in_mpx_max,
1584 in_vc_num,
1585 in_sess_key,
1586 username,
1587 domain,
1588 state->apassword_blob,
1589 in_native_os,
1590 in_native_lm);
1591 if (tevent_req_nomem(subreq, req)) {
1592 return tevent_req_post(req, ev);
1594 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1595 req);
1596 return req;
1599 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1601 struct tevent_req *req = tevent_req_callback_data(
1602 subreq, struct tevent_req);
1603 ADS_STATUS status;
1605 status = cli_session_setup_spnego_recv(subreq);
1606 TALLOC_FREE(subreq);
1607 if (!ADS_ERR_OK(status)) {
1608 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1609 tevent_req_nterror(req, ads_ntstatus(status));
1610 return;
1612 tevent_req_done(req);
1615 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1617 struct tevent_req *req = tevent_req_callback_data(
1618 subreq, struct tevent_req);
1619 struct cli_session_setup_creds_state *state = tevent_req_data(
1620 req, struct cli_session_setup_creds_state);
1621 struct cli_state *cli = state->cli;
1622 NTSTATUS status;
1623 struct iovec *recv_iov = NULL;
1624 const uint8_t *inbuf = NULL;
1625 bool ok;
1627 status = smb1cli_session_setup_nt1_recv(subreq, state,
1628 &recv_iov,
1629 &inbuf,
1630 &state->out_native_os,
1631 &state->out_native_lm,
1632 &state->out_primary_domain);
1633 TALLOC_FREE(subreq);
1634 if (!NT_STATUS_IS_OK(status)) {
1635 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1636 tevent_req_nterror(req, status);
1637 return;
1640 if (cli->server_os == NULL) {
1641 cli->server_os = talloc_move(cli, &state->out_native_os);
1643 if (cli->server_type == NULL) {
1644 cli->server_type = talloc_move(cli, &state->out_native_lm);
1646 if (cli->server_domain == NULL) {
1647 cli->server_domain = talloc_move(cli, &state->out_primary_domain);
1650 ok = smb1cli_conn_activate_signing(cli->conn,
1651 state->session_key,
1652 state->upassword_blob);
1653 if (ok) {
1654 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1655 if (!ok) {
1656 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1657 return;
1661 if (state->session_key.data) {
1662 struct smbXcli_session *session = cli->smb1.session;
1664 status = smb1cli_session_set_session_key(session,
1665 state->session_key);
1666 if (tevent_req_nterror(req, status)) {
1667 return;
1671 tevent_req_done(req);
1674 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1676 struct tevent_req *req = tevent_req_callback_data(
1677 subreq, struct tevent_req);
1678 struct cli_session_setup_creds_state *state = tevent_req_data(
1679 req, struct cli_session_setup_creds_state);
1680 struct cli_state *cli = state->cli;
1681 NTSTATUS status;
1683 status = smb1cli_session_setup_lm21_recv(subreq, state,
1684 &state->out_native_os,
1685 &state->out_native_lm);
1686 TALLOC_FREE(subreq);
1687 if (!NT_STATUS_IS_OK(status)) {
1688 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1689 tevent_req_nterror(req, status);
1690 return;
1693 if (cli->server_os == NULL) {
1694 cli->server_os = talloc_move(cli, &state->out_native_os);
1696 if (cli->server_type == NULL) {
1697 cli->server_type = talloc_move(cli, &state->out_native_lm);
1700 tevent_req_done(req);
1703 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1705 return tevent_req_simple_recv_ntstatus(req);
1708 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1709 struct cli_credentials *creds)
1711 struct tevent_context *ev;
1712 struct tevent_req *req;
1713 NTSTATUS status = NT_STATUS_NO_MEMORY;
1715 if (smbXcli_conn_has_async_calls(cli->conn)) {
1716 return NT_STATUS_INVALID_PARAMETER;
1718 ev = samba_tevent_context_init(talloc_tos());
1719 if (ev == NULL) {
1720 goto fail;
1722 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1723 if (req == NULL) {
1724 goto fail;
1726 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1727 goto fail;
1729 status = cli_session_setup_creds_recv(req);
1730 fail:
1731 TALLOC_FREE(ev);
1732 return status;
1735 NTSTATUS cli_session_setup(struct cli_state *cli,
1736 const char *user,
1737 const char *pass,
1738 const char *workgroup)
1740 NTSTATUS status = NT_STATUS_NO_MEMORY;
1741 const char *dest_realm = NULL;
1742 struct cli_credentials *creds = NULL;
1745 * dest_realm is only valid in the winbindd use case,
1746 * where we also have the account in that realm.
1748 dest_realm = cli_state_remote_realm(cli);
1750 creds = cli_session_creds_init(cli,
1751 user,
1752 workgroup,
1753 dest_realm,
1754 pass,
1755 cli->use_kerberos,
1756 cli->fallback_after_kerberos,
1757 cli->use_ccache,
1758 cli->pw_nt_hash);
1759 if (creds == NULL) {
1760 return NT_STATUS_NO_MEMORY;
1763 status = cli_session_setup_creds(cli, creds);
1764 TALLOC_FREE(creds);
1765 if (!NT_STATUS_IS_OK(status)) {
1766 return status;
1769 return NT_STATUS_OK;
1772 /****************************************************************************
1773 Send a uloggoff.
1774 *****************************************************************************/
1776 struct cli_ulogoff_state {
1777 struct cli_state *cli;
1778 uint16_t vwv[3];
1781 static void cli_ulogoff_done(struct tevent_req *subreq);
1783 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1784 struct tevent_context *ev,
1785 struct cli_state *cli)
1787 struct tevent_req *req, *subreq;
1788 struct cli_ulogoff_state *state;
1790 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1791 if (req == NULL) {
1792 return NULL;
1794 state->cli = cli;
1796 SCVAL(state->vwv+0, 0, 0xFF);
1797 SCVAL(state->vwv+1, 0, 0);
1798 SSVAL(state->vwv+2, 0, 0);
1800 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1801 0, NULL);
1802 if (tevent_req_nomem(subreq, req)) {
1803 return tevent_req_post(req, ev);
1805 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1806 return req;
1809 static void cli_ulogoff_done(struct tevent_req *subreq)
1811 struct tevent_req *req = tevent_req_callback_data(
1812 subreq, struct tevent_req);
1813 struct cli_ulogoff_state *state = tevent_req_data(
1814 req, struct cli_ulogoff_state);
1815 NTSTATUS status;
1817 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1818 if (!NT_STATUS_IS_OK(status)) {
1819 tevent_req_nterror(req, status);
1820 return;
1822 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1823 tevent_req_done(req);
1826 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1828 return tevent_req_simple_recv_ntstatus(req);
1831 NTSTATUS cli_ulogoff(struct cli_state *cli)
1833 struct tevent_context *ev;
1834 struct tevent_req *req;
1835 NTSTATUS status = NT_STATUS_NO_MEMORY;
1837 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1838 status = smb2cli_logoff(cli->conn,
1839 cli->timeout,
1840 cli->smb2.session);
1841 if (!NT_STATUS_IS_OK(status)) {
1842 return status;
1844 smb2cli_session_set_id_and_flags(cli->smb2.session,
1845 UINT64_MAX, 0);
1846 return NT_STATUS_OK;
1849 if (smbXcli_conn_has_async_calls(cli->conn)) {
1850 return NT_STATUS_INVALID_PARAMETER;
1852 ev = samba_tevent_context_init(talloc_tos());
1853 if (ev == NULL) {
1854 goto fail;
1856 req = cli_ulogoff_send(ev, ev, cli);
1857 if (req == NULL) {
1858 goto fail;
1860 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1861 goto fail;
1863 status = cli_ulogoff_recv(req);
1864 fail:
1865 TALLOC_FREE(ev);
1866 return status;
1869 /****************************************************************************
1870 Send a tconX.
1871 ****************************************************************************/
1873 struct cli_tcon_andx_state {
1874 struct cli_state *cli;
1875 uint16_t vwv[4];
1876 struct iovec bytes;
1879 static void cli_tcon_andx_done(struct tevent_req *subreq);
1881 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1882 struct tevent_context *ev,
1883 struct cli_state *cli,
1884 const char *share, const char *dev,
1885 const char *pass, int passlen,
1886 struct tevent_req **psmbreq)
1888 struct tevent_req *req, *subreq;
1889 struct cli_tcon_andx_state *state;
1890 uint8_t p24[24];
1891 uint16_t *vwv;
1892 char *tmp = NULL;
1893 uint8_t *bytes;
1894 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1895 uint16_t tcon_flags = 0;
1897 *psmbreq = NULL;
1899 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1900 if (req == NULL) {
1901 return NULL;
1903 state->cli = cli;
1904 vwv = state->vwv;
1906 cli->share = talloc_strdup(cli, share);
1907 if (!cli->share) {
1908 return NULL;
1911 /* in user level security don't send a password now */
1912 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1913 passlen = 1;
1914 pass = "";
1915 } else if (pass == NULL) {
1916 DEBUG(1, ("Server not using user level security and no "
1917 "password supplied.\n"));
1918 goto access_denied;
1921 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1922 *pass && passlen != 24) {
1923 if (!lp_client_lanman_auth()) {
1924 DEBUG(1, ("Server requested LANMAN password "
1925 "(share-level security) but "
1926 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1927 goto access_denied;
1931 * Non-encrypted passwords - convert to DOS codepage before
1932 * encryption.
1934 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1935 passlen = 24;
1936 pass = (const char *)p24;
1937 } else {
1938 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1939 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1940 == 0) {
1941 uint8_t *tmp_pass;
1943 if (!lp_client_plaintext_auth() && (*pass)) {
1944 DEBUG(1, ("Server requested PLAINTEXT "
1945 "password but "
1946 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
1947 goto access_denied;
1951 * Non-encrypted passwords - convert to DOS codepage
1952 * before using.
1954 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
1955 if (tevent_req_nomem(tmp_pass, req)) {
1956 return tevent_req_post(req, ev);
1958 tmp_pass = trans2_bytes_push_str(tmp_pass,
1959 false, /* always DOS */
1960 pass,
1961 passlen,
1962 NULL);
1963 if (tevent_req_nomem(tmp_pass, req)) {
1964 return tevent_req_post(req, ev);
1966 pass = (const char *)tmp_pass;
1967 passlen = talloc_get_size(tmp_pass);
1971 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
1972 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
1974 SCVAL(vwv+0, 0, 0xFF);
1975 SCVAL(vwv+0, 1, 0);
1976 SSVAL(vwv+1, 0, 0);
1977 SSVAL(vwv+2, 0, tcon_flags);
1978 SSVAL(vwv+3, 0, passlen);
1980 if (passlen && pass) {
1981 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
1982 } else {
1983 bytes = talloc_array(state, uint8_t, 0);
1987 * Add the sharename
1989 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1990 smbXcli_conn_remote_name(cli->conn), share);
1991 if (tmp == NULL) {
1992 TALLOC_FREE(req);
1993 return NULL;
1995 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
1996 NULL);
1997 TALLOC_FREE(tmp);
2000 * Add the devicetype
2002 tmp = talloc_strdup_upper(talloc_tos(), dev);
2003 if (tmp == NULL) {
2004 TALLOC_FREE(req);
2005 return NULL;
2007 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2008 TALLOC_FREE(tmp);
2010 if (bytes == NULL) {
2011 TALLOC_FREE(req);
2012 return NULL;
2015 state->bytes.iov_base = (void *)bytes;
2016 state->bytes.iov_len = talloc_get_size(bytes);
2018 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2019 1, &state->bytes);
2020 if (subreq == NULL) {
2021 TALLOC_FREE(req);
2022 return NULL;
2024 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2025 *psmbreq = subreq;
2026 return req;
2028 access_denied:
2029 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2030 return tevent_req_post(req, ev);
2033 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2034 struct tevent_context *ev,
2035 struct cli_state *cli,
2036 const char *share, const char *dev,
2037 const char *pass, int passlen)
2039 struct tevent_req *req, *subreq;
2040 NTSTATUS status;
2042 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2043 &subreq);
2044 if (req == NULL) {
2045 return NULL;
2047 if (subreq == NULL) {
2048 return req;
2050 status = smb1cli_req_chain_submit(&subreq, 1);
2051 if (!NT_STATUS_IS_OK(status)) {
2052 tevent_req_nterror(req, status);
2053 return tevent_req_post(req, ev);
2055 return req;
2058 static void cli_tcon_andx_done(struct tevent_req *subreq)
2060 struct tevent_req *req = tevent_req_callback_data(
2061 subreq, struct tevent_req);
2062 struct cli_tcon_andx_state *state = tevent_req_data(
2063 req, struct cli_tcon_andx_state);
2064 struct cli_state *cli = state->cli;
2065 uint8_t *in;
2066 uint8_t *inhdr;
2067 uint8_t wct;
2068 uint16_t *vwv;
2069 uint32_t num_bytes;
2070 uint8_t *bytes;
2071 NTSTATUS status;
2072 uint16_t optional_support = 0;
2074 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2075 &num_bytes, &bytes);
2076 TALLOC_FREE(subreq);
2077 if (!NT_STATUS_IS_OK(status)) {
2078 tevent_req_nterror(req, status);
2079 return;
2082 inhdr = in + NBT_HDR_SIZE;
2084 if (num_bytes) {
2085 if (clistr_pull_talloc(cli,
2086 (const char *)inhdr,
2087 SVAL(inhdr, HDR_FLG2),
2088 &cli->dev,
2089 bytes,
2090 num_bytes,
2091 STR_TERMINATE|STR_ASCII) == -1) {
2092 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2093 return;
2095 } else {
2096 cli->dev = talloc_strdup(cli, "");
2097 if (cli->dev == NULL) {
2098 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2099 return;
2103 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2104 /* almost certainly win95 - enable bug fixes */
2105 cli->win95 = True;
2109 * Make sure that we have the optional support 16-bit field. WCT > 2.
2110 * Avoids issues when connecting to Win9x boxes sharing files
2113 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2114 optional_support = SVAL(vwv+2, 0);
2117 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2118 smb1cli_session_protect_session_key(cli->smb1.session);
2121 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2122 SVAL(inhdr, HDR_TID),
2123 optional_support,
2124 0, /* maximal_access */
2125 0, /* guest_maximal_access */
2126 NULL, /* service */
2127 NULL); /* fs_type */
2129 tevent_req_done(req);
2132 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2134 return tevent_req_simple_recv_ntstatus(req);
2137 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2138 const char *dev, const char *pass, int passlen)
2140 TALLOC_CTX *frame = talloc_stackframe();
2141 struct tevent_context *ev;
2142 struct tevent_req *req;
2143 NTSTATUS status = NT_STATUS_NO_MEMORY;
2145 if (smbXcli_conn_has_async_calls(cli->conn)) {
2147 * Can't use sync call while an async call is in flight
2149 status = NT_STATUS_INVALID_PARAMETER;
2150 goto fail;
2153 ev = samba_tevent_context_init(frame);
2154 if (ev == NULL) {
2155 goto fail;
2158 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2159 if (req == NULL) {
2160 goto fail;
2163 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2164 goto fail;
2167 status = cli_tcon_andx_recv(req);
2168 fail:
2169 TALLOC_FREE(frame);
2170 return status;
2173 struct cli_tree_connect_state {
2174 struct cli_state *cli;
2177 static struct tevent_req *cli_raw_tcon_send(
2178 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2179 const char *service, const char *pass, const char *dev);
2180 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2181 uint16_t *max_xmit, uint16_t *tid);
2183 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2184 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2185 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2187 static struct tevent_req *cli_tree_connect_send(
2188 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2189 const char *share, const char *dev, const char *pass, int passlen)
2191 struct tevent_req *req, *subreq;
2192 struct cli_tree_connect_state *state;
2194 req = tevent_req_create(mem_ctx, &state,
2195 struct cli_tree_connect_state);
2196 if (req == NULL) {
2197 return NULL;
2199 state->cli = cli;
2201 cli->share = talloc_strdup(cli, share);
2202 if (tevent_req_nomem(cli->share, req)) {
2203 return tevent_req_post(req, ev);
2206 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2207 char *unc;
2209 cli->smb2.tcon = smbXcli_tcon_create(cli);
2210 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2211 return tevent_req_post(req, ev);
2214 unc = talloc_asprintf(state, "\\\\%s\\%s",
2215 smbXcli_conn_remote_name(cli->conn),
2216 share);
2217 if (tevent_req_nomem(unc, req)) {
2218 return tevent_req_post(req, ev);
2221 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2222 cli->smb2.session, cli->smb2.tcon,
2223 0, /* flags */
2224 unc);
2225 if (tevent_req_nomem(subreq, req)) {
2226 return tevent_req_post(req, ev);
2228 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2229 req);
2230 return req;
2233 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2234 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2235 pass, passlen);
2236 if (tevent_req_nomem(subreq, req)) {
2237 return tevent_req_post(req, ev);
2239 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2240 req);
2241 return req;
2244 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2245 if (tevent_req_nomem(subreq, req)) {
2246 return tevent_req_post(req, ev);
2248 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2250 return req;
2253 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2255 tevent_req_simple_finish_ntstatus(
2256 subreq, smb2cli_tcon_recv(subreq));
2259 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2261 tevent_req_simple_finish_ntstatus(
2262 subreq, cli_tcon_andx_recv(subreq));
2265 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2267 struct tevent_req *req = tevent_req_callback_data(
2268 subreq, struct tevent_req);
2269 struct cli_tree_connect_state *state = tevent_req_data(
2270 req, struct cli_tree_connect_state);
2271 NTSTATUS status;
2272 uint16_t max_xmit = 0;
2273 uint16_t tid = 0;
2275 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2276 if (tevent_req_nterror(req, status)) {
2277 return;
2280 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2281 tid,
2282 0, /* optional_support */
2283 0, /* maximal_access */
2284 0, /* guest_maximal_access */
2285 NULL, /* service */
2286 NULL); /* fs_type */
2288 tevent_req_done(req);
2291 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2293 return tevent_req_simple_recv_ntstatus(req);
2296 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2297 const char *dev, const char *pass, int passlen)
2299 struct tevent_context *ev;
2300 struct tevent_req *req;
2301 NTSTATUS status = NT_STATUS_NO_MEMORY;
2303 if (smbXcli_conn_has_async_calls(cli->conn)) {
2304 return NT_STATUS_INVALID_PARAMETER;
2306 ev = samba_tevent_context_init(talloc_tos());
2307 if (ev == NULL) {
2308 goto fail;
2310 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2311 if (req == NULL) {
2312 goto fail;
2314 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2315 goto fail;
2317 status = cli_tree_connect_recv(req);
2318 fail:
2319 TALLOC_FREE(ev);
2320 return status;
2323 /****************************************************************************
2324 Send a tree disconnect.
2325 ****************************************************************************/
2327 struct cli_tdis_state {
2328 struct cli_state *cli;
2331 static void cli_tdis_done(struct tevent_req *subreq);
2333 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2334 struct tevent_context *ev,
2335 struct cli_state *cli)
2337 struct tevent_req *req, *subreq;
2338 struct cli_tdis_state *state;
2340 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2341 if (req == NULL) {
2342 return NULL;
2344 state->cli = cli;
2346 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2347 if (tevent_req_nomem(subreq, req)) {
2348 return tevent_req_post(req, ev);
2350 tevent_req_set_callback(subreq, cli_tdis_done, req);
2351 return req;
2354 static void cli_tdis_done(struct tevent_req *subreq)
2356 struct tevent_req *req = tevent_req_callback_data(
2357 subreq, struct tevent_req);
2358 struct cli_tdis_state *state = tevent_req_data(
2359 req, struct cli_tdis_state);
2360 NTSTATUS status;
2362 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2363 TALLOC_FREE(subreq);
2364 if (!NT_STATUS_IS_OK(status)) {
2365 tevent_req_nterror(req, status);
2366 return;
2368 cli_state_set_tid(state->cli, UINT16_MAX);
2369 tevent_req_done(req);
2372 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2374 return tevent_req_simple_recv_ntstatus(req);
2377 NTSTATUS cli_tdis(struct cli_state *cli)
2379 struct tevent_context *ev;
2380 struct tevent_req *req;
2381 NTSTATUS status = NT_STATUS_NO_MEMORY;
2383 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2384 return smb2cli_tdis(cli->conn,
2385 cli->timeout,
2386 cli->smb2.session,
2387 cli->smb2.tcon);
2390 if (smbXcli_conn_has_async_calls(cli->conn)) {
2391 return NT_STATUS_INVALID_PARAMETER;
2393 ev = samba_tevent_context_init(talloc_tos());
2394 if (ev == NULL) {
2395 goto fail;
2397 req = cli_tdis_send(ev, ev, cli);
2398 if (req == NULL) {
2399 goto fail;
2401 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2402 goto fail;
2404 status = cli_tdis_recv(req);
2405 fail:
2406 TALLOC_FREE(ev);
2407 return status;
2410 struct cli_connect_sock_state {
2411 const char **called_names;
2412 const char **calling_names;
2413 int *called_types;
2414 int fd;
2415 uint16_t port;
2418 static void cli_connect_sock_done(struct tevent_req *subreq);
2421 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2422 * nonzero address.
2425 static struct tevent_req *cli_connect_sock_send(
2426 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2427 const char *host, int name_type, const struct sockaddr_storage *pss,
2428 const char *myname, uint16_t port)
2430 struct tevent_req *req, *subreq;
2431 struct cli_connect_sock_state *state;
2432 const char *prog;
2433 struct sockaddr_storage *addrs;
2434 unsigned i, num_addrs;
2435 NTSTATUS status;
2437 req = tevent_req_create(mem_ctx, &state,
2438 struct cli_connect_sock_state);
2439 if (req == NULL) {
2440 return NULL;
2443 prog = getenv("LIBSMB_PROG");
2444 if (prog != NULL) {
2445 state->fd = sock_exec(prog);
2446 if (state->fd == -1) {
2447 status = map_nt_error_from_unix(errno);
2448 tevent_req_nterror(req, status);
2449 } else {
2450 state->port = 0;
2451 tevent_req_done(req);
2453 return tevent_req_post(req, ev);
2456 if ((pss == NULL) || is_zero_addr(pss)) {
2459 * Here we cheat. resolve_name_list is not async at all. So
2460 * this call will only be really async if the name lookup has
2461 * been done externally.
2464 status = resolve_name_list(state, host, name_type,
2465 &addrs, &num_addrs);
2466 if (!NT_STATUS_IS_OK(status)) {
2467 tevent_req_nterror(req, status);
2468 return tevent_req_post(req, ev);
2470 } else {
2471 addrs = talloc_array(state, struct sockaddr_storage, 1);
2472 if (tevent_req_nomem(addrs, req)) {
2473 return tevent_req_post(req, ev);
2475 addrs[0] = *pss;
2476 num_addrs = 1;
2479 state->called_names = talloc_array(state, const char *, num_addrs);
2480 if (tevent_req_nomem(state->called_names, req)) {
2481 return tevent_req_post(req, ev);
2483 state->called_types = talloc_array(state, int, num_addrs);
2484 if (tevent_req_nomem(state->called_types, req)) {
2485 return tevent_req_post(req, ev);
2487 state->calling_names = talloc_array(state, const char *, num_addrs);
2488 if (tevent_req_nomem(state->calling_names, req)) {
2489 return tevent_req_post(req, ev);
2491 for (i=0; i<num_addrs; i++) {
2492 state->called_names[i] = host;
2493 state->called_types[i] = name_type;
2494 state->calling_names[i] = myname;
2497 subreq = smbsock_any_connect_send(
2498 state, ev, addrs, state->called_names, state->called_types,
2499 state->calling_names, NULL, num_addrs, port);
2500 if (tevent_req_nomem(subreq, req)) {
2501 return tevent_req_post(req, ev);
2503 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2504 return req;
2507 static void cli_connect_sock_done(struct tevent_req *subreq)
2509 struct tevent_req *req = tevent_req_callback_data(
2510 subreq, struct tevent_req);
2511 struct cli_connect_sock_state *state = tevent_req_data(
2512 req, struct cli_connect_sock_state);
2513 NTSTATUS status;
2515 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2516 &state->port);
2517 TALLOC_FREE(subreq);
2518 if (tevent_req_nterror(req, status)) {
2519 return;
2521 set_socket_options(state->fd, lp_socket_options());
2522 tevent_req_done(req);
2525 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2526 int *pfd, uint16_t *pport)
2528 struct cli_connect_sock_state *state = tevent_req_data(
2529 req, struct cli_connect_sock_state);
2530 NTSTATUS status;
2532 if (tevent_req_is_nterror(req, &status)) {
2533 return status;
2535 *pfd = state->fd;
2536 *pport = state->port;
2537 return NT_STATUS_OK;
2540 struct cli_connect_nb_state {
2541 const char *desthost;
2542 int signing_state;
2543 int flags;
2544 struct cli_state *cli;
2547 static void cli_connect_nb_done(struct tevent_req *subreq);
2549 static struct tevent_req *cli_connect_nb_send(
2550 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2551 const char *host, const struct sockaddr_storage *dest_ss,
2552 uint16_t port, int name_type, const char *myname,
2553 int signing_state, int flags)
2555 struct tevent_req *req, *subreq;
2556 struct cli_connect_nb_state *state;
2558 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2559 if (req == NULL) {
2560 return NULL;
2562 state->signing_state = signing_state;
2563 state->flags = flags;
2565 if (host != NULL) {
2566 char *p = strchr(host, '#');
2568 if (p != NULL) {
2569 name_type = strtol(p+1, NULL, 16);
2570 host = talloc_strndup(state, host, p - host);
2571 if (tevent_req_nomem(host, req)) {
2572 return tevent_req_post(req, ev);
2576 state->desthost = host;
2577 } else if (dest_ss != NULL) {
2578 state->desthost = print_canonical_sockaddr(state, dest_ss);
2579 if (tevent_req_nomem(state->desthost, req)) {
2580 return tevent_req_post(req, ev);
2582 } else {
2583 /* No host or dest_ss given. Error out. */
2584 tevent_req_error(req, EINVAL);
2585 return tevent_req_post(req, ev);
2588 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2589 myname, port);
2590 if (tevent_req_nomem(subreq, req)) {
2591 return tevent_req_post(req, ev);
2593 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2594 return req;
2597 static void cli_connect_nb_done(struct tevent_req *subreq)
2599 struct tevent_req *req = tevent_req_callback_data(
2600 subreq, struct tevent_req);
2601 struct cli_connect_nb_state *state = tevent_req_data(
2602 req, struct cli_connect_nb_state);
2603 NTSTATUS status;
2604 int fd = 0;
2605 uint16_t port;
2607 status = cli_connect_sock_recv(subreq, &fd, &port);
2608 TALLOC_FREE(subreq);
2609 if (tevent_req_nterror(req, status)) {
2610 return;
2613 state->cli = cli_state_create(state, fd, state->desthost, NULL,
2614 state->signing_state, state->flags);
2615 if (tevent_req_nomem(state->cli, req)) {
2616 close(fd);
2617 return;
2619 tevent_req_done(req);
2622 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2623 struct cli_state **pcli)
2625 struct cli_connect_nb_state *state = tevent_req_data(
2626 req, struct cli_connect_nb_state);
2627 NTSTATUS status;
2629 if (tevent_req_is_nterror(req, &status)) {
2630 return status;
2632 *pcli = talloc_move(NULL, &state->cli);
2633 return NT_STATUS_OK;
2636 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2637 uint16_t port, int name_type, const char *myname,
2638 int signing_state, int flags, struct cli_state **pcli)
2640 struct tevent_context *ev;
2641 struct tevent_req *req;
2642 NTSTATUS status = NT_STATUS_NO_MEMORY;
2644 ev = samba_tevent_context_init(talloc_tos());
2645 if (ev == NULL) {
2646 goto fail;
2648 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2649 myname, signing_state, flags);
2650 if (req == NULL) {
2651 goto fail;
2653 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2654 goto fail;
2656 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2657 goto fail;
2659 status = cli_connect_nb_recv(req, pcli);
2660 fail:
2661 TALLOC_FREE(ev);
2662 return status;
2665 struct cli_start_connection_state {
2666 struct tevent_context *ev;
2667 struct cli_state *cli;
2668 int min_protocol;
2669 int max_protocol;
2672 static void cli_start_connection_connected(struct tevent_req *subreq);
2673 static void cli_start_connection_done(struct tevent_req *subreq);
2676 establishes a connection to after the negprot.
2677 @param output_cli A fully initialised cli structure, non-null only on success
2678 @param dest_host The netbios name of the remote host
2679 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2680 @param port (optional) The destination port (0 for default)
2683 static struct tevent_req *cli_start_connection_send(
2684 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2685 const char *my_name, const char *dest_host,
2686 const struct sockaddr_storage *dest_ss, int port,
2687 int signing_state, int flags)
2689 struct tevent_req *req, *subreq;
2690 struct cli_start_connection_state *state;
2692 req = tevent_req_create(mem_ctx, &state,
2693 struct cli_start_connection_state);
2694 if (req == NULL) {
2695 return NULL;
2697 state->ev = ev;
2699 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
2700 state->min_protocol = lp_client_ipc_min_protocol();
2701 state->max_protocol = lp_client_ipc_max_protocol();
2702 } else {
2703 state->min_protocol = lp_client_min_protocol();
2704 state->max_protocol = lp_client_max_protocol();
2707 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2708 0x20, my_name, signing_state, flags);
2709 if (tevent_req_nomem(subreq, req)) {
2710 return tevent_req_post(req, ev);
2712 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2713 return req;
2716 static void cli_start_connection_connected(struct tevent_req *subreq)
2718 struct tevent_req *req = tevent_req_callback_data(
2719 subreq, struct tevent_req);
2720 struct cli_start_connection_state *state = tevent_req_data(
2721 req, struct cli_start_connection_state);
2722 NTSTATUS status;
2724 status = cli_connect_nb_recv(subreq, &state->cli);
2725 TALLOC_FREE(subreq);
2726 if (tevent_req_nterror(req, status)) {
2727 return;
2730 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2731 state->cli->timeout,
2732 state->min_protocol,
2733 state->max_protocol);
2734 if (tevent_req_nomem(subreq, req)) {
2735 return;
2737 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2740 static void cli_start_connection_done(struct tevent_req *subreq)
2742 struct tevent_req *req = tevent_req_callback_data(
2743 subreq, struct tevent_req);
2744 struct cli_start_connection_state *state = tevent_req_data(
2745 req, struct cli_start_connection_state);
2746 NTSTATUS status;
2748 status = smbXcli_negprot_recv(subreq);
2749 TALLOC_FREE(subreq);
2750 if (tevent_req_nterror(req, status)) {
2751 return;
2754 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2755 /* Ensure we ask for some initial credits. */
2756 smb2cli_conn_set_max_credits(state->cli->conn,
2757 DEFAULT_SMB2_MAX_CREDITS);
2760 tevent_req_done(req);
2763 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2764 struct cli_state **output_cli)
2766 struct cli_start_connection_state *state = tevent_req_data(
2767 req, struct cli_start_connection_state);
2768 NTSTATUS status;
2770 if (tevent_req_is_nterror(req, &status)) {
2771 return status;
2773 *output_cli = state->cli;
2775 return NT_STATUS_OK;
2778 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2779 const char *my_name,
2780 const char *dest_host,
2781 const struct sockaddr_storage *dest_ss, int port,
2782 int signing_state, int flags)
2784 struct tevent_context *ev;
2785 struct tevent_req *req;
2786 NTSTATUS status = NT_STATUS_NO_MEMORY;
2788 ev = samba_tevent_context_init(talloc_tos());
2789 if (ev == NULL) {
2790 goto fail;
2792 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2793 port, signing_state, flags);
2794 if (req == NULL) {
2795 goto fail;
2797 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2798 goto fail;
2800 status = cli_start_connection_recv(req, output_cli);
2801 fail:
2802 TALLOC_FREE(ev);
2803 return status;
2807 establishes a connection right up to doing tconX, password specified.
2808 @param output_cli A fully initialised cli structure, non-null only on success
2809 @param dest_host The netbios name of the remote host
2810 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2811 @param port (optional) The destination port (0 for default)
2812 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2813 @param service_type The 'type' of serivice.
2814 @param user Username, unix string
2815 @param domain User's domain
2816 @param password User's password, unencrypted unix string.
2819 struct cli_full_connection_state {
2820 struct tevent_context *ev;
2821 const char *service;
2822 const char *service_type;
2823 const char *user;
2824 const char *domain;
2825 const char *password;
2826 int pw_len;
2827 int flags;
2828 struct cli_state *cli;
2831 static int cli_full_connection_state_destructor(
2832 struct cli_full_connection_state *s);
2833 static void cli_full_connection_started(struct tevent_req *subreq);
2834 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
2835 static void cli_full_connection_done(struct tevent_req *subreq);
2837 struct tevent_req *cli_full_connection_send(
2838 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2839 const char *my_name, const char *dest_host,
2840 const struct sockaddr_storage *dest_ss, int port,
2841 const char *service, const char *service_type,
2842 const char *user, const char *domain,
2843 const char *password, int flags, int signing_state)
2845 struct tevent_req *req, *subreq;
2846 struct cli_full_connection_state *state;
2848 req = tevent_req_create(mem_ctx, &state,
2849 struct cli_full_connection_state);
2850 if (req == NULL) {
2851 return NULL;
2853 talloc_set_destructor(state, cli_full_connection_state_destructor);
2855 state->ev = ev;
2856 state->service = service;
2857 state->service_type = service_type;
2858 state->user = user;
2859 state->domain = domain;
2860 state->password = password;
2861 state->flags = flags;
2863 state->pw_len = state->password ? strlen(state->password)+1 : 0;
2864 if (state->password == NULL) {
2865 state->password = "";
2868 subreq = cli_start_connection_send(
2869 state, ev, my_name, dest_host, dest_ss, port,
2870 signing_state, flags);
2871 if (tevent_req_nomem(subreq, req)) {
2872 return tevent_req_post(req, ev);
2874 tevent_req_set_callback(subreq, cli_full_connection_started, req);
2875 return req;
2878 static int cli_full_connection_state_destructor(
2879 struct cli_full_connection_state *s)
2881 if (s->cli != NULL) {
2882 cli_shutdown(s->cli);
2883 s->cli = NULL;
2885 return 0;
2888 static void cli_full_connection_started(struct tevent_req *subreq)
2890 struct tevent_req *req = tevent_req_callback_data(
2891 subreq, struct tevent_req);
2892 struct cli_full_connection_state *state = tevent_req_data(
2893 req, struct cli_full_connection_state);
2894 NTSTATUS status;
2895 struct cli_credentials *creds = NULL;
2897 status = cli_start_connection_recv(subreq, &state->cli);
2898 TALLOC_FREE(subreq);
2899 if (tevent_req_nterror(req, status)) {
2900 return;
2903 creds = cli_session_creds_init(state,
2904 state->user,
2905 state->domain,
2906 NULL, /* realm (use default) */
2907 state->password,
2908 state->cli->use_kerberos,
2909 state->cli->fallback_after_kerberos,
2910 state->cli->use_ccache,
2911 state->cli->pw_nt_hash);
2912 if (tevent_req_nomem(creds, req)) {
2913 return;
2916 subreq = cli_session_setup_creds_send(
2917 state, state->ev, state->cli, creds);
2918 if (tevent_req_nomem(subreq, req)) {
2919 return;
2921 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
2924 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
2926 struct tevent_req *req = tevent_req_callback_data(
2927 subreq, struct tevent_req);
2928 struct cli_full_connection_state *state = tevent_req_data(
2929 req, struct cli_full_connection_state);
2930 NTSTATUS status;
2932 status = cli_session_setup_creds_recv(subreq);
2933 TALLOC_FREE(subreq);
2935 if (!NT_STATUS_IS_OK(status) &&
2936 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2937 struct cli_credentials *creds = NULL;
2939 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2941 creds = cli_credentials_init_anon(state);
2942 if (tevent_req_nomem(creds, req)) {
2943 return;
2946 subreq = cli_session_setup_creds_send(
2947 state, state->ev, state->cli, creds);
2948 if (tevent_req_nomem(subreq, req)) {
2949 return;
2951 tevent_req_set_callback(
2952 subreq, cli_full_connection_sess_set_up, req);
2953 return;
2956 if (tevent_req_nterror(req, status)) {
2957 return;
2960 if (state->service != NULL) {
2961 subreq = cli_tree_connect_send(
2962 state, state->ev, state->cli,
2963 state->service, state->service_type,
2964 state->password, state->pw_len);
2965 if (tevent_req_nomem(subreq, req)) {
2966 return;
2968 tevent_req_set_callback(subreq, cli_full_connection_done, req);
2969 return;
2972 tevent_req_done(req);
2975 static void cli_full_connection_done(struct tevent_req *subreq)
2977 struct tevent_req *req = tevent_req_callback_data(
2978 subreq, struct tevent_req);
2979 NTSTATUS status;
2981 status = cli_tree_connect_recv(subreq);
2982 TALLOC_FREE(subreq);
2983 if (tevent_req_nterror(req, status)) {
2984 return;
2987 tevent_req_done(req);
2990 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
2991 struct cli_state **output_cli)
2993 struct cli_full_connection_state *state = tevent_req_data(
2994 req, struct cli_full_connection_state);
2995 NTSTATUS status;
2997 if (tevent_req_is_nterror(req, &status)) {
2998 return status;
3000 *output_cli = state->cli;
3001 talloc_set_destructor(state, NULL);
3002 return NT_STATUS_OK;
3005 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3006 const char *my_name,
3007 const char *dest_host,
3008 const struct sockaddr_storage *dest_ss, int port,
3009 const char *service, const char *service_type,
3010 const char *user, const char *domain,
3011 const char *password, int flags,
3012 int signing_state)
3014 struct tevent_context *ev;
3015 struct tevent_req *req;
3016 NTSTATUS status = NT_STATUS_NO_MEMORY;
3018 ev = samba_tevent_context_init(talloc_tos());
3019 if (ev == NULL) {
3020 goto fail;
3022 req = cli_full_connection_send(
3023 ev, ev, my_name, dest_host, dest_ss, port, service,
3024 service_type, user, domain, password, flags, signing_state);
3025 if (req == NULL) {
3026 goto fail;
3028 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3029 goto fail;
3031 status = cli_full_connection_recv(req, output_cli);
3032 fail:
3033 TALLOC_FREE(ev);
3034 return status;
3037 /****************************************************************************
3038 Send an old style tcon.
3039 ****************************************************************************/
3040 struct cli_raw_tcon_state {
3041 uint16_t *ret_vwv;
3044 static void cli_raw_tcon_done(struct tevent_req *subreq);
3046 static struct tevent_req *cli_raw_tcon_send(
3047 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3048 const char *service, const char *pass, const char *dev)
3050 struct tevent_req *req, *subreq;
3051 struct cli_raw_tcon_state *state;
3052 uint8_t *bytes;
3054 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3055 if (req == NULL) {
3056 return NULL;
3059 if (!lp_client_plaintext_auth() && (*pass)) {
3060 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3061 " or 'client ntlmv2 auth = yes'\n"));
3062 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3063 return tevent_req_post(req, ev);
3066 bytes = talloc_array(state, uint8_t, 0);
3067 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3068 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3069 service, strlen(service)+1, NULL);
3070 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3071 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3072 pass, strlen(pass)+1, NULL);
3073 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3074 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3075 dev, strlen(dev)+1, NULL);
3077 if (tevent_req_nomem(bytes, req)) {
3078 return tevent_req_post(req, ev);
3081 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3082 talloc_get_size(bytes), bytes);
3083 if (tevent_req_nomem(subreq, req)) {
3084 return tevent_req_post(req, ev);
3086 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3087 return req;
3090 static void cli_raw_tcon_done(struct tevent_req *subreq)
3092 struct tevent_req *req = tevent_req_callback_data(
3093 subreq, struct tevent_req);
3094 struct cli_raw_tcon_state *state = tevent_req_data(
3095 req, struct cli_raw_tcon_state);
3096 NTSTATUS status;
3098 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3099 NULL, NULL);
3100 TALLOC_FREE(subreq);
3101 if (tevent_req_nterror(req, status)) {
3102 return;
3104 tevent_req_done(req);
3107 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3108 uint16_t *max_xmit, uint16_t *tid)
3110 struct cli_raw_tcon_state *state = tevent_req_data(
3111 req, struct cli_raw_tcon_state);
3112 NTSTATUS status;
3114 if (tevent_req_is_nterror(req, &status)) {
3115 return status;
3117 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3118 *tid = SVAL(state->ret_vwv + 1, 0);
3119 return NT_STATUS_OK;
3122 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3123 const char *service, const char *pass, const char *dev,
3124 uint16_t *max_xmit, uint16_t *tid)
3126 struct tevent_context *ev;
3127 struct tevent_req *req;
3128 NTSTATUS status = NT_STATUS_NO_MEMORY;
3130 ev = samba_tevent_context_init(talloc_tos());
3131 if (ev == NULL) {
3132 goto fail;
3134 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3135 if (req == NULL) {
3136 goto fail;
3138 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3139 goto fail;
3141 status = cli_raw_tcon_recv(req, max_xmit, tid);
3142 fail:
3143 TALLOC_FREE(ev);
3144 return status;
3147 /* Return a cli_state pointing at the IPC$ share for the given server */
3149 struct cli_state *get_ipc_connect(char *server,
3150 struct sockaddr_storage *server_ss,
3151 const struct user_auth_info *user_info)
3153 struct cli_state *cli;
3154 NTSTATUS nt_status;
3155 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3157 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3158 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3161 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3162 get_cmdline_auth_info_username(user_info),
3163 lp_workgroup(),
3164 get_cmdline_auth_info_password(user_info),
3165 flags,
3166 SMB_SIGNING_DEFAULT);
3168 if (NT_STATUS_IS_OK(nt_status)) {
3169 return cli;
3170 } else if (is_ipaddress(server)) {
3171 /* windows 9* needs a correct NMB name for connections */
3172 fstring remote_name;
3174 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3175 cli = get_ipc_connect(remote_name, server_ss, user_info);
3176 if (cli)
3177 return cli;
3180 return NULL;
3184 * Given the IP address of a master browser on the network, return its
3185 * workgroup and connect to it.
3187 * This function is provided to allow additional processing beyond what
3188 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3189 * browsers and obtain each master browsers' list of domains (in case the
3190 * first master browser is recently on the network and has not yet
3191 * synchronized with other master browsers and therefore does not yet have the
3192 * entire network browse list)
3195 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3196 struct sockaddr_storage *mb_ip,
3197 const struct user_auth_info *user_info,
3198 char **pp_workgroup_out)
3200 char addr[INET6_ADDRSTRLEN];
3201 fstring name;
3202 struct cli_state *cli;
3203 struct sockaddr_storage server_ss;
3205 *pp_workgroup_out = NULL;
3207 print_sockaddr(addr, sizeof(addr), mb_ip);
3208 DEBUG(99, ("Looking up name of master browser %s\n",
3209 addr));
3212 * Do a name status query to find out the name of the master browser.
3213 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3214 * master browser will not respond to a wildcard query (or, at least,
3215 * an NT4 server acting as the domain master browser will not).
3217 * We might be able to use ONLY the query on MSBROWSE, but that's not
3218 * yet been tested with all Windows versions, so until it is, leave
3219 * the original wildcard query as the first choice and fall back to
3220 * MSBROWSE if the wildcard query fails.
3222 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3223 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3225 DEBUG(99, ("Could not retrieve name status for %s\n",
3226 addr));
3227 return NULL;
3230 if (!find_master_ip(name, &server_ss)) {
3231 DEBUG(99, ("Could not find master ip for %s\n", name));
3232 return NULL;
3235 *pp_workgroup_out = talloc_strdup(ctx, name);
3237 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3239 print_sockaddr(addr, sizeof(addr), &server_ss);
3240 cli = get_ipc_connect(addr, &server_ss, user_info);
3242 return cli;
3246 * Return the IP address and workgroup of a master browser on the network, and
3247 * connect to it.
3250 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3251 const struct user_auth_info *user_info,
3252 char **pp_workgroup_out)
3254 struct sockaddr_storage *ip_list;
3255 struct cli_state *cli;
3256 int i, count;
3257 NTSTATUS status;
3259 *pp_workgroup_out = NULL;
3261 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3263 /* Go looking for workgroups by broadcasting on the local network */
3265 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3266 &ip_list, &count);
3267 if (!NT_STATUS_IS_OK(status)) {
3268 DEBUG(99, ("No master browsers responded: %s\n",
3269 nt_errstr(status)));
3270 return NULL;
3273 for (i = 0; i < count; i++) {
3274 char addr[INET6_ADDRSTRLEN];
3275 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3276 DEBUG(99, ("Found master browser %s\n", addr));
3278 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3279 user_info, pp_workgroup_out);
3280 if (cli)
3281 return(cli);
3284 return NULL;