s3:libsmb: use password = NULL for anonymous connections
[Samba.git] / source3 / libsmb / cliconnect.c
blobb8a8c7a0839e496ffbde2c5ddf8e3b4aa6ea521c
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"
41 #define STAR_SMBSERVER "*SMBSERVER"
43 /********************************************************
44 Utility function to ensure we always return at least
45 a valid char * pointer to an empty string for the
46 cli->server_os, cli->server_type and cli->server_domain
47 strings.
48 *******************************************************/
50 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
51 const uint8_t *hdr,
52 char **dest,
53 uint8_t *src,
54 size_t srclen,
55 ssize_t *destlen)
57 *destlen = clistr_pull_talloc(mem_ctx,
58 (const char *)hdr,
59 SVAL(hdr, HDR_FLG2),
60 dest,
61 (char *)src,
62 srclen,
63 STR_TERMINATE);
64 if (*destlen == -1) {
65 return NT_STATUS_NO_MEMORY;
68 if (*dest == NULL) {
69 *dest = talloc_strdup(mem_ctx, "");
70 if (*dest == NULL) {
71 return NT_STATUS_NO_MEMORY;
74 return NT_STATUS_OK;
77 /****************************************************************************
78 Do an old lanman2 style session setup.
79 ****************************************************************************/
81 struct cli_session_setup_lanman2_state {
82 struct cli_state *cli;
83 uint16_t vwv[10];
84 const char *user;
87 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
89 static struct tevent_req *cli_session_setup_lanman2_send(
90 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
91 struct cli_state *cli, const char *user,
92 const char *pass, size_t passlen,
93 const char *workgroup)
95 struct tevent_req *req, *subreq;
96 struct cli_session_setup_lanman2_state *state;
97 DATA_BLOB lm_response = data_blob_null;
98 uint16_t *vwv;
99 uint8_t *bytes;
100 char *tmp;
101 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
103 req = tevent_req_create(mem_ctx, &state,
104 struct cli_session_setup_lanman2_state);
105 if (req == NULL) {
106 return NULL;
108 state->cli = cli;
109 state->user = user;
110 vwv = state->vwv;
113 * if in share level security then don't send a password now
115 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
116 passlen = 0;
119 if (passlen > 0
120 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
121 && passlen != 24) {
123 * Encrypted mode needed, and non encrypted password
124 * supplied.
126 lm_response = data_blob(NULL, 24);
127 if (tevent_req_nomem(lm_response.data, req)) {
128 return tevent_req_post(req, ev);
131 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
132 (uint8_t *)lm_response.data)) {
133 DEBUG(1, ("Password is > 14 chars in length, and is "
134 "therefore incompatible with Lanman "
135 "authentication\n"));
136 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
137 return tevent_req_post(req, ev);
139 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
140 && passlen == 24) {
142 * Encrypted mode needed, and encrypted password
143 * supplied.
145 lm_response = data_blob(pass, passlen);
146 if (tevent_req_nomem(lm_response.data, req)) {
147 return tevent_req_post(req, ev);
149 } else if (passlen > 0) {
150 uint8_t *buf;
151 size_t converted_size;
153 * Plaintext mode needed, assume plaintext supplied.
155 buf = talloc_array(talloc_tos(), uint8_t, 0);
156 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
157 &converted_size);
158 if (tevent_req_nomem(buf, req)) {
159 return tevent_req_post(req, ev);
161 lm_response = data_blob(pass, passlen);
162 TALLOC_FREE(buf);
163 if (tevent_req_nomem(lm_response.data, req)) {
164 return tevent_req_post(req, ev);
168 SCVAL(vwv+0, 0, 0xff);
169 SCVAL(vwv+0, 1, 0);
170 SSVAL(vwv+1, 0, 0);
171 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
172 SSVAL(vwv+3, 0, 2);
173 SSVAL(vwv+4, 0, 1);
174 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
175 SSVAL(vwv+7, 0, lm_response.length);
177 bytes = talloc_array(state, uint8_t, lm_response.length);
178 if (tevent_req_nomem(bytes, req)) {
179 return tevent_req_post(req, ev);
181 if (lm_response.length != 0) {
182 memcpy(bytes, lm_response.data, lm_response.length);
184 data_blob_free(&lm_response);
186 tmp = talloc_strdup_upper(talloc_tos(), user);
187 if (tevent_req_nomem(tmp, req)) {
188 return tevent_req_post(req, ev);
190 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
191 NULL);
192 TALLOC_FREE(tmp);
194 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
195 if (tevent_req_nomem(tmp, req)) {
196 return tevent_req_post(req, ev);
198 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
199 NULL);
200 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
201 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
203 if (tevent_req_nomem(bytes, req)) {
204 return tevent_req_post(req, ev);
207 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
208 talloc_get_size(bytes), bytes);
209 if (tevent_req_nomem(subreq, req)) {
210 return tevent_req_post(req, ev);
212 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
213 return req;
216 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
218 struct tevent_req *req = tevent_req_callback_data(
219 subreq, struct tevent_req);
220 struct cli_session_setup_lanman2_state *state = tevent_req_data(
221 req, struct cli_session_setup_lanman2_state);
222 struct cli_state *cli = state->cli;
223 uint32_t num_bytes;
224 uint8_t *in;
225 uint8_t *inhdr;
226 uint8_t *bytes;
227 uint8_t *p;
228 NTSTATUS status;
229 ssize_t ret;
230 uint8_t wct;
231 uint16_t *vwv;
233 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
234 &num_bytes, &bytes);
235 TALLOC_FREE(subreq);
236 if (!NT_STATUS_IS_OK(status)) {
237 tevent_req_nterror(req, status);
238 return;
241 inhdr = in + NBT_HDR_SIZE;
242 p = bytes;
244 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
246 status = smb_bytes_talloc_string(cli,
247 inhdr,
248 &cli->server_os,
250 bytes+num_bytes-p,
251 &ret);
253 if (!NT_STATUS_IS_OK(status)) {
254 tevent_req_nterror(req, status);
255 return;
257 p += ret;
259 status = smb_bytes_talloc_string(cli,
260 inhdr,
261 &cli->server_type,
263 bytes+num_bytes-p,
264 &ret);
266 if (!NT_STATUS_IS_OK(status)) {
267 tevent_req_nterror(req, status);
268 return;
270 p += ret;
272 status = smb_bytes_talloc_string(cli,
273 inhdr,
274 &cli->server_domain,
276 bytes+num_bytes-p,
277 &ret);
279 if (!NT_STATUS_IS_OK(status)) {
280 tevent_req_nterror(req, status);
281 return;
283 p += ret;
285 tevent_req_done(req);
288 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
290 return tevent_req_simple_recv_ntstatus(req);
293 /****************************************************************************
294 Work out suitable capabilities to offer the server.
295 ****************************************************************************/
297 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
298 uint32_t sesssetup_capabilities)
300 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
303 * We only send capabilities based on the mask for:
304 * - client only flags
305 * - flags used in both directions
307 * We do not echo the server only flags, except some legacy flags.
309 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
310 * CAP_LARGE_WRITEX in order to allow us to do large reads
311 * against old Samba releases (<= 3.6.x).
313 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
316 * Session Setup specific flags CAP_DYNAMIC_REAUTH
317 * and CAP_EXTENDED_SECURITY are passed by the caller.
318 * We need that in order to do guest logins even if
319 * CAP_EXTENDED_SECURITY is negotiated.
321 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
322 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
323 client_capabilities |= sesssetup_capabilities;
325 return client_capabilities;
328 /****************************************************************************
329 Do a NT1 guest session setup.
330 ****************************************************************************/
332 struct cli_session_setup_guest_state {
333 struct cli_state *cli;
334 uint16_t vwv[13];
335 struct iovec bytes;
338 static void cli_session_setup_guest_done(struct tevent_req *subreq);
340 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
341 struct tevent_context *ev,
342 struct cli_state *cli,
343 struct tevent_req **psmbreq)
345 struct tevent_req *req, *subreq;
346 struct cli_session_setup_guest_state *state;
347 uint16_t *vwv;
348 uint8_t *bytes;
350 req = tevent_req_create(mem_ctx, &state,
351 struct cli_session_setup_guest_state);
352 if (req == NULL) {
353 return NULL;
355 state->cli = cli;
356 vwv = state->vwv;
358 SCVAL(vwv+0, 0, 0xFF);
359 SCVAL(vwv+0, 1, 0);
360 SSVAL(vwv+1, 0, 0);
361 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
362 SSVAL(vwv+3, 0, 2);
363 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
364 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
365 SSVAL(vwv+7, 0, 0);
366 SSVAL(vwv+8, 0, 0);
367 SSVAL(vwv+9, 0, 0);
368 SSVAL(vwv+10, 0, 0);
369 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
371 bytes = talloc_array(state, uint8_t, 0);
373 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
374 NULL);
375 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
376 NULL);
377 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
378 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
380 if (bytes == NULL) {
381 TALLOC_FREE(req);
382 return NULL;
385 state->bytes.iov_base = (void *)bytes;
386 state->bytes.iov_len = talloc_get_size(bytes);
388 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
389 1, &state->bytes);
390 if (subreq == NULL) {
391 TALLOC_FREE(req);
392 return NULL;
394 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
395 *psmbreq = subreq;
396 return req;
399 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
400 struct tevent_context *ev,
401 struct cli_state *cli)
403 struct tevent_req *req, *subreq;
404 NTSTATUS status;
406 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
407 if (req == NULL) {
408 return NULL;
411 status = smb1cli_req_chain_submit(&subreq, 1);
412 if (!NT_STATUS_IS_OK(status)) {
413 tevent_req_nterror(req, status);
414 return tevent_req_post(req, ev);
416 return req;
419 static void cli_session_setup_guest_done(struct tevent_req *subreq)
421 struct tevent_req *req = tevent_req_callback_data(
422 subreq, struct tevent_req);
423 struct cli_session_setup_guest_state *state = tevent_req_data(
424 req, struct cli_session_setup_guest_state);
425 struct cli_state *cli = state->cli;
426 uint32_t num_bytes;
427 uint8_t *in;
428 uint8_t *inhdr;
429 uint8_t *bytes;
430 uint8_t *p;
431 NTSTATUS status;
432 ssize_t ret;
433 uint8_t wct;
434 uint16_t *vwv;
436 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
437 &num_bytes, &bytes);
438 TALLOC_FREE(subreq);
439 if (!NT_STATUS_IS_OK(status)) {
440 tevent_req_nterror(req, status);
441 return;
444 inhdr = in + NBT_HDR_SIZE;
445 p = bytes;
447 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
449 status = smb_bytes_talloc_string(cli,
450 inhdr,
451 &cli->server_os,
453 bytes+num_bytes-p,
454 &ret);
456 if (!NT_STATUS_IS_OK(status)) {
457 tevent_req_nterror(req, status);
458 return;
460 p += ret;
462 status = smb_bytes_talloc_string(cli,
463 inhdr,
464 &cli->server_type,
466 bytes+num_bytes-p,
467 &ret);
469 if (!NT_STATUS_IS_OK(status)) {
470 tevent_req_nterror(req, status);
471 return;
473 p += ret;
475 status = smb_bytes_talloc_string(cli,
476 inhdr,
477 &cli->server_domain,
479 bytes+num_bytes-p,
480 &ret);
482 if (!NT_STATUS_IS_OK(status)) {
483 tevent_req_nterror(req, status);
484 return;
486 p += ret;
488 tevent_req_done(req);
491 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
493 return tevent_req_simple_recv_ntstatus(req);
496 /****************************************************************************
497 Do a NT1 plaintext session setup.
498 ****************************************************************************/
500 struct cli_session_setup_plain_state {
501 struct cli_state *cli;
502 uint16_t vwv[13];
503 const char *user;
506 static void cli_session_setup_plain_done(struct tevent_req *subreq);
508 static struct tevent_req *cli_session_setup_plain_send(
509 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
510 struct cli_state *cli,
511 const char *user, const char *pass, const char *workgroup)
513 struct tevent_req *req, *subreq;
514 struct cli_session_setup_plain_state *state;
515 uint16_t *vwv;
516 uint8_t *bytes;
517 size_t passlen;
518 char *version;
520 req = tevent_req_create(mem_ctx, &state,
521 struct cli_session_setup_plain_state);
522 if (req == NULL) {
523 return NULL;
525 state->cli = cli;
526 state->user = user;
527 vwv = state->vwv;
529 SCVAL(vwv+0, 0, 0xff);
530 SCVAL(vwv+0, 1, 0);
531 SSVAL(vwv+1, 0, 0);
532 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
533 SSVAL(vwv+3, 0, 2);
534 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
535 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
536 SSVAL(vwv+7, 0, 0);
537 SSVAL(vwv+8, 0, 0);
538 SSVAL(vwv+9, 0, 0);
539 SSVAL(vwv+10, 0, 0);
540 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
542 bytes = talloc_array(state, uint8_t, 0);
543 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
544 &passlen);
545 if (tevent_req_nomem(bytes, req)) {
546 return tevent_req_post(req, ev);
548 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
550 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
551 user, strlen(user)+1, NULL);
552 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
553 workgroup, strlen(workgroup)+1, NULL);
554 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
555 "Unix", 5, NULL);
557 version = talloc_asprintf(talloc_tos(), "Samba %s",
558 samba_version_string());
559 if (tevent_req_nomem(version, req)){
560 return tevent_req_post(req, ev);
562 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
563 version, strlen(version)+1, NULL);
564 TALLOC_FREE(version);
566 if (tevent_req_nomem(bytes, req)) {
567 return tevent_req_post(req, ev);
570 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
571 talloc_get_size(bytes), bytes);
572 if (tevent_req_nomem(subreq, req)) {
573 return tevent_req_post(req, ev);
575 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
576 return req;
579 static void cli_session_setup_plain_done(struct tevent_req *subreq)
581 struct tevent_req *req = tevent_req_callback_data(
582 subreq, struct tevent_req);
583 struct cli_session_setup_plain_state *state = tevent_req_data(
584 req, struct cli_session_setup_plain_state);
585 struct cli_state *cli = state->cli;
586 uint32_t num_bytes;
587 uint8_t *in;
588 uint8_t *inhdr;
589 uint8_t *bytes;
590 uint8_t *p;
591 NTSTATUS status;
592 ssize_t ret;
593 uint8_t wct;
594 uint16_t *vwv;
596 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
597 &num_bytes, &bytes);
598 TALLOC_FREE(subreq);
599 if (tevent_req_nterror(req, status)) {
600 return;
603 inhdr = in + NBT_HDR_SIZE;
604 p = bytes;
606 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
608 status = smb_bytes_talloc_string(cli,
609 inhdr,
610 &cli->server_os,
612 bytes+num_bytes-p,
613 &ret);
615 if (!NT_STATUS_IS_OK(status)) {
616 tevent_req_nterror(req, status);
617 return;
619 p += ret;
621 status = smb_bytes_talloc_string(cli,
622 inhdr,
623 &cli->server_type,
625 bytes+num_bytes-p,
626 &ret);
628 if (!NT_STATUS_IS_OK(status)) {
629 tevent_req_nterror(req, status);
630 return;
632 p += ret;
634 status = smb_bytes_talloc_string(cli,
635 inhdr,
636 &cli->server_domain,
638 bytes+num_bytes-p,
639 &ret);
641 if (!NT_STATUS_IS_OK(status)) {
642 tevent_req_nterror(req, status);
643 return;
645 p += ret;
647 tevent_req_done(req);
650 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
652 return tevent_req_simple_recv_ntstatus(req);
655 /****************************************************************************
656 do a NT1 NTLM/LM encrypted session setup - for when extended security
657 is not negotiated.
658 @param cli client state to create do session setup on
659 @param user username
660 @param pass *either* cleartext password (passlen !=24) or LM response.
661 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
662 @param workgroup The user's domain.
663 ****************************************************************************/
665 struct cli_session_setup_nt1_state {
666 struct cli_state *cli;
667 uint16_t vwv[13];
668 DATA_BLOB response;
669 DATA_BLOB session_key;
670 const char *user;
673 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
675 static struct tevent_req *cli_session_setup_nt1_send(
676 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
677 struct cli_state *cli, const char *user,
678 const char *pass, size_t passlen,
679 const char *ntpass, size_t ntpasslen,
680 const char *workgroup)
682 struct tevent_req *req, *subreq;
683 struct cli_session_setup_nt1_state *state;
684 DATA_BLOB lm_response = data_blob_null;
685 DATA_BLOB nt_response = data_blob_null;
686 DATA_BLOB session_key = data_blob_null;
687 uint16_t *vwv;
688 uint8_t *bytes;
689 char *workgroup_upper;
691 req = tevent_req_create(mem_ctx, &state,
692 struct cli_session_setup_nt1_state);
693 if (req == NULL) {
694 return NULL;
696 state->cli = cli;
697 state->user = user;
698 vwv = state->vwv;
700 if (passlen == 0) {
701 /* do nothing - guest login */
702 } else if (passlen != 24) {
703 if (lp_client_ntlmv2_auth()) {
704 DATA_BLOB server_chal;
705 DATA_BLOB names_blob;
707 server_chal =
708 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
712 * note that the 'workgroup' here is a best
713 * guess - we don't know the server's domain
714 * at this point. Windows clients also don't
715 * use hostname...
717 names_blob = NTLMv2_generate_names_blob(
718 NULL, NULL, workgroup);
720 if (tevent_req_nomem(names_blob.data, req)) {
721 return tevent_req_post(req, ev);
724 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
725 &server_chal, &names_blob,
726 &lm_response, &nt_response,
727 NULL, &session_key)) {
728 data_blob_free(&names_blob);
729 tevent_req_nterror(
730 req, NT_STATUS_ACCESS_DENIED);
731 return tevent_req_post(req, ev);
733 data_blob_free(&names_blob);
735 } else {
736 uchar nt_hash[16];
737 E_md4hash(pass, nt_hash);
739 #ifdef LANMAN_ONLY
740 nt_response = data_blob_null;
741 #else
742 nt_response = data_blob(NULL, 24);
743 if (tevent_req_nomem(nt_response.data, req)) {
744 return tevent_req_post(req, ev);
747 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
748 nt_response.data);
749 #endif
750 /* non encrypted password supplied. Ignore ntpass. */
751 if (lp_client_lanman_auth()) {
753 lm_response = data_blob(NULL, 24);
754 if (tevent_req_nomem(lm_response.data, req)) {
755 return tevent_req_post(req, ev);
758 if (!SMBencrypt(pass,
759 smb1cli_conn_server_challenge(cli->conn),
760 lm_response.data)) {
762 * Oops, the LM response is
763 * invalid, just put the NT
764 * response there instead
766 data_blob_free(&lm_response);
767 lm_response = data_blob(
768 nt_response.data,
769 nt_response.length);
771 } else {
773 * LM disabled, place NT# in LM field
774 * instead
776 lm_response = data_blob(
777 nt_response.data, nt_response.length);
780 if (tevent_req_nomem(lm_response.data, req)) {
781 return tevent_req_post(req, ev);
784 session_key = data_blob(NULL, 16);
785 if (tevent_req_nomem(session_key.data, req)) {
786 return tevent_req_post(req, ev);
788 #ifdef LANMAN_ONLY
789 E_deshash(pass, session_key.data);
790 memset(&session_key.data[8], '\0', 8);
791 #else
792 SMBsesskeygen_ntv1(nt_hash, session_key.data);
793 #endif
795 } else {
796 /* pre-encrypted password supplied. Only used for
797 security=server, can't do
798 signing because we don't have original key */
800 lm_response = data_blob(pass, passlen);
801 if (tevent_req_nomem(lm_response.data, req)) {
802 return tevent_req_post(req, ev);
805 nt_response = data_blob(ntpass, ntpasslen);
806 if (tevent_req_nomem(nt_response.data, req)) {
807 return tevent_req_post(req, ev);
811 #ifdef LANMAN_ONLY
812 state->response = data_blob_talloc(
813 state, lm_response.data, lm_response.length);
814 #else
815 state->response = data_blob_talloc(
816 state, nt_response.data, nt_response.length);
817 #endif
818 if (tevent_req_nomem(state->response.data, req)) {
819 return tevent_req_post(req, ev);
822 if (session_key.data) {
823 state->session_key = data_blob_talloc(
824 state, session_key.data, session_key.length);
825 if (tevent_req_nomem(state->session_key.data, req)) {
826 return tevent_req_post(req, ev);
829 data_blob_free(&session_key);
831 SCVAL(vwv+0, 0, 0xff);
832 SCVAL(vwv+0, 1, 0);
833 SSVAL(vwv+1, 0, 0);
834 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
835 SSVAL(vwv+3, 0, 2);
836 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
837 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
838 SSVAL(vwv+7, 0, lm_response.length);
839 SSVAL(vwv+8, 0, nt_response.length);
840 SSVAL(vwv+9, 0, 0);
841 SSVAL(vwv+10, 0, 0);
842 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
844 bytes = talloc_array(state, uint8_t,
845 lm_response.length + nt_response.length);
846 if (tevent_req_nomem(bytes, req)) {
847 return tevent_req_post(req, ev);
849 if (lm_response.length != 0) {
850 memcpy(bytes, lm_response.data, lm_response.length);
852 if (nt_response.length != 0) {
853 memcpy(bytes + lm_response.length,
854 nt_response.data, nt_response.length);
856 data_blob_free(&lm_response);
857 data_blob_free(&nt_response);
859 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
860 user, strlen(user)+1, NULL);
863 * Upper case here might help some NTLMv2 implementations
865 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
866 if (tevent_req_nomem(workgroup_upper, req)) {
867 return tevent_req_post(req, ev);
869 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
870 workgroup_upper, strlen(workgroup_upper)+1,
871 NULL);
872 TALLOC_FREE(workgroup_upper);
874 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
875 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
876 if (tevent_req_nomem(bytes, req)) {
877 return tevent_req_post(req, ev);
880 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
881 talloc_get_size(bytes), bytes);
882 if (tevent_req_nomem(subreq, req)) {
883 return tevent_req_post(req, ev);
885 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
886 return req;
889 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
891 struct tevent_req *req = tevent_req_callback_data(
892 subreq, struct tevent_req);
893 struct cli_session_setup_nt1_state *state = tevent_req_data(
894 req, struct cli_session_setup_nt1_state);
895 struct cli_state *cli = state->cli;
896 uint32_t num_bytes;
897 uint8_t *in;
898 uint8_t *inhdr;
899 uint8_t *bytes;
900 uint8_t *p;
901 NTSTATUS status;
902 ssize_t ret;
903 uint8_t wct;
904 uint16_t *vwv;
906 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
907 &num_bytes, &bytes);
908 TALLOC_FREE(subreq);
909 if (!NT_STATUS_IS_OK(status)) {
910 tevent_req_nterror(req, status);
911 return;
914 inhdr = in + NBT_HDR_SIZE;
915 p = bytes;
917 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
919 status = smb_bytes_talloc_string(cli,
920 inhdr,
921 &cli->server_os,
923 bytes+num_bytes-p,
924 &ret);
925 if (!NT_STATUS_IS_OK(status)) {
926 tevent_req_nterror(req, status);
927 return;
929 p += ret;
931 status = smb_bytes_talloc_string(cli,
932 inhdr,
933 &cli->server_type,
935 bytes+num_bytes-p,
936 &ret);
937 if (!NT_STATUS_IS_OK(status)) {
938 tevent_req_nterror(req, status);
939 return;
941 p += ret;
943 status = smb_bytes_talloc_string(cli,
944 inhdr,
945 &cli->server_domain,
947 bytes+num_bytes-p,
948 &ret);
949 if (!NT_STATUS_IS_OK(status)) {
950 tevent_req_nterror(req, status);
951 return;
953 p += ret;
955 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
956 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
957 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
958 return;
960 if (state->session_key.data) {
961 struct smbXcli_session *session = state->cli->smb1.session;
963 status = smb1cli_session_set_session_key(session,
964 state->session_key);
965 if (tevent_req_nterror(req, status)) {
966 return;
969 tevent_req_done(req);
972 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
974 return tevent_req_simple_recv_ntstatus(req);
977 /* The following is calculated from :
978 * (smb_size-4) = 35
979 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
980 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
981 * end of packet.
984 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
986 struct cli_sesssetup_blob_state {
987 struct tevent_context *ev;
988 struct cli_state *cli;
989 DATA_BLOB blob;
990 uint16_t max_blob_size;
991 uint16_t vwv[12];
992 uint8_t *buf;
994 DATA_BLOB smb2_blob;
995 struct iovec *recv_iov;
997 NTSTATUS status;
998 uint8_t *inbuf;
999 DATA_BLOB ret_blob;
1002 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1003 struct tevent_req **psubreq);
1004 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1006 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1007 struct tevent_context *ev,
1008 struct cli_state *cli,
1009 DATA_BLOB blob)
1011 struct tevent_req *req, *subreq;
1012 struct cli_sesssetup_blob_state *state;
1013 uint32_t usable_space;
1015 req = tevent_req_create(mem_ctx, &state,
1016 struct cli_sesssetup_blob_state);
1017 if (req == NULL) {
1018 return NULL;
1020 state->ev = ev;
1021 state->blob = blob;
1022 state->cli = cli;
1024 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1025 usable_space = UINT16_MAX;
1026 } else {
1027 usable_space = cli_state_available_size(cli,
1028 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1031 if (usable_space == 0) {
1032 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1033 "(not possible to send %u bytes)\n",
1034 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1035 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1036 return tevent_req_post(req, ev);
1038 state->max_blob_size = MIN(usable_space, 0xFFFF);
1040 if (!cli_sesssetup_blob_next(state, &subreq)) {
1041 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1042 return tevent_req_post(req, ev);
1044 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1045 return req;
1048 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1049 struct tevent_req **psubreq)
1051 struct tevent_req *subreq;
1052 uint16_t thistime;
1054 thistime = MIN(state->blob.length, state->max_blob_size);
1056 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1058 state->smb2_blob.data = state->blob.data;
1059 state->smb2_blob.length = thistime;
1061 state->blob.data += thistime;
1062 state->blob.length -= thistime;
1064 subreq = smb2cli_session_setup_send(state, state->ev,
1065 state->cli->conn,
1066 state->cli->timeout,
1067 state->cli->smb2.session,
1068 0, /* in_flags */
1069 SMB2_CAP_DFS, /* in_capabilities */
1070 0, /* in_channel */
1071 0, /* in_previous_session_id */
1072 &state->smb2_blob);
1073 if (subreq == NULL) {
1074 return false;
1076 *psubreq = subreq;
1077 return true;
1080 SCVAL(state->vwv+0, 0, 0xFF);
1081 SCVAL(state->vwv+0, 1, 0);
1082 SSVAL(state->vwv+1, 0, 0);
1083 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1084 SSVAL(state->vwv+3, 0, 2);
1085 SSVAL(state->vwv+4, 0, 1);
1086 SIVAL(state->vwv+5, 0, 0);
1088 SSVAL(state->vwv+7, 0, thistime);
1090 SSVAL(state->vwv+8, 0, 0);
1091 SSVAL(state->vwv+9, 0, 0);
1092 SIVAL(state->vwv+10, 0,
1093 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1095 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1096 thistime);
1097 if (state->buf == NULL) {
1098 return false;
1100 state->blob.data += thistime;
1101 state->blob.length -= thistime;
1103 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1104 "Unix", 5, NULL);
1105 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1106 "Samba", 6, NULL);
1107 if (state->buf == NULL) {
1108 return false;
1110 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1111 12, state->vwv,
1112 talloc_get_size(state->buf), state->buf);
1113 if (subreq == NULL) {
1114 return false;
1116 *psubreq = subreq;
1117 return true;
1120 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1122 struct tevent_req *req = tevent_req_callback_data(
1123 subreq, struct tevent_req);
1124 struct cli_sesssetup_blob_state *state = tevent_req_data(
1125 req, struct cli_sesssetup_blob_state);
1126 struct cli_state *cli = state->cli;
1127 uint8_t wct;
1128 uint16_t *vwv;
1129 uint32_t num_bytes;
1130 uint8_t *bytes;
1131 NTSTATUS status;
1132 uint8_t *p;
1133 uint16_t blob_length;
1134 uint8_t *in;
1135 uint8_t *inhdr;
1136 ssize_t ret;
1138 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1139 status = smb2cli_session_setup_recv(subreq, state,
1140 &state->recv_iov,
1141 &state->ret_blob);
1142 } else {
1143 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1144 &num_bytes, &bytes);
1145 TALLOC_FREE(state->buf);
1147 TALLOC_FREE(subreq);
1148 if (!NT_STATUS_IS_OK(status)
1149 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1150 tevent_req_nterror(req, status);
1151 return;
1154 state->status = status;
1156 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1157 goto next;
1160 state->inbuf = in;
1161 inhdr = in + NBT_HDR_SIZE;
1162 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1164 blob_length = SVAL(vwv+3, 0);
1165 if (blob_length > num_bytes) {
1166 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1167 return;
1169 state->ret_blob = data_blob_const(bytes, blob_length);
1171 p = bytes + blob_length;
1173 status = smb_bytes_talloc_string(cli,
1174 inhdr,
1175 &cli->server_os,
1177 bytes+num_bytes-p,
1178 &ret);
1180 if (!NT_STATUS_IS_OK(status)) {
1181 tevent_req_nterror(req, status);
1182 return;
1184 p += ret;
1186 status = smb_bytes_talloc_string(cli,
1187 inhdr,
1188 &cli->server_type,
1190 bytes+num_bytes-p,
1191 &ret);
1193 if (!NT_STATUS_IS_OK(status)) {
1194 tevent_req_nterror(req, status);
1195 return;
1197 p += ret;
1199 status = smb_bytes_talloc_string(cli,
1200 inhdr,
1201 &cli->server_domain,
1203 bytes+num_bytes-p,
1204 &ret);
1206 if (!NT_STATUS_IS_OK(status)) {
1207 tevent_req_nterror(req, status);
1208 return;
1210 p += ret;
1212 next:
1213 if (state->blob.length != 0) {
1215 * More to send
1217 if (!cli_sesssetup_blob_next(state, &subreq)) {
1218 tevent_req_oom(req);
1219 return;
1221 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1222 return;
1224 tevent_req_done(req);
1227 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1228 TALLOC_CTX *mem_ctx,
1229 DATA_BLOB *pblob,
1230 uint8_t **pinbuf,
1231 struct iovec **precv_iov)
1233 struct cli_sesssetup_blob_state *state = tevent_req_data(
1234 req, struct cli_sesssetup_blob_state);
1235 NTSTATUS status;
1236 uint8_t *inbuf;
1237 struct iovec *recv_iov;
1239 if (tevent_req_is_nterror(req, &status)) {
1240 TALLOC_FREE(state->cli->smb2.session);
1241 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1242 return status;
1245 inbuf = talloc_move(mem_ctx, &state->inbuf);
1246 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1247 if (pblob != NULL) {
1248 *pblob = state->ret_blob;
1250 if (pinbuf != NULL) {
1251 *pinbuf = inbuf;
1253 if (precv_iov != NULL) {
1254 *precv_iov = recv_iov;
1256 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1257 return state->status;
1260 #ifdef HAVE_KRB5
1262 /****************************************************************************
1263 Use in-memory credentials cache
1264 ****************************************************************************/
1266 static void use_in_memory_ccache(void) {
1267 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1270 #endif /* HAVE_KRB5 */
1272 /****************************************************************************
1273 Do a spnego/NTLMSSP encrypted session setup.
1274 ****************************************************************************/
1276 struct cli_session_setup_gensec_state {
1277 struct tevent_context *ev;
1278 struct cli_state *cli;
1279 struct auth_generic_state *auth_generic;
1280 bool is_anonymous;
1281 DATA_BLOB blob_in;
1282 uint8_t *inbuf;
1283 struct iovec *recv_iov;
1284 DATA_BLOB blob_out;
1285 bool local_ready;
1286 bool remote_ready;
1287 DATA_BLOB session_key;
1290 static int cli_session_setup_gensec_state_destructor(
1291 struct cli_session_setup_gensec_state *state)
1293 TALLOC_FREE(state->auth_generic);
1294 data_blob_clear_free(&state->session_key);
1295 return 0;
1298 static void cli_session_setup_gensec_local_next(struct tevent_req *req);
1299 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq);
1300 static void cli_session_setup_gensec_remote_next(struct tevent_req *req);
1301 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq);
1302 static void cli_session_setup_gensec_ready(struct tevent_req *req);
1304 static struct tevent_req *cli_session_setup_gensec_send(
1305 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1306 const char *user, const char *pass, const char *domain,
1307 enum credentials_use_kerberos krb5_state,
1308 const char *target_service,
1309 const char *target_hostname,
1310 const char *target_principal)
1312 struct tevent_req *req;
1313 struct cli_session_setup_gensec_state *state;
1314 NTSTATUS status;
1315 bool use_spnego_principal = lp_client_use_spnego_principal();
1317 req = tevent_req_create(mem_ctx, &state,
1318 struct cli_session_setup_gensec_state);
1319 if (req == NULL) {
1320 return NULL;
1322 state->ev = ev;
1323 state->cli = cli;
1325 talloc_set_destructor(
1326 state, cli_session_setup_gensec_state_destructor);
1328 if (user == NULL || strlen(user) == 0) {
1329 if (pass != NULL && strlen(pass) == 0) {
1331 * some callers pass "" as no password
1333 * gensec only handles NULL as no password.
1335 pass = NULL;
1339 status = auth_generic_client_prepare(state, &state->auth_generic);
1340 if (tevent_req_nterror(req, status)) {
1341 return tevent_req_post(req, ev);
1344 gensec_want_feature(state->auth_generic->gensec_security,
1345 GENSEC_FEATURE_SESSION_KEY);
1346 if (cli->use_ccache) {
1347 gensec_want_feature(state->auth_generic->gensec_security,
1348 GENSEC_FEATURE_NTLM_CCACHE);
1349 if (pass != NULL && strlen(pass) == 0) {
1351 * some callers pass "" as no password
1353 * GENSEC_FEATURE_NTLM_CCACHE only handles
1354 * NULL as no password.
1356 pass = NULL;
1360 status = auth_generic_set_username(state->auth_generic, user);
1361 if (tevent_req_nterror(req, status)) {
1362 return tevent_req_post(req, ev);
1365 status = auth_generic_set_domain(state->auth_generic, domain);
1366 if (tevent_req_nterror(req, status)) {
1367 return tevent_req_post(req, ev);
1370 if (cli->pw_nt_hash) {
1371 struct samr_Password nt_hash;
1372 size_t converted;
1373 bool ok;
1375 if (pass == NULL) {
1376 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1377 return tevent_req_post(req, ev);
1380 converted = strhex_to_str((char *)nt_hash.hash,
1381 sizeof(nt_hash.hash),
1382 pass, strlen(pass));
1383 if (converted != sizeof(nt_hash.hash)) {
1384 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1385 return tevent_req_post(req, ev);
1388 ok = cli_credentials_set_nt_hash(state->auth_generic->credentials,
1389 &nt_hash, CRED_SPECIFIED);
1390 if (!ok) {
1391 tevent_req_oom(req);
1392 return tevent_req_post(req, ev);
1394 } else {
1395 status = auth_generic_set_password(state->auth_generic, pass);
1396 if (tevent_req_nterror(req, status)) {
1397 return tevent_req_post(req, ev);
1401 cli_credentials_set_kerberos_state(state->auth_generic->credentials,
1402 krb5_state);
1404 if (krb5_state == CRED_DONT_USE_KERBEROS) {
1405 use_spnego_principal = false;
1408 if (target_service != NULL) {
1409 status = gensec_set_target_service(
1410 state->auth_generic->gensec_security,
1411 target_service);
1412 if (tevent_req_nterror(req, status)) {
1413 return tevent_req_post(req, ev);
1417 if (target_hostname != NULL) {
1418 status = gensec_set_target_hostname(
1419 state->auth_generic->gensec_security,
1420 target_hostname);
1421 if (tevent_req_nterror(req, status)) {
1422 return tevent_req_post(req, ev);
1426 if (target_principal != NULL) {
1427 status = gensec_set_target_principal(
1428 state->auth_generic->gensec_security,
1429 target_principal);
1430 if (tevent_req_nterror(req, status)) {
1431 return tevent_req_post(req, ev);
1433 use_spnego_principal = false;
1434 } else if (target_service != NULL && target_hostname != NULL) {
1435 use_spnego_principal = false;
1438 if (use_spnego_principal) {
1439 const DATA_BLOB *b;
1440 b = smbXcli_conn_server_gss_blob(cli->conn);
1441 if (b != NULL) {
1442 state->blob_in = *b;
1446 state->is_anonymous = cli_credentials_is_anonymous(state->auth_generic->credentials);
1448 status = auth_generic_client_start(state->auth_generic,
1449 GENSEC_OID_SPNEGO);
1450 if (tevent_req_nterror(req, status)) {
1451 return tevent_req_post(req, ev);
1454 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1455 state->cli->smb2.session = smbXcli_session_create(cli,
1456 cli->conn);
1457 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1458 return tevent_req_post(req, ev);
1462 cli_session_setup_gensec_local_next(req);
1463 if (!tevent_req_is_in_progress(req)) {
1464 return tevent_req_post(req, ev);
1467 return req;
1470 static void cli_session_setup_gensec_local_next(struct tevent_req *req)
1472 struct cli_session_setup_gensec_state *state =
1473 tevent_req_data(req,
1474 struct cli_session_setup_gensec_state);
1475 struct tevent_req *subreq = NULL;
1477 if (state->local_ready) {
1478 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1479 return;
1482 subreq = gensec_update_send(state, state->ev,
1483 state->auth_generic->gensec_security,
1484 state->blob_in);
1485 if (tevent_req_nomem(subreq, req)) {
1486 return;
1488 tevent_req_set_callback(subreq, cli_session_setup_gensec_local_done, req);
1491 static void cli_session_setup_gensec_local_done(struct tevent_req *subreq)
1493 struct tevent_req *req =
1494 tevent_req_callback_data(subreq,
1495 struct tevent_req);
1496 struct cli_session_setup_gensec_state *state =
1497 tevent_req_data(req,
1498 struct cli_session_setup_gensec_state);
1499 NTSTATUS status;
1501 status = gensec_update_recv(subreq, state, &state->blob_out);
1502 TALLOC_FREE(subreq);
1503 state->blob_in = data_blob_null;
1504 if (!NT_STATUS_IS_OK(status) &&
1505 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1507 tevent_req_nterror(req, status);
1508 return;
1511 if (NT_STATUS_IS_OK(status)) {
1512 state->local_ready = true;
1515 if (state->local_ready && state->remote_ready) {
1516 cli_session_setup_gensec_ready(req);
1517 return;
1520 cli_session_setup_gensec_remote_next(req);
1523 static void cli_session_setup_gensec_remote_next(struct tevent_req *req)
1525 struct cli_session_setup_gensec_state *state =
1526 tevent_req_data(req,
1527 struct cli_session_setup_gensec_state);
1528 struct tevent_req *subreq = NULL;
1530 if (state->remote_ready) {
1531 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1532 return;
1535 subreq = cli_sesssetup_blob_send(state, state->ev,
1536 state->cli, state->blob_out);
1537 if (tevent_req_nomem(subreq, req)) {
1538 return;
1540 tevent_req_set_callback(subreq,
1541 cli_session_setup_gensec_remote_done,
1542 req);
1545 static void cli_session_setup_gensec_remote_done(struct tevent_req *subreq)
1547 struct tevent_req *req =
1548 tevent_req_callback_data(subreq,
1549 struct tevent_req);
1550 struct cli_session_setup_gensec_state *state =
1551 tevent_req_data(req,
1552 struct cli_session_setup_gensec_state);
1553 NTSTATUS status;
1555 TALLOC_FREE(state->inbuf);
1556 TALLOC_FREE(state->recv_iov);
1558 status = cli_sesssetup_blob_recv(subreq, state, &state->blob_in,
1559 &state->inbuf, &state->recv_iov);
1560 TALLOC_FREE(subreq);
1561 data_blob_free(&state->blob_out);
1562 if (!NT_STATUS_IS_OK(status) &&
1563 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1565 tevent_req_nterror(req, status);
1566 return;
1569 if (NT_STATUS_IS_OK(status)) {
1570 state->remote_ready = true;
1573 if (state->local_ready && state->remote_ready) {
1574 cli_session_setup_gensec_ready(req);
1575 return;
1578 cli_session_setup_gensec_local_next(req);
1581 static void cli_session_setup_gensec_ready(struct tevent_req *req)
1583 struct cli_session_setup_gensec_state *state =
1584 tevent_req_data(req,
1585 struct cli_session_setup_gensec_state);
1586 const char *server_domain = NULL;
1587 NTSTATUS status;
1589 if (state->blob_in.length != 0) {
1590 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1591 return;
1594 if (state->blob_out.length != 0) {
1595 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1596 return;
1600 * gensec_ntlmssp_server_domain() returns NULL
1601 * if NTLMSSP is not used.
1603 * We can remove this later
1604 * and leave the server domain empty for SMB2 and above
1605 * in future releases.
1607 server_domain = gensec_ntlmssp_server_domain(
1608 state->auth_generic->gensec_security);
1610 if (state->cli->server_domain[0] == '\0' && server_domain != NULL) {
1611 TALLOC_FREE(state->cli->server_domain);
1612 state->cli->server_domain = talloc_strdup(state->cli,
1613 server_domain);
1614 if (state->cli->server_domain == NULL) {
1615 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1616 return;
1620 status = gensec_session_key(state->auth_generic->gensec_security,
1621 state, &state->session_key);
1622 if (tevent_req_nterror(req, status)) {
1623 return;
1626 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1627 struct smbXcli_session *session = state->cli->smb2.session;
1629 if (state->is_anonymous) {
1631 * Windows server does not set the
1632 * SMB2_SESSION_FLAG_IS_GUEST nor
1633 * SMB2_SESSION_FLAG_IS_NULL flag.
1635 * This fix makes sure we do not try
1636 * to verify a signature on the final
1637 * session setup response.
1639 tevent_req_done(req);
1640 return;
1643 status = smb2cli_session_set_session_key(session,
1644 state->session_key,
1645 state->recv_iov);
1646 if (tevent_req_nterror(req, status)) {
1647 return;
1649 } else {
1650 struct smbXcli_session *session = state->cli->smb1.session;
1651 bool active;
1653 status = smb1cli_session_set_session_key(session,
1654 state->session_key);
1655 if (tevent_req_nterror(req, status)) {
1656 return;
1659 active = smb1cli_conn_activate_signing(state->cli->conn,
1660 state->session_key,
1661 data_blob_null);
1662 if (active) {
1663 bool ok;
1665 ok = smb1cli_conn_check_signing(state->cli->conn,
1666 state->inbuf, 1);
1667 if (!ok) {
1668 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1669 return;
1674 tevent_req_done(req);
1677 static NTSTATUS cli_session_setup_gensec_recv(struct tevent_req *req)
1679 struct cli_session_setup_gensec_state *state =
1680 tevent_req_data(req,
1681 struct cli_session_setup_gensec_state);
1682 NTSTATUS status;
1684 if (tevent_req_is_nterror(req, &status)) {
1685 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1686 return status;
1688 return NT_STATUS_OK;
1691 #ifdef HAVE_KRB5
1693 static char *cli_session_setup_get_principal(
1694 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1695 const char *remote_name, const char *dest_realm)
1697 char *principal = NULL;
1699 if (!lp_client_use_spnego_principal() ||
1700 strequal(spnego_principal, ADS_IGNORE_PRINCIPAL)) {
1701 spnego_principal = NULL;
1703 if (spnego_principal != NULL) {
1704 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1705 "principal %s\n", spnego_principal));
1706 return talloc_strdup(mem_ctx, spnego_principal);
1708 if (is_ipaddress(remote_name) ||
1709 strequal(remote_name, STAR_SMBSERVER)) {
1710 return NULL;
1713 DEBUG(3, ("cli_session_setup_spnego: using target "
1714 "hostname not SPNEGO principal\n"));
1716 if (dest_realm) {
1717 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1718 if (realm == NULL) {
1719 return NULL;
1721 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1722 remote_name, realm);
1723 TALLOC_FREE(realm);
1724 } else {
1725 principal = kerberos_get_principal_from_service_hostname(
1726 talloc_tos(), "cifs", remote_name, lp_realm());
1728 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1729 principal ? principal : "<null>"));
1731 return principal;
1733 #endif
1735 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1736 const char *principal)
1738 char *account, *p;
1740 account = talloc_strdup(mem_ctx, principal);
1741 if (account == NULL) {
1742 return NULL;
1744 p = strchr_m(account, '@');
1745 if (p != NULL) {
1746 *p = '\0';
1748 return account;
1751 /****************************************************************************
1752 Do a spnego encrypted session setup.
1754 user_domain: The shortname of the domain the user/machine is a member of.
1755 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1756 ****************************************************************************/
1758 struct cli_session_setup_spnego_state {
1759 struct tevent_context *ev;
1760 struct cli_state *cli;
1761 const char *target_hostname;
1762 const char *user;
1763 const char *account;
1764 const char *pass;
1765 const char *user_domain;
1766 const char *dest_realm;
1767 ADS_STATUS result;
1770 #ifdef HAVE_KRB5
1771 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1772 #endif
1774 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1776 static struct tevent_req *cli_session_setup_spnego_send(
1777 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1778 const char *user, const char *pass, const char *user_domain)
1780 struct tevent_req *req, *subreq;
1781 struct cli_session_setup_spnego_state *state;
1782 char *principal = NULL;
1783 char *OIDs[ASN1_MAX_OIDS];
1784 int i;
1785 const char *dest_realm = cli_state_remote_realm(cli);
1786 const DATA_BLOB *server_blob;
1788 req = tevent_req_create(mem_ctx, &state,
1789 struct cli_session_setup_spnego_state);
1790 if (req == NULL) {
1791 return NULL;
1793 state->ev = ev;
1794 state->cli = cli;
1795 state->user = user;
1796 state->pass = pass;
1797 state->user_domain = user_domain;
1798 state->dest_realm = dest_realm;
1800 state->account = cli_session_setup_get_account(state, user);
1801 if (tevent_req_nomem(state->account, req)) {
1802 return tevent_req_post(req, ev);
1805 state->target_hostname = smbXcli_conn_remote_name(cli->conn);
1806 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1808 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1809 (unsigned long)server_blob->length));
1811 /* the server might not even do spnego */
1812 if (server_blob->length == 0) {
1813 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1814 goto ntlmssp;
1817 #if 0
1818 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1819 #endif
1821 /* The server sent us the first part of the SPNEGO exchange in the
1822 * negprot reply. It is WRONG to depend on the principal sent in the
1823 * negprot reply, but right now we do it. If we don't receive one,
1824 * we try to best guess, then fall back to NTLM. */
1825 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1826 &principal, NULL) ||
1827 OIDs[0] == NULL) {
1828 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1829 tevent_req_done(req);
1830 return tevent_req_post(req, ev);
1833 /* make sure the server understands kerberos */
1834 for (i=0;OIDs[i];i++) {
1835 if (i == 0)
1836 DEBUG(3,("got OID=%s\n", OIDs[i]));
1837 else
1838 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1839 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1840 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1841 cli->got_kerberos_mechanism = True;
1843 talloc_free(OIDs[i]);
1846 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1848 #ifdef HAVE_KRB5
1849 /* If password is set we reauthenticate to kerberos server
1850 * and do not store results */
1852 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1853 char *tmp;
1855 tmp = cli_session_setup_get_principal(
1856 talloc_tos(), principal, state->target_hostname, dest_realm);
1857 TALLOC_FREE(principal);
1858 principal = tmp;
1860 if (pass && *pass) {
1861 int ret;
1863 use_in_memory_ccache();
1864 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1866 if (ret){
1867 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1868 TALLOC_FREE(principal);
1869 if (cli->fallback_after_kerberos)
1870 goto ntlmssp;
1871 state->result = ADS_ERROR_KRB5(ret);
1872 tevent_req_done(req);
1873 return tevent_req_post(req, ev);
1877 if (principal) {
1878 subreq = cli_session_setup_gensec_send(
1879 state, ev, cli,
1880 state->account, pass, user_domain,
1881 CRED_MUST_USE_KERBEROS,
1882 "cifs", state->target_hostname, principal);
1883 if (tevent_req_nomem(subreq, req)) {
1884 return tevent_req_post(req, ev);
1886 tevent_req_set_callback(
1887 subreq, cli_session_setup_spnego_done_krb,
1888 req);
1889 return req;
1892 #endif
1894 ntlmssp:
1895 subreq = cli_session_setup_gensec_send(
1896 state, state->ev, state->cli,
1897 state->account, state->pass, state->user_domain,
1898 CRED_DONT_USE_KERBEROS,
1899 "cifs", state->target_hostname, NULL);
1900 if (tevent_req_nomem(subreq, req)) {
1901 return tevent_req_post(req, ev);
1903 tevent_req_set_callback(
1904 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1905 return req;
1908 #ifdef HAVE_KRB5
1909 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1911 struct tevent_req *req = tevent_req_callback_data(
1912 subreq, struct tevent_req);
1913 struct cli_session_setup_spnego_state *state = tevent_req_data(
1914 req, struct cli_session_setup_spnego_state);
1915 NTSTATUS status;
1917 status = cli_session_setup_gensec_recv(subreq);
1918 TALLOC_FREE(subreq);
1919 state->result = ADS_ERROR_NT(status);
1921 if (ADS_ERR_OK(state->result) ||
1922 !state->cli->fallback_after_kerberos) {
1923 tevent_req_done(req);
1924 return;
1927 subreq = cli_session_setup_gensec_send(
1928 state, state->ev, state->cli,
1929 state->account, state->pass, state->user_domain,
1930 CRED_DONT_USE_KERBEROS,
1931 "cifs", state->target_hostname, NULL);
1932 if (tevent_req_nomem(subreq, req)) {
1933 return;
1935 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1936 req);
1938 #endif
1940 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1942 struct tevent_req *req = tevent_req_callback_data(
1943 subreq, struct tevent_req);
1944 struct cli_session_setup_spnego_state *state = tevent_req_data(
1945 req, struct cli_session_setup_spnego_state);
1946 NTSTATUS status;
1948 status = cli_session_setup_gensec_recv(subreq);
1949 TALLOC_FREE(subreq);
1950 state->result = ADS_ERROR_NT(status);
1951 tevent_req_done(req);
1954 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1956 struct cli_session_setup_spnego_state *state = tevent_req_data(
1957 req, struct cli_session_setup_spnego_state);
1959 return state->result;
1962 struct cli_session_setup_state {
1963 uint8_t dummy;
1966 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1967 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1968 static void cli_session_setup_done_guest(struct tevent_req *subreq);
1969 static void cli_session_setup_done_plain(struct tevent_req *subreq);
1970 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1972 /****************************************************************************
1973 Send a session setup. The username and workgroup is in UNIX character
1974 format and must be converted to DOS codepage format before sending. If the
1975 password is in plaintext, the same should be done.
1976 ****************************************************************************/
1978 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1979 struct tevent_context *ev,
1980 struct cli_state *cli,
1981 const char *user,
1982 const char *pass, int passlen,
1983 const char *ntpass, int ntpasslen,
1984 const char *workgroup)
1986 struct tevent_req *req, *subreq;
1987 struct cli_session_setup_state *state;
1988 char *p;
1989 char *user2;
1990 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1992 req = tevent_req_create(mem_ctx, &state,
1993 struct cli_session_setup_state);
1994 if (req == NULL) {
1995 return NULL;
1998 if (user) {
1999 user2 = talloc_strdup(state, user);
2000 } else {
2001 user2 = talloc_strdup(state, "");
2003 if (user2 == NULL) {
2004 tevent_req_oom(req);
2005 return tevent_req_post(req, ev);
2008 if (!workgroup) {
2009 workgroup = "";
2012 /* allow for workgroups as part of the username */
2013 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2014 (p=strchr_m(user2,*lp_winbind_separator()))) {
2015 *p = 0;
2016 user = p+1;
2017 if (!strupper_m(user2)) {
2018 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2019 return tevent_req_post(req, ev);
2021 workgroup = user2;
2024 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2025 tevent_req_done(req);
2026 return tevent_req_post(req, ev);
2029 /* now work out what sort of session setup we are going to
2030 do. I have split this into separate functions to make the
2031 flow a bit easier to understand (tridge) */
2033 /* if its an older server then we have to use the older request format */
2035 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2036 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2037 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2038 " or 'client ntlmv2 auth = yes'\n"));
2039 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2040 return tevent_req_post(req, ev);
2043 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2044 !lp_client_plaintext_auth() && (*pass)) {
2045 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2046 " or 'client ntlmv2 auth = yes'\n"));
2047 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2048 return tevent_req_post(req, ev);
2051 subreq = cli_session_setup_lanman2_send(
2052 state, ev, cli, user, pass, passlen, workgroup);
2053 if (tevent_req_nomem(subreq, req)) {
2054 return tevent_req_post(req, ev);
2056 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2057 req);
2058 return req;
2061 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2062 subreq = cli_session_setup_spnego_send(
2063 state, ev, cli, user, pass, workgroup);
2064 if (tevent_req_nomem(subreq, req)) {
2065 return tevent_req_post(req, ev);
2067 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2068 req);
2069 return req;
2072 /* if no user is supplied then we have to do an anonymous connection.
2073 passwords are ignored */
2075 if (!user || !*user) {
2076 subreq = cli_session_setup_guest_send(state, ev, cli);
2077 if (tevent_req_nomem(subreq, req)) {
2078 return tevent_req_post(req, ev);
2080 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2081 req);
2082 return req;
2085 /* if the server is share level then send a plaintext null
2086 password at this point. The password is sent in the tree
2087 connect */
2089 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2090 subreq = cli_session_setup_plain_send(
2091 state, ev, cli, user, "", workgroup);
2092 if (tevent_req_nomem(subreq, req)) {
2093 return tevent_req_post(req, ev);
2095 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2096 req);
2097 return req;
2100 /* if the server doesn't support encryption then we have to use
2101 plaintext. The second password is ignored */
2103 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2104 if (!lp_client_plaintext_auth() && (*pass)) {
2105 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2106 " or 'client ntlmv2 auth = yes'\n"));
2107 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2108 return tevent_req_post(req, ev);
2110 subreq = cli_session_setup_plain_send(
2111 state, ev, cli, user, pass, workgroup);
2112 if (tevent_req_nomem(subreq, req)) {
2113 return tevent_req_post(req, ev);
2115 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2116 req);
2117 return req;
2120 /* if the server supports extended security then use SPNEGO */
2122 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2123 subreq = cli_session_setup_spnego_send(
2124 state, ev, cli, user, pass, workgroup);
2125 if (tevent_req_nomem(subreq, req)) {
2126 return tevent_req_post(req, ev);
2128 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2129 req);
2130 return req;
2131 } else {
2132 /* otherwise do a NT1 style session setup */
2133 if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) {
2135 * Don't send an NTLMv2 response without NTLMSSP
2136 * if we want to use spnego support
2138 DEBUG(1, ("Server does not support EXTENDED_SECURITY "
2139 " but 'client use spnego = yes"
2140 " and 'client ntlmv2 auth = yes'\n"));
2141 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2142 return tevent_req_post(req, ev);
2145 subreq = cli_session_setup_nt1_send(
2146 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2147 workgroup);
2148 if (tevent_req_nomem(subreq, req)) {
2149 return tevent_req_post(req, ev);
2151 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2152 req);
2153 return req;
2156 tevent_req_done(req);
2157 return tevent_req_post(req, ev);
2160 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2162 struct tevent_req *req = tevent_req_callback_data(
2163 subreq, struct tevent_req);
2164 NTSTATUS status;
2166 status = cli_session_setup_lanman2_recv(subreq);
2167 TALLOC_FREE(subreq);
2168 if (!NT_STATUS_IS_OK(status)) {
2169 tevent_req_nterror(req, status);
2170 return;
2172 tevent_req_done(req);
2175 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2177 struct tevent_req *req = tevent_req_callback_data(
2178 subreq, struct tevent_req);
2179 ADS_STATUS status;
2181 status = cli_session_setup_spnego_recv(subreq);
2182 TALLOC_FREE(subreq);
2183 if (!ADS_ERR_OK(status)) {
2184 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2185 tevent_req_nterror(req, ads_ntstatus(status));
2186 return;
2188 tevent_req_done(req);
2191 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2193 struct tevent_req *req = tevent_req_callback_data(
2194 subreq, struct tevent_req);
2195 NTSTATUS status;
2197 status = cli_session_setup_guest_recv(subreq);
2198 TALLOC_FREE(subreq);
2199 if (!NT_STATUS_IS_OK(status)) {
2200 tevent_req_nterror(req, status);
2201 return;
2203 tevent_req_done(req);
2206 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2208 struct tevent_req *req = tevent_req_callback_data(
2209 subreq, struct tevent_req);
2210 NTSTATUS status;
2212 status = cli_session_setup_plain_recv(subreq);
2213 TALLOC_FREE(subreq);
2214 if (!NT_STATUS_IS_OK(status)) {
2215 tevent_req_nterror(req, status);
2216 return;
2218 tevent_req_done(req);
2221 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2223 struct tevent_req *req = tevent_req_callback_data(
2224 subreq, struct tevent_req);
2225 NTSTATUS status;
2227 status = cli_session_setup_nt1_recv(subreq);
2228 TALLOC_FREE(subreq);
2229 if (!NT_STATUS_IS_OK(status)) {
2230 DEBUG(3, ("cli_session_setup: NT1 session setup "
2231 "failed: %s\n", nt_errstr(status)));
2232 tevent_req_nterror(req, status);
2233 return;
2235 tevent_req_done(req);
2238 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2240 return tevent_req_simple_recv_ntstatus(req);
2243 NTSTATUS cli_session_setup(struct cli_state *cli,
2244 const char *user,
2245 const char *pass, int passlen,
2246 const char *ntpass, int ntpasslen,
2247 const char *workgroup)
2249 struct tevent_context *ev;
2250 struct tevent_req *req;
2251 NTSTATUS status = NT_STATUS_NO_MEMORY;
2253 if (smbXcli_conn_has_async_calls(cli->conn)) {
2254 return NT_STATUS_INVALID_PARAMETER;
2256 ev = samba_tevent_context_init(talloc_tos());
2257 if (ev == NULL) {
2258 goto fail;
2260 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2261 ntpass, ntpasslen, workgroup);
2262 if (req == NULL) {
2263 goto fail;
2265 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2266 goto fail;
2268 status = cli_session_setup_recv(req);
2269 fail:
2270 TALLOC_FREE(ev);
2271 return status;
2274 /****************************************************************************
2275 Send a uloggoff.
2276 *****************************************************************************/
2278 struct cli_ulogoff_state {
2279 struct cli_state *cli;
2280 uint16_t vwv[3];
2283 static void cli_ulogoff_done(struct tevent_req *subreq);
2285 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2286 struct tevent_context *ev,
2287 struct cli_state *cli)
2289 struct tevent_req *req, *subreq;
2290 struct cli_ulogoff_state *state;
2292 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2293 if (req == NULL) {
2294 return NULL;
2296 state->cli = cli;
2298 SCVAL(state->vwv+0, 0, 0xFF);
2299 SCVAL(state->vwv+1, 0, 0);
2300 SSVAL(state->vwv+2, 0, 0);
2302 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2303 0, NULL);
2304 if (tevent_req_nomem(subreq, req)) {
2305 return tevent_req_post(req, ev);
2307 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2308 return req;
2311 static void cli_ulogoff_done(struct tevent_req *subreq)
2313 struct tevent_req *req = tevent_req_callback_data(
2314 subreq, struct tevent_req);
2315 struct cli_ulogoff_state *state = tevent_req_data(
2316 req, struct cli_ulogoff_state);
2317 NTSTATUS status;
2319 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2320 if (!NT_STATUS_IS_OK(status)) {
2321 tevent_req_nterror(req, status);
2322 return;
2324 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2325 tevent_req_done(req);
2328 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2330 return tevent_req_simple_recv_ntstatus(req);
2333 NTSTATUS cli_ulogoff(struct cli_state *cli)
2335 struct tevent_context *ev;
2336 struct tevent_req *req;
2337 NTSTATUS status = NT_STATUS_NO_MEMORY;
2339 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2340 status = smb2cli_logoff(cli->conn,
2341 cli->timeout,
2342 cli->smb2.session);
2343 if (!NT_STATUS_IS_OK(status)) {
2344 return status;
2346 smb2cli_session_set_id_and_flags(cli->smb2.session,
2347 UINT64_MAX, 0);
2348 return NT_STATUS_OK;
2351 if (smbXcli_conn_has_async_calls(cli->conn)) {
2352 return NT_STATUS_INVALID_PARAMETER;
2354 ev = samba_tevent_context_init(talloc_tos());
2355 if (ev == NULL) {
2356 goto fail;
2358 req = cli_ulogoff_send(ev, ev, cli);
2359 if (req == NULL) {
2360 goto fail;
2362 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2363 goto fail;
2365 status = cli_ulogoff_recv(req);
2366 fail:
2367 TALLOC_FREE(ev);
2368 return status;
2371 /****************************************************************************
2372 Send a tconX.
2373 ****************************************************************************/
2375 struct cli_tcon_andx_state {
2376 struct cli_state *cli;
2377 uint16_t vwv[4];
2378 struct iovec bytes;
2381 static void cli_tcon_andx_done(struct tevent_req *subreq);
2383 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2384 struct tevent_context *ev,
2385 struct cli_state *cli,
2386 const char *share, const char *dev,
2387 const char *pass, int passlen,
2388 struct tevent_req **psmbreq)
2390 struct tevent_req *req, *subreq;
2391 struct cli_tcon_andx_state *state;
2392 uint8_t p24[24];
2393 uint16_t *vwv;
2394 char *tmp = NULL;
2395 uint8_t *bytes;
2396 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2397 uint16_t tcon_flags = 0;
2399 *psmbreq = NULL;
2401 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2402 if (req == NULL) {
2403 return NULL;
2405 state->cli = cli;
2406 vwv = state->vwv;
2408 cli->share = talloc_strdup(cli, share);
2409 if (!cli->share) {
2410 return NULL;
2413 /* in user level security don't send a password now */
2414 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2415 passlen = 1;
2416 pass = "";
2417 } else if (pass == NULL) {
2418 DEBUG(1, ("Server not using user level security and no "
2419 "password supplied.\n"));
2420 goto access_denied;
2423 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2424 *pass && passlen != 24) {
2425 if (!lp_client_lanman_auth()) {
2426 DEBUG(1, ("Server requested LANMAN password "
2427 "(share-level security) but "
2428 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2429 goto access_denied;
2433 * Non-encrypted passwords - convert to DOS codepage before
2434 * encryption.
2436 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2437 passlen = 24;
2438 pass = (const char *)p24;
2439 } else {
2440 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2441 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2442 == 0) {
2443 uint8_t *tmp_pass;
2445 if (!lp_client_plaintext_auth() && (*pass)) {
2446 DEBUG(1, ("Server requested PLAINTEXT "
2447 "password but "
2448 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2449 goto access_denied;
2453 * Non-encrypted passwords - convert to DOS codepage
2454 * before using.
2456 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2457 if (tevent_req_nomem(tmp_pass, req)) {
2458 return tevent_req_post(req, ev);
2460 tmp_pass = trans2_bytes_push_str(tmp_pass,
2461 false, /* always DOS */
2462 pass,
2463 passlen,
2464 NULL);
2465 if (tevent_req_nomem(tmp_pass, req)) {
2466 return tevent_req_post(req, ev);
2468 pass = (const char *)tmp_pass;
2469 passlen = talloc_get_size(tmp_pass);
2473 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2474 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2476 SCVAL(vwv+0, 0, 0xFF);
2477 SCVAL(vwv+0, 1, 0);
2478 SSVAL(vwv+1, 0, 0);
2479 SSVAL(vwv+2, 0, tcon_flags);
2480 SSVAL(vwv+3, 0, passlen);
2482 if (passlen && pass) {
2483 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2484 } else {
2485 bytes = talloc_array(state, uint8_t, 0);
2489 * Add the sharename
2491 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2492 smbXcli_conn_remote_name(cli->conn), share);
2493 if (tmp == NULL) {
2494 TALLOC_FREE(req);
2495 return NULL;
2497 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2498 NULL);
2499 TALLOC_FREE(tmp);
2502 * Add the devicetype
2504 tmp = talloc_strdup_upper(talloc_tos(), dev);
2505 if (tmp == NULL) {
2506 TALLOC_FREE(req);
2507 return NULL;
2509 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2510 TALLOC_FREE(tmp);
2512 if (bytes == NULL) {
2513 TALLOC_FREE(req);
2514 return NULL;
2517 state->bytes.iov_base = (void *)bytes;
2518 state->bytes.iov_len = talloc_get_size(bytes);
2520 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2521 1, &state->bytes);
2522 if (subreq == NULL) {
2523 TALLOC_FREE(req);
2524 return NULL;
2526 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2527 *psmbreq = subreq;
2528 return req;
2530 access_denied:
2531 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2532 return tevent_req_post(req, ev);
2535 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2536 struct tevent_context *ev,
2537 struct cli_state *cli,
2538 const char *share, const char *dev,
2539 const char *pass, int passlen)
2541 struct tevent_req *req, *subreq;
2542 NTSTATUS status;
2544 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2545 &subreq);
2546 if (req == NULL) {
2547 return NULL;
2549 if (subreq == NULL) {
2550 return req;
2552 status = smb1cli_req_chain_submit(&subreq, 1);
2553 if (!NT_STATUS_IS_OK(status)) {
2554 tevent_req_nterror(req, status);
2555 return tevent_req_post(req, ev);
2557 return req;
2560 static void cli_tcon_andx_done(struct tevent_req *subreq)
2562 struct tevent_req *req = tevent_req_callback_data(
2563 subreq, struct tevent_req);
2564 struct cli_tcon_andx_state *state = tevent_req_data(
2565 req, struct cli_tcon_andx_state);
2566 struct cli_state *cli = state->cli;
2567 uint8_t *in;
2568 uint8_t *inhdr;
2569 uint8_t wct;
2570 uint16_t *vwv;
2571 uint32_t num_bytes;
2572 uint8_t *bytes;
2573 NTSTATUS status;
2574 uint16_t optional_support = 0;
2576 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2577 &num_bytes, &bytes);
2578 TALLOC_FREE(subreq);
2579 if (!NT_STATUS_IS_OK(status)) {
2580 tevent_req_nterror(req, status);
2581 return;
2584 inhdr = in + NBT_HDR_SIZE;
2586 if (num_bytes) {
2587 if (clistr_pull_talloc(cli,
2588 (const char *)inhdr,
2589 SVAL(inhdr, HDR_FLG2),
2590 &cli->dev,
2591 bytes,
2592 num_bytes,
2593 STR_TERMINATE|STR_ASCII) == -1) {
2594 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2595 return;
2597 } else {
2598 cli->dev = talloc_strdup(cli, "");
2599 if (cli->dev == NULL) {
2600 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2601 return;
2605 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2606 /* almost certainly win95 - enable bug fixes */
2607 cli->win95 = True;
2611 * Make sure that we have the optional support 16-bit field. WCT > 2.
2612 * Avoids issues when connecting to Win9x boxes sharing files
2615 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2616 optional_support = SVAL(vwv+2, 0);
2619 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2620 smb1cli_session_protect_session_key(cli->smb1.session);
2623 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2624 SVAL(inhdr, HDR_TID),
2625 optional_support,
2626 0, /* maximal_access */
2627 0, /* guest_maximal_access */
2628 NULL, /* service */
2629 NULL); /* fs_type */
2631 tevent_req_done(req);
2634 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2636 return tevent_req_simple_recv_ntstatus(req);
2639 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2640 const char *dev, const char *pass, int passlen)
2642 TALLOC_CTX *frame = talloc_stackframe();
2643 struct tevent_context *ev;
2644 struct tevent_req *req;
2645 NTSTATUS status = NT_STATUS_NO_MEMORY;
2647 if (smbXcli_conn_has_async_calls(cli->conn)) {
2649 * Can't use sync call while an async call is in flight
2651 status = NT_STATUS_INVALID_PARAMETER;
2652 goto fail;
2655 ev = samba_tevent_context_init(frame);
2656 if (ev == NULL) {
2657 goto fail;
2660 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2661 if (req == NULL) {
2662 goto fail;
2665 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2666 goto fail;
2669 status = cli_tcon_andx_recv(req);
2670 fail:
2671 TALLOC_FREE(frame);
2672 return status;
2675 struct cli_tree_connect_state {
2676 struct cli_state *cli;
2679 static struct tevent_req *cli_raw_tcon_send(
2680 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2681 const char *service, const char *pass, const char *dev);
2682 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2683 uint16_t *max_xmit, uint16_t *tid);
2685 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2686 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2687 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2689 static struct tevent_req *cli_tree_connect_send(
2690 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2691 const char *share, const char *dev, const char *pass, int passlen)
2693 struct tevent_req *req, *subreq;
2694 struct cli_tree_connect_state *state;
2696 req = tevent_req_create(mem_ctx, &state,
2697 struct cli_tree_connect_state);
2698 if (req == NULL) {
2699 return NULL;
2701 state->cli = cli;
2703 cli->share = talloc_strdup(cli, share);
2704 if (tevent_req_nomem(cli->share, req)) {
2705 return tevent_req_post(req, ev);
2708 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2709 char *unc;
2711 cli->smb2.tcon = smbXcli_tcon_create(cli);
2712 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2713 return tevent_req_post(req, ev);
2716 unc = talloc_asprintf(state, "\\\\%s\\%s",
2717 smbXcli_conn_remote_name(cli->conn),
2718 share);
2719 if (tevent_req_nomem(unc, req)) {
2720 return tevent_req_post(req, ev);
2723 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2724 cli->smb2.session, cli->smb2.tcon,
2725 0, /* flags */
2726 unc);
2727 if (tevent_req_nomem(subreq, req)) {
2728 return tevent_req_post(req, ev);
2730 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2731 req);
2732 return req;
2735 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2736 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2737 pass, passlen);
2738 if (tevent_req_nomem(subreq, req)) {
2739 return tevent_req_post(req, ev);
2741 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2742 req);
2743 return req;
2746 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2747 if (tevent_req_nomem(subreq, req)) {
2748 return tevent_req_post(req, ev);
2750 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2752 return req;
2755 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2757 tevent_req_simple_finish_ntstatus(
2758 subreq, smb2cli_tcon_recv(subreq));
2761 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2763 tevent_req_simple_finish_ntstatus(
2764 subreq, cli_tcon_andx_recv(subreq));
2767 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2769 struct tevent_req *req = tevent_req_callback_data(
2770 subreq, struct tevent_req);
2771 struct cli_tree_connect_state *state = tevent_req_data(
2772 req, struct cli_tree_connect_state);
2773 NTSTATUS status;
2774 uint16_t max_xmit = 0;
2775 uint16_t tid = 0;
2777 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2778 if (tevent_req_nterror(req, status)) {
2779 return;
2782 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2783 tid,
2784 0, /* optional_support */
2785 0, /* maximal_access */
2786 0, /* guest_maximal_access */
2787 NULL, /* service */
2788 NULL); /* fs_type */
2790 tevent_req_done(req);
2793 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2795 return tevent_req_simple_recv_ntstatus(req);
2798 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2799 const char *dev, const char *pass, int passlen)
2801 struct tevent_context *ev;
2802 struct tevent_req *req;
2803 NTSTATUS status = NT_STATUS_NO_MEMORY;
2805 if (smbXcli_conn_has_async_calls(cli->conn)) {
2806 return NT_STATUS_INVALID_PARAMETER;
2808 ev = samba_tevent_context_init(talloc_tos());
2809 if (ev == NULL) {
2810 goto fail;
2812 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2813 if (req == NULL) {
2814 goto fail;
2816 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2817 goto fail;
2819 status = cli_tree_connect_recv(req);
2820 fail:
2821 TALLOC_FREE(ev);
2822 return status;
2825 /****************************************************************************
2826 Send a tree disconnect.
2827 ****************************************************************************/
2829 struct cli_tdis_state {
2830 struct cli_state *cli;
2833 static void cli_tdis_done(struct tevent_req *subreq);
2835 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2836 struct tevent_context *ev,
2837 struct cli_state *cli)
2839 struct tevent_req *req, *subreq;
2840 struct cli_tdis_state *state;
2842 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2843 if (req == NULL) {
2844 return NULL;
2846 state->cli = cli;
2848 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2849 if (tevent_req_nomem(subreq, req)) {
2850 return tevent_req_post(req, ev);
2852 tevent_req_set_callback(subreq, cli_tdis_done, req);
2853 return req;
2856 static void cli_tdis_done(struct tevent_req *subreq)
2858 struct tevent_req *req = tevent_req_callback_data(
2859 subreq, struct tevent_req);
2860 struct cli_tdis_state *state = tevent_req_data(
2861 req, struct cli_tdis_state);
2862 NTSTATUS status;
2864 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2865 TALLOC_FREE(subreq);
2866 if (!NT_STATUS_IS_OK(status)) {
2867 tevent_req_nterror(req, status);
2868 return;
2870 cli_state_set_tid(state->cli, UINT16_MAX);
2871 tevent_req_done(req);
2874 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2876 return tevent_req_simple_recv_ntstatus(req);
2879 NTSTATUS cli_tdis(struct cli_state *cli)
2881 struct tevent_context *ev;
2882 struct tevent_req *req;
2883 NTSTATUS status = NT_STATUS_NO_MEMORY;
2885 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2886 return smb2cli_tdis(cli->conn,
2887 cli->timeout,
2888 cli->smb2.session,
2889 cli->smb2.tcon);
2892 if (smbXcli_conn_has_async_calls(cli->conn)) {
2893 return NT_STATUS_INVALID_PARAMETER;
2895 ev = samba_tevent_context_init(talloc_tos());
2896 if (ev == NULL) {
2897 goto fail;
2899 req = cli_tdis_send(ev, ev, cli);
2900 if (req == NULL) {
2901 goto fail;
2903 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2904 goto fail;
2906 status = cli_tdis_recv(req);
2907 fail:
2908 TALLOC_FREE(ev);
2909 return status;
2912 struct cli_connect_sock_state {
2913 const char **called_names;
2914 const char **calling_names;
2915 int *called_types;
2916 int fd;
2917 uint16_t port;
2920 static void cli_connect_sock_done(struct tevent_req *subreq);
2923 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2924 * nonzero address.
2927 static struct tevent_req *cli_connect_sock_send(
2928 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2929 const char *host, int name_type, const struct sockaddr_storage *pss,
2930 const char *myname, uint16_t port)
2932 struct tevent_req *req, *subreq;
2933 struct cli_connect_sock_state *state;
2934 const char *prog;
2935 struct sockaddr_storage *addrs;
2936 unsigned i, num_addrs;
2937 NTSTATUS status;
2939 req = tevent_req_create(mem_ctx, &state,
2940 struct cli_connect_sock_state);
2941 if (req == NULL) {
2942 return NULL;
2945 prog = getenv("LIBSMB_PROG");
2946 if (prog != NULL) {
2947 state->fd = sock_exec(prog);
2948 if (state->fd == -1) {
2949 status = map_nt_error_from_unix(errno);
2950 tevent_req_nterror(req, status);
2951 } else {
2952 state->port = 0;
2953 tevent_req_done(req);
2955 return tevent_req_post(req, ev);
2958 if ((pss == NULL) || is_zero_addr(pss)) {
2961 * Here we cheat. resolve_name_list is not async at all. So
2962 * this call will only be really async if the name lookup has
2963 * been done externally.
2966 status = resolve_name_list(state, host, name_type,
2967 &addrs, &num_addrs);
2968 if (!NT_STATUS_IS_OK(status)) {
2969 tevent_req_nterror(req, status);
2970 return tevent_req_post(req, ev);
2972 } else {
2973 addrs = talloc_array(state, struct sockaddr_storage, 1);
2974 if (tevent_req_nomem(addrs, req)) {
2975 return tevent_req_post(req, ev);
2977 addrs[0] = *pss;
2978 num_addrs = 1;
2981 state->called_names = talloc_array(state, const char *, num_addrs);
2982 if (tevent_req_nomem(state->called_names, req)) {
2983 return tevent_req_post(req, ev);
2985 state->called_types = talloc_array(state, int, num_addrs);
2986 if (tevent_req_nomem(state->called_types, req)) {
2987 return tevent_req_post(req, ev);
2989 state->calling_names = talloc_array(state, const char *, num_addrs);
2990 if (tevent_req_nomem(state->calling_names, req)) {
2991 return tevent_req_post(req, ev);
2993 for (i=0; i<num_addrs; i++) {
2994 state->called_names[i] = host;
2995 state->called_types[i] = name_type;
2996 state->calling_names[i] = myname;
2999 subreq = smbsock_any_connect_send(
3000 state, ev, addrs, state->called_names, state->called_types,
3001 state->calling_names, NULL, num_addrs, port);
3002 if (tevent_req_nomem(subreq, req)) {
3003 return tevent_req_post(req, ev);
3005 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
3006 return req;
3009 static void cli_connect_sock_done(struct tevent_req *subreq)
3011 struct tevent_req *req = tevent_req_callback_data(
3012 subreq, struct tevent_req);
3013 struct cli_connect_sock_state *state = tevent_req_data(
3014 req, struct cli_connect_sock_state);
3015 NTSTATUS status;
3017 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
3018 &state->port);
3019 TALLOC_FREE(subreq);
3020 if (tevent_req_nterror(req, status)) {
3021 return;
3023 set_socket_options(state->fd, lp_socket_options());
3024 tevent_req_done(req);
3027 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
3028 int *pfd, uint16_t *pport)
3030 struct cli_connect_sock_state *state = tevent_req_data(
3031 req, struct cli_connect_sock_state);
3032 NTSTATUS status;
3034 if (tevent_req_is_nterror(req, &status)) {
3035 return status;
3037 *pfd = state->fd;
3038 *pport = state->port;
3039 return NT_STATUS_OK;
3042 struct cli_connect_nb_state {
3043 const char *desthost;
3044 int signing_state;
3045 int flags;
3046 struct cli_state *cli;
3049 static void cli_connect_nb_done(struct tevent_req *subreq);
3051 static struct tevent_req *cli_connect_nb_send(
3052 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3053 const char *host, const struct sockaddr_storage *dest_ss,
3054 uint16_t port, int name_type, const char *myname,
3055 int signing_state, int flags)
3057 struct tevent_req *req, *subreq;
3058 struct cli_connect_nb_state *state;
3060 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3061 if (req == NULL) {
3062 return NULL;
3064 state->signing_state = signing_state;
3065 state->flags = flags;
3067 if (host != NULL) {
3068 char *p = strchr(host, '#');
3070 if (p != NULL) {
3071 name_type = strtol(p+1, NULL, 16);
3072 host = talloc_strndup(state, host, p - host);
3073 if (tevent_req_nomem(host, req)) {
3074 return tevent_req_post(req, ev);
3078 state->desthost = host;
3079 } else {
3080 state->desthost = print_canonical_sockaddr(state, dest_ss);
3081 if (tevent_req_nomem(state->desthost, req)) {
3082 return tevent_req_post(req, ev);
3086 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3087 myname, port);
3088 if (tevent_req_nomem(subreq, req)) {
3089 return tevent_req_post(req, ev);
3091 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3092 return req;
3095 static void cli_connect_nb_done(struct tevent_req *subreq)
3097 struct tevent_req *req = tevent_req_callback_data(
3098 subreq, struct tevent_req);
3099 struct cli_connect_nb_state *state = tevent_req_data(
3100 req, struct cli_connect_nb_state);
3101 NTSTATUS status;
3102 int fd = 0;
3103 uint16_t port;
3105 status = cli_connect_sock_recv(subreq, &fd, &port);
3106 TALLOC_FREE(subreq);
3107 if (tevent_req_nterror(req, status)) {
3108 return;
3111 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3112 state->signing_state, state->flags);
3113 if (tevent_req_nomem(state->cli, req)) {
3114 close(fd);
3115 return;
3117 tevent_req_done(req);
3120 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3121 struct cli_state **pcli)
3123 struct cli_connect_nb_state *state = tevent_req_data(
3124 req, struct cli_connect_nb_state);
3125 NTSTATUS status;
3127 if (tevent_req_is_nterror(req, &status)) {
3128 return status;
3130 *pcli = talloc_move(NULL, &state->cli);
3131 return NT_STATUS_OK;
3134 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3135 uint16_t port, int name_type, const char *myname,
3136 int signing_state, int flags, struct cli_state **pcli)
3138 struct tevent_context *ev;
3139 struct tevent_req *req;
3140 NTSTATUS status = NT_STATUS_NO_MEMORY;
3142 ev = samba_tevent_context_init(talloc_tos());
3143 if (ev == NULL) {
3144 goto fail;
3146 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3147 myname, signing_state, flags);
3148 if (req == NULL) {
3149 goto fail;
3151 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3152 goto fail;
3154 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3155 goto fail;
3157 status = cli_connect_nb_recv(req, pcli);
3158 fail:
3159 TALLOC_FREE(ev);
3160 return status;
3163 struct cli_start_connection_state {
3164 struct tevent_context *ev;
3165 struct cli_state *cli;
3166 int min_protocol;
3167 int max_protocol;
3170 static void cli_start_connection_connected(struct tevent_req *subreq);
3171 static void cli_start_connection_done(struct tevent_req *subreq);
3174 establishes a connection to after the negprot.
3175 @param output_cli A fully initialised cli structure, non-null only on success
3176 @param dest_host The netbios name of the remote host
3177 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3178 @param port (optional) The destination port (0 for default)
3181 static struct tevent_req *cli_start_connection_send(
3182 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3183 const char *my_name, const char *dest_host,
3184 const struct sockaddr_storage *dest_ss, int port,
3185 int signing_state, int flags)
3187 struct tevent_req *req, *subreq;
3188 struct cli_start_connection_state *state;
3190 req = tevent_req_create(mem_ctx, &state,
3191 struct cli_start_connection_state);
3192 if (req == NULL) {
3193 return NULL;
3195 state->ev = ev;
3197 if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
3198 state->min_protocol = lp_client_ipc_min_protocol();
3199 state->max_protocol = lp_client_ipc_max_protocol();
3200 } else {
3201 state->min_protocol = lp_client_min_protocol();
3202 state->max_protocol = lp_client_max_protocol();
3205 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3206 0x20, my_name, signing_state, flags);
3207 if (tevent_req_nomem(subreq, req)) {
3208 return tevent_req_post(req, ev);
3210 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3211 return req;
3214 static void cli_start_connection_connected(struct tevent_req *subreq)
3216 struct tevent_req *req = tevent_req_callback_data(
3217 subreq, struct tevent_req);
3218 struct cli_start_connection_state *state = tevent_req_data(
3219 req, struct cli_start_connection_state);
3220 NTSTATUS status;
3222 status = cli_connect_nb_recv(subreq, &state->cli);
3223 TALLOC_FREE(subreq);
3224 if (tevent_req_nterror(req, status)) {
3225 return;
3228 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3229 state->cli->timeout,
3230 state->min_protocol,
3231 state->max_protocol);
3232 if (tevent_req_nomem(subreq, req)) {
3233 return;
3235 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3238 static void cli_start_connection_done(struct tevent_req *subreq)
3240 struct tevent_req *req = tevent_req_callback_data(
3241 subreq, struct tevent_req);
3242 struct cli_start_connection_state *state = tevent_req_data(
3243 req, struct cli_start_connection_state);
3244 NTSTATUS status;
3246 status = smbXcli_negprot_recv(subreq);
3247 TALLOC_FREE(subreq);
3248 if (tevent_req_nterror(req, status)) {
3249 return;
3252 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3253 /* Ensure we ask for some initial credits. */
3254 smb2cli_conn_set_max_credits(state->cli->conn,
3255 DEFAULT_SMB2_MAX_CREDITS);
3258 tevent_req_done(req);
3261 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3262 struct cli_state **output_cli)
3264 struct cli_start_connection_state *state = tevent_req_data(
3265 req, struct cli_start_connection_state);
3266 NTSTATUS status;
3268 if (tevent_req_is_nterror(req, &status)) {
3269 return status;
3271 *output_cli = state->cli;
3273 return NT_STATUS_OK;
3276 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3277 const char *my_name,
3278 const char *dest_host,
3279 const struct sockaddr_storage *dest_ss, int port,
3280 int signing_state, int flags)
3282 struct tevent_context *ev;
3283 struct tevent_req *req;
3284 NTSTATUS status = NT_STATUS_NO_MEMORY;
3286 ev = samba_tevent_context_init(talloc_tos());
3287 if (ev == NULL) {
3288 goto fail;
3290 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3291 port, signing_state, flags);
3292 if (req == NULL) {
3293 goto fail;
3295 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3296 goto fail;
3298 status = cli_start_connection_recv(req, output_cli);
3299 fail:
3300 TALLOC_FREE(ev);
3301 return status;
3305 establishes a connection right up to doing tconX, password specified.
3306 @param output_cli A fully initialised cli structure, non-null only on success
3307 @param dest_host The netbios name of the remote host
3308 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3309 @param port (optional) The destination port (0 for default)
3310 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3311 @param service_type The 'type' of serivice.
3312 @param user Username, unix string
3313 @param domain User's domain
3314 @param password User's password, unencrypted unix string.
3317 struct cli_full_connection_state {
3318 struct tevent_context *ev;
3319 const char *service;
3320 const char *service_type;
3321 const char *user;
3322 const char *domain;
3323 const char *password;
3324 int pw_len;
3325 int flags;
3326 struct cli_state *cli;
3329 static int cli_full_connection_state_destructor(
3330 struct cli_full_connection_state *s);
3331 static void cli_full_connection_started(struct tevent_req *subreq);
3332 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3333 static void cli_full_connection_done(struct tevent_req *subreq);
3335 struct tevent_req *cli_full_connection_send(
3336 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3337 const char *my_name, const char *dest_host,
3338 const struct sockaddr_storage *dest_ss, int port,
3339 const char *service, const char *service_type,
3340 const char *user, const char *domain,
3341 const char *password, int flags, int signing_state)
3343 struct tevent_req *req, *subreq;
3344 struct cli_full_connection_state *state;
3346 req = tevent_req_create(mem_ctx, &state,
3347 struct cli_full_connection_state);
3348 if (req == NULL) {
3349 return NULL;
3351 talloc_set_destructor(state, cli_full_connection_state_destructor);
3353 state->ev = ev;
3354 state->service = service;
3355 state->service_type = service_type;
3356 state->user = user;
3357 state->domain = domain;
3358 state->password = password;
3359 state->flags = flags;
3361 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3362 if (state->password == NULL) {
3363 state->password = "";
3366 subreq = cli_start_connection_send(
3367 state, ev, my_name, dest_host, dest_ss, port,
3368 signing_state, flags);
3369 if (tevent_req_nomem(subreq, req)) {
3370 return tevent_req_post(req, ev);
3372 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3373 return req;
3376 static int cli_full_connection_state_destructor(
3377 struct cli_full_connection_state *s)
3379 if (s->cli != NULL) {
3380 cli_shutdown(s->cli);
3381 s->cli = NULL;
3383 return 0;
3386 static void cli_full_connection_started(struct tevent_req *subreq)
3388 struct tevent_req *req = tevent_req_callback_data(
3389 subreq, struct tevent_req);
3390 struct cli_full_connection_state *state = tevent_req_data(
3391 req, struct cli_full_connection_state);
3392 NTSTATUS status;
3394 status = cli_start_connection_recv(subreq, &state->cli);
3395 TALLOC_FREE(subreq);
3396 if (tevent_req_nterror(req, status)) {
3397 return;
3399 subreq = cli_session_setup_send(
3400 state, state->ev, state->cli, state->user,
3401 state->password, state->pw_len, state->password, state->pw_len,
3402 state->domain);
3403 if (tevent_req_nomem(subreq, req)) {
3404 return;
3406 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3409 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3411 struct tevent_req *req = tevent_req_callback_data(
3412 subreq, struct tevent_req);
3413 struct cli_full_connection_state *state = tevent_req_data(
3414 req, struct cli_full_connection_state);
3415 NTSTATUS status;
3417 status = cli_session_setup_recv(subreq);
3418 TALLOC_FREE(subreq);
3420 if (!NT_STATUS_IS_OK(status) &&
3421 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3423 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3425 subreq = cli_session_setup_send(
3426 state, state->ev, state->cli, "", "", 0, "", 0,
3427 state->domain);
3428 if (tevent_req_nomem(subreq, req)) {
3429 return;
3431 tevent_req_set_callback(
3432 subreq, cli_full_connection_sess_set_up, req);
3433 return;
3436 if (tevent_req_nterror(req, status)) {
3437 return;
3440 if (state->service != NULL) {
3441 subreq = cli_tree_connect_send(
3442 state, state->ev, state->cli,
3443 state->service, state->service_type,
3444 state->password, state->pw_len);
3445 if (tevent_req_nomem(subreq, req)) {
3446 return;
3448 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3449 return;
3452 tevent_req_done(req);
3455 static void cli_full_connection_done(struct tevent_req *subreq)
3457 struct tevent_req *req = tevent_req_callback_data(
3458 subreq, struct tevent_req);
3459 NTSTATUS status;
3461 status = cli_tree_connect_recv(subreq);
3462 TALLOC_FREE(subreq);
3463 if (tevent_req_nterror(req, status)) {
3464 return;
3467 tevent_req_done(req);
3470 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3471 struct cli_state **output_cli)
3473 struct cli_full_connection_state *state = tevent_req_data(
3474 req, struct cli_full_connection_state);
3475 NTSTATUS status;
3477 if (tevent_req_is_nterror(req, &status)) {
3478 return status;
3480 *output_cli = state->cli;
3481 talloc_set_destructor(state, NULL);
3482 return NT_STATUS_OK;
3485 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3486 const char *my_name,
3487 const char *dest_host,
3488 const struct sockaddr_storage *dest_ss, int port,
3489 const char *service, const char *service_type,
3490 const char *user, const char *domain,
3491 const char *password, int flags,
3492 int signing_state)
3494 struct tevent_context *ev;
3495 struct tevent_req *req;
3496 NTSTATUS status = NT_STATUS_NO_MEMORY;
3498 ev = samba_tevent_context_init(talloc_tos());
3499 if (ev == NULL) {
3500 goto fail;
3502 req = cli_full_connection_send(
3503 ev, ev, my_name, dest_host, dest_ss, port, service,
3504 service_type, user, domain, password, flags, signing_state);
3505 if (req == NULL) {
3506 goto fail;
3508 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3509 goto fail;
3511 status = cli_full_connection_recv(req, output_cli);
3512 fail:
3513 TALLOC_FREE(ev);
3514 return status;
3517 /****************************************************************************
3518 Send an old style tcon.
3519 ****************************************************************************/
3520 struct cli_raw_tcon_state {
3521 uint16_t *ret_vwv;
3524 static void cli_raw_tcon_done(struct tevent_req *subreq);
3526 static struct tevent_req *cli_raw_tcon_send(
3527 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3528 const char *service, const char *pass, const char *dev)
3530 struct tevent_req *req, *subreq;
3531 struct cli_raw_tcon_state *state;
3532 uint8_t *bytes;
3534 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3535 if (req == NULL) {
3536 return NULL;
3539 if (!lp_client_plaintext_auth() && (*pass)) {
3540 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3541 " or 'client ntlmv2 auth = yes'\n"));
3542 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3543 return tevent_req_post(req, ev);
3546 bytes = talloc_array(state, uint8_t, 0);
3547 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3548 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3549 service, strlen(service)+1, NULL);
3550 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3551 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3552 pass, strlen(pass)+1, NULL);
3553 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3554 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3555 dev, strlen(dev)+1, NULL);
3557 if (tevent_req_nomem(bytes, req)) {
3558 return tevent_req_post(req, ev);
3561 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3562 talloc_get_size(bytes), bytes);
3563 if (tevent_req_nomem(subreq, req)) {
3564 return tevent_req_post(req, ev);
3566 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3567 return req;
3570 static void cli_raw_tcon_done(struct tevent_req *subreq)
3572 struct tevent_req *req = tevent_req_callback_data(
3573 subreq, struct tevent_req);
3574 struct cli_raw_tcon_state *state = tevent_req_data(
3575 req, struct cli_raw_tcon_state);
3576 NTSTATUS status;
3578 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3579 NULL, NULL);
3580 TALLOC_FREE(subreq);
3581 if (tevent_req_nterror(req, status)) {
3582 return;
3584 tevent_req_done(req);
3587 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3588 uint16_t *max_xmit, uint16_t *tid)
3590 struct cli_raw_tcon_state *state = tevent_req_data(
3591 req, struct cli_raw_tcon_state);
3592 NTSTATUS status;
3594 if (tevent_req_is_nterror(req, &status)) {
3595 return status;
3597 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3598 *tid = SVAL(state->ret_vwv + 1, 0);
3599 return NT_STATUS_OK;
3602 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3603 const char *service, const char *pass, const char *dev,
3604 uint16_t *max_xmit, uint16_t *tid)
3606 struct tevent_context *ev;
3607 struct tevent_req *req;
3608 NTSTATUS status = NT_STATUS_NO_MEMORY;
3610 ev = samba_tevent_context_init(talloc_tos());
3611 if (ev == NULL) {
3612 goto fail;
3614 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3615 if (req == NULL) {
3616 goto fail;
3618 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3619 goto fail;
3621 status = cli_raw_tcon_recv(req, max_xmit, tid);
3622 fail:
3623 TALLOC_FREE(ev);
3624 return status;
3627 /* Return a cli_state pointing at the IPC$ share for the given server */
3629 struct cli_state *get_ipc_connect(char *server,
3630 struct sockaddr_storage *server_ss,
3631 const struct user_auth_info *user_info)
3633 struct cli_state *cli;
3634 NTSTATUS nt_status;
3635 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3637 if (user_info->use_kerberos) {
3638 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3641 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3642 user_info->username ? user_info->username : "",
3643 lp_workgroup(),
3644 user_info->password ? user_info->password : "",
3645 flags,
3646 SMB_SIGNING_DEFAULT);
3648 if (NT_STATUS_IS_OK(nt_status)) {
3649 return cli;
3650 } else if (is_ipaddress(server)) {
3651 /* windows 9* needs a correct NMB name for connections */
3652 fstring remote_name;
3654 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3655 cli = get_ipc_connect(remote_name, server_ss, user_info);
3656 if (cli)
3657 return cli;
3660 return NULL;
3664 * Given the IP address of a master browser on the network, return its
3665 * workgroup and connect to it.
3667 * This function is provided to allow additional processing beyond what
3668 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3669 * browsers and obtain each master browsers' list of domains (in case the
3670 * first master browser is recently on the network and has not yet
3671 * synchronized with other master browsers and therefore does not yet have the
3672 * entire network browse list)
3675 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3676 struct sockaddr_storage *mb_ip,
3677 const struct user_auth_info *user_info,
3678 char **pp_workgroup_out)
3680 char addr[INET6_ADDRSTRLEN];
3681 fstring name;
3682 struct cli_state *cli;
3683 struct sockaddr_storage server_ss;
3685 *pp_workgroup_out = NULL;
3687 print_sockaddr(addr, sizeof(addr), mb_ip);
3688 DEBUG(99, ("Looking up name of master browser %s\n",
3689 addr));
3692 * Do a name status query to find out the name of the master browser.
3693 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3694 * master browser will not respond to a wildcard query (or, at least,
3695 * an NT4 server acting as the domain master browser will not).
3697 * We might be able to use ONLY the query on MSBROWSE, but that's not
3698 * yet been tested with all Windows versions, so until it is, leave
3699 * the original wildcard query as the first choice and fall back to
3700 * MSBROWSE if the wildcard query fails.
3702 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3703 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3705 DEBUG(99, ("Could not retrieve name status for %s\n",
3706 addr));
3707 return NULL;
3710 if (!find_master_ip(name, &server_ss)) {
3711 DEBUG(99, ("Could not find master ip for %s\n", name));
3712 return NULL;
3715 *pp_workgroup_out = talloc_strdup(ctx, name);
3717 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3719 print_sockaddr(addr, sizeof(addr), &server_ss);
3720 cli = get_ipc_connect(addr, &server_ss, user_info);
3722 return cli;
3726 * Return the IP address and workgroup of a master browser on the network, and
3727 * connect to it.
3730 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3731 const struct user_auth_info *user_info,
3732 char **pp_workgroup_out)
3734 struct sockaddr_storage *ip_list;
3735 struct cli_state *cli;
3736 int i, count;
3737 NTSTATUS status;
3739 *pp_workgroup_out = NULL;
3741 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3743 /* Go looking for workgroups by broadcasting on the local network */
3745 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3746 &ip_list, &count);
3747 if (!NT_STATUS_IS_OK(status)) {
3748 DEBUG(99, ("No master browsers responded: %s\n",
3749 nt_errstr(status)));
3750 return NULL;
3753 for (i = 0; i < count; i++) {
3754 char addr[INET6_ADDRSTRLEN];
3755 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3756 DEBUG(99, ("Found master browser %s\n", addr));
3758 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3759 user_info, pp_workgroup_out);
3760 if (cli)
3761 return(cli);
3764 return NULL;