build: Move uid_wrapper to third_party
[Samba.git] / source3 / libsmb / cliconnect.c
blob26bf56962adb153342a11f86b25e2db335d9b06f
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 "../libcli/smb/smb_seal.h"
41 #include "lib/param/param.h"
42 #include "../libcli/smb/smb2_negotiate_context.h"
44 #define STAR_SMBSERVER "*SMBSERVER"
46 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
47 const char *principal);
49 struct cli_credentials *cli_session_creds_init(TALLOC_CTX *mem_ctx,
50 const char *username,
51 const char *domain,
52 const char *realm,
53 const char *password,
54 bool use_kerberos,
55 bool fallback_after_kerberos,
56 bool use_ccache,
57 bool password_is_nt_hash)
59 struct loadparm_context *lp_ctx = NULL;
60 struct cli_credentials *creds = NULL;
61 const char *principal = NULL;
62 char *tmp = NULL;
63 char *p = NULL;
64 bool ok;
66 creds = cli_credentials_init(mem_ctx);
67 if (creds == NULL) {
68 return NULL;
71 lp_ctx = loadparm_init_s3(creds, loadparm_s3_helpers());
72 if (lp_ctx == NULL) {
73 goto fail;
75 cli_credentials_set_conf(creds, lp_ctx);
77 if (username == NULL) {
78 username = "";
81 if (strlen(username) == 0) {
82 if (password != NULL && strlen(password) == 0) {
84 * some callers pass "" as no password
86 * gensec only handles NULL as no password.
88 password = NULL;
90 if (password == NULL) {
91 cli_credentials_set_anonymous(creds);
92 return creds;
96 tmp = talloc_strdup(creds, username);
97 if (tmp == NULL) {
98 goto fail;
100 username = tmp;
102 /* allow for workgroups as part of the username */
103 if ((p = strchr_m(tmp, '\\')) ||
104 (p = strchr_m(tmp, '/')) ||
105 (p = strchr_m(tmp, *lp_winbind_separator()))) {
106 *p = 0;
107 username = p + 1;
108 domain = tmp;
111 principal = username;
112 username = cli_session_setup_get_account(creds, principal);
113 if (username == NULL) {
114 goto fail;
116 ok = strequal(username, principal);
117 if (ok) {
119 * Ok still the same, so it's not a principal
121 principal = NULL;
124 if (use_kerberos && fallback_after_kerberos) {
125 cli_credentials_set_kerberos_state(creds,
126 CRED_AUTO_USE_KERBEROS);
127 } else if (use_kerberos) {
128 cli_credentials_set_kerberos_state(creds,
129 CRED_MUST_USE_KERBEROS);
130 } else {
131 cli_credentials_set_kerberos_state(creds,
132 CRED_DONT_USE_KERBEROS);
135 if (use_ccache) {
136 uint32_t features;
138 features = cli_credentials_get_gensec_features(creds);
139 features |= GENSEC_FEATURE_NTLM_CCACHE;
140 cli_credentials_set_gensec_features(creds, features);
142 if (password != NULL && strlen(password) == 0) {
144 * some callers pass "" as no password
146 * GENSEC_FEATURE_NTLM_CCACHE only handles
147 * NULL as no password.
149 password = NULL;
153 ok = cli_credentials_set_username(creds,
154 username,
155 CRED_SPECIFIED);
156 if (!ok) {
157 goto fail;
160 if (domain != NULL) {
161 ok = cli_credentials_set_domain(creds,
162 domain,
163 CRED_SPECIFIED);
164 if (!ok) {
165 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 NTSTATUS cli_session_creds_prepare_krb5(struct cli_state *cli,
223 struct cli_credentials *creds)
225 TALLOC_CTX *frame = talloc_stackframe();
226 const char *user_principal = NULL;
227 const char *user_account = NULL;
228 const char *user_domain = NULL;
229 const char *pass = NULL;
230 const char *target_hostname = NULL;
231 const DATA_BLOB *server_blob = NULL;
232 bool got_kerberos_mechanism = false;
233 enum credentials_use_kerberos krb5_state;
234 bool try_kerberos = false;
235 bool need_kinit = false;
236 bool auth_requested = true;
237 int ret;
239 target_hostname = smbXcli_conn_remote_name(cli->conn);
240 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
242 /* the server might not even do spnego */
243 if (server_blob != NULL && server_blob->length != 0) {
244 char *OIDs[ASN1_MAX_OIDS] = { NULL, };
245 size_t i;
246 bool ok;
249 * The server sent us the first part of the SPNEGO exchange in the
250 * negprot reply. It is WRONG to depend on the principal sent in the
251 * negprot reply, but right now we do it. If we don't receive one,
252 * we try to best guess, then fall back to NTLM.
254 ok = spnego_parse_negTokenInit(frame,
255 *server_blob,
256 OIDs,
257 NULL,
258 NULL);
259 if (!ok) {
260 TALLOC_FREE(frame);
261 return NT_STATUS_INVALID_PARAMETER;
263 if (OIDs[0] == NULL) {
264 TALLOC_FREE(frame);
265 return NT_STATUS_INVALID_PARAMETER;
268 /* make sure the server understands kerberos */
269 for (i = 0; OIDs[i] != NULL; i++) {
270 if (i == 0) {
271 DEBUG(3,("got OID=%s\n", OIDs[i]));
272 } else {
273 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
276 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
277 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
278 got_kerberos_mechanism = true;
279 break;
284 auth_requested = cli_credentials_authentication_requested(creds);
285 if (auth_requested) {
286 user_principal = cli_credentials_get_principal(creds, frame);
287 if (user_principal == NULL) {
288 TALLOC_FREE(frame);
289 return NT_STATUS_NO_MEMORY;
292 user_account = cli_credentials_get_username(creds);
293 user_domain = cli_credentials_get_domain(creds);
294 pass = cli_credentials_get_password(creds);
296 krb5_state = cli_credentials_get_kerberos_state(creds);
298 if (krb5_state != CRED_DONT_USE_KERBEROS) {
299 try_kerberos = true;
302 if (target_hostname == NULL) {
303 try_kerberos = false;
304 } else if (is_ipaddress(target_hostname)) {
305 try_kerberos = false;
306 } else if (strequal(target_hostname, "localhost")) {
307 try_kerberos = false;
308 } else if (strequal(target_hostname, STAR_SMBSERVER)) {
309 try_kerberos = false;
310 } else if (!auth_requested) {
311 try_kerberos = false;
314 if (krb5_state == CRED_MUST_USE_KERBEROS && !try_kerberos) {
315 DEBUG(0, ("Kerberos auth with '%s' (%s\\%s) to access "
316 "'%s' not possible\n",
317 user_principal, user_domain, user_account,
318 target_hostname));
319 TALLOC_FREE(frame);
320 return NT_STATUS_ACCESS_DENIED;
323 if (pass == NULL || strlen(pass) == 0) {
324 need_kinit = false;
325 } else if (krb5_state == CRED_MUST_USE_KERBEROS) {
326 need_kinit = try_kerberos;
327 } else if (!got_kerberos_mechanism) {
329 * Most likely the server doesn't support
330 * Kerberos, don't waste time doing a kinit
332 need_kinit = false;
333 } else {
334 need_kinit = try_kerberos;
337 if (!need_kinit) {
338 TALLOC_FREE(frame);
339 return NT_STATUS_OK;
344 * TODO: This should be done within the gensec layer
345 * only if required!
347 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
348 ret = kerberos_kinit_password(user_principal, pass,
349 0 /* no time correction for now */,
350 NULL);
351 if (ret != 0) {
352 int dbglvl = DBGLVL_NOTICE;
354 if (krb5_state == CRED_MUST_USE_KERBEROS) {
355 dbglvl = DBGLVL_ERR;
358 DEBUG(dbglvl, ("Kinit for %s to access %s failed: %s\n",
359 user_principal, target_hostname,
360 error_message(ret)));
361 if (krb5_state == CRED_MUST_USE_KERBEROS) {
362 TALLOC_FREE(frame);
363 return krb5_to_nt_status(ret);
367 * Ignore the error and hope that NTLM will work
371 TALLOC_FREE(frame);
372 return NT_STATUS_OK;
375 static NTSTATUS cli_state_update_after_sesssetup(struct cli_state *cli,
376 const char *native_os,
377 const char *native_lm,
378 const char *primary_domain)
380 #define _VALID_STR(p) ((p) != NULL && (p)[0] != '\0')
382 if (!_VALID_STR(cli->server_os) && _VALID_STR(native_os)) {
383 cli->server_os = talloc_strdup(cli, native_os);
384 if (cli->server_os == NULL) {
385 return NT_STATUS_NO_MEMORY;
389 if (!_VALID_STR(cli->server_type) && _VALID_STR(native_lm)) {
390 cli->server_type = talloc_strdup(cli, native_lm);
391 if (cli->server_type == NULL) {
392 return NT_STATUS_NO_MEMORY;
396 if (!_VALID_STR(cli->server_domain) && _VALID_STR(primary_domain)) {
397 cli->server_domain = talloc_strdup(cli, primary_domain);
398 if (cli->server_domain == NULL) {
399 return NT_STATUS_NO_MEMORY;
403 #undef _VALID_STRING
404 return NT_STATUS_OK;
407 /********************************************************
408 Utility function to ensure we always return at least
409 a valid char * pointer to an empty string for the
410 cli->server_os, cli->server_type and cli->server_domain
411 strings.
412 *******************************************************/
414 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
415 const uint8_t *hdr,
416 char **dest,
417 uint8_t *src,
418 size_t srclen,
419 ssize_t *destlen)
421 *destlen = clistr_pull_talloc(mem_ctx,
422 (const char *)hdr,
423 SVAL(hdr, HDR_FLG2),
424 dest,
425 (char *)src,
426 srclen,
427 STR_TERMINATE);
428 if (*destlen == -1) {
429 return NT_STATUS_NO_MEMORY;
432 if (*dest == NULL) {
433 *dest = talloc_strdup(mem_ctx, "");
434 if (*dest == NULL) {
435 return NT_STATUS_NO_MEMORY;
438 return NT_STATUS_OK;
441 /****************************************************************************
442 Work out suitable capabilities to offer the server.
443 ****************************************************************************/
445 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
446 uint32_t sesssetup_capabilities)
448 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
451 * We only send capabilities based on the mask for:
452 * - client only flags
453 * - flags used in both directions
455 * We do not echo the server only flags, except some legacy flags.
457 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
458 * CAP_LARGE_WRITEX in order to allow us to do large reads
459 * against old Samba releases (<= 3.6.x).
461 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
464 * Session Setup specific flags CAP_DYNAMIC_REAUTH
465 * and CAP_EXTENDED_SECURITY are passed by the caller.
466 * We need that in order to do guest logins even if
467 * CAP_EXTENDED_SECURITY is negotiated.
469 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
470 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
471 client_capabilities |= sesssetup_capabilities;
473 return client_capabilities;
476 /****************************************************************************
477 Do a NT1 guest session setup.
478 ****************************************************************************/
480 struct cli_session_setup_guest_state {
481 struct cli_state *cli;
482 uint16_t vwv[13];
483 struct iovec bytes;
486 static void cli_session_setup_guest_done(struct tevent_req *subreq);
488 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
489 struct tevent_context *ev,
490 struct cli_state *cli,
491 struct tevent_req **psmbreq)
493 struct tevent_req *req, *subreq;
494 struct cli_session_setup_guest_state *state;
495 uint16_t *vwv;
496 uint8_t *bytes;
498 req = tevent_req_create(mem_ctx, &state,
499 struct cli_session_setup_guest_state);
500 if (req == NULL) {
501 return NULL;
503 state->cli = cli;
504 vwv = state->vwv;
506 SCVAL(vwv+0, 0, 0xFF);
507 SCVAL(vwv+0, 1, 0);
508 SSVAL(vwv+1, 0, 0);
509 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
510 SSVAL(vwv+3, 0, 2);
511 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
512 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
513 SSVAL(vwv+7, 0, 0);
514 SSVAL(vwv+8, 0, 0);
515 SSVAL(vwv+9, 0, 0);
516 SSVAL(vwv+10, 0, 0);
517 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
519 bytes = talloc_array(state, uint8_t, 0);
521 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
522 NULL);
523 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
524 NULL);
525 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
526 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
528 if (bytes == NULL) {
529 TALLOC_FREE(req);
530 return NULL;
533 state->bytes.iov_base = (void *)bytes;
534 state->bytes.iov_len = talloc_get_size(bytes);
536 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
537 vwv, 1, &state->bytes);
538 if (subreq == NULL) {
539 TALLOC_FREE(req);
540 return NULL;
542 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
543 *psmbreq = subreq;
544 return req;
547 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
548 struct tevent_context *ev,
549 struct cli_state *cli)
551 struct tevent_req *req, *subreq;
552 NTSTATUS status;
554 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
555 if (req == NULL) {
556 return NULL;
559 status = smb1cli_req_chain_submit(&subreq, 1);
560 if (!NT_STATUS_IS_OK(status)) {
561 tevent_req_nterror(req, status);
562 return tevent_req_post(req, ev);
564 return req;
567 static void cli_session_setup_guest_done(struct tevent_req *subreq)
569 struct tevent_req *req = tevent_req_callback_data(
570 subreq, struct tevent_req);
571 struct cli_session_setup_guest_state *state = tevent_req_data(
572 req, struct cli_session_setup_guest_state);
573 struct cli_state *cli = state->cli;
574 uint32_t num_bytes;
575 uint8_t *in;
576 uint8_t *inhdr;
577 uint8_t *bytes;
578 uint8_t *p;
579 NTSTATUS status;
580 ssize_t ret;
581 uint8_t wct;
582 uint16_t *vwv;
584 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
585 &num_bytes, &bytes);
586 TALLOC_FREE(subreq);
587 if (!NT_STATUS_IS_OK(status)) {
588 tevent_req_nterror(req, status);
589 return;
592 inhdr = in + NBT_HDR_SIZE;
593 p = bytes;
595 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
596 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
598 status = smb_bytes_talloc_string(cli,
599 inhdr,
600 &cli->server_os,
602 bytes+num_bytes-p,
603 &ret);
605 if (!NT_STATUS_IS_OK(status)) {
606 tevent_req_nterror(req, status);
607 return;
609 p += ret;
611 status = smb_bytes_talloc_string(cli,
612 inhdr,
613 &cli->server_type,
615 bytes+num_bytes-p,
616 &ret);
618 if (!NT_STATUS_IS_OK(status)) {
619 tevent_req_nterror(req, status);
620 return;
622 p += ret;
624 status = smb_bytes_talloc_string(cli,
625 inhdr,
626 &cli->server_domain,
628 bytes+num_bytes-p,
629 &ret);
631 if (!NT_STATUS_IS_OK(status)) {
632 tevent_req_nterror(req, status);
633 return;
635 p += ret;
637 tevent_req_done(req);
640 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
642 return tevent_req_simple_recv_ntstatus(req);
645 /* The following is calculated from :
646 * (smb_size-4) = 35
647 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
648 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
649 * end of packet.
652 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
654 struct cli_sesssetup_blob_state {
655 struct tevent_context *ev;
656 struct cli_state *cli;
657 DATA_BLOB blob;
658 uint16_t max_blob_size;
660 DATA_BLOB this_blob;
661 struct iovec *recv_iov;
663 NTSTATUS status;
664 const uint8_t *inbuf;
665 DATA_BLOB ret_blob;
667 char *out_native_os;
668 char *out_native_lm;
671 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
672 struct tevent_req **psubreq);
673 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
675 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
676 struct tevent_context *ev,
677 struct cli_state *cli,
678 DATA_BLOB blob)
680 struct tevent_req *req, *subreq;
681 struct cli_sesssetup_blob_state *state;
682 uint32_t usable_space;
684 req = tevent_req_create(mem_ctx, &state,
685 struct cli_sesssetup_blob_state);
686 if (req == NULL) {
687 return NULL;
689 state->ev = ev;
690 state->blob = blob;
691 state->cli = cli;
693 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
694 usable_space = UINT16_MAX;
695 } else {
696 usable_space = cli_state_available_size(cli,
697 BASE_SESSSETUP_BLOB_PACKET_SIZE);
700 if (usable_space == 0) {
701 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
702 "(not possible to send %u bytes)\n",
703 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
704 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
705 return tevent_req_post(req, ev);
707 state->max_blob_size = MIN(usable_space, 0xFFFF);
709 if (!cli_sesssetup_blob_next(state, &subreq)) {
710 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
711 return tevent_req_post(req, ev);
713 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
714 return req;
717 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
718 struct tevent_req **psubreq)
720 struct tevent_req *subreq;
721 uint16_t thistime;
723 thistime = MIN(state->blob.length, state->max_blob_size);
725 state->this_blob.data = state->blob.data;
726 state->this_blob.length = thistime;
728 state->blob.data += thistime;
729 state->blob.length -= thistime;
731 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
732 subreq = smb2cli_session_setup_send(state, state->ev,
733 state->cli->conn,
734 state->cli->timeout,
735 state->cli->smb2.session,
736 0, /* in_flags */
737 SMB2_CAP_DFS, /* in_capabilities */
738 0, /* in_channel */
739 0, /* in_previous_session_id */
740 &state->this_blob);
741 if (subreq == NULL) {
742 return false;
744 } else {
745 uint16_t in_buf_size = 0;
746 uint16_t in_mpx_max = 0;
747 uint16_t in_vc_num = 0;
748 uint32_t in_sess_key = 0;
749 uint32_t in_capabilities = 0;
750 const char *in_native_os = NULL;
751 const char *in_native_lm = NULL;
753 in_buf_size = CLI_BUFFER_SIZE;
754 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
755 in_vc_num = cli_state_get_vc_num(state->cli);
756 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
757 in_capabilities = cli_session_setup_capabilities(state->cli,
758 CAP_EXTENDED_SECURITY);
759 in_native_os = "Unix";
760 in_native_lm = "Samba";
763 * For now we keep the same values as before,
764 * we may remove these in a separate commit later.
766 in_mpx_max = 2;
767 in_vc_num = 1;
768 in_sess_key = 0;
770 subreq = smb1cli_session_setup_ext_send(state, state->ev,
771 state->cli->conn,
772 state->cli->timeout,
773 state->cli->smb1.pid,
774 state->cli->smb1.session,
775 in_buf_size,
776 in_mpx_max,
777 in_vc_num,
778 in_sess_key,
779 state->this_blob,
780 in_capabilities,
781 in_native_os,
782 in_native_lm);
783 if (subreq == NULL) {
784 return false;
787 *psubreq = subreq;
788 return true;
791 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
793 struct tevent_req *req = tevent_req_callback_data(
794 subreq, struct tevent_req);
795 struct cli_sesssetup_blob_state *state = tevent_req_data(
796 req, struct cli_sesssetup_blob_state);
797 NTSTATUS status;
799 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
800 status = smb2cli_session_setup_recv(subreq, state,
801 &state->recv_iov,
802 &state->ret_blob);
803 } else {
804 status = smb1cli_session_setup_ext_recv(subreq, state,
805 &state->recv_iov,
806 &state->inbuf,
807 &state->ret_blob,
808 &state->out_native_os,
809 &state->out_native_lm);
811 TALLOC_FREE(subreq);
812 if (!NT_STATUS_IS_OK(status)
813 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
814 tevent_req_nterror(req, status);
815 return;
818 state->status = status;
820 status = cli_state_update_after_sesssetup(state->cli,
821 state->out_native_os,
822 state->out_native_lm,
823 NULL);
824 if (tevent_req_nterror(req, status)) {
825 return;
828 if (state->blob.length != 0) {
830 * More to send
832 if (!cli_sesssetup_blob_next(state, &subreq)) {
833 tevent_req_oom(req);
834 return;
836 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
837 return;
839 tevent_req_done(req);
842 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
843 TALLOC_CTX *mem_ctx,
844 DATA_BLOB *pblob,
845 const uint8_t **pinbuf,
846 struct iovec **precv_iov)
848 struct cli_sesssetup_blob_state *state = tevent_req_data(
849 req, struct cli_sesssetup_blob_state);
850 NTSTATUS status;
851 struct iovec *recv_iov;
853 if (tevent_req_is_nterror(req, &status)) {
854 TALLOC_FREE(state->cli->smb2.session);
855 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
856 tevent_req_received(req);
857 return status;
860 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
861 if (pblob != NULL) {
862 *pblob = state->ret_blob;
864 if (pinbuf != NULL) {
865 *pinbuf = state->inbuf;
867 if (precv_iov != NULL) {
868 *precv_iov = recv_iov;
870 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
871 status = state->status;
872 tevent_req_received(req);
873 return status;
876 /****************************************************************************
877 Do a spnego/NTLMSSP encrypted session setup.
878 ****************************************************************************/
880 struct cli_session_setup_gensec_state {
881 struct tevent_context *ev;
882 struct cli_state *cli;
883 struct auth_generic_state *auth_generic;
884 bool is_anonymous;
885 DATA_BLOB blob_in;
886 const uint8_t *inbuf;
887 struct iovec *recv_iov;
888 DATA_BLOB blob_out;
889 bool local_ready;
890 bool remote_ready;
891 DATA_BLOB session_key;
894 static int cli_session_setup_gensec_state_destructor(
895 struct cli_session_setup_gensec_state *state)
897 TALLOC_FREE(state->auth_generic);
898 data_blob_clear_free(&state->session_key);
899 return 0;
902 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
903 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
904 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
905 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
906 static void cli_session_setup_gensec_ready(struct tevent_req *req);
908 static struct tevent_req *cli_session_setup_gensec_send(
909 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
910 struct cli_credentials *creds,
911 const char *target_service,
912 const char *target_hostname)
914 struct tevent_req *req;
915 struct cli_session_setup_gensec_state *state;
916 NTSTATUS status;
917 const DATA_BLOB *b = NULL;
919 req = tevent_req_create(mem_ctx, &state,
920 struct cli_session_setup_gensec_state);
921 if (req == NULL) {
922 return NULL;
924 state->ev = ev;
925 state->cli = cli;
927 talloc_set_destructor(
928 state, cli_session_setup_gensec_state_destructor);
930 status = auth_generic_client_prepare(state, &state->auth_generic);
931 if (tevent_req_nterror(req, status)) {
932 return tevent_req_post(req, ev);
935 status = auth_generic_set_creds(state->auth_generic, creds);
936 if (tevent_req_nterror(req, status)) {
937 return tevent_req_post(req, ev);
940 gensec_want_feature(state->auth_generic->gensec_security,
941 GENSEC_FEATURE_SESSION_KEY);
943 if (target_service != NULL) {
944 status = gensec_set_target_service(
945 state->auth_generic->gensec_security,
946 target_service);
947 if (tevent_req_nterror(req, status)) {
948 return tevent_req_post(req, ev);
952 if (target_hostname != NULL) {
953 status = gensec_set_target_hostname(
954 state->auth_generic->gensec_security,
955 target_hostname);
956 if (tevent_req_nterror(req, status)) {
957 return tevent_req_post(req, ev);
961 b = smbXcli_conn_server_gss_blob(cli->conn);
962 if (b != NULL) {
963 state->blob_in = *b;
966 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
968 status = auth_generic_client_start(state->auth_generic,
969 GENSEC_OID_SPNEGO);
970 if (tevent_req_nterror(req, status)) {
971 return tevent_req_post(req, ev);
974 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
975 state->cli->smb2.session = smbXcli_session_create(cli,
976 cli->conn);
977 if (tevent_req_nomem(state->cli->smb2.session, req)) {
978 return tevent_req_post(req, ev);
982 cli_session_setup_gensec_local_next(req);
983 if (!tevent_req_is_in_progress(req)) {
984 return tevent_req_post(req, ev);
987 return req;
990 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
992 struct cli_session_setup_gensec_state *state =
993 tevent_req_data(req,
994 struct cli_session_setup_gensec_state);
995 struct tevent_req *subreq = NULL;
997 if (state->local_ready) {
998 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
999 return;
1002 subreq = gensec_update_send(state, state->ev,
1003 state->auth_generic->gensec_security,
1004 state->blob_in);
1005 if (tevent_req_nomem(subreq, req)) {
1006 return;
1008 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1011 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1013 struct tevent_req *req =
1014 tevent_req_callback_data(subreq,
1015 struct tevent_req);
1016 struct cli_session_setup_gensec_state *state =
1017 tevent_req_data(req,
1018 struct cli_session_setup_gensec_state);
1019 NTSTATUS status;
1021 status = gensec_update_recv(subreq, state, &state->blob_out);
1022 TALLOC_FREE(subreq);
1023 state->blob_in = data_blob_null;
1024 if (!NT_STATUS_IS_OK(status) &&
1025 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1027 tevent_req_nterror(req, status);
1028 return;
1031 if (NT_STATUS_IS_OK(status)) {
1032 state->local_ready = true;
1035 if (state->local_ready && state->remote_ready) {
1036 cli_session_setup_gensec_ready(req);
1037 return;
1040 cli_session_setup_gensec_remote_next(req);
1043 static void cli_session_setup_gensec_remote_next(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 struct tevent_req *subreq = NULL;
1050 if (state->remote_ready) {
1051 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1052 return;
1055 subreq = cli_sesssetup_blob_send(state, state->ev,
1056 state->cli, state->blob_out);
1057 if (tevent_req_nomem(subreq, req)) {
1058 return;
1060 tevent_req_set_callback(subreq,
1061 cli_session_setup_gensec_remote_done,
1062 req);
1065 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1067 struct tevent_req *req =
1068 tevent_req_callback_data(subreq,
1069 struct tevent_req);
1070 struct cli_session_setup_gensec_state *state =
1071 tevent_req_data(req,
1072 struct cli_session_setup_gensec_state);
1073 NTSTATUS status;
1075 state->inbuf = NULL;
1076 TALLOC_FREE(state->recv_iov);
1078 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1079 &state->inbuf, &state->recv_iov);
1080 TALLOC_FREE(subreq);
1081 data_blob_free(&state->blob_out);
1082 if (!NT_STATUS_IS_OK(status) &&
1083 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1085 tevent_req_nterror(req, status);
1086 return;
1089 if (NT_STATUS_IS_OK(status)) {
1090 struct smbXcli_session *session = NULL;
1091 bool is_guest = false;
1093 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1094 session = state->cli->smb2.session;
1095 } else {
1096 session = state->cli->smb1.session;
1099 is_guest = smbXcli_session_is_guest(session);
1100 if (is_guest) {
1102 * We can't finish the gensec handshake, we don't
1103 * have a negotiated session key.
1105 * So just pretend we are completely done,
1106 * we need to continue as anonymous from this point,
1107 * as we can't get a session key.
1109 * Note that smbXcli_session_is_guest()
1110 * always returns false if we require signing.
1112 state->blob_in = data_blob_null;
1113 state->local_ready = true;
1114 state->is_anonymous = true;
1117 state->remote_ready = true;
1120 if (state->local_ready && state->remote_ready) {
1121 cli_session_setup_gensec_ready(req);
1122 return;
1125 cli_session_setup_gensec_local_next(req);
1128 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1130 struct cli_session_setup_gensec_state *state =
1131 tevent_req_data(req,
1132 struct cli_session_setup_gensec_state);
1133 const char *server_domain = NULL;
1134 NTSTATUS status;
1136 if (state->blob_in.length != 0) {
1137 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1138 return;
1141 if (state->blob_out.length != 0) {
1142 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1143 return;
1147 * gensec_ntlmssp_server_domain() returns NULL
1148 * if NTLMSSP is not used.
1150 * We can remove this later
1151 * and leave the server domain empty for SMB2 and above
1152 * in future releases.
1154 server_domain = gensec_ntlmssp_server_domain(
1155 state->auth_generic->gensec_security);
1157 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1158 TALLOC_FREE(state->cli->server_domain);
1159 state->cli->server_domain = talloc_strdup(state->cli,
1160 server_domain);
1161 if (state->cli->server_domain == NULL) {
1162 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1163 return;
1167 if (state->is_anonymous) {
1169 * Windows server does not set the
1170 * SMB2_SESSION_FLAG_IS_NULL flag.
1172 * This fix makes sure we do not try
1173 * to verify a signature on the final
1174 * session setup response.
1176 tevent_req_done(req);
1177 return;
1180 status = gensec_session_key(state->auth_generic->gensec_security,
1181 state, &state->session_key);
1182 if (tevent_req_nterror(req, status)) {
1183 return;
1186 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1187 struct smbXcli_session *session = state->cli->smb2.session;
1189 status = smb2cli_session_set_session_key(session,
1190 state->session_key,
1191 state->recv_iov);
1192 if (tevent_req_nterror(req, status)) {
1193 return;
1195 } else {
1196 struct smbXcli_session *session = state->cli->smb1.session;
1197 bool active;
1199 status = smb1cli_session_set_session_key(session,
1200 state->session_key);
1201 if (tevent_req_nterror(req, status)) {
1202 return;
1205 active = smb1cli_conn_activate_signing(state->cli->conn,
1206 state->session_key,
1207 data_blob_null);
1208 if (active) {
1209 bool ok;
1211 ok = smb1cli_conn_check_signing(state->cli->conn,
1212 state->inbuf, 1);
1213 if (!ok) {
1214 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1215 return;
1220 tevent_req_done(req);
1223 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1225 struct cli_session_setup_gensec_state *state =
1226 tevent_req_data(req,
1227 struct cli_session_setup_gensec_state);
1228 NTSTATUS status;
1230 if (tevent_req_is_nterror(req, &status)) {
1231 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1232 return status;
1234 return NT_STATUS_OK;
1237 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1238 const char *principal)
1240 char *account, *p;
1242 account = talloc_strdup(mem_ctx, principal);
1243 if (account == NULL) {
1244 return NULL;
1246 p = strchr_m(account, '@');
1247 if (p != NULL) {
1248 *p = '\0';
1250 return account;
1253 /****************************************************************************
1254 Do a spnego encrypted session setup.
1256 user_domain: The shortname of the domain the user/machine is a member of.
1257 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1258 ****************************************************************************/
1260 struct cli_session_setup_spnego_state {
1261 ADS_STATUS result;
1264 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1266 static struct tevent_req *cli_session_setup_spnego_send(
1267 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1268 struct cli_credentials *creds)
1270 struct tevent_req *req, *subreq;
1271 struct cli_session_setup_spnego_state *state;
1272 const char *target_service = NULL;
1273 const char *target_hostname = NULL;
1274 NTSTATUS status;
1276 req = tevent_req_create(mem_ctx, &state,
1277 struct cli_session_setup_spnego_state);
1278 if (req == NULL) {
1279 return NULL;
1282 target_service = "cifs";
1283 target_hostname = smbXcli_conn_remote_name(cli->conn);
1285 status = cli_session_creds_prepare_krb5(cli, creds);
1286 if (tevent_req_nterror(req, status)) {
1287 return tevent_req_post(req, ev);;
1290 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1291 target_service, target_hostname);
1292 if (tevent_req_nomem(subreq, req)) {
1293 return tevent_req_post(req, ev);
1295 tevent_req_set_callback(
1296 subreq, cli_session_setup_spnego_done, req);
1297 return req;
1300 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1302 struct tevent_req *req = tevent_req_callback_data(
1303 subreq, struct tevent_req);
1304 NTSTATUS status;
1306 status = cli_session_setup_gensec_recv(subreq);
1307 TALLOC_FREE(subreq);
1308 if (tevent_req_nterror(req, status)) {
1309 return;
1312 tevent_req_done(req);
1315 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1317 struct cli_session_setup_spnego_state *state = tevent_req_data(
1318 req, struct cli_session_setup_spnego_state);
1319 NTSTATUS status;
1321 if (tevent_req_is_nterror(req, &status)) {
1322 state->result = ADS_ERROR_NT(status);
1325 return state->result;
1328 struct cli_session_setup_creds_state {
1329 struct cli_state *cli;
1330 DATA_BLOB apassword_blob;
1331 DATA_BLOB upassword_blob;
1332 DATA_BLOB lm_session_key;
1333 DATA_BLOB session_key;
1334 char *out_native_os;
1335 char *out_native_lm;
1336 char *out_primary_domain;
1339 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1340 enum tevent_req_state req_state)
1342 struct cli_session_setup_creds_state *state = tevent_req_data(
1343 req, struct cli_session_setup_creds_state);
1345 if (req_state != TEVENT_REQ_RECEIVED) {
1346 return;
1350 * We only call data_blob_clear() as
1351 * some of the blobs point to the same memory.
1353 * We let the talloc hierachy free the memory.
1355 data_blob_clear(&state->apassword_blob);
1356 data_blob_clear(&state->upassword_blob);
1357 data_blob_clear(&state->lm_session_key);
1358 data_blob_clear(&state->session_key);
1359 ZERO_STRUCTP(state);
1362 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1363 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1364 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1366 /****************************************************************************
1367 Send a session setup. The username and workgroup is in UNIX character
1368 format and must be converted to DOS codepage format before sending. If the
1369 password is in plaintext, the same should be done.
1370 ****************************************************************************/
1372 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1373 struct tevent_context *ev,
1374 struct cli_state *cli,
1375 struct cli_credentials *creds)
1377 struct tevent_req *req, *subreq;
1378 struct cli_session_setup_creds_state *state;
1379 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1380 bool use_spnego = false;
1381 int flags = 0;
1382 enum credentials_use_kerberos krb5_state;
1383 uint32_t gensec_features;
1384 const char *username = "";
1385 const char *domain = "";
1386 DATA_BLOB target_info = data_blob_null;
1387 DATA_BLOB challenge = data_blob_null;
1388 uint16_t in_buf_size = 0;
1389 uint16_t in_mpx_max = 0;
1390 uint16_t in_vc_num = 0;
1391 uint32_t in_sess_key = 0;
1392 const char *in_native_os = NULL;
1393 const char *in_native_lm = NULL;
1394 NTSTATUS status;
1396 req = tevent_req_create(mem_ctx, &state,
1397 struct cli_session_setup_creds_state);
1398 if (req == NULL) {
1399 return NULL;
1401 state->cli = cli;
1403 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1405 krb5_state = cli_credentials_get_kerberos_state(creds);
1406 gensec_features = cli_credentials_get_gensec_features(creds);
1408 switch (krb5_state) {
1409 case CRED_MUST_USE_KERBEROS:
1410 cli->use_kerberos = true;
1411 cli->fallback_after_kerberos = false;
1412 break;
1413 case CRED_AUTO_USE_KERBEROS:
1414 cli->use_kerberos = true;
1415 cli->fallback_after_kerberos = true;
1416 break;
1417 case CRED_DONT_USE_KERBEROS:
1418 cli->use_kerberos = false;
1419 cli->fallback_after_kerberos = false;
1420 break;
1423 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
1424 cli->use_ccache = true;
1425 } else {
1426 cli->use_ccache = false;
1430 * Now work out what sort of session setup we are going to
1431 * do. I have split this into separate functions to make the flow a bit
1432 * easier to understand (tridge).
1434 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1435 use_spnego = false;
1436 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1437 use_spnego = true;
1438 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1440 * if the server supports extended security then use SPNEGO
1441 * even for anonymous connections.
1443 use_spnego = true;
1444 } else {
1445 use_spnego = false;
1448 if (use_spnego) {
1449 subreq = cli_session_setup_spnego_send(
1450 state, ev, cli, creds);
1451 if (tevent_req_nomem(subreq, req)) {
1452 return tevent_req_post(req, ev);
1454 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1455 req);
1456 return req;
1459 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1461 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1462 * this step against older servers.
1464 tevent_req_done(req);
1465 return tevent_req_post(req, ev);
1468 if (cli_credentials_is_anonymous(creds)) {
1470 * Do an anonymous session setup
1472 goto non_spnego_creds_done;
1475 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1477 * Do an anonymous session setup,
1478 * the password is passed via the tree connect.
1480 goto non_spnego_creds_done;
1483 cli_credentials_get_ntlm_username_domain(creds, state,
1484 &username,
1485 &domain);
1486 if (tevent_req_nomem(username, req)) {
1487 return tevent_req_post(req, ev);
1489 if (tevent_req_nomem(domain, req)) {
1490 return tevent_req_post(req, ev);
1493 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1494 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1495 uint8_t *bytes = NULL;
1496 size_t bytes_len = 0;
1497 const char *pw = cli_credentials_get_password(creds);
1498 size_t pw_len = 0;
1500 if (pw == NULL) {
1501 pw = "";
1503 pw_len = strlen(pw) + 1;
1505 if (!lp_client_plaintext_auth()) {
1506 DEBUG(1, ("Server requested PLAINTEXT password but "
1507 "'client plaintext auth = no'\n"));
1508 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1509 return tevent_req_post(req, ev);
1512 bytes = talloc_array(state, uint8_t, 0);
1513 bytes = trans2_bytes_push_str(bytes, use_unicode,
1514 pw, pw_len, &bytes_len);
1515 if (tevent_req_nomem(bytes, req)) {
1516 return tevent_req_post(req, ev);
1519 if (use_unicode) {
1521 * CAP_UNICODE, can only be negotiated by NT1.
1523 state->upassword_blob = data_blob_const(bytes,
1524 bytes_len);
1525 } else {
1526 state->apassword_blob = data_blob_const(bytes,
1527 bytes_len);
1530 goto non_spnego_creds_done;
1533 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1535 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1536 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1538 * Don't send an NTLMv2 response without NTLMSSP if we
1539 * want to use spnego support.
1541 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1542 " but 'client use spnego = yes'"
1543 " and 'client ntlmv2 auth = yes' is set\n"));
1544 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1545 return tevent_req_post(req, ev);
1548 if (lp_client_ntlmv2_auth()) {
1549 flags |= CLI_CRED_NTLMv2_AUTH;
1552 * note that the 'domain' here is a best
1553 * guess - we don't know the server's domain
1554 * at this point. Windows clients also don't
1555 * use hostname...
1557 target_info = NTLMv2_generate_names_blob(state,
1558 NULL,
1559 domain);
1560 if (tevent_req_nomem(target_info.data, req)) {
1561 return tevent_req_post(req, ev);
1563 } else {
1564 flags |= CLI_CRED_NTLM_AUTH;
1565 if (lp_client_lanman_auth()) {
1566 flags |= CLI_CRED_LANMAN_AUTH;
1569 } else {
1570 if (!lp_client_lanman_auth()) {
1571 DEBUG(1, ("Server requested user level LM password but "
1572 "'client lanman auth = no' is set.\n"));
1573 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1574 return tevent_req_post(req, ev);
1577 flags |= CLI_CRED_LANMAN_AUTH;
1580 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1581 challenge, NULL,
1582 target_info,
1583 &state->apassword_blob,
1584 &state->upassword_blob,
1585 &state->lm_session_key,
1586 &state->session_key);
1587 if (tevent_req_nterror(req, status)) {
1588 return tevent_req_post(req, ev);
1591 non_spnego_creds_done:
1593 in_buf_size = CLI_BUFFER_SIZE;
1594 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1595 in_vc_num = cli_state_get_vc_num(cli);
1596 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1597 in_native_os = "Unix";
1598 in_native_lm = "Samba";
1600 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1601 uint32_t in_capabilities = 0;
1603 in_capabilities = cli_session_setup_capabilities(cli, 0);
1606 * For now we keep the same values as before,
1607 * we may remove these in a separate commit later.
1609 in_mpx_max = 2;
1611 subreq = smb1cli_session_setup_nt1_send(state, ev,
1612 cli->conn,
1613 cli->timeout,
1614 cli->smb1.pid,
1615 cli->smb1.session,
1616 in_buf_size,
1617 in_mpx_max,
1618 in_vc_num,
1619 in_sess_key,
1620 username,
1621 domain,
1622 state->apassword_blob,
1623 state->upassword_blob,
1624 in_capabilities,
1625 in_native_os,
1626 in_native_lm);
1627 if (tevent_req_nomem(subreq, req)) {
1628 return tevent_req_post(req, ev);
1630 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1631 req);
1632 return req;
1636 * For now we keep the same values as before,
1637 * we may remove these in a separate commit later.
1639 in_mpx_max = 2;
1640 in_vc_num = 1;
1642 subreq = smb1cli_session_setup_lm21_send(state, ev,
1643 cli->conn,
1644 cli->timeout,
1645 cli->smb1.pid,
1646 cli->smb1.session,
1647 in_buf_size,
1648 in_mpx_max,
1649 in_vc_num,
1650 in_sess_key,
1651 username,
1652 domain,
1653 state->apassword_blob,
1654 in_native_os,
1655 in_native_lm);
1656 if (tevent_req_nomem(subreq, req)) {
1657 return tevent_req_post(req, ev);
1659 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1660 req);
1661 return req;
1664 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1666 struct tevent_req *req = tevent_req_callback_data(
1667 subreq, struct tevent_req);
1668 ADS_STATUS status;
1670 status = cli_session_setup_spnego_recv(subreq);
1671 TALLOC_FREE(subreq);
1672 if (!ADS_ERR_OK(status)) {
1673 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1674 tevent_req_nterror(req, ads_ntstatus(status));
1675 return;
1677 tevent_req_done(req);
1680 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1682 struct tevent_req *req = tevent_req_callback_data(
1683 subreq, struct tevent_req);
1684 struct cli_session_setup_creds_state *state = tevent_req_data(
1685 req, struct cli_session_setup_creds_state);
1686 struct cli_state *cli = state->cli;
1687 NTSTATUS status;
1688 struct iovec *recv_iov = NULL;
1689 const uint8_t *inbuf = NULL;
1690 bool ok;
1692 status = smb1cli_session_setup_nt1_recv(subreq, state,
1693 &recv_iov,
1694 &inbuf,
1695 &state->out_native_os,
1696 &state->out_native_lm,
1697 &state->out_primary_domain);
1698 TALLOC_FREE(subreq);
1699 if (!NT_STATUS_IS_OK(status)) {
1700 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1701 tevent_req_nterror(req, status);
1702 return;
1705 status = cli_state_update_after_sesssetup(state->cli,
1706 state->out_native_os,
1707 state->out_native_lm,
1708 state->out_primary_domain);
1709 if (tevent_req_nterror(req, status)) {
1710 return;
1713 ok = smb1cli_conn_activate_signing(cli->conn,
1714 state->session_key,
1715 state->upassword_blob);
1716 if (ok) {
1717 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1718 if (!ok) {
1719 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1720 return;
1724 if (state->session_key.data) {
1725 struct smbXcli_session *session = cli->smb1.session;
1727 status = smb1cli_session_set_session_key(session,
1728 state->session_key);
1729 if (tevent_req_nterror(req, status)) {
1730 return;
1734 tevent_req_done(req);
1737 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1739 struct tevent_req *req = tevent_req_callback_data(
1740 subreq, struct tevent_req);
1741 struct cli_session_setup_creds_state *state = tevent_req_data(
1742 req, struct cli_session_setup_creds_state);
1743 NTSTATUS status;
1745 status = smb1cli_session_setup_lm21_recv(subreq, state,
1746 &state->out_native_os,
1747 &state->out_native_lm);
1748 TALLOC_FREE(subreq);
1749 if (!NT_STATUS_IS_OK(status)) {
1750 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1751 tevent_req_nterror(req, status);
1752 return;
1755 status = cli_state_update_after_sesssetup(state->cli,
1756 state->out_native_os,
1757 state->out_native_lm,
1758 NULL);
1759 if (tevent_req_nterror(req, status)) {
1760 return;
1763 tevent_req_done(req);
1766 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1768 return tevent_req_simple_recv_ntstatus(req);
1771 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1772 struct cli_credentials *creds)
1774 struct tevent_context *ev;
1775 struct tevent_req *req;
1776 NTSTATUS status = NT_STATUS_NO_MEMORY;
1778 if (smbXcli_conn_has_async_calls(cli->conn)) {
1779 return NT_STATUS_INVALID_PARAMETER;
1781 ev = samba_tevent_context_init(talloc_tos());
1782 if (ev == NULL) {
1783 goto fail;
1785 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1786 if (req == NULL) {
1787 goto fail;
1789 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1790 goto fail;
1792 status = cli_session_setup_creds_recv(req);
1793 fail:
1794 TALLOC_FREE(ev);
1795 return status;
1798 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1800 NTSTATUS status = NT_STATUS_NO_MEMORY;
1801 struct cli_credentials *creds = NULL;
1803 creds = cli_credentials_init_anon(cli);
1804 if (creds == NULL) {
1805 return NT_STATUS_NO_MEMORY;
1808 status = cli_session_setup_creds(cli, creds);
1809 TALLOC_FREE(creds);
1810 if (!NT_STATUS_IS_OK(status)) {
1811 return status;
1814 return NT_STATUS_OK;
1817 /****************************************************************************
1818 Send a uloggoff.
1819 *****************************************************************************/
1821 struct cli_ulogoff_state {
1822 struct cli_state *cli;
1823 uint16_t vwv[3];
1826 static void cli_ulogoff_done(struct tevent_req *subreq);
1828 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1829 struct tevent_context *ev,
1830 struct cli_state *cli)
1832 struct tevent_req *req, *subreq;
1833 struct cli_ulogoff_state *state;
1835 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1836 if (req == NULL) {
1837 return NULL;
1839 state->cli = cli;
1841 SCVAL(state->vwv+0, 0, 0xFF);
1842 SCVAL(state->vwv+1, 0, 0);
1843 SSVAL(state->vwv+2, 0, 0);
1845 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1846 0, NULL);
1847 if (tevent_req_nomem(subreq, req)) {
1848 return tevent_req_post(req, ev);
1850 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1851 return req;
1854 static void cli_ulogoff_done(struct tevent_req *subreq)
1856 struct tevent_req *req = tevent_req_callback_data(
1857 subreq, struct tevent_req);
1858 struct cli_ulogoff_state *state = tevent_req_data(
1859 req, struct cli_ulogoff_state);
1860 NTSTATUS status;
1862 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1863 if (!NT_STATUS_IS_OK(status)) {
1864 tevent_req_nterror(req, status);
1865 return;
1867 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1868 tevent_req_done(req);
1871 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1873 return tevent_req_simple_recv_ntstatus(req);
1876 NTSTATUS cli_ulogoff(struct cli_state *cli)
1878 struct tevent_context *ev;
1879 struct tevent_req *req;
1880 NTSTATUS status = NT_STATUS_NO_MEMORY;
1882 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1883 status = smb2cli_logoff(cli->conn,
1884 cli->timeout,
1885 cli->smb2.session);
1886 if (!NT_STATUS_IS_OK(status)) {
1887 return status;
1889 smb2cli_session_set_id_and_flags(cli->smb2.session,
1890 UINT64_MAX, 0);
1891 return NT_STATUS_OK;
1894 if (smbXcli_conn_has_async_calls(cli->conn)) {
1895 return NT_STATUS_INVALID_PARAMETER;
1897 ev = samba_tevent_context_init(talloc_tos());
1898 if (ev == NULL) {
1899 goto fail;
1901 req = cli_ulogoff_send(ev, ev, cli);
1902 if (req == NULL) {
1903 goto fail;
1905 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1906 goto fail;
1908 status = cli_ulogoff_recv(req);
1909 fail:
1910 TALLOC_FREE(ev);
1911 return status;
1914 /****************************************************************************
1915 Send a tconX.
1916 ****************************************************************************/
1918 struct cli_tcon_andx_state {
1919 struct cli_state *cli;
1920 uint16_t vwv[4];
1921 struct iovec bytes;
1924 static void cli_tcon_andx_done(struct tevent_req *subreq);
1926 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1927 struct tevent_context *ev,
1928 struct cli_state *cli,
1929 const char *share, const char *dev,
1930 const char *pass, int passlen,
1931 struct tevent_req **psmbreq)
1933 struct tevent_req *req, *subreq;
1934 struct cli_tcon_andx_state *state;
1935 uint8_t p24[24];
1936 uint16_t *vwv;
1937 char *tmp = NULL;
1938 uint8_t *bytes;
1939 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1940 uint16_t tcon_flags = 0;
1942 *psmbreq = NULL;
1944 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1945 if (req == NULL) {
1946 return NULL;
1948 state->cli = cli;
1949 vwv = state->vwv;
1951 TALLOC_FREE(cli->smb1.tcon);
1952 cli->smb1.tcon = smbXcli_tcon_create(cli);
1953 if (tevent_req_nomem(cli->smb1.tcon, req)) {
1954 return tevent_req_post(req, ev);
1956 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
1958 cli->share = talloc_strdup(cli, share);
1959 if (!cli->share) {
1960 return NULL;
1963 /* in user level security don't send a password now */
1964 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1965 passlen = 1;
1966 pass = "";
1967 } else if (pass == NULL) {
1968 DEBUG(1, ("Server not using user level security and no "
1969 "password supplied.\n"));
1970 goto access_denied;
1973 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1974 *pass && passlen != 24) {
1975 if (!lp_client_lanman_auth()) {
1976 DEBUG(1, ("Server requested LANMAN password "
1977 "(share-level security) but "
1978 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1979 goto access_denied;
1983 * Non-encrypted passwords - convert to DOS codepage before
1984 * encryption.
1986 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1987 passlen = 24;
1988 pass = (const char *)p24;
1989 } else {
1990 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1991 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1992 == 0) {
1993 uint8_t *tmp_pass;
1995 if (!lp_client_plaintext_auth() && (*pass)) {
1996 DEBUG(1, ("Server requested PLAINTEXT "
1997 "password but "
1998 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
1999 goto access_denied;
2003 * Non-encrypted passwords - convert to DOS codepage
2004 * before using.
2006 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2007 if (tevent_req_nomem(tmp_pass, req)) {
2008 return tevent_req_post(req, ev);
2010 tmp_pass = trans2_bytes_push_str(tmp_pass,
2011 false, /* always DOS */
2012 pass,
2013 passlen,
2014 NULL);
2015 if (tevent_req_nomem(tmp_pass, req)) {
2016 return tevent_req_post(req, ev);
2018 pass = (const char *)tmp_pass;
2019 passlen = talloc_get_size(tmp_pass);
2023 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2024 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2026 SCVAL(vwv+0, 0, 0xFF);
2027 SCVAL(vwv+0, 1, 0);
2028 SSVAL(vwv+1, 0, 0);
2029 SSVAL(vwv+2, 0, tcon_flags);
2030 SSVAL(vwv+3, 0, passlen);
2032 if (passlen && pass) {
2033 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2034 } else {
2035 bytes = talloc_array(state, uint8_t, 0);
2039 * Add the sharename
2041 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2042 smbXcli_conn_remote_name(cli->conn), share);
2043 if (tmp == NULL) {
2044 TALLOC_FREE(req);
2045 return NULL;
2047 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2048 NULL);
2049 TALLOC_FREE(tmp);
2052 * Add the devicetype
2054 tmp = talloc_strdup_upper(talloc_tos(), dev);
2055 if (tmp == NULL) {
2056 TALLOC_FREE(req);
2057 return NULL;
2059 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2060 TALLOC_FREE(tmp);
2062 if (bytes == NULL) {
2063 TALLOC_FREE(req);
2064 return NULL;
2067 state->bytes.iov_base = (void *)bytes;
2068 state->bytes.iov_len = talloc_get_size(bytes);
2070 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2071 1, &state->bytes);
2072 if (subreq == NULL) {
2073 TALLOC_FREE(req);
2074 return NULL;
2076 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2077 *psmbreq = subreq;
2078 return req;
2080 access_denied:
2081 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2082 return tevent_req_post(req, ev);
2085 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2086 struct tevent_context *ev,
2087 struct cli_state *cli,
2088 const char *share, const char *dev,
2089 const char *pass, int passlen)
2091 struct tevent_req *req, *subreq;
2092 NTSTATUS status;
2094 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2095 &subreq);
2096 if (req == NULL) {
2097 return NULL;
2099 if (subreq == NULL) {
2100 return req;
2102 status = smb1cli_req_chain_submit(&subreq, 1);
2103 if (!NT_STATUS_IS_OK(status)) {
2104 tevent_req_nterror(req, status);
2105 return tevent_req_post(req, ev);
2107 return req;
2110 static void cli_tcon_andx_done(struct tevent_req *subreq)
2112 struct tevent_req *req = tevent_req_callback_data(
2113 subreq, struct tevent_req);
2114 struct cli_tcon_andx_state *state = tevent_req_data(
2115 req, struct cli_tcon_andx_state);
2116 struct cli_state *cli = state->cli;
2117 uint8_t *in;
2118 uint8_t *inhdr;
2119 uint8_t wct;
2120 uint16_t *vwv;
2121 uint32_t num_bytes;
2122 uint8_t *bytes;
2123 NTSTATUS status;
2124 uint16_t optional_support = 0;
2126 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2127 &num_bytes, &bytes);
2128 TALLOC_FREE(subreq);
2129 if (!NT_STATUS_IS_OK(status)) {
2130 tevent_req_nterror(req, status);
2131 return;
2134 inhdr = in + NBT_HDR_SIZE;
2136 if (num_bytes) {
2137 if (clistr_pull_talloc(cli,
2138 (const char *)inhdr,
2139 SVAL(inhdr, HDR_FLG2),
2140 &cli->dev,
2141 bytes,
2142 num_bytes,
2143 STR_TERMINATE|STR_ASCII) == -1) {
2144 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2145 return;
2147 } else {
2148 cli->dev = talloc_strdup(cli, "");
2149 if (cli->dev == NULL) {
2150 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2151 return;
2155 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2156 /* almost certainly win95 - enable bug fixes */
2157 cli->win95 = True;
2161 * Make sure that we have the optional support 16-bit field. WCT > 2.
2162 * Avoids issues when connecting to Win9x boxes sharing files
2165 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2166 optional_support = SVAL(vwv+2, 0);
2169 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2170 smb1cli_session_protect_session_key(cli->smb1.session);
2173 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2174 SVAL(inhdr, HDR_TID),
2175 optional_support,
2176 0, /* maximal_access */
2177 0, /* guest_maximal_access */
2178 NULL, /* service */
2179 NULL); /* fs_type */
2181 tevent_req_done(req);
2184 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2186 return tevent_req_simple_recv_ntstatus(req);
2189 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2190 const char *dev, const char *pass, int passlen)
2192 TALLOC_CTX *frame = talloc_stackframe();
2193 struct tevent_context *ev;
2194 struct tevent_req *req;
2195 NTSTATUS status = NT_STATUS_NO_MEMORY;
2197 if (smbXcli_conn_has_async_calls(cli->conn)) {
2199 * Can't use sync call while an async call is in flight
2201 status = NT_STATUS_INVALID_PARAMETER;
2202 goto fail;
2205 ev = samba_tevent_context_init(frame);
2206 if (ev == NULL) {
2207 goto fail;
2210 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2211 if (req == NULL) {
2212 goto fail;
2215 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2216 goto fail;
2219 status = cli_tcon_andx_recv(req);
2220 fail:
2221 TALLOC_FREE(frame);
2222 return status;
2225 struct cli_tree_connect_state {
2226 struct cli_state *cli;
2229 static struct tevent_req *cli_raw_tcon_send(
2230 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2231 const char *service, const char *pass, const char *dev);
2232 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2233 uint16_t *max_xmit, uint16_t *tid);
2235 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2236 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2237 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2239 static struct tevent_req *cli_tree_connect_send(
2240 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2241 const char *share, const char *dev, const char *pass)
2243 struct tevent_req *req, *subreq;
2244 struct cli_tree_connect_state *state;
2245 int passlen;
2247 if (pass == NULL) {
2248 pass = "";
2250 passlen = strlen(pass) + 1;
2252 req = tevent_req_create(mem_ctx, &state,
2253 struct cli_tree_connect_state);
2254 if (req == NULL) {
2255 return NULL;
2257 state->cli = cli;
2259 cli->share = talloc_strdup(cli, share);
2260 if (tevent_req_nomem(cli->share, req)) {
2261 return tevent_req_post(req, ev);
2264 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2265 char *unc;
2267 TALLOC_FREE(cli->smb2.tcon);
2268 cli->smb2.tcon = smbXcli_tcon_create(cli);
2269 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2270 return tevent_req_post(req, ev);
2273 unc = talloc_asprintf(state, "\\\\%s\\%s",
2274 smbXcli_conn_remote_name(cli->conn),
2275 share);
2276 if (tevent_req_nomem(unc, req)) {
2277 return tevent_req_post(req, ev);
2280 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2281 cli->smb2.session, cli->smb2.tcon,
2282 0, /* flags */
2283 unc);
2284 if (tevent_req_nomem(subreq, req)) {
2285 return tevent_req_post(req, ev);
2287 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2288 req);
2289 return req;
2292 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2293 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2294 pass, passlen);
2295 if (tevent_req_nomem(subreq, req)) {
2296 return tevent_req_post(req, ev);
2298 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2299 req);
2300 return req;
2303 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2304 if (tevent_req_nomem(subreq, req)) {
2305 return tevent_req_post(req, ev);
2307 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2309 return req;
2312 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2314 tevent_req_simple_finish_ntstatus(
2315 subreq, smb2cli_tcon_recv(subreq));
2318 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2320 tevent_req_simple_finish_ntstatus(
2321 subreq, cli_tcon_andx_recv(subreq));
2324 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2326 struct tevent_req *req = tevent_req_callback_data(
2327 subreq, struct tevent_req);
2328 struct cli_tree_connect_state *state = tevent_req_data(
2329 req, struct cli_tree_connect_state);
2330 NTSTATUS status;
2331 uint16_t max_xmit = 0;
2332 uint16_t tid = 0;
2334 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2335 if (tevent_req_nterror(req, status)) {
2336 return;
2339 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2340 tid,
2341 0, /* optional_support */
2342 0, /* maximal_access */
2343 0, /* guest_maximal_access */
2344 NULL, /* service */
2345 NULL); /* fs_type */
2347 tevent_req_done(req);
2350 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2352 return tevent_req_simple_recv_ntstatus(req);
2355 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2356 const char *dev, const char *pass)
2358 struct tevent_context *ev;
2359 struct tevent_req *req;
2360 NTSTATUS status = NT_STATUS_NO_MEMORY;
2362 if (smbXcli_conn_has_async_calls(cli->conn)) {
2363 return NT_STATUS_INVALID_PARAMETER;
2365 ev = samba_tevent_context_init(talloc_tos());
2366 if (ev == NULL) {
2367 goto fail;
2369 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2370 if (req == NULL) {
2371 goto fail;
2373 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2374 goto fail;
2376 status = cli_tree_connect_recv(req);
2377 fail:
2378 TALLOC_FREE(ev);
2379 return status;
2382 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2383 const char *share, const char *dev,
2384 struct cli_credentials *creds)
2386 const char *pw = NULL;
2388 if (creds != NULL) {
2389 pw = cli_credentials_get_password(creds);
2392 return cli_tree_connect(cli, share, dev, pw);
2395 /****************************************************************************
2396 Send a tree disconnect.
2397 ****************************************************************************/
2399 struct cli_tdis_state {
2400 struct cli_state *cli;
2403 static void cli_tdis_done(struct tevent_req *subreq);
2405 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2406 struct tevent_context *ev,
2407 struct cli_state *cli)
2409 struct tevent_req *req, *subreq;
2410 struct cli_tdis_state *state;
2412 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2413 if (req == NULL) {
2414 return NULL;
2416 state->cli = cli;
2418 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2419 if (tevent_req_nomem(subreq, req)) {
2420 return tevent_req_post(req, ev);
2422 tevent_req_set_callback(subreq, cli_tdis_done, req);
2423 return req;
2426 static void cli_tdis_done(struct tevent_req *subreq)
2428 struct tevent_req *req = tevent_req_callback_data(
2429 subreq, struct tevent_req);
2430 struct cli_tdis_state *state = tevent_req_data(
2431 req, struct cli_tdis_state);
2432 NTSTATUS status;
2434 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2435 TALLOC_FREE(subreq);
2436 if (!NT_STATUS_IS_OK(status)) {
2437 tevent_req_nterror(req, status);
2438 return;
2440 TALLOC_FREE(state->cli->smb1.tcon);
2441 tevent_req_done(req);
2444 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2446 return tevent_req_simple_recv_ntstatus(req);
2449 NTSTATUS cli_tdis(struct cli_state *cli)
2451 struct tevent_context *ev;
2452 struct tevent_req *req;
2453 NTSTATUS status = NT_STATUS_NO_MEMORY;
2455 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2456 status = smb2cli_tdis(cli->conn,
2457 cli->timeout,
2458 cli->smb2.session,
2459 cli->smb2.tcon);
2460 if (NT_STATUS_IS_OK(status)) {
2461 TALLOC_FREE(cli->smb2.tcon);
2463 return status;
2466 if (smbXcli_conn_has_async_calls(cli->conn)) {
2467 return NT_STATUS_INVALID_PARAMETER;
2469 ev = samba_tevent_context_init(talloc_tos());
2470 if (ev == NULL) {
2471 goto fail;
2473 req = cli_tdis_send(ev, ev, cli);
2474 if (req == NULL) {
2475 goto fail;
2477 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2478 goto fail;
2480 status = cli_tdis_recv(req);
2481 fail:
2482 TALLOC_FREE(ev);
2483 return status;
2486 struct cli_connect_sock_state {
2487 const char **called_names;
2488 const char **calling_names;
2489 int *called_types;
2490 int fd;
2491 uint16_t port;
2494 static void cli_connect_sock_done(struct tevent_req *subreq);
2497 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2498 * nonzero address.
2501 static struct tevent_req *cli_connect_sock_send(
2502 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2503 const char *host, int name_type, const struct sockaddr_storage *pss,
2504 const char *myname, uint16_t port)
2506 struct tevent_req *req, *subreq;
2507 struct cli_connect_sock_state *state;
2508 struct sockaddr_storage *addrs;
2509 unsigned i, num_addrs;
2510 NTSTATUS status;
2512 req = tevent_req_create(mem_ctx, &state,
2513 struct cli_connect_sock_state);
2514 if (req == NULL) {
2515 return NULL;
2518 if ((pss == NULL) || is_zero_addr(pss)) {
2521 * Here we cheat. resolve_name_list is not async at all. So
2522 * this call will only be really async if the name lookup has
2523 * been done externally.
2526 status = resolve_name_list(state, host, name_type,
2527 &addrs, &num_addrs);
2528 if (!NT_STATUS_IS_OK(status)) {
2529 tevent_req_nterror(req, status);
2530 return tevent_req_post(req, ev);
2532 } else {
2533 addrs = talloc_array(state, struct sockaddr_storage, 1);
2534 if (tevent_req_nomem(addrs, req)) {
2535 return tevent_req_post(req, ev);
2537 addrs[0] = *pss;
2538 num_addrs = 1;
2541 state->called_names = talloc_array(state, const char *, num_addrs);
2542 if (tevent_req_nomem(state->called_names, req)) {
2543 return tevent_req_post(req, ev);
2545 state->called_types = talloc_array(state, int, num_addrs);
2546 if (tevent_req_nomem(state->called_types, req)) {
2547 return tevent_req_post(req, ev);
2549 state->calling_names = talloc_array(state, const char *, num_addrs);
2550 if (tevent_req_nomem(state->calling_names, req)) {
2551 return tevent_req_post(req, ev);
2553 for (i=0; i<num_addrs; i++) {
2554 state->called_names[i] = host;
2555 state->called_types[i] = name_type;
2556 state->calling_names[i] = myname;
2559 subreq = smbsock_any_connect_send(
2560 state, ev, addrs, state->called_names, state->called_types,
2561 state->calling_names, NULL, num_addrs, port);
2562 if (tevent_req_nomem(subreq, req)) {
2563 return tevent_req_post(req, ev);
2565 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2566 return req;
2569 static void cli_connect_sock_done(struct tevent_req *subreq)
2571 struct tevent_req *req = tevent_req_callback_data(
2572 subreq, struct tevent_req);
2573 struct cli_connect_sock_state *state = tevent_req_data(
2574 req, struct cli_connect_sock_state);
2575 NTSTATUS status;
2577 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2578 &state->port);
2579 TALLOC_FREE(subreq);
2580 if (tevent_req_nterror(req, status)) {
2581 return;
2583 set_socket_options(state->fd, lp_socket_options());
2584 tevent_req_done(req);
2587 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2588 int *pfd, uint16_t *pport)
2590 struct cli_connect_sock_state *state = tevent_req_data(
2591 req, struct cli_connect_sock_state);
2592 NTSTATUS status;
2594 if (tevent_req_is_nterror(req, &status)) {
2595 return status;
2597 *pfd = state->fd;
2598 *pport = state->port;
2599 return NT_STATUS_OK;
2602 struct cli_connect_nb_state {
2603 const char *desthost;
2604 int signing_state;
2605 int flags;
2606 struct cli_state *cli;
2609 static void cli_connect_nb_done(struct tevent_req *subreq);
2611 static struct tevent_req *cli_connect_nb_send(
2612 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2613 const char *host, const struct sockaddr_storage *dest_ss,
2614 uint16_t port, int name_type, const char *myname,
2615 int signing_state, int flags)
2617 struct tevent_req *req, *subreq;
2618 struct cli_connect_nb_state *state;
2620 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2621 if (req == NULL) {
2622 return NULL;
2624 state->signing_state = signing_state;
2625 state->flags = flags;
2627 if (host != NULL) {
2628 char *p = strchr(host, '#');
2630 if (p != NULL) {
2631 name_type = strtol(p+1, NULL, 16);
2632 host = talloc_strndup(state, host, p - host);
2633 if (tevent_req_nomem(host, req)) {
2634 return tevent_req_post(req, ev);
2638 state->desthost = host;
2639 } else if (dest_ss != NULL) {
2640 state->desthost = print_canonical_sockaddr(state, dest_ss);
2641 if (tevent_req_nomem(state->desthost, req)) {
2642 return tevent_req_post(req, ev);
2644 } else {
2645 /* No host or dest_ss given. Error out. */
2646 tevent_req_error(req, EINVAL);
2647 return tevent_req_post(req, ev);
2650 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2651 myname, port);
2652 if (tevent_req_nomem(subreq, req)) {
2653 return tevent_req_post(req, ev);
2655 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2656 return req;
2659 static void cli_connect_nb_done(struct tevent_req *subreq)
2661 struct tevent_req *req = tevent_req_callback_data(
2662 subreq, struct tevent_req);
2663 struct cli_connect_nb_state *state = tevent_req_data(
2664 req, struct cli_connect_nb_state);
2665 NTSTATUS status;
2666 int fd = 0;
2667 uint16_t port;
2669 status = cli_connect_sock_recv(subreq, &fd, &port);
2670 TALLOC_FREE(subreq);
2671 if (tevent_req_nterror(req, status)) {
2672 return;
2675 state->cli = cli_state_create(state, fd, state->desthost,
2676 state->signing_state, state->flags);
2677 if (tevent_req_nomem(state->cli, req)) {
2678 close(fd);
2679 return;
2681 tevent_req_done(req);
2684 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2685 struct cli_state **pcli)
2687 struct cli_connect_nb_state *state = tevent_req_data(
2688 req, struct cli_connect_nb_state);
2689 NTSTATUS status;
2691 if (tevent_req_is_nterror(req, &status)) {
2692 return status;
2694 *pcli = talloc_move(NULL, &state->cli);
2695 return NT_STATUS_OK;
2698 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2699 uint16_t port, int name_type, const char *myname,
2700 int signing_state, int flags, struct cli_state **pcli)
2702 struct tevent_context *ev;
2703 struct tevent_req *req;
2704 NTSTATUS status = NT_STATUS_NO_MEMORY;
2706 ev = samba_tevent_context_init(talloc_tos());
2707 if (ev == NULL) {
2708 goto fail;
2710 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2711 myname, signing_state, flags);
2712 if (req == NULL) {
2713 goto fail;
2715 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2716 goto fail;
2718 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2719 goto fail;
2721 status = cli_connect_nb_recv(req, pcli);
2722 fail:
2723 TALLOC_FREE(ev);
2724 return status;
2727 struct cli_start_connection_state {
2728 struct tevent_context *ev;
2729 struct cli_state *cli;
2730 int min_protocol;
2731 int max_protocol;
2734 static void cli_start_connection_connected(struct tevent_req *subreq);
2735 static void cli_start_connection_done(struct tevent_req *subreq);
2738 establishes a connection to after the negprot.
2739 @param output_cli A fully initialised cli structure, non-null only on success
2740 @param dest_host The netbios name of the remote host
2741 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2742 @param port (optional) The destination port (0 for default)
2745 static struct tevent_req *cli_start_connection_send(
2746 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2747 const char *my_name, const char *dest_host,
2748 const struct sockaddr_storage *dest_ss, int port,
2749 int signing_state, int flags)
2751 struct tevent_req *req, *subreq;
2752 struct cli_start_connection_state *state;
2754 req = tevent_req_create(mem_ctx, &state,
2755 struct cli_start_connection_state);
2756 if (req == NULL) {
2757 return NULL;
2759 state->ev = ev;
2761 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
2762 state->min_protocol = lp_client_ipc_min_protocol();
2763 state->max_protocol = lp_client_ipc_max_protocol();
2764 } else {
2765 state->min_protocol = lp_client_min_protocol();
2766 state->max_protocol = lp_client_max_protocol();
2769 if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
2770 state->max_protocol = MIN(state->max_protocol, PROTOCOL_NT1);
2773 if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
2774 state->min_protocol = MAX(state->max_protocol, PROTOCOL_SMB2_02);
2775 state->max_protocol = MAX(state->max_protocol, PROTOCOL_LATEST);
2778 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2779 0x20, my_name, signing_state, flags);
2780 if (tevent_req_nomem(subreq, req)) {
2781 return tevent_req_post(req, ev);
2783 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2784 return req;
2787 static void cli_start_connection_connected(struct tevent_req *subreq)
2789 struct tevent_req *req = tevent_req_callback_data(
2790 subreq, struct tevent_req);
2791 struct cli_start_connection_state *state = tevent_req_data(
2792 req, struct cli_start_connection_state);
2793 NTSTATUS status;
2795 status = cli_connect_nb_recv(subreq, &state->cli);
2796 TALLOC_FREE(subreq);
2797 if (tevent_req_nterror(req, status)) {
2798 return;
2801 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2802 state->cli->timeout,
2803 state->min_protocol,
2804 state->max_protocol,
2805 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK);
2806 if (tevent_req_nomem(subreq, req)) {
2807 return;
2809 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2812 static void cli_start_connection_done(struct tevent_req *subreq)
2814 struct tevent_req *req = tevent_req_callback_data(
2815 subreq, struct tevent_req);
2816 struct cli_start_connection_state *state = tevent_req_data(
2817 req, struct cli_start_connection_state);
2818 NTSTATUS status;
2820 status = smbXcli_negprot_recv(subreq);
2821 TALLOC_FREE(subreq);
2822 if (tevent_req_nterror(req, status)) {
2823 return;
2826 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2827 /* Ensure we ask for some initial credits. */
2828 smb2cli_conn_set_max_credits(state->cli->conn,
2829 DEFAULT_SMB2_MAX_CREDITS);
2832 tevent_req_done(req);
2835 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2836 struct cli_state **output_cli)
2838 struct cli_start_connection_state *state = tevent_req_data(
2839 req, struct cli_start_connection_state);
2840 NTSTATUS status;
2842 if (tevent_req_is_nterror(req, &status)) {
2843 return status;
2845 *output_cli = state->cli;
2847 return NT_STATUS_OK;
2850 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2851 const char *my_name,
2852 const char *dest_host,
2853 const struct sockaddr_storage *dest_ss, int port,
2854 int signing_state, int flags)
2856 struct tevent_context *ev;
2857 struct tevent_req *req;
2858 NTSTATUS status = NT_STATUS_NO_MEMORY;
2860 ev = samba_tevent_context_init(talloc_tos());
2861 if (ev == NULL) {
2862 goto fail;
2864 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2865 port, signing_state, flags);
2866 if (req == NULL) {
2867 goto fail;
2869 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2870 goto fail;
2872 status = cli_start_connection_recv(req, output_cli);
2873 fail:
2874 TALLOC_FREE(ev);
2875 return status;
2878 struct cli_smb1_setup_encryption_blob_state {
2879 uint16_t setup[1];
2880 uint8_t param[4];
2881 NTSTATUS status;
2882 DATA_BLOB out;
2883 uint16_t enc_ctx_id;
2886 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2888 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2889 struct tevent_context *ev,
2890 struct cli_state *cli,
2891 const DATA_BLOB in)
2893 struct tevent_req *req = NULL;
2894 struct cli_smb1_setup_encryption_blob_state *state = NULL;
2895 struct tevent_req *subreq = NULL;
2897 req = tevent_req_create(mem_ctx, &state,
2898 struct cli_smb1_setup_encryption_blob_state);
2899 if (req == NULL) {
2900 return NULL;
2903 if (in.length > CLI_BUFFER_SIZE) {
2904 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2905 return tevent_req_post(req, ev);
2908 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
2909 SSVAL(state->param, 0, 0);
2910 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
2912 subreq = smb1cli_trans_send(state, ev, cli->conn,
2913 SMBtrans2,
2914 0, 0, /* _flags */
2915 0, 0, /* _flags2 */
2916 cli->timeout,
2917 cli->smb1.pid,
2918 cli->smb1.tcon,
2919 cli->smb1.session,
2920 NULL, /* pipe_name */
2921 0, /* fid */
2922 0, /* function */
2923 0, /* flags */
2924 state->setup, 1, 0,
2925 state->param, 4, 2,
2926 in.data, in.length, CLI_BUFFER_SIZE);
2927 if (tevent_req_nomem(subreq, req)) {
2928 return tevent_req_post(req, ev);
2930 tevent_req_set_callback(subreq,
2931 cli_smb1_setup_encryption_blob_done,
2932 req);
2934 return req;
2937 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
2939 struct tevent_req *req =
2940 tevent_req_callback_data(subreq,
2941 struct tevent_req);
2942 struct cli_smb1_setup_encryption_blob_state *state =
2943 tevent_req_data(req,
2944 struct cli_smb1_setup_encryption_blob_state);
2945 uint8_t *rparam=NULL, *rdata=NULL;
2946 uint32_t num_rparam, num_rdata;
2947 NTSTATUS status;
2949 status = smb1cli_trans_recv(subreq, state,
2950 NULL, /* recv_flags */
2951 NULL, 0, NULL, /* rsetup */
2952 &rparam, 0, &num_rparam,
2953 &rdata, 0, &num_rdata);
2954 TALLOC_FREE(subreq);
2955 state->status = status;
2956 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2957 status = NT_STATUS_OK;
2959 if (tevent_req_nterror(req, status)) {
2960 return;
2963 if (num_rparam == 2) {
2964 state->enc_ctx_id = SVAL(rparam, 0);
2966 TALLOC_FREE(rparam);
2968 state->out = data_blob_const(rdata, num_rdata);
2970 tevent_req_done(req);
2973 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
2974 TALLOC_CTX *mem_ctx,
2975 DATA_BLOB *out,
2976 uint16_t *enc_ctx_id)
2978 struct cli_smb1_setup_encryption_blob_state *state =
2979 tevent_req_data(req,
2980 struct cli_smb1_setup_encryption_blob_state);
2981 NTSTATUS status;
2983 if (tevent_req_is_nterror(req, &status)) {
2984 tevent_req_received(req);
2985 return status;
2988 status = state->status;
2990 *out = state->out;
2991 talloc_steal(mem_ctx, out->data);
2993 *enc_ctx_id = state->enc_ctx_id;
2995 tevent_req_received(req);
2996 return status;
2999 struct cli_smb1_setup_encryption_state {
3000 struct tevent_context *ev;
3001 struct cli_state *cli;
3002 struct smb_trans_enc_state *es;
3003 DATA_BLOB blob_in;
3004 DATA_BLOB blob_out;
3005 bool local_ready;
3006 bool remote_ready;
3009 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
3010 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
3011 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
3012 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
3013 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
3015 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
3016 struct tevent_context *ev,
3017 struct cli_state *cli,
3018 struct cli_credentials *creds)
3020 struct tevent_req *req = NULL;
3021 struct cli_smb1_setup_encryption_state *state = NULL;
3022 struct auth_generic_state *ags = NULL;
3023 const DATA_BLOB *b = NULL;
3024 bool auth_requested = false;
3025 const char *target_service = NULL;
3026 const char *target_hostname = NULL;
3027 NTSTATUS status;
3029 req = tevent_req_create(mem_ctx, &state,
3030 struct cli_smb1_setup_encryption_state);
3031 if (req == NULL) {
3032 return NULL;
3034 state->ev = ev;
3035 state->cli = cli;
3037 auth_requested = cli_credentials_authentication_requested(creds);
3038 if (!auth_requested) {
3039 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3040 return tevent_req_post(req, ev);
3043 target_service = "cifs";
3044 target_hostname = smbXcli_conn_remote_name(cli->conn);
3046 status = cli_session_creds_prepare_krb5(cli, creds);
3047 if (tevent_req_nterror(req, status)) {
3048 return tevent_req_post(req, ev);
3051 state->es = talloc_zero(state, struct smb_trans_enc_state);
3052 if (tevent_req_nomem(state->es, req)) {
3053 return tevent_req_post(req, ev);
3056 status = auth_generic_client_prepare(state->es, &ags);
3057 if (tevent_req_nterror(req, status)) {
3058 return tevent_req_post(req, ev);
3061 gensec_want_feature(ags->gensec_security,
3062 GENSEC_FEATURE_SIGN);
3063 gensec_want_feature(ags->gensec_security,
3064 GENSEC_FEATURE_SEAL);
3066 status = auth_generic_set_creds(ags, creds);
3067 if (tevent_req_nterror(req, status)) {
3068 return tevent_req_post(req, ev);
3071 if (target_service != NULL) {
3072 status = gensec_set_target_service(ags->gensec_security,
3073 target_service);
3074 if (tevent_req_nterror(req, status)) {
3075 return tevent_req_post(req, ev);
3079 if (target_hostname != NULL) {
3080 status = gensec_set_target_hostname(ags->gensec_security,
3081 target_hostname);
3082 if (tevent_req_nterror(req, status)) {
3083 return tevent_req_post(req, ev);
3087 gensec_set_max_update_size(ags->gensec_security,
3088 CLI_BUFFER_SIZE);
3090 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3091 if (b != NULL) {
3092 state->blob_in = *b;
3095 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3096 if (tevent_req_nterror(req, status)) {
3097 return tevent_req_post(req, ev);
3101 * We only need the gensec_security part from here.
3103 state->es->gensec_security = talloc_move(state->es,
3104 &ags->gensec_security);
3105 TALLOC_FREE(ags);
3107 cli_smb1_setup_encryption_local_next(req);
3108 if (!tevent_req_is_in_progress(req)) {
3109 return tevent_req_post(req, ev);
3112 return req;
3115 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3117 struct cli_smb1_setup_encryption_state *state =
3118 tevent_req_data(req,
3119 struct cli_smb1_setup_encryption_state);
3120 struct tevent_req *subreq = NULL;
3122 if (state->local_ready) {
3123 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3124 return;
3127 subreq = gensec_update_send(state, state->ev,
3128 state->es->gensec_security,
3129 state->blob_in);
3130 if (tevent_req_nomem(subreq, req)) {
3131 return;
3133 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3136 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3138 struct tevent_req *req =
3139 tevent_req_callback_data(subreq,
3140 struct tevent_req);
3141 struct cli_smb1_setup_encryption_state *state =
3142 tevent_req_data(req,
3143 struct cli_smb1_setup_encryption_state);
3144 NTSTATUS status;
3146 status = gensec_update_recv(subreq, state, &state->blob_out);
3147 TALLOC_FREE(subreq);
3148 state->blob_in = data_blob_null;
3149 if (!NT_STATUS_IS_OK(status) &&
3150 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3152 tevent_req_nterror(req, status);
3153 return;
3156 if (NT_STATUS_IS_OK(status)) {
3157 state->local_ready = true;
3161 * We always get NT_STATUS_OK from the server even if it is not ready.
3162 * So guess the server is ready when we are ready and already sent
3163 * our last blob to the server.
3165 if (state->local_ready && state->blob_out.length == 0) {
3166 state->remote_ready = true;
3169 if (state->local_ready && state->remote_ready) {
3170 cli_smb1_setup_encryption_ready(req);
3171 return;
3174 cli_smb1_setup_encryption_remote_next(req);
3177 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3179 struct cli_smb1_setup_encryption_state *state =
3180 tevent_req_data(req,
3181 struct cli_smb1_setup_encryption_state);
3182 struct tevent_req *subreq = NULL;
3184 if (state->remote_ready) {
3185 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3186 return;
3189 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3190 state->cli, state->blob_out);
3191 if (tevent_req_nomem(subreq, req)) {
3192 return;
3194 tevent_req_set_callback(subreq,
3195 cli_smb1_setup_encryption_remote_done,
3196 req);
3199 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3201 struct tevent_req *req =
3202 tevent_req_callback_data(subreq,
3203 struct tevent_req);
3204 struct cli_smb1_setup_encryption_state *state =
3205 tevent_req_data(req,
3206 struct cli_smb1_setup_encryption_state);
3207 NTSTATUS status;
3209 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3210 &state->blob_in,
3211 &state->es->enc_ctx_num);
3212 TALLOC_FREE(subreq);
3213 data_blob_free(&state->blob_out);
3214 if (!NT_STATUS_IS_OK(status) &&
3215 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3217 tevent_req_nterror(req, status);
3218 return;
3222 * We always get NT_STATUS_OK even if the server is not ready.
3223 * So guess the server is ready when we are ready and sent
3224 * our last blob to the server.
3226 if (state->local_ready) {
3227 state->remote_ready = true;
3230 if (state->local_ready && state->remote_ready) {
3231 cli_smb1_setup_encryption_ready(req);
3232 return;
3235 cli_smb1_setup_encryption_local_next(req);
3238 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3240 struct cli_smb1_setup_encryption_state *state =
3241 tevent_req_data(req,
3242 struct cli_smb1_setup_encryption_state);
3243 struct smb_trans_enc_state *es = NULL;
3245 if (state->blob_in.length != 0) {
3246 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3247 return;
3250 if (state->blob_out.length != 0) {
3251 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3252 return;
3255 es = talloc_move(state->cli->conn, &state->es);
3256 es->enc_on = true;
3257 smb1cli_conn_set_encryption(state->cli->conn, es);
3258 es = NULL;
3260 tevent_req_done(req);
3263 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3265 return tevent_req_simple_recv_ntstatus(req);
3268 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3269 struct cli_credentials *creds)
3271 struct tevent_context *ev = NULL;
3272 struct tevent_req *req = NULL;
3273 NTSTATUS status = NT_STATUS_NO_MEMORY;
3275 ev = samba_tevent_context_init(talloc_tos());
3276 if (ev == NULL) {
3277 goto fail;
3279 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3280 if (req == NULL) {
3281 goto fail;
3283 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3284 goto fail;
3286 status = cli_smb1_setup_encryption_recv(req);
3287 fail:
3288 TALLOC_FREE(ev);
3289 return status;
3293 establishes a connection right up to doing tconX, password specified.
3294 @param output_cli A fully initialised cli structure, non-null only on success
3295 @param dest_host The netbios name of the remote host
3296 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3297 @param port (optional) The destination port (0 for default)
3298 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3299 @param service_type The 'type' of serivice.
3300 @param creds The used user credentials
3303 struct cli_full_connection_creds_state {
3304 struct tevent_context *ev;
3305 const char *service;
3306 const char *service_type;
3307 struct cli_credentials *creds;
3308 int flags;
3309 struct cli_state *cli;
3312 static int cli_full_connection_creds_state_destructor(
3313 struct cli_full_connection_creds_state *s)
3315 if (s->cli != NULL) {
3316 cli_shutdown(s->cli);
3317 s->cli = NULL;
3319 return 0;
3322 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3323 static void cli_full_connection_creds_sess_start(struct tevent_req *req);
3324 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3325 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3326 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3328 struct tevent_req *cli_full_connection_creds_send(
3329 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3330 const char *my_name, const char *dest_host,
3331 const struct sockaddr_storage *dest_ss, int port,
3332 const char *service, const char *service_type,
3333 struct cli_credentials *creds,
3334 int flags, int signing_state)
3336 struct tevent_req *req, *subreq;
3337 struct cli_full_connection_creds_state *state;
3338 enum credentials_use_kerberos krb5_state;
3339 uint32_t gensec_features = 0;
3341 req = tevent_req_create(mem_ctx, &state,
3342 struct cli_full_connection_creds_state);
3343 if (req == NULL) {
3344 return NULL;
3346 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3348 flags &= ~CLI_FULL_CONNECTION_USE_KERBEROS;
3349 flags &= ~CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3350 flags &= ~CLI_FULL_CONNECTION_USE_CCACHE;
3351 flags &= ~CLI_FULL_CONNECTION_USE_NT_HASH;
3353 krb5_state = cli_credentials_get_kerberos_state(creds);
3354 switch (krb5_state) {
3355 case CRED_MUST_USE_KERBEROS:
3356 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3357 flags &= ~CLI_FULL_CONNECTION_DONT_SPNEGO;
3358 break;
3359 case CRED_AUTO_USE_KERBEROS:
3360 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3361 flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3362 break;
3363 case CRED_DONT_USE_KERBEROS:
3364 break;
3367 gensec_features = cli_credentials_get_gensec_features(creds);
3368 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
3369 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
3372 state->ev = ev;
3373 state->service = service;
3374 state->service_type = service_type;
3375 state->creds = creds;
3376 state->flags = flags;
3378 subreq = cli_start_connection_send(
3379 state, ev, my_name, dest_host, dest_ss, port,
3380 signing_state, flags);
3381 if (tevent_req_nomem(subreq, req)) {
3382 return tevent_req_post(req, ev);
3384 tevent_req_set_callback(subreq,
3385 cli_full_connection_creds_conn_done,
3386 req);
3387 return req;
3390 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3392 struct tevent_req *req = tevent_req_callback_data(
3393 subreq, struct tevent_req);
3394 struct cli_full_connection_creds_state *state = tevent_req_data(
3395 req, struct cli_full_connection_creds_state);
3396 NTSTATUS status;
3398 status = cli_start_connection_recv(subreq, &state->cli);
3399 TALLOC_FREE(subreq);
3400 if (tevent_req_nterror(req, status)) {
3401 return;
3404 cli_full_connection_creds_sess_start(req);
3407 static void cli_full_connection_creds_sess_start(struct tevent_req *req)
3409 struct cli_full_connection_creds_state *state = tevent_req_data(
3410 req, struct cli_full_connection_creds_state);
3411 struct tevent_req *subreq = NULL;
3413 subreq = cli_session_setup_creds_send(
3414 state, state->ev, state->cli, state->creds);
3415 if (tevent_req_nomem(subreq, req)) {
3416 return;
3418 tevent_req_set_callback(subreq,
3419 cli_full_connection_creds_sess_done,
3420 req);
3423 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3425 struct tevent_req *req = tevent_req_callback_data(
3426 subreq, struct tevent_req);
3427 struct cli_full_connection_creds_state *state = tevent_req_data(
3428 req, struct cli_full_connection_creds_state);
3429 NTSTATUS status;
3431 status = cli_session_setup_creds_recv(subreq);
3432 TALLOC_FREE(subreq);
3434 if (!NT_STATUS_IS_OK(status) &&
3435 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3437 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3439 state->creds = cli_credentials_init_anon(state);
3440 if (tevent_req_nomem(state->creds, req)) {
3441 return;
3444 cli_full_connection_creds_sess_start(req);
3445 return;
3448 if (tevent_req_nterror(req, status)) {
3449 return;
3452 cli_full_connection_creds_tcon_start(req);
3455 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3457 struct cli_full_connection_creds_state *state = tevent_req_data(
3458 req, struct cli_full_connection_creds_state);
3459 struct tevent_req *subreq = NULL;
3460 const char *password = NULL;
3462 if (state->service == NULL) {
3463 tevent_req_done(req);
3464 return;
3467 password = cli_credentials_get_password(state->creds);
3469 subreq = cli_tree_connect_send(state, state->ev,
3470 state->cli,
3471 state->service,
3472 state->service_type,
3473 password);
3474 if (tevent_req_nomem(subreq, req)) {
3475 return;
3477 tevent_req_set_callback(subreq,
3478 cli_full_connection_creds_tcon_done,
3479 req);
3482 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3484 struct tevent_req *req = tevent_req_callback_data(
3485 subreq, struct tevent_req);
3486 NTSTATUS status;
3488 status = cli_tree_connect_recv(subreq);
3489 TALLOC_FREE(subreq);
3490 if (tevent_req_nterror(req, status)) {
3491 return;
3494 tevent_req_done(req);
3497 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3498 struct cli_state **output_cli)
3500 struct cli_full_connection_creds_state *state = tevent_req_data(
3501 req, struct cli_full_connection_creds_state);
3502 NTSTATUS status;
3504 if (tevent_req_is_nterror(req, &status)) {
3505 return status;
3507 *output_cli = state->cli;
3508 talloc_set_destructor(state, NULL);
3509 return NT_STATUS_OK;
3512 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3513 const char *my_name,
3514 const char *dest_host,
3515 const struct sockaddr_storage *dest_ss, int port,
3516 const char *service, const char *service_type,
3517 struct cli_credentials *creds,
3518 int flags,
3519 int signing_state)
3521 struct tevent_context *ev;
3522 struct tevent_req *req;
3523 NTSTATUS status = NT_STATUS_NO_MEMORY;
3525 ev = samba_tevent_context_init(talloc_tos());
3526 if (ev == NULL) {
3527 goto fail;
3529 req = cli_full_connection_creds_send(
3530 ev, ev, my_name, dest_host, dest_ss, port, service,
3531 service_type, creds, flags, signing_state);
3532 if (req == NULL) {
3533 goto fail;
3535 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3536 goto fail;
3538 status = cli_full_connection_creds_recv(req, output_cli);
3539 fail:
3540 TALLOC_FREE(ev);
3541 return status;
3544 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3545 const char *my_name,
3546 const char *dest_host,
3547 const struct sockaddr_storage *dest_ss, int port,
3548 const char *service, const char *service_type,
3549 const char *user, const char *domain,
3550 const char *password, int flags,
3551 int signing_state)
3553 TALLOC_CTX *frame = talloc_stackframe();
3554 NTSTATUS status;
3555 bool use_kerberos = false;
3556 bool fallback_after_kerberos = false;
3557 bool use_ccache = false;
3558 bool pw_nt_hash = false;
3559 struct cli_credentials *creds = NULL;
3561 if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
3562 use_kerberos = true;
3565 if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) {
3566 fallback_after_kerberos = true;
3569 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3570 use_ccache = true;
3573 if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) {
3574 pw_nt_hash = true;
3577 creds = cli_session_creds_init(frame,
3578 user,
3579 domain,
3580 NULL, /* realm (use default) */
3581 password,
3582 use_kerberos,
3583 fallback_after_kerberos,
3584 use_ccache,
3585 pw_nt_hash);
3586 if (creds == NULL) {
3587 TALLOC_FREE(frame);
3588 return NT_STATUS_NO_MEMORY;
3591 status = cli_full_connection_creds(output_cli, my_name,
3592 dest_host, dest_ss, port,
3593 service, service_type,
3594 creds, flags, signing_state);
3595 if (!NT_STATUS_IS_OK(status)) {
3596 TALLOC_FREE(frame);
3597 return status;
3600 TALLOC_FREE(frame);
3601 return NT_STATUS_OK;
3604 /****************************************************************************
3605 Send an old style tcon.
3606 ****************************************************************************/
3607 struct cli_raw_tcon_state {
3608 uint16_t *ret_vwv;
3611 static void cli_raw_tcon_done(struct tevent_req *subreq);
3613 static struct tevent_req *cli_raw_tcon_send(
3614 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3615 const char *service, const char *pass, const char *dev)
3617 struct tevent_req *req, *subreq;
3618 struct cli_raw_tcon_state *state;
3619 uint8_t *bytes;
3621 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3622 if (req == NULL) {
3623 return NULL;
3626 if (!lp_client_plaintext_auth() && (*pass)) {
3627 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3628 " or 'client ntlmv2 auth = yes'\n"));
3629 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3630 return tevent_req_post(req, ev);
3633 TALLOC_FREE(cli->smb1.tcon);
3634 cli->smb1.tcon = smbXcli_tcon_create(cli);
3635 if (tevent_req_nomem(cli->smb1.tcon, req)) {
3636 return tevent_req_post(req, ev);
3638 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
3640 bytes = talloc_array(state, uint8_t, 0);
3641 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3642 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3643 service, strlen(service)+1, NULL);
3644 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3645 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3646 pass, strlen(pass)+1, NULL);
3647 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3648 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3649 dev, strlen(dev)+1, NULL);
3651 if (tevent_req_nomem(bytes, req)) {
3652 return tevent_req_post(req, ev);
3655 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3656 talloc_get_size(bytes), bytes);
3657 if (tevent_req_nomem(subreq, req)) {
3658 return tevent_req_post(req, ev);
3660 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3661 return req;
3664 static void cli_raw_tcon_done(struct tevent_req *subreq)
3666 struct tevent_req *req = tevent_req_callback_data(
3667 subreq, struct tevent_req);
3668 struct cli_raw_tcon_state *state = tevent_req_data(
3669 req, struct cli_raw_tcon_state);
3670 NTSTATUS status;
3672 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3673 NULL, NULL);
3674 TALLOC_FREE(subreq);
3675 if (tevent_req_nterror(req, status)) {
3676 return;
3678 tevent_req_done(req);
3681 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3682 uint16_t *max_xmit, uint16_t *tid)
3684 struct cli_raw_tcon_state *state = tevent_req_data(
3685 req, struct cli_raw_tcon_state);
3686 NTSTATUS status;
3688 if (tevent_req_is_nterror(req, &status)) {
3689 return status;
3691 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3692 *tid = SVAL(state->ret_vwv + 1, 0);
3693 return NT_STATUS_OK;
3696 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3697 const char *service, const char *pass, const char *dev,
3698 uint16_t *max_xmit, uint16_t *tid)
3700 struct tevent_context *ev;
3701 struct tevent_req *req;
3702 NTSTATUS status = NT_STATUS_NO_MEMORY;
3704 ev = samba_tevent_context_init(talloc_tos());
3705 if (ev == NULL) {
3706 goto fail;
3708 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3709 if (req == NULL) {
3710 goto fail;
3712 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3713 goto fail;
3715 status = cli_raw_tcon_recv(req, max_xmit, tid);
3716 fail:
3717 TALLOC_FREE(ev);
3718 return status;
3721 /* Return a cli_state pointing at the IPC$ share for the given server */
3723 struct cli_state *get_ipc_connect(char *server,
3724 struct sockaddr_storage *server_ss,
3725 const struct user_auth_info *user_info)
3727 struct cli_state *cli;
3728 NTSTATUS nt_status;
3729 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3731 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3732 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3735 flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
3737 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3738 get_cmdline_auth_info_username(user_info),
3739 lp_workgroup(),
3740 get_cmdline_auth_info_password(user_info),
3741 flags,
3742 SMB_SIGNING_DEFAULT);
3744 if (NT_STATUS_IS_OK(nt_status)) {
3745 return cli;
3746 } else if (is_ipaddress(server)) {
3747 /* windows 9* needs a correct NMB name for connections */
3748 fstring remote_name;
3750 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3751 cli = get_ipc_connect(remote_name, server_ss, user_info);
3752 if (cli)
3753 return cli;
3756 return NULL;
3760 * Given the IP address of a master browser on the network, return its
3761 * workgroup and connect to it.
3763 * This function is provided to allow additional processing beyond what
3764 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3765 * browsers and obtain each master browsers' list of domains (in case the
3766 * first master browser is recently on the network and has not yet
3767 * synchronized with other master browsers and therefore does not yet have the
3768 * entire network browse list)
3771 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3772 struct sockaddr_storage *mb_ip,
3773 const struct user_auth_info *user_info,
3774 char **pp_workgroup_out)
3776 char addr[INET6_ADDRSTRLEN];
3777 fstring name;
3778 struct cli_state *cli;
3779 struct sockaddr_storage server_ss;
3781 *pp_workgroup_out = NULL;
3783 print_sockaddr(addr, sizeof(addr), mb_ip);
3784 DEBUG(99, ("Looking up name of master browser %s\n",
3785 addr));
3788 * Do a name status query to find out the name of the master browser.
3789 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3790 * master browser will not respond to a wildcard query (or, at least,
3791 * an NT4 server acting as the domain master browser will not).
3793 * We might be able to use ONLY the query on MSBROWSE, but that's not
3794 * yet been tested with all Windows versions, so until it is, leave
3795 * the original wildcard query as the first choice and fall back to
3796 * MSBROWSE if the wildcard query fails.
3798 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3799 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3801 DEBUG(99, ("Could not retrieve name status for %s\n",
3802 addr));
3803 return NULL;
3806 if (!find_master_ip(name, &server_ss)) {
3807 DEBUG(99, ("Could not find master ip for %s\n", name));
3808 return NULL;
3811 *pp_workgroup_out = talloc_strdup(ctx, name);
3813 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3815 print_sockaddr(addr, sizeof(addr), &server_ss);
3816 cli = get_ipc_connect(addr, &server_ss, user_info);
3818 return cli;
3822 * Return the IP address and workgroup of a master browser on the network, and
3823 * connect to it.
3826 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3827 const struct user_auth_info *user_info,
3828 char **pp_workgroup_out)
3830 struct sockaddr_storage *ip_list;
3831 struct cli_state *cli;
3832 int i, count;
3833 NTSTATUS status;
3835 *pp_workgroup_out = NULL;
3837 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3839 /* Go looking for workgroups by broadcasting on the local network */
3841 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3842 &ip_list, &count);
3843 if (!NT_STATUS_IS_OK(status)) {
3844 DEBUG(99, ("No master browsers responded: %s\n",
3845 nt_errstr(status)));
3846 return NULL;
3849 for (i = 0; i < count; i++) {
3850 char addr[INET6_ADDRSTRLEN];
3851 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3852 DEBUG(99, ("Found master browser %s\n", addr));
3854 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3855 user_info, pp_workgroup_out);
3856 if (cli)
3857 return(cli);
3860 return NULL;