s4:selftest: explicitly set NSS/RESOLV_WAPPER_* in wait_for_start
[Samba.git] / source3 / libsmb / cliconnect.c
blob7689910fae9f226266458e96a8700f1fe4bc6867
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 errno = 0;
287 user_principal = cli_credentials_get_principal(creds, frame);
288 if (errno != 0) {
289 TALLOC_FREE(frame);
290 return NT_STATUS_NO_MEMORY;
293 user_account = cli_credentials_get_username(creds);
294 user_domain = cli_credentials_get_domain(creds);
295 pass = cli_credentials_get_password(creds);
297 krb5_state = cli_credentials_get_kerberos_state(creds);
299 if (krb5_state != CRED_DONT_USE_KERBEROS) {
300 try_kerberos = true;
303 if (user_principal == NULL) {
304 try_kerberos = false;
307 if (target_hostname == NULL) {
308 try_kerberos = false;
309 } else if (is_ipaddress(target_hostname)) {
310 try_kerberos = false;
311 } else if (strequal(target_hostname, "localhost")) {
312 try_kerberos = false;
313 } else if (strequal(target_hostname, STAR_SMBSERVER)) {
314 try_kerberos = false;
315 } else if (!auth_requested) {
316 try_kerberos = false;
319 if (krb5_state == CRED_MUST_USE_KERBEROS && !try_kerberos) {
320 DEBUG(0, ("Kerberos auth with '%s' (%s\\%s) to access "
321 "'%s' not possible\n",
322 user_principal, user_domain, user_account,
323 target_hostname));
324 TALLOC_FREE(frame);
325 return NT_STATUS_ACCESS_DENIED;
328 if (pass == NULL || strlen(pass) == 0) {
329 need_kinit = false;
330 } else if (krb5_state == CRED_MUST_USE_KERBEROS) {
331 need_kinit = try_kerberos;
332 } else if (!got_kerberos_mechanism) {
334 * Most likely the server doesn't support
335 * Kerberos, don't waste time doing a kinit
337 need_kinit = false;
338 } else {
339 need_kinit = try_kerberos;
342 if (!need_kinit) {
343 TALLOC_FREE(frame);
344 return NT_STATUS_OK;
349 * TODO: This should be done within the gensec layer
350 * only if required!
352 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
353 ret = kerberos_kinit_password(user_principal, pass,
354 0 /* no time correction for now */,
355 NULL);
356 if (ret != 0) {
357 int dbglvl = DBGLVL_NOTICE;
359 if (krb5_state == CRED_MUST_USE_KERBEROS) {
360 dbglvl = DBGLVL_ERR;
363 DEBUG(dbglvl, ("Kinit for %s to access %s failed: %s\n",
364 user_principal, target_hostname,
365 error_message(ret)));
366 if (krb5_state == CRED_MUST_USE_KERBEROS) {
367 TALLOC_FREE(frame);
368 return krb5_to_nt_status(ret);
372 * Ignore the error and hope that NTLM will work
376 TALLOC_FREE(frame);
377 return NT_STATUS_OK;
380 static NTSTATUS cli_state_update_after_sesssetup(struct cli_state *cli,
381 const char *native_os,
382 const char *native_lm,
383 const char *primary_domain)
385 #define _VALID_STR(p) ((p) != NULL && (p)[0] != '\0')
387 if (!_VALID_STR(cli->server_os) && _VALID_STR(native_os)) {
388 cli->server_os = talloc_strdup(cli, native_os);
389 if (cli->server_os == NULL) {
390 return NT_STATUS_NO_MEMORY;
394 if (!_VALID_STR(cli->server_type) && _VALID_STR(native_lm)) {
395 cli->server_type = talloc_strdup(cli, native_lm);
396 if (cli->server_type == NULL) {
397 return NT_STATUS_NO_MEMORY;
401 if (!_VALID_STR(cli->server_domain) && _VALID_STR(primary_domain)) {
402 cli->server_domain = talloc_strdup(cli, primary_domain);
403 if (cli->server_domain == NULL) {
404 return NT_STATUS_NO_MEMORY;
408 #undef _VALID_STRING
409 return NT_STATUS_OK;
412 /********************************************************
413 Utility function to ensure we always return at least
414 a valid char * pointer to an empty string for the
415 cli->server_os, cli->server_type and cli->server_domain
416 strings.
417 *******************************************************/
419 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
420 const uint8_t *hdr,
421 char **dest,
422 uint8_t *src,
423 size_t srclen,
424 ssize_t *destlen)
426 *destlen = clistr_pull_talloc(mem_ctx,
427 (const char *)hdr,
428 SVAL(hdr, HDR_FLG2),
429 dest,
430 (char *)src,
431 srclen,
432 STR_TERMINATE);
433 if (*destlen == -1) {
434 return NT_STATUS_NO_MEMORY;
437 if (*dest == NULL) {
438 *dest = talloc_strdup(mem_ctx, "");
439 if (*dest == NULL) {
440 return NT_STATUS_NO_MEMORY;
443 return NT_STATUS_OK;
446 /****************************************************************************
447 Work out suitable capabilities to offer the server.
448 ****************************************************************************/
450 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
451 uint32_t sesssetup_capabilities)
453 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
456 * We only send capabilities based on the mask for:
457 * - client only flags
458 * - flags used in both directions
460 * We do not echo the server only flags, except some legacy flags.
462 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
463 * CAP_LARGE_WRITEX in order to allow us to do large reads
464 * against old Samba releases (<= 3.6.x).
466 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
469 * Session Setup specific flags CAP_DYNAMIC_REAUTH
470 * and CAP_EXTENDED_SECURITY are passed by the caller.
471 * We need that in order to do guest logins even if
472 * CAP_EXTENDED_SECURITY is negotiated.
474 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
475 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
476 client_capabilities |= sesssetup_capabilities;
478 return client_capabilities;
481 /****************************************************************************
482 Do a NT1 guest session setup.
483 ****************************************************************************/
485 struct cli_session_setup_guest_state {
486 struct cli_state *cli;
487 uint16_t vwv[13];
488 struct iovec bytes;
491 static void cli_session_setup_guest_done(struct tevent_req *subreq);
493 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
494 struct tevent_context *ev,
495 struct cli_state *cli,
496 struct tevent_req **psmbreq)
498 struct tevent_req *req, *subreq;
499 struct cli_session_setup_guest_state *state;
500 uint16_t *vwv;
501 uint8_t *bytes;
503 req = tevent_req_create(mem_ctx, &state,
504 struct cli_session_setup_guest_state);
505 if (req == NULL) {
506 return NULL;
508 state->cli = cli;
509 vwv = state->vwv;
511 SCVAL(vwv+0, 0, 0xFF);
512 SCVAL(vwv+0, 1, 0);
513 SSVAL(vwv+1, 0, 0);
514 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
515 SSVAL(vwv+3, 0, 2);
516 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
517 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
518 SSVAL(vwv+7, 0, 0);
519 SSVAL(vwv+8, 0, 0);
520 SSVAL(vwv+9, 0, 0);
521 SSVAL(vwv+10, 0, 0);
522 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
524 bytes = talloc_array(state, uint8_t, 0);
526 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
527 NULL);
528 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
529 NULL);
530 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
531 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
533 if (bytes == NULL) {
534 TALLOC_FREE(req);
535 return NULL;
538 state->bytes.iov_base = (void *)bytes;
539 state->bytes.iov_len = talloc_get_size(bytes);
541 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 0, 13,
542 vwv, 1, &state->bytes);
543 if (subreq == NULL) {
544 TALLOC_FREE(req);
545 return NULL;
547 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
548 *psmbreq = subreq;
549 return req;
552 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
553 struct tevent_context *ev,
554 struct cli_state *cli)
556 struct tevent_req *req, *subreq;
557 NTSTATUS status;
559 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
560 if (req == NULL) {
561 return NULL;
564 status = smb1cli_req_chain_submit(&subreq, 1);
565 if (!NT_STATUS_IS_OK(status)) {
566 tevent_req_nterror(req, status);
567 return tevent_req_post(req, ev);
569 return req;
572 static void cli_session_setup_guest_done(struct tevent_req *subreq)
574 struct tevent_req *req = tevent_req_callback_data(
575 subreq, struct tevent_req);
576 struct cli_session_setup_guest_state *state = tevent_req_data(
577 req, struct cli_session_setup_guest_state);
578 struct cli_state *cli = state->cli;
579 uint32_t num_bytes;
580 uint8_t *in;
581 uint8_t *inhdr;
582 uint8_t *bytes;
583 uint8_t *p;
584 NTSTATUS status;
585 ssize_t ret;
586 uint8_t wct;
587 uint16_t *vwv;
589 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
590 &num_bytes, &bytes);
591 TALLOC_FREE(subreq);
592 if (!NT_STATUS_IS_OK(status)) {
593 tevent_req_nterror(req, status);
594 return;
597 inhdr = in + NBT_HDR_SIZE;
598 p = bytes;
600 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
601 smb1cli_session_set_action(cli->smb1.session, SVAL(vwv+2, 0));
603 status = smb_bytes_talloc_string(cli,
604 inhdr,
605 &cli->server_os,
607 bytes+num_bytes-p,
608 &ret);
610 if (!NT_STATUS_IS_OK(status)) {
611 tevent_req_nterror(req, status);
612 return;
614 p += ret;
616 status = smb_bytes_talloc_string(cli,
617 inhdr,
618 &cli->server_type,
620 bytes+num_bytes-p,
621 &ret);
623 if (!NT_STATUS_IS_OK(status)) {
624 tevent_req_nterror(req, status);
625 return;
627 p += ret;
629 status = smb_bytes_talloc_string(cli,
630 inhdr,
631 &cli->server_domain,
633 bytes+num_bytes-p,
634 &ret);
636 if (!NT_STATUS_IS_OK(status)) {
637 tevent_req_nterror(req, status);
638 return;
640 p += ret;
642 tevent_req_done(req);
645 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
647 return tevent_req_simple_recv_ntstatus(req);
650 /* The following is calculated from :
651 * (smb_size-4) = 35
652 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
653 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
654 * end of packet.
657 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
659 struct cli_sesssetup_blob_state {
660 struct tevent_context *ev;
661 struct cli_state *cli;
662 DATA_BLOB blob;
663 uint16_t max_blob_size;
665 DATA_BLOB this_blob;
666 struct iovec *recv_iov;
668 NTSTATUS status;
669 const uint8_t *inbuf;
670 DATA_BLOB ret_blob;
672 char *out_native_os;
673 char *out_native_lm;
676 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
677 struct tevent_req **psubreq);
678 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
680 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
681 struct tevent_context *ev,
682 struct cli_state *cli,
683 DATA_BLOB blob)
685 struct tevent_req *req, *subreq;
686 struct cli_sesssetup_blob_state *state;
687 uint32_t usable_space;
689 req = tevent_req_create(mem_ctx, &state,
690 struct cli_sesssetup_blob_state);
691 if (req == NULL) {
692 return NULL;
694 state->ev = ev;
695 state->blob = blob;
696 state->cli = cli;
698 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
699 usable_space = UINT16_MAX;
700 } else {
701 usable_space = cli_state_available_size(cli,
702 BASE_SESSSETUP_BLOB_PACKET_SIZE);
705 if (usable_space == 0) {
706 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
707 "(not possible to send %u bytes)\n",
708 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
709 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
710 return tevent_req_post(req, ev);
712 state->max_blob_size = MIN(usable_space, 0xFFFF);
714 if (!cli_sesssetup_blob_next(state, &subreq)) {
715 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
716 return tevent_req_post(req, ev);
718 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
719 return req;
722 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
723 struct tevent_req **psubreq)
725 struct tevent_req *subreq;
726 uint16_t thistime;
728 thistime = MIN(state->blob.length, state->max_blob_size);
730 state->this_blob.data = state->blob.data;
731 state->this_blob.length = thistime;
733 state->blob.data += thistime;
734 state->blob.length -= thistime;
736 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
737 subreq = smb2cli_session_setup_send(state, state->ev,
738 state->cli->conn,
739 state->cli->timeout,
740 state->cli->smb2.session,
741 0, /* in_flags */
742 SMB2_CAP_DFS, /* in_capabilities */
743 0, /* in_channel */
744 0, /* in_previous_session_id */
745 &state->this_blob);
746 if (subreq == NULL) {
747 return false;
749 } else {
750 uint16_t in_buf_size = 0;
751 uint16_t in_mpx_max = 0;
752 uint16_t in_vc_num = 0;
753 uint32_t in_sess_key = 0;
754 uint32_t in_capabilities = 0;
755 const char *in_native_os = NULL;
756 const char *in_native_lm = NULL;
758 in_buf_size = CLI_BUFFER_SIZE;
759 in_mpx_max = smbXcli_conn_max_requests(state->cli->conn);
760 in_vc_num = cli_state_get_vc_num(state->cli);
761 in_sess_key = smb1cli_conn_server_session_key(state->cli->conn);
762 in_capabilities = cli_session_setup_capabilities(state->cli,
763 CAP_EXTENDED_SECURITY);
764 in_native_os = "Unix";
765 in_native_lm = "Samba";
768 * For now we keep the same values as before,
769 * we may remove these in a separate commit later.
771 in_mpx_max = 2;
772 in_vc_num = 1;
773 in_sess_key = 0;
775 subreq = smb1cli_session_setup_ext_send(state, state->ev,
776 state->cli->conn,
777 state->cli->timeout,
778 state->cli->smb1.pid,
779 state->cli->smb1.session,
780 in_buf_size,
781 in_mpx_max,
782 in_vc_num,
783 in_sess_key,
784 state->this_blob,
785 in_capabilities,
786 in_native_os,
787 in_native_lm);
788 if (subreq == NULL) {
789 return false;
792 *psubreq = subreq;
793 return true;
796 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
798 struct tevent_req *req = tevent_req_callback_data(
799 subreq, struct tevent_req);
800 struct cli_sesssetup_blob_state *state = tevent_req_data(
801 req, struct cli_sesssetup_blob_state);
802 NTSTATUS status;
804 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
805 status = smb2cli_session_setup_recv(subreq, state,
806 &state->recv_iov,
807 &state->ret_blob);
808 } else {
809 status = smb1cli_session_setup_ext_recv(subreq, state,
810 &state->recv_iov,
811 &state->inbuf,
812 &state->ret_blob,
813 &state->out_native_os,
814 &state->out_native_lm);
816 TALLOC_FREE(subreq);
817 if (!NT_STATUS_IS_OK(status)
818 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
819 tevent_req_nterror(req, status);
820 return;
823 state->status = status;
825 status = cli_state_update_after_sesssetup(state->cli,
826 state->out_native_os,
827 state->out_native_lm,
828 NULL);
829 if (tevent_req_nterror(req, status)) {
830 return;
833 if (state->blob.length != 0) {
835 * More to send
837 if (!cli_sesssetup_blob_next(state, &subreq)) {
838 tevent_req_oom(req);
839 return;
841 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
842 return;
844 tevent_req_done(req);
847 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
848 TALLOC_CTX *mem_ctx,
849 DATA_BLOB *pblob,
850 const uint8_t **pinbuf,
851 struct iovec **precv_iov)
853 struct cli_sesssetup_blob_state *state = tevent_req_data(
854 req, struct cli_sesssetup_blob_state);
855 NTSTATUS status;
856 struct iovec *recv_iov;
858 if (tevent_req_is_nterror(req, &status)) {
859 TALLOC_FREE(state->cli->smb2.session);
860 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
861 tevent_req_received(req);
862 return status;
865 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
866 if (pblob != NULL) {
867 *pblob = state->ret_blob;
869 if (pinbuf != NULL) {
870 *pinbuf = state->inbuf;
872 if (precv_iov != NULL) {
873 *precv_iov = recv_iov;
875 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
876 status = state->status;
877 tevent_req_received(req);
878 return status;
881 /****************************************************************************
882 Do a spnego/NTLMSSP encrypted session setup.
883 ****************************************************************************/
885 struct cli_session_setup_gensec_state {
886 struct tevent_context *ev;
887 struct cli_state *cli;
888 struct auth_generic_state *auth_generic;
889 bool is_anonymous;
890 DATA_BLOB blob_in;
891 const uint8_t *inbuf;
892 struct iovec *recv_iov;
893 DATA_BLOB blob_out;
894 bool local_ready;
895 bool remote_ready;
896 DATA_BLOB session_key;
899 static int cli_session_setup_gensec_state_destructor(
900 struct cli_session_setup_gensec_state *state)
902 TALLOC_FREE(state->auth_generic);
903 data_blob_clear_free(&state->session_key);
904 return 0;
907 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
908 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
909 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
910 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
911 static void cli_session_setup_gensec_ready(struct tevent_req *req);
913 static struct tevent_req *cli_session_setup_gensec_send(
914 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
915 struct cli_credentials *creds,
916 const char *target_service,
917 const char *target_hostname)
919 struct tevent_req *req;
920 struct cli_session_setup_gensec_state *state;
921 NTSTATUS status;
922 const DATA_BLOB *b = NULL;
924 req = tevent_req_create(mem_ctx, &state,
925 struct cli_session_setup_gensec_state);
926 if (req == NULL) {
927 return NULL;
929 state->ev = ev;
930 state->cli = cli;
932 talloc_set_destructor(
933 state, cli_session_setup_gensec_state_destructor);
935 status = auth_generic_client_prepare(state, &state->auth_generic);
936 if (tevent_req_nterror(req, status)) {
937 return tevent_req_post(req, ev);
940 status = auth_generic_set_creds(state->auth_generic, creds);
941 if (tevent_req_nterror(req, status)) {
942 return tevent_req_post(req, ev);
945 gensec_want_feature(state->auth_generic->gensec_security,
946 GENSEC_FEATURE_SESSION_KEY);
948 if (target_service != NULL) {
949 status = gensec_set_target_service(
950 state->auth_generic->gensec_security,
951 target_service);
952 if (tevent_req_nterror(req, status)) {
953 return tevent_req_post(req, ev);
957 if (target_hostname != NULL) {
958 status = gensec_set_target_hostname(
959 state->auth_generic->gensec_security,
960 target_hostname);
961 if (tevent_req_nterror(req, status)) {
962 return tevent_req_post(req, ev);
966 b = smbXcli_conn_server_gss_blob(cli->conn);
967 if (b != NULL) {
968 state->blob_in = *b;
971 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
973 status = auth_generic_client_start(state->auth_generic,
974 GENSEC_OID_SPNEGO);
975 if (tevent_req_nterror(req, status)) {
976 return tevent_req_post(req, ev);
979 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
980 state->cli->smb2.session = smbXcli_session_create(cli,
981 cli->conn);
982 if (tevent_req_nomem(state->cli->smb2.session, req)) {
983 return tevent_req_post(req, ev);
987 cli_session_setup_gensec_local_next(req);
988 if (!tevent_req_is_in_progress(req)) {
989 return tevent_req_post(req, ev);
992 return req;
995 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
997 struct cli_session_setup_gensec_state *state =
998 tevent_req_data(req,
999 struct cli_session_setup_gensec_state);
1000 struct tevent_req *subreq = NULL;
1002 if (state->local_ready) {
1003 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1004 return;
1007 subreq = gensec_update_send(state, state->ev,
1008 state->auth_generic->gensec_security,
1009 state->blob_in);
1010 if (tevent_req_nomem(subreq, req)) {
1011 return;
1013 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1016 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1018 struct tevent_req *req =
1019 tevent_req_callback_data(subreq,
1020 struct tevent_req);
1021 struct cli_session_setup_gensec_state *state =
1022 tevent_req_data(req,
1023 struct cli_session_setup_gensec_state);
1024 NTSTATUS status;
1026 status = gensec_update_recv(subreq, state, &state->blob_out);
1027 TALLOC_FREE(subreq);
1028 state->blob_in = data_blob_null;
1029 if (!NT_STATUS_IS_OK(status) &&
1030 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1032 tevent_req_nterror(req, status);
1033 return;
1036 if (NT_STATUS_IS_OK(status)) {
1037 state->local_ready = true;
1040 if (state->local_ready && state->remote_ready) {
1041 cli_session_setup_gensec_ready(req);
1042 return;
1045 cli_session_setup_gensec_remote_next(req);
1048 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1050 struct cli_session_setup_gensec_state *state =
1051 tevent_req_data(req,
1052 struct cli_session_setup_gensec_state);
1053 struct tevent_req *subreq = NULL;
1055 if (state->remote_ready) {
1056 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1057 return;
1060 subreq = cli_sesssetup_blob_send(state, state->ev,
1061 state->cli, state->blob_out);
1062 if (tevent_req_nomem(subreq, req)) {
1063 return;
1065 tevent_req_set_callback(subreq,
1066 cli_session_setup_gensec_remote_done,
1067 req);
1070 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1072 struct tevent_req *req =
1073 tevent_req_callback_data(subreq,
1074 struct tevent_req);
1075 struct cli_session_setup_gensec_state *state =
1076 tevent_req_data(req,
1077 struct cli_session_setup_gensec_state);
1078 NTSTATUS status;
1080 state->inbuf = NULL;
1081 TALLOC_FREE(state->recv_iov);
1083 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1084 &state->inbuf, &state->recv_iov);
1085 TALLOC_FREE(subreq);
1086 data_blob_free(&state->blob_out);
1087 if (!NT_STATUS_IS_OK(status) &&
1088 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1090 tevent_req_nterror(req, status);
1091 return;
1094 if (NT_STATUS_IS_OK(status)) {
1095 struct smbXcli_session *session = NULL;
1096 bool is_guest = false;
1098 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1099 session = state->cli->smb2.session;
1100 } else {
1101 session = state->cli->smb1.session;
1104 is_guest = smbXcli_session_is_guest(session);
1105 if (is_guest) {
1107 * We can't finish the gensec handshake, we don't
1108 * have a negotiated session key.
1110 * So just pretend we are completely done,
1111 * we need to continue as anonymous from this point,
1112 * as we can't get a session key.
1114 * Note that smbXcli_session_is_guest()
1115 * always returns false if we require signing.
1117 state->blob_in = data_blob_null;
1118 state->local_ready = true;
1119 state->is_anonymous = true;
1122 state->remote_ready = true;
1125 if (state->local_ready && state->remote_ready) {
1126 cli_session_setup_gensec_ready(req);
1127 return;
1130 cli_session_setup_gensec_local_next(req);
1133 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1135 struct cli_session_setup_gensec_state *state =
1136 tevent_req_data(req,
1137 struct cli_session_setup_gensec_state);
1138 const char *server_domain = NULL;
1139 NTSTATUS status;
1141 if (state->blob_in.length != 0) {
1142 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1143 return;
1146 if (state->blob_out.length != 0) {
1147 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1148 return;
1152 * gensec_ntlmssp_server_domain() returns NULL
1153 * if NTLMSSP is not used.
1155 * We can remove this later
1156 * and leave the server domain empty for SMB2 and above
1157 * in future releases.
1159 server_domain = gensec_ntlmssp_server_domain(
1160 state->auth_generic->gensec_security);
1162 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1163 TALLOC_FREE(state->cli->server_domain);
1164 state->cli->server_domain = talloc_strdup(state->cli,
1165 server_domain);
1166 if (state->cli->server_domain == NULL) {
1167 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1168 return;
1172 if (state->is_anonymous) {
1174 * Windows server does not set the
1175 * SMB2_SESSION_FLAG_IS_NULL flag.
1177 * This fix makes sure we do not try
1178 * to verify a signature on the final
1179 * session setup response.
1181 tevent_req_done(req);
1182 return;
1185 status = gensec_session_key(state->auth_generic->gensec_security,
1186 state, &state->session_key);
1187 if (tevent_req_nterror(req, status)) {
1188 return;
1191 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1192 struct smbXcli_session *session = state->cli->smb2.session;
1194 status = smb2cli_session_set_session_key(session,
1195 state->session_key,
1196 state->recv_iov);
1197 if (tevent_req_nterror(req, status)) {
1198 return;
1200 } else {
1201 struct smbXcli_session *session = state->cli->smb1.session;
1202 bool active;
1204 status = smb1cli_session_set_session_key(session,
1205 state->session_key);
1206 if (tevent_req_nterror(req, status)) {
1207 return;
1210 active = smb1cli_conn_activate_signing(state->cli->conn,
1211 state->session_key,
1212 data_blob_null);
1213 if (active) {
1214 bool ok;
1216 ok = smb1cli_conn_check_signing(state->cli->conn,
1217 state->inbuf, 1);
1218 if (!ok) {
1219 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1220 return;
1225 tevent_req_done(req);
1228 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1230 struct cli_session_setup_gensec_state *state =
1231 tevent_req_data(req,
1232 struct cli_session_setup_gensec_state);
1233 NTSTATUS status;
1235 if (tevent_req_is_nterror(req, &status)) {
1236 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1237 return status;
1239 return NT_STATUS_OK;
1242 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1243 const char *principal)
1245 char *account, *p;
1247 account = talloc_strdup(mem_ctx, principal);
1248 if (account == NULL) {
1249 return NULL;
1251 p = strchr_m(account, '@');
1252 if (p != NULL) {
1253 *p = '\0';
1255 return account;
1258 /****************************************************************************
1259 Do a spnego encrypted session setup.
1261 user_domain: The shortname of the domain the user/machine is a member of.
1262 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1263 ****************************************************************************/
1265 struct cli_session_setup_spnego_state {
1266 ADS_STATUS result;
1269 static void cli_session_setup_spnego_done(struct tevent_req *subreq);
1271 static struct tevent_req *cli_session_setup_spnego_send(
1272 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1273 struct cli_credentials *creds)
1275 struct tevent_req *req, *subreq;
1276 struct cli_session_setup_spnego_state *state;
1277 const char *target_service = NULL;
1278 const char *target_hostname = NULL;
1279 NTSTATUS status;
1281 req = tevent_req_create(mem_ctx, &state,
1282 struct cli_session_setup_spnego_state);
1283 if (req == NULL) {
1284 return NULL;
1287 target_service = "cifs";
1288 target_hostname = smbXcli_conn_remote_name(cli->conn);
1290 status = cli_session_creds_prepare_krb5(cli, creds);
1291 if (tevent_req_nterror(req, status)) {
1292 return tevent_req_post(req, ev);
1295 subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
1296 target_service, target_hostname);
1297 if (tevent_req_nomem(subreq, req)) {
1298 return tevent_req_post(req, ev);
1300 tevent_req_set_callback(
1301 subreq, cli_session_setup_spnego_done, req);
1302 return req;
1305 static void cli_session_setup_spnego_done(struct tevent_req *subreq)
1307 struct tevent_req *req = tevent_req_callback_data(
1308 subreq, struct tevent_req);
1309 NTSTATUS status;
1311 status = cli_session_setup_gensec_recv(subreq);
1312 TALLOC_FREE(subreq);
1313 if (tevent_req_nterror(req, status)) {
1314 return;
1317 tevent_req_done(req);
1320 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1322 struct cli_session_setup_spnego_state *state = tevent_req_data(
1323 req, struct cli_session_setup_spnego_state);
1324 NTSTATUS status;
1326 if (tevent_req_is_nterror(req, &status)) {
1327 state->result = ADS_ERROR_NT(status);
1330 return state->result;
1333 struct cli_session_setup_creds_state {
1334 struct cli_state *cli;
1335 DATA_BLOB apassword_blob;
1336 DATA_BLOB upassword_blob;
1337 DATA_BLOB lm_session_key;
1338 DATA_BLOB session_key;
1339 char *out_native_os;
1340 char *out_native_lm;
1341 char *out_primary_domain;
1344 static void cli_session_setup_creds_cleanup(struct tevent_req *req,
1345 enum tevent_req_state req_state)
1347 struct cli_session_setup_creds_state *state = tevent_req_data(
1348 req, struct cli_session_setup_creds_state);
1350 if (req_state != TEVENT_REQ_RECEIVED) {
1351 return;
1355 * We only call data_blob_clear() as
1356 * some of the blobs point to the same memory.
1358 * We let the talloc hierachy free the memory.
1360 data_blob_clear(&state->apassword_blob);
1361 data_blob_clear(&state->upassword_blob);
1362 data_blob_clear(&state->lm_session_key);
1363 data_blob_clear(&state->session_key);
1364 ZERO_STRUCTP(state);
1367 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq);
1368 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq);
1369 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq);
1371 /****************************************************************************
1372 Send a session setup. The username and workgroup is in UNIX character
1373 format and must be converted to DOS codepage format before sending. If the
1374 password is in plaintext, the same should be done.
1375 ****************************************************************************/
1377 struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
1378 struct tevent_context *ev,
1379 struct cli_state *cli,
1380 struct cli_credentials *creds)
1382 struct tevent_req *req, *subreq;
1383 struct cli_session_setup_creds_state *state;
1384 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1385 bool use_spnego = false;
1386 int flags = 0;
1387 enum credentials_use_kerberos krb5_state;
1388 uint32_t gensec_features;
1389 const char *username = "";
1390 const char *domain = "";
1391 DATA_BLOB target_info = data_blob_null;
1392 DATA_BLOB challenge = data_blob_null;
1393 uint16_t in_buf_size = 0;
1394 uint16_t in_mpx_max = 0;
1395 uint16_t in_vc_num = 0;
1396 uint32_t in_sess_key = 0;
1397 const char *in_native_os = NULL;
1398 const char *in_native_lm = NULL;
1399 NTSTATUS status;
1401 req = tevent_req_create(mem_ctx, &state,
1402 struct cli_session_setup_creds_state);
1403 if (req == NULL) {
1404 return NULL;
1406 state->cli = cli;
1408 tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
1410 krb5_state = cli_credentials_get_kerberos_state(creds);
1411 gensec_features = cli_credentials_get_gensec_features(creds);
1413 switch (krb5_state) {
1414 case CRED_MUST_USE_KERBEROS:
1415 cli->use_kerberos = true;
1416 cli->fallback_after_kerberos = false;
1417 break;
1418 case CRED_AUTO_USE_KERBEROS:
1419 cli->use_kerberos = true;
1420 cli->fallback_after_kerberos = true;
1421 break;
1422 case CRED_DONT_USE_KERBEROS:
1423 cli->use_kerberos = false;
1424 cli->fallback_after_kerberos = false;
1425 break;
1428 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
1429 cli->use_ccache = true;
1430 } else {
1431 cli->use_ccache = false;
1435 * Now work out what sort of session setup we are going to
1436 * do. I have split this into separate functions to make the flow a bit
1437 * easier to understand (tridge).
1439 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1440 use_spnego = false;
1441 } else if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1442 use_spnego = true;
1443 } else if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
1445 * if the server supports extended security then use SPNEGO
1446 * even for anonymous connections.
1448 use_spnego = true;
1449 } else {
1450 use_spnego = false;
1453 if (use_spnego) {
1454 subreq = cli_session_setup_spnego_send(
1455 state, ev, cli, creds);
1456 if (tevent_req_nomem(subreq, req)) {
1457 return tevent_req_post(req, ev);
1459 tevent_req_set_callback(subreq, cli_session_setup_creds_done_spnego,
1460 req);
1461 return req;
1464 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1466 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
1467 * this step against older servers.
1469 tevent_req_done(req);
1470 return tevent_req_post(req, ev);
1473 if (cli_credentials_is_anonymous(creds)) {
1475 * Do an anonymous session setup
1477 goto non_spnego_creds_done;
1480 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
1482 * Do an anonymous session setup,
1483 * the password is passed via the tree connect.
1485 goto non_spnego_creds_done;
1488 cli_credentials_get_ntlm_username_domain(creds, state,
1489 &username,
1490 &domain);
1491 if (tevent_req_nomem(username, req)) {
1492 return tevent_req_post(req, ev);
1494 if (tevent_req_nomem(domain, req)) {
1495 return tevent_req_post(req, ev);
1498 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1499 bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
1500 uint8_t *bytes = NULL;
1501 size_t bytes_len = 0;
1502 const char *pw = cli_credentials_get_password(creds);
1503 size_t pw_len = 0;
1505 if (pw == NULL) {
1506 pw = "";
1508 pw_len = strlen(pw) + 1;
1510 if (!lp_client_plaintext_auth()) {
1511 DEBUG(1, ("Server requested PLAINTEXT password but "
1512 "'client plaintext auth = no'\n"));
1513 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1514 return tevent_req_post(req, ev);
1517 bytes = talloc_array(state, uint8_t, 0);
1518 bytes = trans2_bytes_push_str(bytes, use_unicode,
1519 pw, pw_len, &bytes_len);
1520 if (tevent_req_nomem(bytes, req)) {
1521 return tevent_req_post(req, ev);
1524 if (use_unicode) {
1526 * CAP_UNICODE, can only be negotiated by NT1.
1528 state->upassword_blob = data_blob_const(bytes,
1529 bytes_len);
1530 } else {
1531 state->apassword_blob = data_blob_const(bytes,
1532 bytes_len);
1535 goto non_spnego_creds_done;
1538 challenge = data_blob_const(smb1cli_conn_server_challenge(cli->conn), 8);
1540 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1541 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
1543 * Don't send an NTLMv2 response without NTLMSSP if we
1544 * want to use spnego support.
1546 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
1547 " but 'client use spnego = yes'"
1548 " and 'client ntlmv2 auth = yes' is set\n"));
1549 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1550 return tevent_req_post(req, ev);
1553 if (lp_client_ntlmv2_auth()) {
1554 flags |= CLI_CRED_NTLMv2_AUTH;
1557 * note that the 'domain' here is a best
1558 * guess - we don't know the server's domain
1559 * at this point. Windows clients also don't
1560 * use hostname...
1562 target_info = NTLMv2_generate_names_blob(state,
1563 NULL,
1564 domain);
1565 if (tevent_req_nomem(target_info.data, req)) {
1566 return tevent_req_post(req, ev);
1568 } else {
1569 flags |= CLI_CRED_NTLM_AUTH;
1570 if (lp_client_lanman_auth()) {
1571 flags |= CLI_CRED_LANMAN_AUTH;
1574 } else {
1575 if (!lp_client_lanman_auth()) {
1576 DEBUG(1, ("Server requested user level LM password but "
1577 "'client lanman auth = no' is set.\n"));
1578 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1579 return tevent_req_post(req, ev);
1582 flags |= CLI_CRED_LANMAN_AUTH;
1585 status = cli_credentials_get_ntlm_response(creds, state, &flags,
1586 challenge, NULL,
1587 target_info,
1588 &state->apassword_blob,
1589 &state->upassword_blob,
1590 &state->lm_session_key,
1591 &state->session_key);
1592 if (tevent_req_nterror(req, status)) {
1593 return tevent_req_post(req, ev);
1596 non_spnego_creds_done:
1598 in_buf_size = CLI_BUFFER_SIZE;
1599 in_mpx_max = smbXcli_conn_max_requests(cli->conn);
1600 in_vc_num = cli_state_get_vc_num(cli);
1601 in_sess_key = smb1cli_conn_server_session_key(cli->conn);
1602 in_native_os = "Unix";
1603 in_native_lm = "Samba";
1605 if (smbXcli_conn_protocol(cli->conn) == PROTOCOL_NT1) {
1606 uint32_t in_capabilities = 0;
1608 in_capabilities = cli_session_setup_capabilities(cli, 0);
1611 * For now we keep the same values as before,
1612 * we may remove these in a separate commit later.
1614 in_mpx_max = 2;
1616 subreq = smb1cli_session_setup_nt1_send(state, ev,
1617 cli->conn,
1618 cli->timeout,
1619 cli->smb1.pid,
1620 cli->smb1.session,
1621 in_buf_size,
1622 in_mpx_max,
1623 in_vc_num,
1624 in_sess_key,
1625 username,
1626 domain,
1627 state->apassword_blob,
1628 state->upassword_blob,
1629 in_capabilities,
1630 in_native_os,
1631 in_native_lm);
1632 if (tevent_req_nomem(subreq, req)) {
1633 return tevent_req_post(req, ev);
1635 tevent_req_set_callback(subreq, cli_session_setup_creds_done_nt1,
1636 req);
1637 return req;
1641 * For now we keep the same values as before,
1642 * we may remove these in a separate commit later.
1644 in_mpx_max = 2;
1645 in_vc_num = 1;
1647 subreq = smb1cli_session_setup_lm21_send(state, ev,
1648 cli->conn,
1649 cli->timeout,
1650 cli->smb1.pid,
1651 cli->smb1.session,
1652 in_buf_size,
1653 in_mpx_max,
1654 in_vc_num,
1655 in_sess_key,
1656 username,
1657 domain,
1658 state->apassword_blob,
1659 in_native_os,
1660 in_native_lm);
1661 if (tevent_req_nomem(subreq, req)) {
1662 return tevent_req_post(req, ev);
1664 tevent_req_set_callback(subreq, cli_session_setup_creds_done_lm21,
1665 req);
1666 return req;
1669 static void cli_session_setup_creds_done_spnego(struct tevent_req *subreq)
1671 struct tevent_req *req = tevent_req_callback_data(
1672 subreq, struct tevent_req);
1673 ADS_STATUS status;
1675 status = cli_session_setup_spnego_recv(subreq);
1676 TALLOC_FREE(subreq);
1677 if (!ADS_ERR_OK(status)) {
1678 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1679 tevent_req_nterror(req, ads_ntstatus(status));
1680 return;
1682 tevent_req_done(req);
1685 static void cli_session_setup_creds_done_nt1(struct tevent_req *subreq)
1687 struct tevent_req *req = tevent_req_callback_data(
1688 subreq, struct tevent_req);
1689 struct cli_session_setup_creds_state *state = tevent_req_data(
1690 req, struct cli_session_setup_creds_state);
1691 struct cli_state *cli = state->cli;
1692 NTSTATUS status;
1693 struct iovec *recv_iov = NULL;
1694 const uint8_t *inbuf = NULL;
1695 bool ok;
1697 status = smb1cli_session_setup_nt1_recv(subreq, state,
1698 &recv_iov,
1699 &inbuf,
1700 &state->out_native_os,
1701 &state->out_native_lm,
1702 &state->out_primary_domain);
1703 TALLOC_FREE(subreq);
1704 if (!NT_STATUS_IS_OK(status)) {
1705 DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
1706 tevent_req_nterror(req, status);
1707 return;
1710 status = cli_state_update_after_sesssetup(state->cli,
1711 state->out_native_os,
1712 state->out_native_lm,
1713 state->out_primary_domain);
1714 if (tevent_req_nterror(req, status)) {
1715 return;
1718 ok = smb1cli_conn_activate_signing(cli->conn,
1719 state->session_key,
1720 state->upassword_blob);
1721 if (ok) {
1722 ok = smb1cli_conn_check_signing(cli->conn, inbuf, 1);
1723 if (!ok) {
1724 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1725 return;
1729 if (state->session_key.data) {
1730 struct smbXcli_session *session = cli->smb1.session;
1732 status = smb1cli_session_set_session_key(session,
1733 state->session_key);
1734 if (tevent_req_nterror(req, status)) {
1735 return;
1739 tevent_req_done(req);
1742 static void cli_session_setup_creds_done_lm21(struct tevent_req *subreq)
1744 struct tevent_req *req = tevent_req_callback_data(
1745 subreq, struct tevent_req);
1746 struct cli_session_setup_creds_state *state = tevent_req_data(
1747 req, struct cli_session_setup_creds_state);
1748 NTSTATUS status;
1750 status = smb1cli_session_setup_lm21_recv(subreq, state,
1751 &state->out_native_os,
1752 &state->out_native_lm);
1753 TALLOC_FREE(subreq);
1754 if (!NT_STATUS_IS_OK(status)) {
1755 DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
1756 tevent_req_nterror(req, status);
1757 return;
1760 status = cli_state_update_after_sesssetup(state->cli,
1761 state->out_native_os,
1762 state->out_native_lm,
1763 NULL);
1764 if (tevent_req_nterror(req, status)) {
1765 return;
1768 tevent_req_done(req);
1771 NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req)
1773 return tevent_req_simple_recv_ntstatus(req);
1776 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
1777 struct cli_credentials *creds)
1779 struct tevent_context *ev;
1780 struct tevent_req *req;
1781 NTSTATUS status = NT_STATUS_NO_MEMORY;
1783 if (smbXcli_conn_has_async_calls(cli->conn)) {
1784 return NT_STATUS_INVALID_PARAMETER;
1786 ev = samba_tevent_context_init(talloc_tos());
1787 if (ev == NULL) {
1788 goto fail;
1790 req = cli_session_setup_creds_send(ev, ev, cli, creds);
1791 if (req == NULL) {
1792 goto fail;
1794 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1795 goto fail;
1797 status = cli_session_setup_creds_recv(req);
1798 fail:
1799 TALLOC_FREE(ev);
1800 return status;
1803 NTSTATUS cli_session_setup_anon(struct cli_state *cli)
1805 NTSTATUS status = NT_STATUS_NO_MEMORY;
1806 struct cli_credentials *creds = NULL;
1808 creds = cli_credentials_init_anon(cli);
1809 if (creds == NULL) {
1810 return NT_STATUS_NO_MEMORY;
1813 status = cli_session_setup_creds(cli, creds);
1814 TALLOC_FREE(creds);
1815 if (!NT_STATUS_IS_OK(status)) {
1816 return status;
1819 return NT_STATUS_OK;
1822 /****************************************************************************
1823 Send a uloggoff.
1824 *****************************************************************************/
1826 struct cli_ulogoff_state {
1827 struct cli_state *cli;
1828 uint16_t vwv[3];
1831 static void cli_ulogoff_done(struct tevent_req *subreq);
1833 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1834 struct tevent_context *ev,
1835 struct cli_state *cli)
1837 struct tevent_req *req, *subreq;
1838 struct cli_ulogoff_state *state;
1840 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1841 if (req == NULL) {
1842 return NULL;
1844 state->cli = cli;
1846 SCVAL(state->vwv+0, 0, 0xFF);
1847 SCVAL(state->vwv+1, 0, 0);
1848 SSVAL(state->vwv+2, 0, 0);
1850 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 0, 2, state->vwv,
1851 0, NULL);
1852 if (tevent_req_nomem(subreq, req)) {
1853 return tevent_req_post(req, ev);
1855 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1856 return req;
1859 static void cli_ulogoff_done(struct tevent_req *subreq)
1861 struct tevent_req *req = tevent_req_callback_data(
1862 subreq, struct tevent_req);
1863 struct cli_ulogoff_state *state = tevent_req_data(
1864 req, struct cli_ulogoff_state);
1865 NTSTATUS status;
1867 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1868 if (!NT_STATUS_IS_OK(status)) {
1869 tevent_req_nterror(req, status);
1870 return;
1872 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1873 tevent_req_done(req);
1876 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1878 return tevent_req_simple_recv_ntstatus(req);
1881 NTSTATUS cli_ulogoff(struct cli_state *cli)
1883 struct tevent_context *ev;
1884 struct tevent_req *req;
1885 NTSTATUS status = NT_STATUS_NO_MEMORY;
1887 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1888 status = smb2cli_logoff(cli->conn,
1889 cli->timeout,
1890 cli->smb2.session);
1891 if (!NT_STATUS_IS_OK(status)) {
1892 return status;
1894 smb2cli_session_set_id_and_flags(cli->smb2.session,
1895 UINT64_MAX, 0);
1896 return NT_STATUS_OK;
1899 if (smbXcli_conn_has_async_calls(cli->conn)) {
1900 return NT_STATUS_INVALID_PARAMETER;
1902 ev = samba_tevent_context_init(talloc_tos());
1903 if (ev == NULL) {
1904 goto fail;
1906 req = cli_ulogoff_send(ev, ev, cli);
1907 if (req == NULL) {
1908 goto fail;
1910 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1911 goto fail;
1913 status = cli_ulogoff_recv(req);
1914 fail:
1915 TALLOC_FREE(ev);
1916 return status;
1919 /****************************************************************************
1920 Send a tconX.
1921 ****************************************************************************/
1923 struct cli_tcon_andx_state {
1924 struct cli_state *cli;
1925 uint16_t vwv[4];
1926 struct iovec bytes;
1929 static void cli_tcon_andx_done(struct tevent_req *subreq);
1931 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1932 struct tevent_context *ev,
1933 struct cli_state *cli,
1934 const char *share, const char *dev,
1935 const char *pass, int passlen,
1936 struct tevent_req **psmbreq)
1938 struct tevent_req *req, *subreq;
1939 struct cli_tcon_andx_state *state;
1940 uint8_t p24[24];
1941 uint16_t *vwv;
1942 char *tmp = NULL;
1943 uint8_t *bytes;
1944 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1945 uint16_t tcon_flags = 0;
1947 *psmbreq = NULL;
1949 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1950 if (req == NULL) {
1951 return NULL;
1953 state->cli = cli;
1954 vwv = state->vwv;
1956 TALLOC_FREE(cli->smb1.tcon);
1957 cli->smb1.tcon = smbXcli_tcon_create(cli);
1958 if (tevent_req_nomem(cli->smb1.tcon, req)) {
1959 return tevent_req_post(req, ev);
1961 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
1963 cli->share = talloc_strdup(cli, share);
1964 if (!cli->share) {
1965 return NULL;
1968 /* in user level security don't send a password now */
1969 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1970 passlen = 1;
1971 pass = "";
1972 } else if (pass == NULL) {
1973 DEBUG(1, ("Server not using user level security and no "
1974 "password supplied.\n"));
1975 goto access_denied;
1978 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1979 *pass && passlen != 24) {
1980 if (!lp_client_lanman_auth()) {
1981 DEBUG(1, ("Server requested LANMAN password "
1982 "(share-level security) but "
1983 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
1984 goto access_denied;
1988 * Non-encrypted passwords - convert to DOS codepage before
1989 * encryption.
1991 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
1992 passlen = 24;
1993 pass = (const char *)p24;
1994 } else {
1995 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1996 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1997 == 0) {
1998 uint8_t *tmp_pass;
2000 if (!lp_client_plaintext_auth() && (*pass)) {
2001 DEBUG(1, ("Server requested PLAINTEXT "
2002 "password but "
2003 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2004 goto access_denied;
2008 * Non-encrypted passwords - convert to DOS codepage
2009 * before using.
2011 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2012 if (tevent_req_nomem(tmp_pass, req)) {
2013 return tevent_req_post(req, ev);
2015 tmp_pass = trans2_bytes_push_str(tmp_pass,
2016 false, /* always DOS */
2017 pass,
2018 passlen,
2019 NULL);
2020 if (tevent_req_nomem(tmp_pass, req)) {
2021 return tevent_req_post(req, ev);
2023 pass = (const char *)tmp_pass;
2024 passlen = talloc_get_size(tmp_pass);
2028 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2029 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2031 SCVAL(vwv+0, 0, 0xFF);
2032 SCVAL(vwv+0, 1, 0);
2033 SSVAL(vwv+1, 0, 0);
2034 SSVAL(vwv+2, 0, tcon_flags);
2035 SSVAL(vwv+3, 0, passlen);
2037 if (passlen && pass) {
2038 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2039 } else {
2040 bytes = talloc_array(state, uint8_t, 0);
2044 * Add the sharename
2046 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2047 smbXcli_conn_remote_name(cli->conn), share);
2048 if (tmp == NULL) {
2049 TALLOC_FREE(req);
2050 return NULL;
2052 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2053 NULL);
2054 TALLOC_FREE(tmp);
2057 * Add the devicetype
2059 tmp = talloc_strdup_upper(talloc_tos(), dev);
2060 if (tmp == NULL) {
2061 TALLOC_FREE(req);
2062 return NULL;
2064 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2065 TALLOC_FREE(tmp);
2067 if (bytes == NULL) {
2068 TALLOC_FREE(req);
2069 return NULL;
2072 state->bytes.iov_base = (void *)bytes;
2073 state->bytes.iov_len = talloc_get_size(bytes);
2075 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 0, 4, vwv,
2076 1, &state->bytes);
2077 if (subreq == NULL) {
2078 TALLOC_FREE(req);
2079 return NULL;
2081 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2082 *psmbreq = subreq;
2083 return req;
2085 access_denied:
2086 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2087 return tevent_req_post(req, ev);
2090 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2091 struct tevent_context *ev,
2092 struct cli_state *cli,
2093 const char *share, const char *dev,
2094 const char *pass, int passlen)
2096 struct tevent_req *req, *subreq;
2097 NTSTATUS status;
2099 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2100 &subreq);
2101 if (req == NULL) {
2102 return NULL;
2104 if (subreq == NULL) {
2105 return req;
2107 status = smb1cli_req_chain_submit(&subreq, 1);
2108 if (!NT_STATUS_IS_OK(status)) {
2109 tevent_req_nterror(req, status);
2110 return tevent_req_post(req, ev);
2112 return req;
2115 static void cli_tcon_andx_done(struct tevent_req *subreq)
2117 struct tevent_req *req = tevent_req_callback_data(
2118 subreq, struct tevent_req);
2119 struct cli_tcon_andx_state *state = tevent_req_data(
2120 req, struct cli_tcon_andx_state);
2121 struct cli_state *cli = state->cli;
2122 uint8_t *in;
2123 uint8_t *inhdr;
2124 uint8_t wct;
2125 uint16_t *vwv;
2126 uint32_t num_bytes;
2127 uint8_t *bytes;
2128 NTSTATUS status;
2129 uint16_t optional_support = 0;
2131 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2132 &num_bytes, &bytes);
2133 TALLOC_FREE(subreq);
2134 if (!NT_STATUS_IS_OK(status)) {
2135 tevent_req_nterror(req, status);
2136 return;
2139 inhdr = in + NBT_HDR_SIZE;
2141 if (num_bytes) {
2142 if (clistr_pull_talloc(cli,
2143 (const char *)inhdr,
2144 SVAL(inhdr, HDR_FLG2),
2145 &cli->dev,
2146 bytes,
2147 num_bytes,
2148 STR_TERMINATE|STR_ASCII) == -1) {
2149 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2150 return;
2152 } else {
2153 cli->dev = talloc_strdup(cli, "");
2154 if (cli->dev == NULL) {
2155 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2156 return;
2160 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2161 /* almost certainly win95 - enable bug fixes */
2162 cli->win95 = True;
2166 * Make sure that we have the optional support 16-bit field. WCT > 2.
2167 * Avoids issues when connecting to Win9x boxes sharing files
2170 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2171 optional_support = SVAL(vwv+2, 0);
2174 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2175 smb1cli_session_protect_session_key(cli->smb1.session);
2178 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2179 SVAL(inhdr, HDR_TID),
2180 optional_support,
2181 0, /* maximal_access */
2182 0, /* guest_maximal_access */
2183 NULL, /* service */
2184 NULL); /* fs_type */
2186 tevent_req_done(req);
2189 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2191 return tevent_req_simple_recv_ntstatus(req);
2194 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2195 const char *dev, const char *pass, int passlen)
2197 TALLOC_CTX *frame = talloc_stackframe();
2198 struct tevent_context *ev;
2199 struct tevent_req *req;
2200 NTSTATUS status = NT_STATUS_NO_MEMORY;
2202 if (smbXcli_conn_has_async_calls(cli->conn)) {
2204 * Can't use sync call while an async call is in flight
2206 status = NT_STATUS_INVALID_PARAMETER;
2207 goto fail;
2210 ev = samba_tevent_context_init(frame);
2211 if (ev == NULL) {
2212 goto fail;
2215 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2216 if (req == NULL) {
2217 goto fail;
2220 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2221 goto fail;
2224 status = cli_tcon_andx_recv(req);
2225 fail:
2226 TALLOC_FREE(frame);
2227 return status;
2230 struct cli_tree_connect_state {
2231 struct cli_state *cli;
2234 static struct tevent_req *cli_raw_tcon_send(
2235 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2236 const char *service, const char *pass, const char *dev);
2237 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2238 uint16_t *max_xmit, uint16_t *tid);
2240 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2241 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2242 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2244 static struct tevent_req *cli_tree_connect_send(
2245 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2246 const char *share, const char *dev, const char *pass)
2248 struct tevent_req *req, *subreq;
2249 struct cli_tree_connect_state *state;
2250 int passlen;
2252 if (pass == NULL) {
2253 pass = "";
2255 passlen = strlen(pass) + 1;
2257 req = tevent_req_create(mem_ctx, &state,
2258 struct cli_tree_connect_state);
2259 if (req == NULL) {
2260 return NULL;
2262 state->cli = cli;
2264 cli->share = talloc_strdup(cli, share);
2265 if (tevent_req_nomem(cli->share, req)) {
2266 return tevent_req_post(req, ev);
2269 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2270 char *unc;
2272 TALLOC_FREE(cli->smb2.tcon);
2273 cli->smb2.tcon = smbXcli_tcon_create(cli);
2274 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2275 return tevent_req_post(req, ev);
2278 unc = talloc_asprintf(state, "\\\\%s\\%s",
2279 smbXcli_conn_remote_name(cli->conn),
2280 share);
2281 if (tevent_req_nomem(unc, req)) {
2282 return tevent_req_post(req, ev);
2285 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2286 cli->smb2.session, cli->smb2.tcon,
2287 0, /* flags */
2288 unc);
2289 if (tevent_req_nomem(subreq, req)) {
2290 return tevent_req_post(req, ev);
2292 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2293 req);
2294 return req;
2297 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2298 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2299 pass, passlen);
2300 if (tevent_req_nomem(subreq, req)) {
2301 return tevent_req_post(req, ev);
2303 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2304 req);
2305 return req;
2308 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2309 if (tevent_req_nomem(subreq, req)) {
2310 return tevent_req_post(req, ev);
2312 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2314 return req;
2317 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2319 tevent_req_simple_finish_ntstatus(
2320 subreq, smb2cli_tcon_recv(subreq));
2323 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2325 tevent_req_simple_finish_ntstatus(
2326 subreq, cli_tcon_andx_recv(subreq));
2329 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2331 struct tevent_req *req = tevent_req_callback_data(
2332 subreq, struct tevent_req);
2333 struct cli_tree_connect_state *state = tevent_req_data(
2334 req, struct cli_tree_connect_state);
2335 NTSTATUS status;
2336 uint16_t max_xmit = 0;
2337 uint16_t tid = 0;
2339 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2340 if (tevent_req_nterror(req, status)) {
2341 return;
2344 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2345 tid,
2346 0, /* optional_support */
2347 0, /* maximal_access */
2348 0, /* guest_maximal_access */
2349 NULL, /* service */
2350 NULL); /* fs_type */
2352 tevent_req_done(req);
2355 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2357 return tevent_req_simple_recv_ntstatus(req);
2360 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2361 const char *dev, const char *pass)
2363 struct tevent_context *ev;
2364 struct tevent_req *req;
2365 NTSTATUS status = NT_STATUS_NO_MEMORY;
2367 if (smbXcli_conn_has_async_calls(cli->conn)) {
2368 return NT_STATUS_INVALID_PARAMETER;
2370 ev = samba_tevent_context_init(talloc_tos());
2371 if (ev == NULL) {
2372 goto fail;
2374 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass);
2375 if (req == NULL) {
2376 goto fail;
2378 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2379 goto fail;
2381 status = cli_tree_connect_recv(req);
2382 fail:
2383 TALLOC_FREE(ev);
2384 return status;
2387 NTSTATUS cli_tree_connect_creds(struct cli_state *cli,
2388 const char *share, const char *dev,
2389 struct cli_credentials *creds)
2391 const char *pw = NULL;
2393 if (creds != NULL) {
2394 pw = cli_credentials_get_password(creds);
2397 return cli_tree_connect(cli, share, dev, pw);
2400 /****************************************************************************
2401 Send a tree disconnect.
2402 ****************************************************************************/
2404 struct cli_tdis_state {
2405 struct cli_state *cli;
2408 static void cli_tdis_done(struct tevent_req *subreq);
2410 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2411 struct tevent_context *ev,
2412 struct cli_state *cli)
2414 struct tevent_req *req, *subreq;
2415 struct cli_tdis_state *state;
2417 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2418 if (req == NULL) {
2419 return NULL;
2421 state->cli = cli;
2423 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, 0, NULL, 0, NULL);
2424 if (tevent_req_nomem(subreq, req)) {
2425 return tevent_req_post(req, ev);
2427 tevent_req_set_callback(subreq, cli_tdis_done, req);
2428 return req;
2431 static void cli_tdis_done(struct tevent_req *subreq)
2433 struct tevent_req *req = tevent_req_callback_data(
2434 subreq, struct tevent_req);
2435 struct cli_tdis_state *state = tevent_req_data(
2436 req, struct cli_tdis_state);
2437 NTSTATUS status;
2439 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2440 TALLOC_FREE(subreq);
2441 if (!NT_STATUS_IS_OK(status)) {
2442 tevent_req_nterror(req, status);
2443 return;
2445 TALLOC_FREE(state->cli->smb1.tcon);
2446 tevent_req_done(req);
2449 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2451 return tevent_req_simple_recv_ntstatus(req);
2454 NTSTATUS cli_tdis(struct cli_state *cli)
2456 struct tevent_context *ev;
2457 struct tevent_req *req;
2458 NTSTATUS status = NT_STATUS_NO_MEMORY;
2460 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2461 status = smb2cli_tdis(cli->conn,
2462 cli->timeout,
2463 cli->smb2.session,
2464 cli->smb2.tcon);
2465 if (NT_STATUS_IS_OK(status)) {
2466 TALLOC_FREE(cli->smb2.tcon);
2468 return status;
2471 if (smbXcli_conn_has_async_calls(cli->conn)) {
2472 return NT_STATUS_INVALID_PARAMETER;
2474 ev = samba_tevent_context_init(talloc_tos());
2475 if (ev == NULL) {
2476 goto fail;
2478 req = cli_tdis_send(ev, ev, cli);
2479 if (req == NULL) {
2480 goto fail;
2482 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2483 goto fail;
2485 status = cli_tdis_recv(req);
2486 fail:
2487 TALLOC_FREE(ev);
2488 return status;
2491 struct cli_connect_sock_state {
2492 const char **called_names;
2493 const char **calling_names;
2494 int *called_types;
2495 int fd;
2496 uint16_t port;
2499 static void cli_connect_sock_done(struct tevent_req *subreq);
2502 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2503 * nonzero address.
2506 static struct tevent_req *cli_connect_sock_send(
2507 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2508 const char *host, int name_type, const struct sockaddr_storage *pss,
2509 const char *myname, uint16_t port)
2511 struct tevent_req *req, *subreq;
2512 struct cli_connect_sock_state *state;
2513 struct sockaddr_storage *addrs;
2514 unsigned i, num_addrs;
2515 NTSTATUS status;
2517 req = tevent_req_create(mem_ctx, &state,
2518 struct cli_connect_sock_state);
2519 if (req == NULL) {
2520 return NULL;
2523 if ((pss == NULL) || is_zero_addr(pss)) {
2526 * Here we cheat. resolve_name_list is not async at all. So
2527 * this call will only be really async if the name lookup has
2528 * been done externally.
2531 status = resolve_name_list(state, host, name_type,
2532 &addrs, &num_addrs);
2533 if (!NT_STATUS_IS_OK(status)) {
2534 tevent_req_nterror(req, status);
2535 return tevent_req_post(req, ev);
2537 } else {
2538 addrs = talloc_array(state, struct sockaddr_storage, 1);
2539 if (tevent_req_nomem(addrs, req)) {
2540 return tevent_req_post(req, ev);
2542 addrs[0] = *pss;
2543 num_addrs = 1;
2546 state->called_names = talloc_array(state, const char *, num_addrs);
2547 if (tevent_req_nomem(state->called_names, req)) {
2548 return tevent_req_post(req, ev);
2550 state->called_types = talloc_array(state, int, num_addrs);
2551 if (tevent_req_nomem(state->called_types, req)) {
2552 return tevent_req_post(req, ev);
2554 state->calling_names = talloc_array(state, const char *, num_addrs);
2555 if (tevent_req_nomem(state->calling_names, req)) {
2556 return tevent_req_post(req, ev);
2558 for (i=0; i<num_addrs; i++) {
2559 state->called_names[i] = host;
2560 state->called_types[i] = name_type;
2561 state->calling_names[i] = myname;
2564 subreq = smbsock_any_connect_send(
2565 state, ev, addrs, state->called_names, state->called_types,
2566 state->calling_names, NULL, num_addrs, port);
2567 if (tevent_req_nomem(subreq, req)) {
2568 return tevent_req_post(req, ev);
2570 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2571 return req;
2574 static void cli_connect_sock_done(struct tevent_req *subreq)
2576 struct tevent_req *req = tevent_req_callback_data(
2577 subreq, struct tevent_req);
2578 struct cli_connect_sock_state *state = tevent_req_data(
2579 req, struct cli_connect_sock_state);
2580 NTSTATUS status;
2582 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2583 &state->port);
2584 TALLOC_FREE(subreq);
2585 if (tevent_req_nterror(req, status)) {
2586 return;
2588 set_socket_options(state->fd, lp_socket_options());
2589 tevent_req_done(req);
2592 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2593 int *pfd, uint16_t *pport)
2595 struct cli_connect_sock_state *state = tevent_req_data(
2596 req, struct cli_connect_sock_state);
2597 NTSTATUS status;
2599 if (tevent_req_is_nterror(req, &status)) {
2600 return status;
2602 *pfd = state->fd;
2603 *pport = state->port;
2604 return NT_STATUS_OK;
2607 struct cli_connect_nb_state {
2608 const char *desthost;
2609 int signing_state;
2610 int flags;
2611 struct cli_state *cli;
2614 static void cli_connect_nb_done(struct tevent_req *subreq);
2616 static struct tevent_req *cli_connect_nb_send(
2617 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2618 const char *host, const struct sockaddr_storage *dest_ss,
2619 uint16_t port, int name_type, const char *myname,
2620 int signing_state, int flags)
2622 struct tevent_req *req, *subreq;
2623 struct cli_connect_nb_state *state;
2625 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2626 if (req == NULL) {
2627 return NULL;
2629 state->signing_state = signing_state;
2630 state->flags = flags;
2632 if (host != NULL) {
2633 char *p = strchr(host, '#');
2635 if (p != NULL) {
2636 name_type = strtol(p+1, NULL, 16);
2637 host = talloc_strndup(state, host, p - host);
2638 if (tevent_req_nomem(host, req)) {
2639 return tevent_req_post(req, ev);
2643 state->desthost = host;
2644 } else if (dest_ss != NULL) {
2645 state->desthost = print_canonical_sockaddr(state, dest_ss);
2646 if (tevent_req_nomem(state->desthost, req)) {
2647 return tevent_req_post(req, ev);
2649 } else {
2650 /* No host or dest_ss given. Error out. */
2651 tevent_req_error(req, EINVAL);
2652 return tevent_req_post(req, ev);
2655 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2656 myname, port);
2657 if (tevent_req_nomem(subreq, req)) {
2658 return tevent_req_post(req, ev);
2660 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2661 return req;
2664 static void cli_connect_nb_done(struct tevent_req *subreq)
2666 struct tevent_req *req = tevent_req_callback_data(
2667 subreq, struct tevent_req);
2668 struct cli_connect_nb_state *state = tevent_req_data(
2669 req, struct cli_connect_nb_state);
2670 NTSTATUS status;
2671 int fd = 0;
2672 uint16_t port;
2674 status = cli_connect_sock_recv(subreq, &fd, &port);
2675 TALLOC_FREE(subreq);
2676 if (tevent_req_nterror(req, status)) {
2677 return;
2680 state->cli = cli_state_create(state, fd, state->desthost,
2681 state->signing_state, state->flags);
2682 if (tevent_req_nomem(state->cli, req)) {
2683 close(fd);
2684 return;
2686 tevent_req_done(req);
2689 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
2690 struct cli_state **pcli)
2692 struct cli_connect_nb_state *state = tevent_req_data(
2693 req, struct cli_connect_nb_state);
2694 NTSTATUS status;
2696 if (tevent_req_is_nterror(req, &status)) {
2697 return status;
2699 *pcli = talloc_move(NULL, &state->cli);
2700 return NT_STATUS_OK;
2703 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2704 uint16_t port, int name_type, const char *myname,
2705 int signing_state, int flags, struct cli_state **pcli)
2707 struct tevent_context *ev;
2708 struct tevent_req *req;
2709 NTSTATUS status = NT_STATUS_NO_MEMORY;
2711 ev = samba_tevent_context_init(talloc_tos());
2712 if (ev == NULL) {
2713 goto fail;
2715 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
2716 myname, signing_state, flags);
2717 if (req == NULL) {
2718 goto fail;
2720 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
2721 goto fail;
2723 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2724 goto fail;
2726 status = cli_connect_nb_recv(req, pcli);
2727 fail:
2728 TALLOC_FREE(ev);
2729 return status;
2732 struct cli_start_connection_state {
2733 struct tevent_context *ev;
2734 struct cli_state *cli;
2735 int min_protocol;
2736 int max_protocol;
2739 static void cli_start_connection_connected(struct tevent_req *subreq);
2740 static void cli_start_connection_done(struct tevent_req *subreq);
2743 establishes a connection to after the negprot.
2744 @param output_cli A fully initialised cli structure, non-null only on success
2745 @param dest_host The netbios name of the remote host
2746 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2747 @param port (optional) The destination port (0 for default)
2750 static struct tevent_req *cli_start_connection_send(
2751 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2752 const char *my_name, const char *dest_host,
2753 const struct sockaddr_storage *dest_ss, int port,
2754 int signing_state, int flags)
2756 struct tevent_req *req, *subreq;
2757 struct cli_start_connection_state *state;
2759 req = tevent_req_create(mem_ctx, &state,
2760 struct cli_start_connection_state);
2761 if (req == NULL) {
2762 return NULL;
2764 state->ev = ev;
2766 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
2767 state->min_protocol = lp_client_ipc_min_protocol();
2768 state->max_protocol = lp_client_ipc_max_protocol();
2769 } else {
2770 state->min_protocol = lp_client_min_protocol();
2771 state->max_protocol = lp_client_max_protocol();
2774 if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
2775 state->max_protocol = MIN(state->max_protocol, PROTOCOL_NT1);
2778 if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
2779 state->min_protocol = MAX(state->max_protocol, PROTOCOL_SMB2_02);
2780 state->max_protocol = MAX(state->max_protocol, PROTOCOL_LATEST);
2783 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
2784 0x20, my_name, signing_state, flags);
2785 if (tevent_req_nomem(subreq, req)) {
2786 return tevent_req_post(req, ev);
2788 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
2789 return req;
2792 static void cli_start_connection_connected(struct tevent_req *subreq)
2794 struct tevent_req *req = tevent_req_callback_data(
2795 subreq, struct tevent_req);
2796 struct cli_start_connection_state *state = tevent_req_data(
2797 req, struct cli_start_connection_state);
2798 NTSTATUS status;
2800 status = cli_connect_nb_recv(subreq, &state->cli);
2801 TALLOC_FREE(subreq);
2802 if (tevent_req_nterror(req, status)) {
2803 return;
2806 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
2807 state->cli->timeout,
2808 state->min_protocol,
2809 state->max_protocol,
2810 WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK);
2811 if (tevent_req_nomem(subreq, req)) {
2812 return;
2814 tevent_req_set_callback(subreq, cli_start_connection_done, req);
2817 static void cli_start_connection_done(struct tevent_req *subreq)
2819 struct tevent_req *req = tevent_req_callback_data(
2820 subreq, struct tevent_req);
2821 struct cli_start_connection_state *state = tevent_req_data(
2822 req, struct cli_start_connection_state);
2823 NTSTATUS status;
2825 status = smbXcli_negprot_recv(subreq);
2826 TALLOC_FREE(subreq);
2827 if (tevent_req_nterror(req, status)) {
2828 return;
2831 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
2832 /* Ensure we ask for some initial credits. */
2833 smb2cli_conn_set_max_credits(state->cli->conn,
2834 DEFAULT_SMB2_MAX_CREDITS);
2837 tevent_req_done(req);
2840 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
2841 struct cli_state **output_cli)
2843 struct cli_start_connection_state *state = tevent_req_data(
2844 req, struct cli_start_connection_state);
2845 NTSTATUS status;
2847 if (tevent_req_is_nterror(req, &status)) {
2848 return status;
2850 *output_cli = state->cli;
2852 return NT_STATUS_OK;
2855 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2856 const char *my_name,
2857 const char *dest_host,
2858 const struct sockaddr_storage *dest_ss, int port,
2859 int signing_state, int flags)
2861 struct tevent_context *ev;
2862 struct tevent_req *req;
2863 NTSTATUS status = NT_STATUS_NO_MEMORY;
2865 ev = samba_tevent_context_init(talloc_tos());
2866 if (ev == NULL) {
2867 goto fail;
2869 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
2870 port, signing_state, flags);
2871 if (req == NULL) {
2872 goto fail;
2874 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2875 goto fail;
2877 status = cli_start_connection_recv(req, output_cli);
2878 fail:
2879 TALLOC_FREE(ev);
2880 return status;
2883 struct cli_smb1_setup_encryption_blob_state {
2884 uint16_t setup[1];
2885 uint8_t param[4];
2886 NTSTATUS status;
2887 DATA_BLOB out;
2888 uint16_t enc_ctx_id;
2891 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
2893 static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
2894 struct tevent_context *ev,
2895 struct cli_state *cli,
2896 const DATA_BLOB in)
2898 struct tevent_req *req = NULL;
2899 struct cli_smb1_setup_encryption_blob_state *state = NULL;
2900 struct tevent_req *subreq = NULL;
2902 req = tevent_req_create(mem_ctx, &state,
2903 struct cli_smb1_setup_encryption_blob_state);
2904 if (req == NULL) {
2905 return NULL;
2908 if (in.length > CLI_BUFFER_SIZE) {
2909 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2910 return tevent_req_post(req, ev);
2913 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
2914 SSVAL(state->param, 0, 0);
2915 SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
2917 subreq = smb1cli_trans_send(state, ev, cli->conn,
2918 SMBtrans2,
2919 0, 0, /* _flags */
2920 0, 0, /* _flags2 */
2921 cli->timeout,
2922 cli->smb1.pid,
2923 cli->smb1.tcon,
2924 cli->smb1.session,
2925 NULL, /* pipe_name */
2926 0, /* fid */
2927 0, /* function */
2928 0, /* flags */
2929 state->setup, 1, 0,
2930 state->param, 4, 2,
2931 in.data, in.length, CLI_BUFFER_SIZE);
2932 if (tevent_req_nomem(subreq, req)) {
2933 return tevent_req_post(req, ev);
2935 tevent_req_set_callback(subreq,
2936 cli_smb1_setup_encryption_blob_done,
2937 req);
2939 return req;
2942 static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
2944 struct tevent_req *req =
2945 tevent_req_callback_data(subreq,
2946 struct tevent_req);
2947 struct cli_smb1_setup_encryption_blob_state *state =
2948 tevent_req_data(req,
2949 struct cli_smb1_setup_encryption_blob_state);
2950 uint8_t *rparam=NULL, *rdata=NULL;
2951 uint32_t num_rparam, num_rdata;
2952 NTSTATUS status;
2954 status = smb1cli_trans_recv(subreq, state,
2955 NULL, /* recv_flags */
2956 NULL, 0, NULL, /* rsetup */
2957 &rparam, 0, &num_rparam,
2958 &rdata, 0, &num_rdata);
2959 TALLOC_FREE(subreq);
2960 state->status = status;
2961 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2962 status = NT_STATUS_OK;
2964 if (tevent_req_nterror(req, status)) {
2965 return;
2968 if (num_rparam == 2) {
2969 state->enc_ctx_id = SVAL(rparam, 0);
2971 TALLOC_FREE(rparam);
2973 state->out = data_blob_const(rdata, num_rdata);
2975 tevent_req_done(req);
2978 static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
2979 TALLOC_CTX *mem_ctx,
2980 DATA_BLOB *out,
2981 uint16_t *enc_ctx_id)
2983 struct cli_smb1_setup_encryption_blob_state *state =
2984 tevent_req_data(req,
2985 struct cli_smb1_setup_encryption_blob_state);
2986 NTSTATUS status;
2988 if (tevent_req_is_nterror(req, &status)) {
2989 tevent_req_received(req);
2990 return status;
2993 status = state->status;
2995 *out = state->out;
2996 talloc_steal(mem_ctx, out->data);
2998 *enc_ctx_id = state->enc_ctx_id;
3000 tevent_req_received(req);
3001 return status;
3004 struct cli_smb1_setup_encryption_state {
3005 struct tevent_context *ev;
3006 struct cli_state *cli;
3007 struct smb_trans_enc_state *es;
3008 DATA_BLOB blob_in;
3009 DATA_BLOB blob_out;
3010 bool local_ready;
3011 bool remote_ready;
3014 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
3015 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
3016 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
3017 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
3018 static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
3020 static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
3021 struct tevent_context *ev,
3022 struct cli_state *cli,
3023 struct cli_credentials *creds)
3025 struct tevent_req *req = NULL;
3026 struct cli_smb1_setup_encryption_state *state = NULL;
3027 struct auth_generic_state *ags = NULL;
3028 const DATA_BLOB *b = NULL;
3029 bool auth_requested = false;
3030 const char *target_service = NULL;
3031 const char *target_hostname = NULL;
3032 NTSTATUS status;
3034 req = tevent_req_create(mem_ctx, &state,
3035 struct cli_smb1_setup_encryption_state);
3036 if (req == NULL) {
3037 return NULL;
3039 state->ev = ev;
3040 state->cli = cli;
3042 auth_requested = cli_credentials_authentication_requested(creds);
3043 if (!auth_requested) {
3044 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3045 return tevent_req_post(req, ev);
3048 target_service = "cifs";
3049 target_hostname = smbXcli_conn_remote_name(cli->conn);
3051 status = cli_session_creds_prepare_krb5(cli, creds);
3052 if (tevent_req_nterror(req, status)) {
3053 return tevent_req_post(req, ev);
3056 state->es = talloc_zero(state, struct smb_trans_enc_state);
3057 if (tevent_req_nomem(state->es, req)) {
3058 return tevent_req_post(req, ev);
3061 status = auth_generic_client_prepare(state->es, &ags);
3062 if (tevent_req_nterror(req, status)) {
3063 return tevent_req_post(req, ev);
3066 gensec_want_feature(ags->gensec_security,
3067 GENSEC_FEATURE_SIGN);
3068 gensec_want_feature(ags->gensec_security,
3069 GENSEC_FEATURE_SEAL);
3071 status = auth_generic_set_creds(ags, creds);
3072 if (tevent_req_nterror(req, status)) {
3073 return tevent_req_post(req, ev);
3076 if (target_service != NULL) {
3077 status = gensec_set_target_service(ags->gensec_security,
3078 target_service);
3079 if (tevent_req_nterror(req, status)) {
3080 return tevent_req_post(req, ev);
3084 if (target_hostname != NULL) {
3085 status = gensec_set_target_hostname(ags->gensec_security,
3086 target_hostname);
3087 if (tevent_req_nterror(req, status)) {
3088 return tevent_req_post(req, ev);
3092 gensec_set_max_update_size(ags->gensec_security,
3093 CLI_BUFFER_SIZE);
3095 b = smbXcli_conn_server_gss_blob(state->cli->conn);
3096 if (b != NULL) {
3097 state->blob_in = *b;
3100 status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
3101 if (tevent_req_nterror(req, status)) {
3102 return tevent_req_post(req, ev);
3106 * We only need the gensec_security part from here.
3108 state->es->gensec_security = talloc_move(state->es,
3109 &ags->gensec_security);
3110 TALLOC_FREE(ags);
3112 cli_smb1_setup_encryption_local_next(req);
3113 if (!tevent_req_is_in_progress(req)) {
3114 return tevent_req_post(req, ev);
3117 return req;
3120 static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
3122 struct cli_smb1_setup_encryption_state *state =
3123 tevent_req_data(req,
3124 struct cli_smb1_setup_encryption_state);
3125 struct tevent_req *subreq = NULL;
3127 if (state->local_ready) {
3128 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3129 return;
3132 subreq = gensec_update_send(state, state->ev,
3133 state->es->gensec_security,
3134 state->blob_in);
3135 if (tevent_req_nomem(subreq, req)) {
3136 return;
3138 tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
3141 static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
3143 struct tevent_req *req =
3144 tevent_req_callback_data(subreq,
3145 struct tevent_req);
3146 struct cli_smb1_setup_encryption_state *state =
3147 tevent_req_data(req,
3148 struct cli_smb1_setup_encryption_state);
3149 NTSTATUS status;
3151 status = gensec_update_recv(subreq, state, &state->blob_out);
3152 TALLOC_FREE(subreq);
3153 state->blob_in = data_blob_null;
3154 if (!NT_STATUS_IS_OK(status) &&
3155 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3157 tevent_req_nterror(req, status);
3158 return;
3161 if (NT_STATUS_IS_OK(status)) {
3162 state->local_ready = true;
3166 * We always get NT_STATUS_OK from the server even if it is not ready.
3167 * So guess the server is ready when we are ready and already sent
3168 * our last blob to the server.
3170 if (state->local_ready && state->blob_out.length == 0) {
3171 state->remote_ready = true;
3174 if (state->local_ready && state->remote_ready) {
3175 cli_smb1_setup_encryption_ready(req);
3176 return;
3179 cli_smb1_setup_encryption_remote_next(req);
3182 static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
3184 struct cli_smb1_setup_encryption_state *state =
3185 tevent_req_data(req,
3186 struct cli_smb1_setup_encryption_state);
3187 struct tevent_req *subreq = NULL;
3189 if (state->remote_ready) {
3190 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3191 return;
3194 subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
3195 state->cli, state->blob_out);
3196 if (tevent_req_nomem(subreq, req)) {
3197 return;
3199 tevent_req_set_callback(subreq,
3200 cli_smb1_setup_encryption_remote_done,
3201 req);
3204 static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
3206 struct tevent_req *req =
3207 tevent_req_callback_data(subreq,
3208 struct tevent_req);
3209 struct cli_smb1_setup_encryption_state *state =
3210 tevent_req_data(req,
3211 struct cli_smb1_setup_encryption_state);
3212 NTSTATUS status;
3214 status = cli_smb1_setup_encryption_blob_recv(subreq, state,
3215 &state->blob_in,
3216 &state->es->enc_ctx_num);
3217 TALLOC_FREE(subreq);
3218 data_blob_free(&state->blob_out);
3219 if (!NT_STATUS_IS_OK(status) &&
3220 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
3222 tevent_req_nterror(req, status);
3223 return;
3227 * We always get NT_STATUS_OK even if the server is not ready.
3228 * So guess the server is ready when we are ready and sent
3229 * our last blob to the server.
3231 if (state->local_ready) {
3232 state->remote_ready = true;
3235 if (state->local_ready && state->remote_ready) {
3236 cli_smb1_setup_encryption_ready(req);
3237 return;
3240 cli_smb1_setup_encryption_local_next(req);
3243 static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
3245 struct cli_smb1_setup_encryption_state *state =
3246 tevent_req_data(req,
3247 struct cli_smb1_setup_encryption_state);
3248 struct smb_trans_enc_state *es = NULL;
3250 if (state->blob_in.length != 0) {
3251 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3252 return;
3255 if (state->blob_out.length != 0) {
3256 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3257 return;
3260 es = talloc_move(state->cli->conn, &state->es);
3261 es->enc_on = true;
3262 smb1cli_conn_set_encryption(state->cli->conn, es);
3263 es = NULL;
3265 tevent_req_done(req);
3268 static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
3270 return tevent_req_simple_recv_ntstatus(req);
3273 NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
3274 struct cli_credentials *creds)
3276 struct tevent_context *ev = NULL;
3277 struct tevent_req *req = NULL;
3278 NTSTATUS status = NT_STATUS_NO_MEMORY;
3280 ev = samba_tevent_context_init(talloc_tos());
3281 if (ev == NULL) {
3282 goto fail;
3284 req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
3285 if (req == NULL) {
3286 goto fail;
3288 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3289 goto fail;
3291 status = cli_smb1_setup_encryption_recv(req);
3292 fail:
3293 TALLOC_FREE(ev);
3294 return status;
3298 establishes a connection right up to doing tconX, password specified.
3299 @param output_cli A fully initialised cli structure, non-null only on success
3300 @param dest_host The netbios name of the remote host
3301 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3302 @param port (optional) The destination port (0 for default)
3303 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3304 @param service_type The 'type' of serivice.
3305 @param creds The used user credentials
3308 struct cli_full_connection_creds_state {
3309 struct tevent_context *ev;
3310 const char *service;
3311 const char *service_type;
3312 struct cli_credentials *creds;
3313 int flags;
3314 struct cli_state *cli;
3317 static int cli_full_connection_creds_state_destructor(
3318 struct cli_full_connection_creds_state *s)
3320 if (s->cli != NULL) {
3321 cli_shutdown(s->cli);
3322 s->cli = NULL;
3324 return 0;
3327 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
3328 static void cli_full_connection_creds_sess_start(struct tevent_req *req);
3329 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
3330 static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
3331 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
3333 struct tevent_req *cli_full_connection_creds_send(
3334 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3335 const char *my_name, const char *dest_host,
3336 const struct sockaddr_storage *dest_ss, int port,
3337 const char *service, const char *service_type,
3338 struct cli_credentials *creds,
3339 int flags, int signing_state)
3341 struct tevent_req *req, *subreq;
3342 struct cli_full_connection_creds_state *state;
3343 enum credentials_use_kerberos krb5_state;
3344 uint32_t gensec_features = 0;
3346 req = tevent_req_create(mem_ctx, &state,
3347 struct cli_full_connection_creds_state);
3348 if (req == NULL) {
3349 return NULL;
3351 talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
3353 flags &= ~CLI_FULL_CONNECTION_USE_KERBEROS;
3354 flags &= ~CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3355 flags &= ~CLI_FULL_CONNECTION_USE_CCACHE;
3356 flags &= ~CLI_FULL_CONNECTION_USE_NT_HASH;
3358 krb5_state = cli_credentials_get_kerberos_state(creds);
3359 switch (krb5_state) {
3360 case CRED_MUST_USE_KERBEROS:
3361 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3362 flags &= ~CLI_FULL_CONNECTION_DONT_SPNEGO;
3363 break;
3364 case CRED_AUTO_USE_KERBEROS:
3365 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3366 flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
3367 break;
3368 case CRED_DONT_USE_KERBEROS:
3369 break;
3372 gensec_features = cli_credentials_get_gensec_features(creds);
3373 if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
3374 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
3377 state->ev = ev;
3378 state->service = service;
3379 state->service_type = service_type;
3380 state->creds = creds;
3381 state->flags = flags;
3383 subreq = cli_start_connection_send(
3384 state, ev, my_name, dest_host, dest_ss, port,
3385 signing_state, flags);
3386 if (tevent_req_nomem(subreq, req)) {
3387 return tevent_req_post(req, ev);
3389 tevent_req_set_callback(subreq,
3390 cli_full_connection_creds_conn_done,
3391 req);
3392 return req;
3395 static void cli_full_connection_creds_conn_done(struct tevent_req *subreq)
3397 struct tevent_req *req = tevent_req_callback_data(
3398 subreq, struct tevent_req);
3399 struct cli_full_connection_creds_state *state = tevent_req_data(
3400 req, struct cli_full_connection_creds_state);
3401 NTSTATUS status;
3403 status = cli_start_connection_recv(subreq, &state->cli);
3404 TALLOC_FREE(subreq);
3405 if (tevent_req_nterror(req, status)) {
3406 return;
3409 cli_full_connection_creds_sess_start(req);
3412 static void cli_full_connection_creds_sess_start(struct tevent_req *req)
3414 struct cli_full_connection_creds_state *state = tevent_req_data(
3415 req, struct cli_full_connection_creds_state);
3416 struct tevent_req *subreq = NULL;
3418 subreq = cli_session_setup_creds_send(
3419 state, state->ev, state->cli, state->creds);
3420 if (tevent_req_nomem(subreq, req)) {
3421 return;
3423 tevent_req_set_callback(subreq,
3424 cli_full_connection_creds_sess_done,
3425 req);
3428 static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
3430 struct tevent_req *req = tevent_req_callback_data(
3431 subreq, struct tevent_req);
3432 struct cli_full_connection_creds_state *state = tevent_req_data(
3433 req, struct cli_full_connection_creds_state);
3434 NTSTATUS status;
3436 status = cli_session_setup_creds_recv(subreq);
3437 TALLOC_FREE(subreq);
3439 if (!NT_STATUS_IS_OK(status) &&
3440 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3442 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3444 state->creds = cli_credentials_init_anon(state);
3445 if (tevent_req_nomem(state->creds, req)) {
3446 return;
3449 cli_full_connection_creds_sess_start(req);
3450 return;
3453 if (tevent_req_nterror(req, status)) {
3454 return;
3457 cli_full_connection_creds_tcon_start(req);
3460 static void cli_full_connection_creds_tcon_start(struct tevent_req *req)
3462 struct cli_full_connection_creds_state *state = tevent_req_data(
3463 req, struct cli_full_connection_creds_state);
3464 struct tevent_req *subreq = NULL;
3465 const char *password = NULL;
3467 if (state->service == NULL) {
3468 tevent_req_done(req);
3469 return;
3472 password = cli_credentials_get_password(state->creds);
3474 subreq = cli_tree_connect_send(state, state->ev,
3475 state->cli,
3476 state->service,
3477 state->service_type,
3478 password);
3479 if (tevent_req_nomem(subreq, req)) {
3480 return;
3482 tevent_req_set_callback(subreq,
3483 cli_full_connection_creds_tcon_done,
3484 req);
3487 static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq)
3489 struct tevent_req *req = tevent_req_callback_data(
3490 subreq, struct tevent_req);
3491 NTSTATUS status;
3493 status = cli_tree_connect_recv(subreq);
3494 TALLOC_FREE(subreq);
3495 if (tevent_req_nterror(req, status)) {
3496 return;
3499 tevent_req_done(req);
3502 NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
3503 struct cli_state **output_cli)
3505 struct cli_full_connection_creds_state *state = tevent_req_data(
3506 req, struct cli_full_connection_creds_state);
3507 NTSTATUS status;
3509 if (tevent_req_is_nterror(req, &status)) {
3510 return status;
3512 *output_cli = state->cli;
3513 talloc_set_destructor(state, NULL);
3514 return NT_STATUS_OK;
3517 NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
3518 const char *my_name,
3519 const char *dest_host,
3520 const struct sockaddr_storage *dest_ss, int port,
3521 const char *service, const char *service_type,
3522 struct cli_credentials *creds,
3523 int flags,
3524 int signing_state)
3526 struct tevent_context *ev;
3527 struct tevent_req *req;
3528 NTSTATUS status = NT_STATUS_NO_MEMORY;
3530 ev = samba_tevent_context_init(talloc_tos());
3531 if (ev == NULL) {
3532 goto fail;
3534 req = cli_full_connection_creds_send(
3535 ev, ev, my_name, dest_host, dest_ss, port, service,
3536 service_type, creds, flags, signing_state);
3537 if (req == NULL) {
3538 goto fail;
3540 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3541 goto fail;
3543 status = cli_full_connection_creds_recv(req, output_cli);
3544 fail:
3545 TALLOC_FREE(ev);
3546 return status;
3549 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3550 const char *my_name,
3551 const char *dest_host,
3552 const struct sockaddr_storage *dest_ss, int port,
3553 const char *service, const char *service_type,
3554 const char *user, const char *domain,
3555 const char *password, int flags,
3556 int signing_state)
3558 TALLOC_CTX *frame = talloc_stackframe();
3559 NTSTATUS status;
3560 bool use_kerberos = false;
3561 bool fallback_after_kerberos = false;
3562 bool use_ccache = false;
3563 bool pw_nt_hash = false;
3564 struct cli_credentials *creds = NULL;
3566 if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
3567 use_kerberos = true;
3570 if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) {
3571 fallback_after_kerberos = true;
3574 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3575 use_ccache = true;
3578 if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) {
3579 pw_nt_hash = true;
3582 creds = cli_session_creds_init(frame,
3583 user,
3584 domain,
3585 NULL, /* realm (use default) */
3586 password,
3587 use_kerberos,
3588 fallback_after_kerberos,
3589 use_ccache,
3590 pw_nt_hash);
3591 if (creds == NULL) {
3592 TALLOC_FREE(frame);
3593 return NT_STATUS_NO_MEMORY;
3596 status = cli_full_connection_creds(output_cli, my_name,
3597 dest_host, dest_ss, port,
3598 service, service_type,
3599 creds, flags, signing_state);
3600 if (!NT_STATUS_IS_OK(status)) {
3601 TALLOC_FREE(frame);
3602 return status;
3605 TALLOC_FREE(frame);
3606 return NT_STATUS_OK;
3609 /****************************************************************************
3610 Send an old style tcon.
3611 ****************************************************************************/
3612 struct cli_raw_tcon_state {
3613 uint16_t *ret_vwv;
3616 static void cli_raw_tcon_done(struct tevent_req *subreq);
3618 static struct tevent_req *cli_raw_tcon_send(
3619 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3620 const char *service, const char *pass, const char *dev)
3622 struct tevent_req *req, *subreq;
3623 struct cli_raw_tcon_state *state;
3624 uint8_t *bytes;
3626 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3627 if (req == NULL) {
3628 return NULL;
3631 if (!lp_client_plaintext_auth() && (*pass)) {
3632 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3633 " or 'client ntlmv2 auth = yes'\n"));
3634 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3635 return tevent_req_post(req, ev);
3638 TALLOC_FREE(cli->smb1.tcon);
3639 cli->smb1.tcon = smbXcli_tcon_create(cli);
3640 if (tevent_req_nomem(cli->smb1.tcon, req)) {
3641 return tevent_req_post(req, ev);
3643 smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
3645 bytes = talloc_array(state, uint8_t, 0);
3646 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3647 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3648 service, strlen(service)+1, NULL);
3649 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3650 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3651 pass, strlen(pass)+1, NULL);
3652 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3653 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3654 dev, strlen(dev)+1, NULL);
3656 if (tevent_req_nomem(bytes, req)) {
3657 return tevent_req_post(req, ev);
3660 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, 0, NULL,
3661 talloc_get_size(bytes), bytes);
3662 if (tevent_req_nomem(subreq, req)) {
3663 return tevent_req_post(req, ev);
3665 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3666 return req;
3669 static void cli_raw_tcon_done(struct tevent_req *subreq)
3671 struct tevent_req *req = tevent_req_callback_data(
3672 subreq, struct tevent_req);
3673 struct cli_raw_tcon_state *state = tevent_req_data(
3674 req, struct cli_raw_tcon_state);
3675 NTSTATUS status;
3677 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3678 NULL, NULL);
3679 TALLOC_FREE(subreq);
3680 if (tevent_req_nterror(req, status)) {
3681 return;
3683 tevent_req_done(req);
3686 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3687 uint16_t *max_xmit, uint16_t *tid)
3689 struct cli_raw_tcon_state *state = tevent_req_data(
3690 req, struct cli_raw_tcon_state);
3691 NTSTATUS status;
3693 if (tevent_req_is_nterror(req, &status)) {
3694 return status;
3696 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3697 *tid = SVAL(state->ret_vwv + 1, 0);
3698 return NT_STATUS_OK;
3701 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3702 const char *service, const char *pass, const char *dev,
3703 uint16_t *max_xmit, uint16_t *tid)
3705 struct tevent_context *ev;
3706 struct tevent_req *req;
3707 NTSTATUS status = NT_STATUS_NO_MEMORY;
3709 ev = samba_tevent_context_init(talloc_tos());
3710 if (ev == NULL) {
3711 goto fail;
3713 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3714 if (req == NULL) {
3715 goto fail;
3717 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3718 goto fail;
3720 status = cli_raw_tcon_recv(req, max_xmit, tid);
3721 fail:
3722 TALLOC_FREE(ev);
3723 return status;
3726 /* Return a cli_state pointing at the IPC$ share for the given server */
3728 struct cli_state *get_ipc_connect(char *server,
3729 struct sockaddr_storage *server_ss,
3730 const struct user_auth_info *user_info)
3732 struct cli_state *cli;
3733 NTSTATUS nt_status;
3734 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3736 if (get_cmdline_auth_info_use_kerberos(user_info)) {
3737 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3740 flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
3742 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3743 get_cmdline_auth_info_username(user_info),
3744 lp_workgroup(),
3745 get_cmdline_auth_info_password(user_info),
3746 flags,
3747 SMB_SIGNING_DEFAULT);
3749 if (NT_STATUS_IS_OK(nt_status)) {
3750 return cli;
3751 } else if (is_ipaddress(server)) {
3752 /* windows 9* needs a correct NMB name for connections */
3753 fstring remote_name;
3755 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3756 cli = get_ipc_connect(remote_name, server_ss, user_info);
3757 if (cli)
3758 return cli;
3761 return NULL;
3765 * Given the IP address of a master browser on the network, return its
3766 * workgroup and connect to it.
3768 * This function is provided to allow additional processing beyond what
3769 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3770 * browsers and obtain each master browsers' list of domains (in case the
3771 * first master browser is recently on the network and has not yet
3772 * synchronized with other master browsers and therefore does not yet have the
3773 * entire network browse list)
3776 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3777 struct sockaddr_storage *mb_ip,
3778 const struct user_auth_info *user_info,
3779 char **pp_workgroup_out)
3781 char addr[INET6_ADDRSTRLEN];
3782 fstring name;
3783 struct cli_state *cli;
3784 struct sockaddr_storage server_ss;
3786 *pp_workgroup_out = NULL;
3788 print_sockaddr(addr, sizeof(addr), mb_ip);
3789 DEBUG(99, ("Looking up name of master browser %s\n",
3790 addr));
3793 * Do a name status query to find out the name of the master browser.
3794 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3795 * master browser will not respond to a wildcard query (or, at least,
3796 * an NT4 server acting as the domain master browser will not).
3798 * We might be able to use ONLY the query on MSBROWSE, but that's not
3799 * yet been tested with all Windows versions, so until it is, leave
3800 * the original wildcard query as the first choice and fall back to
3801 * MSBROWSE if the wildcard query fails.
3803 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3804 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3806 DEBUG(99, ("Could not retrieve name status for %s\n",
3807 addr));
3808 return NULL;
3811 if (!find_master_ip(name, &server_ss)) {
3812 DEBUG(99, ("Could not find master ip for %s\n", name));
3813 return NULL;
3816 *pp_workgroup_out = talloc_strdup(ctx, name);
3818 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3820 print_sockaddr(addr, sizeof(addr), &server_ss);
3821 cli = get_ipc_connect(addr, &server_ss, user_info);
3823 return cli;
3827 * Return the IP address and workgroup of a master browser on the network, and
3828 * connect to it.
3831 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3832 const struct user_auth_info *user_info,
3833 char **pp_workgroup_out)
3835 struct sockaddr_storage *ip_list;
3836 struct cli_state *cli;
3837 int i, count;
3838 NTSTATUS status;
3840 *pp_workgroup_out = NULL;
3842 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3844 /* Go looking for workgroups by broadcasting on the local network */
3846 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3847 &ip_list, &count);
3848 if (!NT_STATUS_IS_OK(status)) {
3849 DEBUG(99, ("No master browsers responded: %s\n",
3850 nt_errstr(status)));
3851 return NULL;
3854 for (i = 0; i < count; i++) {
3855 char addr[INET6_ADDRSTRLEN];
3856 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3857 DEBUG(99, ("Found master browser %s\n", addr));
3859 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3860 user_info, pp_workgroup_out);
3861 if (cli)
3862 return(cli);
3865 return NULL;