s4:torture: Strip trailing whitespaces in session_key.c
[Samba.git] / source3 / libsmb / cliconnect.c
blob7f82d4b48e6544684181a1d8aab1341c3dcfb484
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 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_anon(struct cli_state *cli)
1737 NTSTATUS status = NT_STATUS_NO_MEMORY;
1738 struct cli_credentials *creds = NULL;
1740 creds = cli_credentials_init_anon(cli);
1741 if (creds == NULL) {
1742 return NT_STATUS_NO_MEMORY;
1745 status = cli_session_setup_creds(cli, creds);
1746 TALLOC_FREE(creds);
1747 if (!NT_STATUS_IS_OK(status)) {
1748 return status;
1751 return NT_STATUS_OK;
1754 NTSTATUS cli_session_setup(struct cli_state *cli,
1755 const char *user,
1756 const char *pass,
1757 const char *workgroup)
1759 NTSTATUS status = NT_STATUS_NO_MEMORY;
1760 const char *dest_realm = NULL;
1761 struct cli_credentials *creds = NULL;
1764 * dest_realm is only valid in the winbindd use case,
1765 * where we also have the account in that realm.
1767 dest_realm = cli_state_remote_realm(cli);
1769 creds = cli_session_creds_init(cli,
1770 user,
1771 workgroup,
1772 dest_realm,
1773 pass,
1774 cli->use_kerberos,
1775 cli->fallback_after_kerberos,
1776 cli->use_ccache,
1777 cli->pw_nt_hash);
1778 if (creds == NULL) {
1779 return NT_STATUS_NO_MEMORY;
1782 status = cli_session_setup_creds(cli, creds);
1783 TALLOC_FREE(creds);
1784 if (!NT_STATUS_IS_OK(status)) {
1785 return status;
1788 return NT_STATUS_OK;
1791 /****************************************************************************
1792 Send a uloggoff.
1793 *****************************************************************************/
1795 struct cli_ulogoff_state {
1796 struct cli_state *cli;
1797 uint16_t vwv[3];
1800 static void cli_ulogoff_done(struct tevent_req *subreq);
1802 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1803 struct tevent_context *ev,
1804 struct cli_state *cli)
1806 struct tevent_req *req, *subreq;
1807 struct cli_ulogoff_state *state;
1809 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1810 if (req == NULL) {
1811 return NULL;
1813 state->cli = cli;
1815 SCVAL(state->vwv+0, 0, 0xFF);
1816 SCVAL(state->vwv+1, 0, 0);
1817 SSVAL(state->vwv+2, 0, 0);
1819 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1820 0, NULL);
1821 if (tevent_req_nomem(subreq, req)) {
1822 return tevent_req_post(req, ev);
1824 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1825 return req;
1828 static void cli_ulogoff_done(struct tevent_req *subreq)
1830 struct tevent_req *req = tevent_req_callback_data(
1831 subreq, struct tevent_req);
1832 struct cli_ulogoff_state *state = tevent_req_data(
1833 req, struct cli_ulogoff_state);
1834 NTSTATUS status;
1836 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1837 if (!NT_STATUS_IS_OK(status)) {
1838 tevent_req_nterror(req, status);
1839 return;
1841 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1842 tevent_req_done(req);
1845 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1847 return tevent_req_simple_recv_ntstatus(req);
1850 NTSTATUS cli_ulogoff(struct cli_state *cli)
1852 struct tevent_context *ev;
1853 struct tevent_req *req;
1854 NTSTATUS status = NT_STATUS_NO_MEMORY;
1856 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1857 status = smb2cli_logoff(cli->conn,
1858 cli->timeout,
1859 cli->smb2.session);
1860 if (!NT_STATUS_IS_OK(status)) {
1861 return status;
1863 smb2cli_session_set_id_and_flags(cli->smb2.session,
1864 UINT64_MAX, 0);
1865 return NT_STATUS_OK;
1868 if (smbXcli_conn_has_async_calls(cli->conn)) {
1869 return NT_STATUS_INVALID_PARAMETER;
1871 ev = samba_tevent_context_init(talloc_tos());
1872 if (ev == NULL) {
1873 goto fail;
1875 req = cli_ulogoff_send(ev, ev, cli);
1876 if (req == NULL) {
1877 goto fail;
1879 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1880 goto fail;
1882 status = cli_ulogoff_recv(req);
1883 fail:
1884 TALLOC_FREE(ev);
1885 return status;
1888 /****************************************************************************
1889 Send a tconX.
1890 ****************************************************************************/
1892 struct cli_tcon_andx_state {
1893 struct cli_state *cli;
1894 uint16_t vwv[4];
1895 struct iovec bytes;
1898 static void cli_tcon_andx_done(struct tevent_req *subreq);
1900 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1901 struct tevent_context *ev,
1902 struct cli_state *cli,
1903 const char *share, const char *dev,
1904 const char *pass, int passlen,
1905 struct tevent_req **psmbreq)
1907 struct tevent_req *req, *subreq;
1908 struct cli_tcon_andx_state *state;
1909 uint8_t p24[24];
1910 uint16_t *vwv;
1911 char *tmp = NULL;
1912 uint8_t *bytes;
1913 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1914 uint16_t tcon_flags = 0;
1916 *psmbreq = NULL;
1918 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1919 if (req == NULL) {
1920 return NULL;
1922 state->cli = cli;
1923 vwv = state->vwv;
1925 cli->share = talloc_strdup(cli, share);
1926 if (!cli->share) {
1927 return NULL;
1930 /* in user level security don't send a password now */
1931 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1932 passlen = 1;
1933 pass = "";
1934 } else if (pass == NULL) {
1935 DEBUG(1, ("Server not using user level security and no "
1936 "password supplied.\n"));
1937 goto access_denied;
1940 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1941 *pass && passlen != 24) {
1942 if (!lp_client_lanman_auth()) {
1943 DEBUG(1, ("Server requested LANMAN password "
1944 "(share-level security) but "
1945 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1946 goto access_denied;
1950 * Non-encrypted passwords - convert to DOS codepage before
1951 * encryption.
1953 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1954 passlen = 24;
1955 pass = (const char *)p24;
1956 } else {
1957 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1958 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1959 == 0) {
1960 uint8_t *tmp_pass;
1962 if (!lp_client_plaintext_auth() && (*pass)) {
1963 DEBUG(1, ("Server requested PLAINTEXT "
1964 "password but "
1965 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
1966 goto access_denied;
1970 * Non-encrypted passwords - convert to DOS codepage
1971 * before using.
1973 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
1974 if (tevent_req_nomem(tmp_pass, req)) {
1975 return tevent_req_post(req, ev);
1977 tmp_pass = trans2_bytes_push_str(tmp_pass,
1978 false, /* always DOS */
1979 pass,
1980 passlen,
1981 NULL);
1982 if (tevent_req_nomem(tmp_pass, req)) {
1983 return tevent_req_post(req, ev);
1985 pass = (const char *)tmp_pass;
1986 passlen = talloc_get_size(tmp_pass);
1990 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
1991 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
1993 SCVAL(vwv+0, 0, 0xFF);
1994 SCVAL(vwv+0, 1, 0);
1995 SSVAL(vwv+1, 0, 0);
1996 SSVAL(vwv+2, 0, tcon_flags);
1997 SSVAL(vwv+3, 0, passlen);
1999 if (passlen && pass) {
2000 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2001 } else {
2002 bytes = talloc_array(state, uint8_t, 0);
2006 * Add the sharename
2008 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2009 smbXcli_conn_remote_name(cli->conn), share);
2010 if (tmp == NULL) {
2011 TALLOC_FREE(req);
2012 return NULL;
2014 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2015 NULL);
2016 TALLOC_FREE(tmp);
2019 * Add the devicetype
2021 tmp = talloc_strdup_upper(talloc_tos(), dev);
2022 if (tmp == NULL) {
2023 TALLOC_FREE(req);
2024 return NULL;
2026 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2027 TALLOC_FREE(tmp);
2029 if (bytes == NULL) {
2030 TALLOC_FREE(req);
2031 return NULL;
2034 state->bytes.iov_base = (void *)bytes;
2035 state->bytes.iov_len = talloc_get_size(bytes);
2037 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2038 1, &state->bytes);
2039 if (subreq == NULL) {
2040 TALLOC_FREE(req);
2041 return NULL;
2043 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2044 *psmbreq = subreq;
2045 return req;
2047 access_denied:
2048 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2049 return tevent_req_post(req, ev);
2052 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2053 struct tevent_context *ev,
2054 struct cli_state *cli,
2055 const char *share, const char *dev,
2056 const char *pass, int passlen)
2058 struct tevent_req *req, *subreq;
2059 NTSTATUS status;
2061 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2062 &subreq);
2063 if (req == NULL) {
2064 return NULL;
2066 if (subreq == NULL) {
2067 return req;
2069 status = smb1cli_req_chain_submit(&subreq, 1);
2070 if (!NT_STATUS_IS_OK(status)) {
2071 tevent_req_nterror(req, status);
2072 return tevent_req_post(req, ev);
2074 return req;
2077 static void cli_tcon_andx_done(struct tevent_req *subreq)
2079 struct tevent_req *req = tevent_req_callback_data(
2080 subreq, struct tevent_req);
2081 struct cli_tcon_andx_state *state = tevent_req_data(
2082 req, struct cli_tcon_andx_state);
2083 struct cli_state *cli = state->cli;
2084 uint8_t *in;
2085 uint8_t *inhdr;
2086 uint8_t wct;
2087 uint16_t *vwv;
2088 uint32_t num_bytes;
2089 uint8_t *bytes;
2090 NTSTATUS status;
2091 uint16_t optional_support = 0;
2093 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2094 &num_bytes, &bytes);
2095 TALLOC_FREE(subreq);
2096 if (!NT_STATUS_IS_OK(status)) {
2097 tevent_req_nterror(req, status);
2098 return;
2101 inhdr = in + NBT_HDR_SIZE;
2103 if (num_bytes) {
2104 if (clistr_pull_talloc(cli,
2105 (const char *)inhdr,
2106 SVAL(inhdr, HDR_FLG2),
2107 &cli->dev,
2108 bytes,
2109 num_bytes,
2110 STR_TERMINATE|STR_ASCII) == -1) {
2111 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2112 return;
2114 } else {
2115 cli->dev = talloc_strdup(cli, "");
2116 if (cli->dev == NULL) {
2117 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2118 return;
2122 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2123 /* almost certainly win95 - enable bug fixes */
2124 cli->win95 = True;
2128 * Make sure that we have the optional support 16-bit field. WCT > 2.
2129 * Avoids issues when connecting to Win9x boxes sharing files
2132 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2133 optional_support = SVAL(vwv+2, 0);
2136 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2137 smb1cli_session_protect_session_key(cli->smb1.session);
2140 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2141 SVAL(inhdr, HDR_TID),
2142 optional_support,
2143 0, /* maximal_access */
2144 0, /* guest_maximal_access */
2145 NULL, /* service */
2146 NULL); /* fs_type */
2148 tevent_req_done(req);
2151 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2153 return tevent_req_simple_recv_ntstatus(req);
2156 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2157 const char *dev, const char *pass, int passlen)
2159 TALLOC_CTX *frame = talloc_stackframe();
2160 struct tevent_context *ev;
2161 struct tevent_req *req;
2162 NTSTATUS status = NT_STATUS_NO_MEMORY;
2164 if (smbXcli_conn_has_async_calls(cli->conn)) {
2166 * Can't use sync call while an async call is in flight
2168 status = NT_STATUS_INVALID_PARAMETER;
2169 goto fail;
2172 ev = samba_tevent_context_init(frame);
2173 if (ev == NULL) {
2174 goto fail;
2177 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2178 if (req == NULL) {
2179 goto fail;
2182 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2183 goto fail;
2186 status = cli_tcon_andx_recv(req);
2187 fail:
2188 TALLOC_FREE(frame);
2189 return status;
2192 struct cli_tree_connect_state {
2193 struct cli_state *cli;
2196 static struct tevent_req *cli_raw_tcon_send(
2197 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2198 const char *service, const char *pass, const char *dev);
2199 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2200 uint16_t *max_xmit, uint16_t *tid);
2202 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2203 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2204 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2206 static struct tevent_req *cli_tree_connect_send(
2207 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2208 const char *share, const char *dev, const char *pass, int passlen)
2210 struct tevent_req *req, *subreq;
2211 struct cli_tree_connect_state *state;
2213 req = tevent_req_create(mem_ctx, &state,
2214 struct cli_tree_connect_state);
2215 if (req == NULL) {
2216 return NULL;
2218 state->cli = cli;
2220 cli->share = talloc_strdup(cli, share);
2221 if (tevent_req_nomem(cli->share, req)) {
2222 return tevent_req_post(req, ev);
2225 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2226 char *unc;
2228 cli->smb2.tcon = smbXcli_tcon_create(cli);
2229 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2230 return tevent_req_post(req, ev);
2233 unc = talloc_asprintf(state, "\\\\%s\\%s",
2234 smbXcli_conn_remote_name(cli->conn),
2235 share);
2236 if (tevent_req_nomem(unc, req)) {
2237 return tevent_req_post(req, ev);
2240 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2241 cli->smb2.session, cli->smb2.tcon,
2242 0, /* flags */
2243 unc);
2244 if (tevent_req_nomem(subreq, req)) {
2245 return tevent_req_post(req, ev);
2247 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2248 req);
2249 return req;
2252 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2253 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2254 pass, passlen);
2255 if (tevent_req_nomem(subreq, req)) {
2256 return tevent_req_post(req, ev);
2258 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2259 req);
2260 return req;
2263 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2264 if (tevent_req_nomem(subreq, req)) {
2265 return tevent_req_post(req, ev);
2267 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2269 return req;
2272 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2274 tevent_req_simple_finish_ntstatus(
2275 subreq, smb2cli_tcon_recv(subreq));
2278 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2280 tevent_req_simple_finish_ntstatus(
2281 subreq, cli_tcon_andx_recv(subreq));
2284 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2286 struct tevent_req *req = tevent_req_callback_data(
2287 subreq, struct tevent_req);
2288 struct cli_tree_connect_state *state = tevent_req_data(
2289 req, struct cli_tree_connect_state);
2290 NTSTATUS status;
2291 uint16_t max_xmit = 0;
2292 uint16_t tid = 0;
2294 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2295 if (tevent_req_nterror(req, status)) {
2296 return;
2299 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2300 tid,
2301 0, /* optional_support */
2302 0, /* maximal_access */
2303 0, /* guest_maximal_access */
2304 NULL, /* service */
2305 NULL); /* fs_type */
2307 tevent_req_done(req);
2310 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2312 return tevent_req_simple_recv_ntstatus(req);
2315 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2316 const char *dev, const char *pass, int passlen)
2318 struct tevent_context *ev;
2319 struct tevent_req *req;
2320 NTSTATUS status = NT_STATUS_NO_MEMORY;
2322 if (smbXcli_conn_has_async_calls(cli->conn)) {
2323 return NT_STATUS_INVALID_PARAMETER;
2325 ev = samba_tevent_context_init(talloc_tos());
2326 if (ev == NULL) {
2327 goto fail;
2329 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2330 if (req == NULL) {
2331 goto fail;
2333 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2334 goto fail;
2336 status = cli_tree_connect_recv(req);
2337 fail:
2338 TALLOC_FREE(ev);
2339 return status;
2342 /****************************************************************************
2343 Send a tree disconnect.
2344 ****************************************************************************/
2346 struct cli_tdis_state {
2347 struct cli_state *cli;
2350 static void cli_tdis_done(struct tevent_req *subreq);
2352 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2353 struct tevent_context *ev,
2354 struct cli_state *cli)
2356 struct tevent_req *req, *subreq;
2357 struct cli_tdis_state *state;
2359 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2360 if (req == NULL) {
2361 return NULL;
2363 state->cli = cli;
2365 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2366 if (tevent_req_nomem(subreq, req)) {
2367 return tevent_req_post(req, ev);
2369 tevent_req_set_callback(subreq, cli_tdis_done, req);
2370 return req;
2373 static void cli_tdis_done(struct tevent_req *subreq)
2375 struct tevent_req *req = tevent_req_callback_data(
2376 subreq, struct tevent_req);
2377 struct cli_tdis_state *state = tevent_req_data(
2378 req, struct cli_tdis_state);
2379 NTSTATUS status;
2381 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2382 TALLOC_FREE(subreq);
2383 if (!NT_STATUS_IS_OK(status)) {
2384 tevent_req_nterror(req, status);
2385 return;
2387 cli_state_set_tid(state->cli, UINT16_MAX);
2388 tevent_req_done(req);
2391 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2393 return tevent_req_simple_recv_ntstatus(req);
2396 NTSTATUS cli_tdis(struct cli_state *cli)
2398 struct tevent_context *ev;
2399 struct tevent_req *req;
2400 NTSTATUS status = NT_STATUS_NO_MEMORY;
2402 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2403 return smb2cli_tdis(cli->conn,
2404 cli->timeout,
2405 cli->smb2.session,
2406 cli->smb2.tcon);
2409 if (smbXcli_conn_has_async_calls(cli->conn)) {
2410 return NT_STATUS_INVALID_PARAMETER;
2412 ev = samba_tevent_context_init(talloc_tos());
2413 if (ev == NULL) {
2414 goto fail;
2416 req = cli_tdis_send(ev, ev, cli);
2417 if (req == NULL) {
2418 goto fail;
2420 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2421 goto fail;
2423 status = cli_tdis_recv(req);
2424 fail:
2425 TALLOC_FREE(ev);
2426 return status;
2429 struct cli_connect_sock_state {
2430 const char **called_names;
2431 const char **calling_names;
2432 int *called_types;
2433 int fd;
2434 uint16_t port;
2437 static void cli_connect_sock_done(struct tevent_req *subreq);
2440 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2441 * nonzero address.
2444 static struct tevent_req *cli_connect_sock_send(
2445 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2446 const char *host, int name_type, const struct sockaddr_storage *pss,
2447 const char *myname, uint16_t port)
2449 struct tevent_req *req, *subreq;
2450 struct cli_connect_sock_state *state;
2451 const char *prog;
2452 struct sockaddr_storage *addrs;
2453 unsigned i, num_addrs;
2454 NTSTATUS status;
2456 req = tevent_req_create(mem_ctx, &state,
2457 struct cli_connect_sock_state);
2458 if (req == NULL) {
2459 return NULL;
2462 prog = getenv("LIBSMB_PROG");
2463 if (prog != NULL) {
2464 state->fd = sock_exec(prog);
2465 if (state->fd == -1) {
2466 status = map_nt_error_from_unix(errno);
2467 tevent_req_nterror(req, status);
2468 } else {
2469 state->port = 0;
2470 tevent_req_done(req);
2472 return tevent_req_post(req, ev);
2475 if ((pss == NULL) || is_zero_addr(pss)) {
2478 * Here we cheat. resolve_name_list is not async at all. So
2479 * this call will only be really async if the name lookup has
2480 * been done externally.
2483 status = resolve_name_list(state, host, name_type,
2484 &addrs, &num_addrs);
2485 if (!NT_STATUS_IS_OK(status)) {
2486 tevent_req_nterror(req, status);
2487 return tevent_req_post(req, ev);
2489 } else {
2490 addrs = talloc_array(state, struct sockaddr_storage, 1);
2491 if (tevent_req_nomem(addrs, req)) {
2492 return tevent_req_post(req, ev);
2494 addrs[0] = *pss;
2495 num_addrs = 1;
2498 state->called_names = talloc_array(state, const char *, num_addrs);
2499 if (tevent_req_nomem(state->called_names, req)) {
2500 return tevent_req_post(req, ev);
2502 state->called_types = talloc_array(state, int, num_addrs);
2503 if (tevent_req_nomem(state->called_types, req)) {
2504 return tevent_req_post(req, ev);
2506 state->calling_names = talloc_array(state, const char *, num_addrs);
2507 if (tevent_req_nomem(state->calling_names, req)) {
2508 return tevent_req_post(req, ev);
2510 for (i=0; i<num_addrs; i++) {
2511 state->called_names[i] = host;
2512 state->called_types[i] = name_type;
2513 state->calling_names[i] = myname;
2516 subreq = smbsock_any_connect_send(
2517 state, ev, addrs, state->called_names, state->called_types,
2518 state->calling_names, NULL, num_addrs, port);
2519 if (tevent_req_nomem(subreq, req)) {
2520 return tevent_req_post(req, ev);
2522 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2523 return req;
2526 static void cli_connect_sock_done(struct tevent_req *subreq)
2528 struct tevent_req *req = tevent_req_callback_data(
2529 subreq, struct tevent_req);
2530 struct cli_connect_sock_state *state = tevent_req_data(
2531 req, struct cli_connect_sock_state);
2532 NTSTATUS status;
2534 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2535 &state->port);
2536 TALLOC_FREE(subreq);
2537 if (tevent_req_nterror(req, status)) {
2538 return;
2540 set_socket_options(state->fd, lp_socket_options());
2541 tevent_req_done(req);
2544 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2545 int *pfd, uint16_t *pport)
2547 struct cli_connect_sock_state *state = tevent_req_data(
2548 req, struct cli_connect_sock_state);
2549 NTSTATUS status;
2551 if (tevent_req_is_nterror(req, &status)) {
2552 return status;
2554 *pfd = state->fd;
2555 *pport = state->port;
2556 return NT_STATUS_OK;
2559 struct cli_connect_nb_state {
2560 const char *desthost;
2561 int signing_state;
2562 int flags;
2563 struct cli_state *cli;
2566 static void cli_connect_nb_done(struct tevent_req *subreq);
2568 static struct tevent_req *cli_connect_nb_send(
2569 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2570 const char *host, const struct sockaddr_storage *dest_ss,
2571 uint16_t port, int name_type, const char *myname,
2572 int signing_state, int flags)
2574 struct tevent_req *req, *subreq;
2575 struct cli_connect_nb_state *state;
2577 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2578 if (req == NULL) {
2579 return NULL;
2581 state->signing_state = signing_state;
2582 state->flags = flags;
2584 if (host != NULL) {
2585 char *p = strchr(host, '#');
2587 if (p != NULL) {
2588 name_type = strtol(p+1, NULL, 16);
2589 host = talloc_strndup(state, host, p - host);
2590 if (tevent_req_nomem(host, req)) {
2591 return tevent_req_post(req, ev);
2595 state->desthost = host;
2596 } else if (dest_ss != NULL) {
2597 state->desthost = print_canonical_sockaddr(state, dest_ss);
2598 if (tevent_req_nomem(state->desthost, req)) {
2599 return tevent_req_post(req, ev);
2601 } else {
2602 /* No host or dest_ss given. Error out. */
2603 tevent_req_error(req, EINVAL);
2604 return tevent_req_post(req, ev);
2607 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2608 myname, port);
2609 if (tevent_req_nomem(subreq, req)) {
2610 return tevent_req_post(req, ev);
2612 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2613 return req;
2616 static void cli_connect_nb_done(struct tevent_req *subreq)
2618 struct tevent_req *req = tevent_req_callback_data(
2619 subreq, struct tevent_req);
2620 struct cli_connect_nb_state *state = tevent_req_data(
2621 req, struct cli_connect_nb_state);
2622 NTSTATUS status;
2623 int fd = 0;
2624 uint16_t port;
2626 status = cli_connect_sock_recv(subreq, &fd, &port);
2627 TALLOC_FREE(subreq);
2628 if (tevent_req_nterror(req, status)) {
2629 return;
2632 state->cli = cli_state_create(state, fd, state->desthost, NULL,
2633 state->signing_state, state->flags);
2634 if (tevent_req_nomem(state->cli, req)) {
2635 close(fd);
2636 return;
2638 tevent_req_done(req);
2641 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2642 struct cli_state **pcli)
2644 struct cli_connect_nb_state *state = tevent_req_data(
2645 req, struct cli_connect_nb_state);
2646 NTSTATUS status;
2648 if (tevent_req_is_nterror(req, &status)) {
2649 return status;
2651 *pcli = talloc_move(NULL, &state->cli);
2652 return NT_STATUS_OK;
2655 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2656 uint16_t port, int name_type, const char *myname,
2657 int signing_state, int flags, struct cli_state **pcli)
2659 struct tevent_context *ev;
2660 struct tevent_req *req;
2661 NTSTATUS status = NT_STATUS_NO_MEMORY;
2663 ev = samba_tevent_context_init(talloc_tos());
2664 if (ev == NULL) {
2665 goto fail;
2667 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2668 myname, signing_state, flags);
2669 if (req == NULL) {
2670 goto fail;
2672 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2673 goto fail;
2675 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2676 goto fail;
2678 status = cli_connect_nb_recv(req, pcli);
2679 fail:
2680 TALLOC_FREE(ev);
2681 return status;
2684 struct cli_start_connection_state {
2685 struct tevent_context *ev;
2686 struct cli_state *cli;
2687 int min_protocol;
2688 int max_protocol;
2691 static void cli_start_connection_connected(struct tevent_req *subreq);
2692 static void cli_start_connection_done(struct tevent_req *subreq);
2695 establishes a connection to after the negprot.
2696 @param output_cli A fully initialised cli structure, non-null only on success
2697 @param dest_host The netbios name of the remote host
2698 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2699 @param port (optional) The destination port (0 for default)
2702 static struct tevent_req *cli_start_connection_send(
2703 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2704 const char *my_name, const char *dest_host,
2705 const struct sockaddr_storage *dest_ss, int port,
2706 int signing_state, int flags)
2708 struct tevent_req *req, *subreq;
2709 struct cli_start_connection_state *state;
2711 req = tevent_req_create(mem_ctx, &state,
2712 struct cli_start_connection_state);
2713 if (req == NULL) {
2714 return NULL;
2716 state->ev = ev;
2718 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
2719 state->min_protocol = lp_client_ipc_min_protocol();
2720 state->max_protocol = lp_client_ipc_max_protocol();
2721 } else {
2722 state->min_protocol = lp_client_min_protocol();
2723 state->max_protocol = lp_client_max_protocol();
2726 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2727 0x20, my_name, signing_state, flags);
2728 if (tevent_req_nomem(subreq, req)) {
2729 return tevent_req_post(req, ev);
2731 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2732 return req;
2735 static void cli_start_connection_connected(struct tevent_req *subreq)
2737 struct tevent_req *req = tevent_req_callback_data(
2738 subreq, struct tevent_req);
2739 struct cli_start_connection_state *state = tevent_req_data(
2740 req, struct cli_start_connection_state);
2741 NTSTATUS status;
2743 status = cli_connect_nb_recv(subreq, &state->cli);
2744 TALLOC_FREE(subreq);
2745 if (tevent_req_nterror(req, status)) {
2746 return;
2749 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2750 state->cli->timeout,
2751 state->min_protocol,
2752 state->max_protocol);
2753 if (tevent_req_nomem(subreq, req)) {
2754 return;
2756 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2759 static void cli_start_connection_done(struct tevent_req *subreq)
2761 struct tevent_req *req = tevent_req_callback_data(
2762 subreq, struct tevent_req);
2763 struct cli_start_connection_state *state = tevent_req_data(
2764 req, struct cli_start_connection_state);
2765 NTSTATUS status;
2767 status = smbXcli_negprot_recv(subreq);
2768 TALLOC_FREE(subreq);
2769 if (tevent_req_nterror(req, status)) {
2770 return;
2773 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2774 /* Ensure we ask for some initial credits. */
2775 smb2cli_conn_set_max_credits(state->cli->conn,
2776 DEFAULT_SMB2_MAX_CREDITS);
2779 tevent_req_done(req);
2782 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2783 struct cli_state **output_cli)
2785 struct cli_start_connection_state *state = tevent_req_data(
2786 req, struct cli_start_connection_state);
2787 NTSTATUS status;
2789 if (tevent_req_is_nterror(req, &status)) {
2790 return status;
2792 *output_cli = state->cli;
2794 return NT_STATUS_OK;
2797 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2798 const char *my_name,
2799 const char *dest_host,
2800 const struct sockaddr_storage *dest_ss, int port,
2801 int signing_state, int flags)
2803 struct tevent_context *ev;
2804 struct tevent_req *req;
2805 NTSTATUS status = NT_STATUS_NO_MEMORY;
2807 ev = samba_tevent_context_init(talloc_tos());
2808 if (ev == NULL) {
2809 goto fail;
2811 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2812 port, signing_state, flags);
2813 if (req == NULL) {
2814 goto fail;
2816 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2817 goto fail;
2819 status = cli_start_connection_recv(req, output_cli);
2820 fail:
2821 TALLOC_FREE(ev);
2822 return status;
2826 establishes a connection right up to doing tconX, password specified.
2827 @param output_cli A fully initialised cli structure, non-null only on success
2828 @param dest_host The netbios name of the remote host
2829 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2830 @param port (optional) The destination port (0 for default)
2831 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2832 @param service_type The 'type' of serivice.
2833 @param user Username, unix string
2834 @param domain User's domain
2835 @param password User's password, unencrypted unix string.
2838 struct cli_full_connection_state {
2839 struct tevent_context *ev;
2840 const char *service;
2841 const char *service_type;
2842 const char *user;
2843 const char *domain;
2844 const char *password;
2845 int pw_len;
2846 int flags;
2847 struct cli_state *cli;
2850 static int cli_full_connection_state_destructor(
2851 struct cli_full_connection_state *s);
2852 static void cli_full_connection_started(struct tevent_req *subreq);
2853 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
2854 static void cli_full_connection_done(struct tevent_req *subreq);
2856 struct tevent_req *cli_full_connection_send(
2857 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2858 const char *my_name, const char *dest_host,
2859 const struct sockaddr_storage *dest_ss, int port,
2860 const char *service, const char *service_type,
2861 const char *user, const char *domain,
2862 const char *password, int flags, int signing_state)
2864 struct tevent_req *req, *subreq;
2865 struct cli_full_connection_state *state;
2867 req = tevent_req_create(mem_ctx, &state,
2868 struct cli_full_connection_state);
2869 if (req == NULL) {
2870 return NULL;
2872 talloc_set_destructor(state, cli_full_connection_state_destructor);
2874 state->ev = ev;
2875 state->service = service;
2876 state->service_type = service_type;
2877 state->user = user;
2878 state->domain = domain;
2879 state->password = password;
2880 state->flags = flags;
2882 state->pw_len = state->password ? strlen(state->password)+1 : 0;
2883 if (state->password == NULL) {
2884 state->password = "";
2887 subreq = cli_start_connection_send(
2888 state, ev, my_name, dest_host, dest_ss, port,
2889 signing_state, flags);
2890 if (tevent_req_nomem(subreq, req)) {
2891 return tevent_req_post(req, ev);
2893 tevent_req_set_callback(subreq, cli_full_connection_started, req);
2894 return req;
2897 static int cli_full_connection_state_destructor(
2898 struct cli_full_connection_state *s)
2900 if (s->cli != NULL) {
2901 cli_shutdown(s->cli);
2902 s->cli = NULL;
2904 return 0;
2907 static void cli_full_connection_started(struct tevent_req *subreq)
2909 struct tevent_req *req = tevent_req_callback_data(
2910 subreq, struct tevent_req);
2911 struct cli_full_connection_state *state = tevent_req_data(
2912 req, struct cli_full_connection_state);
2913 NTSTATUS status;
2914 struct cli_credentials *creds = NULL;
2916 status = cli_start_connection_recv(subreq, &state->cli);
2917 TALLOC_FREE(subreq);
2918 if (tevent_req_nterror(req, status)) {
2919 return;
2922 creds = cli_session_creds_init(state,
2923 state->user,
2924 state->domain,
2925 NULL, /* realm (use default) */
2926 state->password,
2927 state->cli->use_kerberos,
2928 state->cli->fallback_after_kerberos,
2929 state->cli->use_ccache,
2930 state->cli->pw_nt_hash);
2931 if (tevent_req_nomem(creds, req)) {
2932 return;
2935 subreq = cli_session_setup_creds_send(
2936 state, state->ev, state->cli, creds);
2937 if (tevent_req_nomem(subreq, req)) {
2938 return;
2940 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
2943 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
2945 struct tevent_req *req = tevent_req_callback_data(
2946 subreq, struct tevent_req);
2947 struct cli_full_connection_state *state = tevent_req_data(
2948 req, struct cli_full_connection_state);
2949 NTSTATUS status;
2951 status = cli_session_setup_creds_recv(subreq);
2952 TALLOC_FREE(subreq);
2954 if (!NT_STATUS_IS_OK(status) &&
2955 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2956 struct cli_credentials *creds = NULL;
2958 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2960 creds = cli_credentials_init_anon(state);
2961 if (tevent_req_nomem(creds, req)) {
2962 return;
2965 subreq = cli_session_setup_creds_send(
2966 state, state->ev, state->cli, creds);
2967 if (tevent_req_nomem(subreq, req)) {
2968 return;
2970 tevent_req_set_callback(
2971 subreq, cli_full_connection_sess_set_up, req);
2972 return;
2975 if (tevent_req_nterror(req, status)) {
2976 return;
2979 if (state->service != NULL) {
2980 subreq = cli_tree_connect_send(
2981 state, state->ev, state->cli,
2982 state->service, state->service_type,
2983 state->password, state->pw_len);
2984 if (tevent_req_nomem(subreq, req)) {
2985 return;
2987 tevent_req_set_callback(subreq, cli_full_connection_done, req);
2988 return;
2991 tevent_req_done(req);
2994 static void cli_full_connection_done(struct tevent_req *subreq)
2996 struct tevent_req *req = tevent_req_callback_data(
2997 subreq, struct tevent_req);
2998 NTSTATUS status;
3000 status = cli_tree_connect_recv(subreq);
3001 TALLOC_FREE(subreq);
3002 if (tevent_req_nterror(req, status)) {
3003 return;
3006 tevent_req_done(req);
3009 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3010 struct cli_state **output_cli)
3012 struct cli_full_connection_state *state = tevent_req_data(
3013 req, struct cli_full_connection_state);
3014 NTSTATUS status;
3016 if (tevent_req_is_nterror(req, &status)) {
3017 return status;
3019 *output_cli = state->cli;
3020 talloc_set_destructor(state, NULL);
3021 return NT_STATUS_OK;
3024 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3025 const char *my_name,
3026 const char *dest_host,
3027 const struct sockaddr_storage *dest_ss, int port,
3028 const char *service, const char *service_type,
3029 const char *user, const char *domain,
3030 const char *password, int flags,
3031 int signing_state)
3033 struct tevent_context *ev;
3034 struct tevent_req *req;
3035 NTSTATUS status = NT_STATUS_NO_MEMORY;
3037 ev = samba_tevent_context_init(talloc_tos());
3038 if (ev == NULL) {
3039 goto fail;
3041 req = cli_full_connection_send(
3042 ev, ev, my_name, dest_host, dest_ss, port, service,
3043 service_type, user, domain, password, flags, signing_state);
3044 if (req == NULL) {
3045 goto fail;
3047 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3048 goto fail;
3050 status = cli_full_connection_recv(req, output_cli);
3051 fail:
3052 TALLOC_FREE(ev);
3053 return status;
3056 /****************************************************************************
3057 Send an old style tcon.
3058 ****************************************************************************/
3059 struct cli_raw_tcon_state {
3060 uint16_t *ret_vwv;
3063 static void cli_raw_tcon_done(struct tevent_req *subreq);
3065 static struct tevent_req *cli_raw_tcon_send(
3066 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3067 const char *service, const char *pass, const char *dev)
3069 struct tevent_req *req, *subreq;
3070 struct cli_raw_tcon_state *state;
3071 uint8_t *bytes;
3073 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3074 if (req == NULL) {
3075 return NULL;
3078 if (!lp_client_plaintext_auth() && (*pass)) {
3079 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3080 " or 'client ntlmv2 auth = yes'\n"));
3081 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3082 return tevent_req_post(req, ev);
3085 bytes = talloc_array(state, uint8_t, 0);
3086 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3087 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3088 service, strlen(service)+1, NULL);
3089 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3090 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3091 pass, strlen(pass)+1, NULL);
3092 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3093 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3094 dev, strlen(dev)+1, NULL);
3096 if (tevent_req_nomem(bytes, req)) {
3097 return tevent_req_post(req, ev);
3100 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3101 talloc_get_size(bytes), bytes);
3102 if (tevent_req_nomem(subreq, req)) {
3103 return tevent_req_post(req, ev);
3105 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3106 return req;
3109 static void cli_raw_tcon_done(struct tevent_req *subreq)
3111 struct tevent_req *req = tevent_req_callback_data(
3112 subreq, struct tevent_req);
3113 struct cli_raw_tcon_state *state = tevent_req_data(
3114 req, struct cli_raw_tcon_state);
3115 NTSTATUS status;
3117 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3118 NULL, NULL);
3119 TALLOC_FREE(subreq);
3120 if (tevent_req_nterror(req, status)) {
3121 return;
3123 tevent_req_done(req);
3126 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3127 uint16_t *max_xmit, uint16_t *tid)
3129 struct cli_raw_tcon_state *state = tevent_req_data(
3130 req, struct cli_raw_tcon_state);
3131 NTSTATUS status;
3133 if (tevent_req_is_nterror(req, &status)) {
3134 return status;
3136 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3137 *tid = SVAL(state->ret_vwv + 1, 0);
3138 return NT_STATUS_OK;
3141 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3142 const char *service, const char *pass, const char *dev,
3143 uint16_t *max_xmit, uint16_t *tid)
3145 struct tevent_context *ev;
3146 struct tevent_req *req;
3147 NTSTATUS status = NT_STATUS_NO_MEMORY;
3149 ev = samba_tevent_context_init(talloc_tos());
3150 if (ev == NULL) {
3151 goto fail;
3153 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3154 if (req == NULL) {
3155 goto fail;
3157 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3158 goto fail;
3160 status = cli_raw_tcon_recv(req, max_xmit, tid);
3161 fail:
3162 TALLOC_FREE(ev);
3163 return status;
3166 /* Return a cli_state pointing at the IPC$ share for the given server */
3168 struct cli_state *get_ipc_connect(char *server,
3169 struct sockaddr_storage *server_ss,
3170 const struct user_auth_info *user_info)
3172 struct cli_state *cli;
3173 NTSTATUS nt_status;
3174 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3176 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3177 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3180 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3181 get_cmdline_auth_info_username(user_info),
3182 lp_workgroup(),
3183 get_cmdline_auth_info_password(user_info),
3184 flags,
3185 SMB_SIGNING_DEFAULT);
3187 if (NT_STATUS_IS_OK(nt_status)) {
3188 return cli;
3189 } else if (is_ipaddress(server)) {
3190 /* windows 9* needs a correct NMB name for connections */
3191 fstring remote_name;
3193 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3194 cli = get_ipc_connect(remote_name, server_ss, user_info);
3195 if (cli)
3196 return cli;
3199 return NULL;
3203 * Given the IP address of a master browser on the network, return its
3204 * workgroup and connect to it.
3206 * This function is provided to allow additional processing beyond what
3207 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3208 * browsers and obtain each master browsers' list of domains (in case the
3209 * first master browser is recently on the network and has not yet
3210 * synchronized with other master browsers and therefore does not yet have the
3211 * entire network browse list)
3214 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3215 struct sockaddr_storage *mb_ip,
3216 const struct user_auth_info *user_info,
3217 char **pp_workgroup_out)
3219 char addr[INET6_ADDRSTRLEN];
3220 fstring name;
3221 struct cli_state *cli;
3222 struct sockaddr_storage server_ss;
3224 *pp_workgroup_out = NULL;
3226 print_sockaddr(addr, sizeof(addr), mb_ip);
3227 DEBUG(99, ("Looking up name of master browser %s\n",
3228 addr));
3231 * Do a name status query to find out the name of the master browser.
3232 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3233 * master browser will not respond to a wildcard query (or, at least,
3234 * an NT4 server acting as the domain master browser will not).
3236 * We might be able to use ONLY the query on MSBROWSE, but that's not
3237 * yet been tested with all Windows versions, so until it is, leave
3238 * the original wildcard query as the first choice and fall back to
3239 * MSBROWSE if the wildcard query fails.
3241 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3242 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3244 DEBUG(99, ("Could not retrieve name status for %s\n",
3245 addr));
3246 return NULL;
3249 if (!find_master_ip(name, &server_ss)) {
3250 DEBUG(99, ("Could not find master ip for %s\n", name));
3251 return NULL;
3254 *pp_workgroup_out = talloc_strdup(ctx, name);
3256 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3258 print_sockaddr(addr, sizeof(addr), &server_ss);
3259 cli = get_ipc_connect(addr, &server_ss, user_info);
3261 return cli;
3265 * Return the IP address and workgroup of a master browser on the network, and
3266 * connect to it.
3269 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3270 const struct user_auth_info *user_info,
3271 char **pp_workgroup_out)
3273 struct sockaddr_storage *ip_list;
3274 struct cli_state *cli;
3275 int i, count;
3276 NTSTATUS status;
3278 *pp_workgroup_out = NULL;
3280 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3282 /* Go looking for workgroups by broadcasting on the local network */
3284 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3285 &ip_list, &count);
3286 if (!NT_STATUS_IS_OK(status)) {
3287 DEBUG(99, ("No master browsers responded: %s\n",
3288 nt_errstr(status)));
3289 return NULL;
3292 for (i = 0; i < count; i++) {
3293 char addr[INET6_ADDRSTRLEN];
3294 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3295 DEBUG(99, ("Found master browser %s\n", addr));
3297 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3298 user_info, pp_workgroup_out);
3299 if (cli)
3300 return(cli);
3303 return NULL;