s3:libsmb: make cli_tdis_send/recv static
[Samba.git] / source3 / libsmb / cliconnect.c
bloba8769e5e7142368b5c1ac0d625b7de1b29e3238f
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/ntlmssp/ntlmssp.h"
30 #include "libads/kerberos_proto.h"
31 #include "krb5_env.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "async_smb.h"
34 #include "libsmb/nmblib.h"
35 #include "librpc/ndr/libndr.h"
36 #include "../libcli/smb/smbXcli_base.h"
37 #include "smb2cli.h"
39 #define STAR_SMBSERVER "*SMBSERVER"
41 /********************************************************
42 Utility function to ensure we always return at least
43 a valid char * pointer to an empty string for the
44 cli->server_os, cli->server_type and cli->server_domain
45 strings.
46 *******************************************************/
48 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
49 const uint8_t *hdr,
50 char **dest,
51 uint8_t *src,
52 size_t srclen,
53 ssize_t *destlen)
55 *destlen = clistr_pull_talloc(mem_ctx,
56 (const char *)hdr,
57 SVAL(hdr, HDR_FLG2),
58 dest,
59 (char *)src,
60 srclen,
61 STR_TERMINATE);
62 if (*destlen == -1) {
63 return NT_STATUS_NO_MEMORY;
66 if (*dest == NULL) {
67 *dest = talloc_strdup(mem_ctx, "");
68 if (*dest == NULL) {
69 return NT_STATUS_NO_MEMORY;
72 return NT_STATUS_OK;
75 /****************************************************************************
76 Do an old lanman2 style session setup.
77 ****************************************************************************/
79 struct cli_session_setup_lanman2_state {
80 struct cli_state *cli;
81 uint16_t vwv[10];
82 const char *user;
85 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
87 static struct tevent_req *cli_session_setup_lanman2_send(
88 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
89 struct cli_state *cli, const char *user,
90 const char *pass, size_t passlen,
91 const char *workgroup)
93 struct tevent_req *req, *subreq;
94 struct cli_session_setup_lanman2_state *state;
95 DATA_BLOB lm_response = data_blob_null;
96 uint16_t *vwv;
97 uint8_t *bytes;
98 char *tmp;
99 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
101 req = tevent_req_create(mem_ctx, &state,
102 struct cli_session_setup_lanman2_state);
103 if (req == NULL) {
104 return NULL;
106 state->cli = cli;
107 state->user = user;
108 vwv = state->vwv;
111 * if in share level security then don't send a password now
113 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
114 passlen = 0;
117 if (passlen > 0
118 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
119 && passlen != 24) {
121 * Encrypted mode needed, and non encrypted password
122 * supplied.
124 lm_response = data_blob(NULL, 24);
125 if (tevent_req_nomem(lm_response.data, req)) {
126 return tevent_req_post(req, ev);
129 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
130 (uint8_t *)lm_response.data)) {
131 DEBUG(1, ("Password is > 14 chars in length, and is "
132 "therefore incompatible with Lanman "
133 "authentication\n"));
134 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
135 return tevent_req_post(req, ev);
137 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
138 && passlen == 24) {
140 * Encrypted mode needed, and encrypted password
141 * supplied.
143 lm_response = data_blob(pass, passlen);
144 if (tevent_req_nomem(lm_response.data, req)) {
145 return tevent_req_post(req, ev);
147 } else if (passlen > 0) {
148 uint8_t *buf;
149 size_t converted_size;
151 * Plaintext mode needed, assume plaintext supplied.
153 buf = talloc_array(talloc_tos(), uint8_t, 0);
154 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
155 &converted_size);
156 if (tevent_req_nomem(buf, req)) {
157 return tevent_req_post(req, ev);
159 lm_response = data_blob(pass, passlen);
160 TALLOC_FREE(buf);
161 if (tevent_req_nomem(lm_response.data, req)) {
162 return tevent_req_post(req, ev);
166 SCVAL(vwv+0, 0, 0xff);
167 SCVAL(vwv+0, 1, 0);
168 SSVAL(vwv+1, 0, 0);
169 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
170 SSVAL(vwv+3, 0, 2);
171 SSVAL(vwv+4, 0, 1);
172 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
173 SSVAL(vwv+7, 0, lm_response.length);
175 bytes = talloc_array(state, uint8_t, lm_response.length);
176 if (tevent_req_nomem(bytes, req)) {
177 return tevent_req_post(req, ev);
179 if (lm_response.length != 0) {
180 memcpy(bytes, lm_response.data, lm_response.length);
182 data_blob_free(&lm_response);
184 tmp = talloc_strdup_upper(talloc_tos(), user);
185 if (tevent_req_nomem(tmp, req)) {
186 return tevent_req_post(req, ev);
188 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
189 NULL);
190 TALLOC_FREE(tmp);
192 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
193 if (tevent_req_nomem(tmp, req)) {
194 return tevent_req_post(req, ev);
196 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
197 NULL);
198 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
199 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
201 if (tevent_req_nomem(bytes, req)) {
202 return tevent_req_post(req, ev);
205 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
206 talloc_get_size(bytes), bytes);
207 if (tevent_req_nomem(subreq, req)) {
208 return tevent_req_post(req, ev);
210 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
211 return req;
214 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
216 struct tevent_req *req = tevent_req_callback_data(
217 subreq, struct tevent_req);
218 struct cli_session_setup_lanman2_state *state = tevent_req_data(
219 req, struct cli_session_setup_lanman2_state);
220 struct cli_state *cli = state->cli;
221 uint32_t num_bytes;
222 uint8_t *in;
223 uint8_t *inhdr;
224 uint8_t *bytes;
225 uint8_t *p;
226 NTSTATUS status;
227 ssize_t ret;
228 uint8_t wct;
229 uint16_t *vwv;
231 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
232 &num_bytes, &bytes);
233 TALLOC_FREE(subreq);
234 if (!NT_STATUS_IS_OK(status)) {
235 tevent_req_nterror(req, status);
236 return;
239 inhdr = in + NBT_HDR_SIZE;
240 p = bytes;
242 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
244 status = smb_bytes_talloc_string(cli,
245 inhdr,
246 &cli->server_os,
248 bytes+num_bytes-p,
249 &ret);
251 if (!NT_STATUS_IS_OK(status)) {
252 tevent_req_nterror(req, status);
253 return;
255 p += ret;
257 status = smb_bytes_talloc_string(cli,
258 inhdr,
259 &cli->server_type,
261 bytes+num_bytes-p,
262 &ret);
264 if (!NT_STATUS_IS_OK(status)) {
265 tevent_req_nterror(req, status);
266 return;
268 p += ret;
270 status = smb_bytes_talloc_string(cli,
271 inhdr,
272 &cli->server_domain,
274 bytes+num_bytes-p,
275 &ret);
277 if (!NT_STATUS_IS_OK(status)) {
278 tevent_req_nterror(req, status);
279 return;
281 p += ret;
283 status = cli_set_username(cli, state->user);
284 if (tevent_req_nterror(req, status)) {
285 return;
287 tevent_req_done(req);
290 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
292 return tevent_req_simple_recv_ntstatus(req);
295 /****************************************************************************
296 Work out suitable capabilities to offer the server.
297 ****************************************************************************/
299 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
300 uint32_t sesssetup_capabilities)
302 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
305 * We only send capabilities based on the mask for:
306 * - client only flags
307 * - flags used in both directions
309 * We do not echo the server only flags, except some legacy flags.
311 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
312 * CAP_LARGE_WRITEX in order to allow us to do large reads
313 * against old Samba releases (<= 3.6.x).
315 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
318 * Session Setup specific flags CAP_DYNAMIC_REAUTH
319 * and CAP_EXTENDED_SECURITY are passed by the caller.
320 * We need that in order to do guest logins even if
321 * CAP_EXTENDED_SECURITY is negotiated.
323 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
324 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
325 client_capabilities |= sesssetup_capabilities;
327 return client_capabilities;
330 /****************************************************************************
331 Do a NT1 guest session setup.
332 ****************************************************************************/
334 struct cli_session_setup_guest_state {
335 struct cli_state *cli;
336 uint16_t vwv[13];
337 struct iovec bytes;
340 static void cli_session_setup_guest_done(struct tevent_req *subreq);
342 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
343 struct tevent_context *ev,
344 struct cli_state *cli,
345 struct tevent_req **psmbreq)
347 struct tevent_req *req, *subreq;
348 struct cli_session_setup_guest_state *state;
349 uint16_t *vwv;
350 uint8_t *bytes;
352 req = tevent_req_create(mem_ctx, &state,
353 struct cli_session_setup_guest_state);
354 if (req == NULL) {
355 return NULL;
357 state->cli = cli;
358 vwv = state->vwv;
360 SCVAL(vwv+0, 0, 0xFF);
361 SCVAL(vwv+0, 1, 0);
362 SSVAL(vwv+1, 0, 0);
363 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
364 SSVAL(vwv+3, 0, 2);
365 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
366 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
367 SSVAL(vwv+7, 0, 0);
368 SSVAL(vwv+8, 0, 0);
369 SSVAL(vwv+9, 0, 0);
370 SSVAL(vwv+10, 0, 0);
371 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
373 bytes = talloc_array(state, uint8_t, 0);
375 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
376 NULL);
377 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
378 NULL);
379 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
380 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
382 if (bytes == NULL) {
383 TALLOC_FREE(req);
384 return NULL;
387 state->bytes.iov_base = (void *)bytes;
388 state->bytes.iov_len = talloc_get_size(bytes);
390 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
391 1, &state->bytes);
392 if (subreq == NULL) {
393 TALLOC_FREE(req);
394 return NULL;
396 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
397 *psmbreq = subreq;
398 return req;
401 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
402 struct tevent_context *ev,
403 struct cli_state *cli)
405 struct tevent_req *req, *subreq;
406 NTSTATUS status;
408 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
409 if (req == NULL) {
410 return NULL;
413 status = smb1cli_req_chain_submit(&subreq, 1);
414 if (!NT_STATUS_IS_OK(status)) {
415 tevent_req_nterror(req, status);
416 return tevent_req_post(req, ev);
418 return req;
421 static void cli_session_setup_guest_done(struct tevent_req *subreq)
423 struct tevent_req *req = tevent_req_callback_data(
424 subreq, struct tevent_req);
425 struct cli_session_setup_guest_state *state = tevent_req_data(
426 req, struct cli_session_setup_guest_state);
427 struct cli_state *cli = state->cli;
428 uint32_t num_bytes;
429 uint8_t *in;
430 uint8_t *inhdr;
431 uint8_t *bytes;
432 uint8_t *p;
433 NTSTATUS status;
434 ssize_t ret;
435 uint8_t wct;
436 uint16_t *vwv;
438 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
439 &num_bytes, &bytes);
440 TALLOC_FREE(subreq);
441 if (!NT_STATUS_IS_OK(status)) {
442 tevent_req_nterror(req, status);
443 return;
446 inhdr = in + NBT_HDR_SIZE;
447 p = bytes;
449 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
451 status = smb_bytes_talloc_string(cli,
452 inhdr,
453 &cli->server_os,
455 bytes+num_bytes-p,
456 &ret);
458 if (!NT_STATUS_IS_OK(status)) {
459 tevent_req_nterror(req, status);
460 return;
462 p += ret;
464 status = smb_bytes_talloc_string(cli,
465 inhdr,
466 &cli->server_type,
468 bytes+num_bytes-p,
469 &ret);
471 if (!NT_STATUS_IS_OK(status)) {
472 tevent_req_nterror(req, status);
473 return;
475 p += ret;
477 status = smb_bytes_talloc_string(cli,
478 inhdr,
479 &cli->server_domain,
481 bytes+num_bytes-p,
482 &ret);
484 if (!NT_STATUS_IS_OK(status)) {
485 tevent_req_nterror(req, status);
486 return;
488 p += ret;
490 status = cli_set_username(cli, "");
491 if (!NT_STATUS_IS_OK(status)) {
492 tevent_req_nterror(req, status);
493 return;
495 tevent_req_done(req);
498 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
500 return tevent_req_simple_recv_ntstatus(req);
503 /****************************************************************************
504 Do a NT1 plaintext session setup.
505 ****************************************************************************/
507 struct cli_session_setup_plain_state {
508 struct cli_state *cli;
509 uint16_t vwv[13];
510 const char *user;
513 static void cli_session_setup_plain_done(struct tevent_req *subreq);
515 static struct tevent_req *cli_session_setup_plain_send(
516 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
517 struct cli_state *cli,
518 const char *user, const char *pass, const char *workgroup)
520 struct tevent_req *req, *subreq;
521 struct cli_session_setup_plain_state *state;
522 uint16_t *vwv;
523 uint8_t *bytes;
524 size_t passlen;
525 char *version;
527 req = tevent_req_create(mem_ctx, &state,
528 struct cli_session_setup_plain_state);
529 if (req == NULL) {
530 return NULL;
532 state->cli = cli;
533 state->user = user;
534 vwv = state->vwv;
536 SCVAL(vwv+0, 0, 0xff);
537 SCVAL(vwv+0, 1, 0);
538 SSVAL(vwv+1, 0, 0);
539 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
540 SSVAL(vwv+3, 0, 2);
541 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
542 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
543 SSVAL(vwv+7, 0, 0);
544 SSVAL(vwv+8, 0, 0);
545 SSVAL(vwv+9, 0, 0);
546 SSVAL(vwv+10, 0, 0);
547 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
549 bytes = talloc_array(state, uint8_t, 0);
550 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
551 &passlen);
552 if (tevent_req_nomem(bytes, req)) {
553 return tevent_req_post(req, ev);
555 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
557 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
558 user, strlen(user)+1, NULL);
559 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
560 workgroup, strlen(workgroup)+1, NULL);
561 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
562 "Unix", 5, NULL);
564 version = talloc_asprintf(talloc_tos(), "Samba %s",
565 samba_version_string());
566 if (tevent_req_nomem(version, req)){
567 return tevent_req_post(req, ev);
569 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
570 version, strlen(version)+1, NULL);
571 TALLOC_FREE(version);
573 if (tevent_req_nomem(bytes, req)) {
574 return tevent_req_post(req, ev);
577 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
578 talloc_get_size(bytes), bytes);
579 if (tevent_req_nomem(subreq, req)) {
580 return tevent_req_post(req, ev);
582 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
583 return req;
586 static void cli_session_setup_plain_done(struct tevent_req *subreq)
588 struct tevent_req *req = tevent_req_callback_data(
589 subreq, struct tevent_req);
590 struct cli_session_setup_plain_state *state = tevent_req_data(
591 req, struct cli_session_setup_plain_state);
592 struct cli_state *cli = state->cli;
593 uint32_t num_bytes;
594 uint8_t *in;
595 uint8_t *inhdr;
596 uint8_t *bytes;
597 uint8_t *p;
598 NTSTATUS status;
599 ssize_t ret;
600 uint8_t wct;
601 uint16_t *vwv;
603 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
604 &num_bytes, &bytes);
605 TALLOC_FREE(subreq);
606 if (tevent_req_nterror(req, status)) {
607 return;
610 inhdr = in + NBT_HDR_SIZE;
611 p = bytes;
613 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
615 status = smb_bytes_talloc_string(cli,
616 inhdr,
617 &cli->server_os,
619 bytes+num_bytes-p,
620 &ret);
622 if (!NT_STATUS_IS_OK(status)) {
623 tevent_req_nterror(req, status);
624 return;
626 p += ret;
628 status = smb_bytes_talloc_string(cli,
629 inhdr,
630 &cli->server_type,
632 bytes+num_bytes-p,
633 &ret);
635 if (!NT_STATUS_IS_OK(status)) {
636 tevent_req_nterror(req, status);
637 return;
639 p += ret;
641 status = smb_bytes_talloc_string(cli,
642 inhdr,
643 &cli->server_domain,
645 bytes+num_bytes-p,
646 &ret);
648 if (!NT_STATUS_IS_OK(status)) {
649 tevent_req_nterror(req, status);
650 return;
652 p += ret;
654 status = cli_set_username(cli, state->user);
655 if (tevent_req_nterror(req, status)) {
656 return;
659 tevent_req_done(req);
662 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
664 return tevent_req_simple_recv_ntstatus(req);
667 /****************************************************************************
668 do a NT1 NTLM/LM encrypted session setup - for when extended security
669 is not negotiated.
670 @param cli client state to create do session setup on
671 @param user username
672 @param pass *either* cleartext password (passlen !=24) or LM response.
673 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
674 @param workgroup The user's domain.
675 ****************************************************************************/
677 struct cli_session_setup_nt1_state {
678 struct cli_state *cli;
679 uint16_t vwv[13];
680 DATA_BLOB response;
681 DATA_BLOB session_key;
682 const char *user;
685 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
687 static struct tevent_req *cli_session_setup_nt1_send(
688 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
689 struct cli_state *cli, const char *user,
690 const char *pass, size_t passlen,
691 const char *ntpass, size_t ntpasslen,
692 const char *workgroup)
694 struct tevent_req *req, *subreq;
695 struct cli_session_setup_nt1_state *state;
696 DATA_BLOB lm_response = data_blob_null;
697 DATA_BLOB nt_response = data_blob_null;
698 DATA_BLOB session_key = data_blob_null;
699 uint16_t *vwv;
700 uint8_t *bytes;
701 char *workgroup_upper;
703 req = tevent_req_create(mem_ctx, &state,
704 struct cli_session_setup_nt1_state);
705 if (req == NULL) {
706 return NULL;
708 state->cli = cli;
709 state->user = user;
710 vwv = state->vwv;
712 if (passlen == 0) {
713 /* do nothing - guest login */
714 } else if (passlen != 24) {
715 if (lp_client_ntlmv2_auth()) {
716 DATA_BLOB server_chal;
717 DATA_BLOB names_blob;
719 server_chal =
720 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
724 * note that the 'workgroup' here is a best
725 * guess - we don't know the server's domain
726 * at this point. Windows clients also don't
727 * use hostname...
729 names_blob = NTLMv2_generate_names_blob(
730 NULL, NULL, workgroup);
732 if (tevent_req_nomem(names_blob.data, req)) {
733 return tevent_req_post(req, ev);
736 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
737 &server_chal, &names_blob,
738 &lm_response, &nt_response,
739 NULL, &session_key)) {
740 data_blob_free(&names_blob);
741 tevent_req_nterror(
742 req, NT_STATUS_ACCESS_DENIED);
743 return tevent_req_post(req, ev);
745 data_blob_free(&names_blob);
747 } else {
748 uchar nt_hash[16];
749 E_md4hash(pass, nt_hash);
751 #ifdef LANMAN_ONLY
752 nt_response = data_blob_null;
753 #else
754 nt_response = data_blob(NULL, 24);
755 if (tevent_req_nomem(nt_response.data, req)) {
756 return tevent_req_post(req, ev);
759 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
760 nt_response.data);
761 #endif
762 /* non encrypted password supplied. Ignore ntpass. */
763 if (lp_client_lanman_auth()) {
765 lm_response = data_blob(NULL, 24);
766 if (tevent_req_nomem(lm_response.data, req)) {
767 return tevent_req_post(req, ev);
770 if (!SMBencrypt(pass,
771 smb1cli_conn_server_challenge(cli->conn),
772 lm_response.data)) {
774 * Oops, the LM response is
775 * invalid, just put the NT
776 * response there instead
778 data_blob_free(&lm_response);
779 lm_response = data_blob(
780 nt_response.data,
781 nt_response.length);
783 } else {
785 * LM disabled, place NT# in LM field
786 * instead
788 lm_response = data_blob(
789 nt_response.data, nt_response.length);
792 if (tevent_req_nomem(lm_response.data, req)) {
793 return tevent_req_post(req, ev);
796 session_key = data_blob(NULL, 16);
797 if (tevent_req_nomem(session_key.data, req)) {
798 return tevent_req_post(req, ev);
800 #ifdef LANMAN_ONLY
801 E_deshash(pass, session_key.data);
802 memset(&session_key.data[8], '\0', 8);
803 #else
804 SMBsesskeygen_ntv1(nt_hash, session_key.data);
805 #endif
807 } else {
808 /* pre-encrypted password supplied. Only used for
809 security=server, can't do
810 signing because we don't have original key */
812 lm_response = data_blob(pass, passlen);
813 if (tevent_req_nomem(lm_response.data, req)) {
814 return tevent_req_post(req, ev);
817 nt_response = data_blob(ntpass, ntpasslen);
818 if (tevent_req_nomem(nt_response.data, req)) {
819 return tevent_req_post(req, ev);
823 #ifdef LANMAN_ONLY
824 state->response = data_blob_talloc(
825 state, lm_response.data, lm_response.length);
826 #else
827 state->response = data_blob_talloc(
828 state, nt_response.data, nt_response.length);
829 #endif
830 if (tevent_req_nomem(state->response.data, req)) {
831 return tevent_req_post(req, ev);
834 if (session_key.data) {
835 state->session_key = data_blob_talloc(
836 state, session_key.data, session_key.length);
837 if (tevent_req_nomem(state->session_key.data, req)) {
838 return tevent_req_post(req, ev);
841 data_blob_free(&session_key);
843 SCVAL(vwv+0, 0, 0xff);
844 SCVAL(vwv+0, 1, 0);
845 SSVAL(vwv+1, 0, 0);
846 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
847 SSVAL(vwv+3, 0, 2);
848 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
849 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
850 SSVAL(vwv+7, 0, lm_response.length);
851 SSVAL(vwv+8, 0, nt_response.length);
852 SSVAL(vwv+9, 0, 0);
853 SSVAL(vwv+10, 0, 0);
854 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
856 bytes = talloc_array(state, uint8_t,
857 lm_response.length + nt_response.length);
858 if (tevent_req_nomem(bytes, req)) {
859 return tevent_req_post(req, ev);
861 if (lm_response.length != 0) {
862 memcpy(bytes, lm_response.data, lm_response.length);
864 if (nt_response.length != 0) {
865 memcpy(bytes + lm_response.length,
866 nt_response.data, nt_response.length);
868 data_blob_free(&lm_response);
869 data_blob_free(&nt_response);
871 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
872 user, strlen(user)+1, NULL);
875 * Upper case here might help some NTLMv2 implementations
877 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
878 if (tevent_req_nomem(workgroup_upper, req)) {
879 return tevent_req_post(req, ev);
881 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
882 workgroup_upper, strlen(workgroup_upper)+1,
883 NULL);
884 TALLOC_FREE(workgroup_upper);
886 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
887 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
888 if (tevent_req_nomem(bytes, req)) {
889 return tevent_req_post(req, ev);
892 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
893 talloc_get_size(bytes), bytes);
894 if (tevent_req_nomem(subreq, req)) {
895 return tevent_req_post(req, ev);
897 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
898 return req;
901 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
903 struct tevent_req *req = tevent_req_callback_data(
904 subreq, struct tevent_req);
905 struct cli_session_setup_nt1_state *state = tevent_req_data(
906 req, struct cli_session_setup_nt1_state);
907 struct cli_state *cli = state->cli;
908 uint32_t num_bytes;
909 uint8_t *in;
910 uint8_t *inhdr;
911 uint8_t *bytes;
912 uint8_t *p;
913 NTSTATUS status;
914 ssize_t ret;
915 uint8_t wct;
916 uint16_t *vwv;
918 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
919 &num_bytes, &bytes);
920 TALLOC_FREE(subreq);
921 if (!NT_STATUS_IS_OK(status)) {
922 tevent_req_nterror(req, status);
923 return;
926 inhdr = in + NBT_HDR_SIZE;
927 p = bytes;
929 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
931 status = smb_bytes_talloc_string(cli,
932 inhdr,
933 &cli->server_os,
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_type,
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 status = smb_bytes_talloc_string(cli,
956 inhdr,
957 &cli->server_domain,
959 bytes+num_bytes-p,
960 &ret);
961 if (!NT_STATUS_IS_OK(status)) {
962 tevent_req_nterror(req, status);
963 return;
965 p += ret;
967 status = cli_set_username(cli, state->user);
968 if (tevent_req_nterror(req, status)) {
969 return;
971 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
972 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
973 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
974 return;
976 if (state->session_key.data) {
977 struct smbXcli_session *session = state->cli->smb1.session;
979 status = smb1cli_session_set_session_key(session,
980 state->session_key);
981 if (tevent_req_nterror(req, status)) {
982 return;
985 tevent_req_done(req);
988 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
990 return tevent_req_simple_recv_ntstatus(req);
993 /* The following is calculated from :
994 * (smb_size-4) = 35
995 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
996 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
997 * end of packet.
1000 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1002 struct cli_sesssetup_blob_state {
1003 struct tevent_context *ev;
1004 struct cli_state *cli;
1005 DATA_BLOB blob;
1006 uint16_t max_blob_size;
1007 uint16_t vwv[12];
1008 uint8_t *buf;
1010 DATA_BLOB smb2_blob;
1011 struct iovec *recv_iov;
1013 NTSTATUS status;
1014 uint8_t *inbuf;
1015 DATA_BLOB ret_blob;
1018 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1019 struct tevent_req **psubreq);
1020 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1022 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1023 struct tevent_context *ev,
1024 struct cli_state *cli,
1025 DATA_BLOB blob)
1027 struct tevent_req *req, *subreq;
1028 struct cli_sesssetup_blob_state *state;
1029 uint32_t usable_space;
1031 req = tevent_req_create(mem_ctx, &state,
1032 struct cli_sesssetup_blob_state);
1033 if (req == NULL) {
1034 return NULL;
1036 state->ev = ev;
1037 state->blob = blob;
1038 state->cli = cli;
1040 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1041 usable_space = UINT16_MAX;
1042 } else {
1043 usable_space = cli_state_available_size(cli,
1044 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1047 if (usable_space == 0) {
1048 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1049 "(not possible to send %u bytes)\n",
1050 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1051 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1052 return tevent_req_post(req, ev);
1054 state->max_blob_size = MIN(usable_space, 0xFFFF);
1056 if (!cli_sesssetup_blob_next(state, &subreq)) {
1057 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1058 return tevent_req_post(req, ev);
1060 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1061 return req;
1064 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1065 struct tevent_req **psubreq)
1067 struct tevent_req *subreq;
1068 uint16_t thistime;
1070 thistime = MIN(state->blob.length, state->max_blob_size);
1072 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1074 state->smb2_blob.data = state->blob.data;
1075 state->smb2_blob.length = thistime;
1077 state->blob.data += thistime;
1078 state->blob.length -= thistime;
1080 subreq = smb2cli_session_setup_send(state, state->ev,
1081 state->cli->conn,
1082 state->cli->timeout,
1083 state->cli->smb2.session,
1084 0, /* in_flags */
1085 SMB2_CAP_DFS, /* in_capabilities */
1086 0, /* in_channel */
1087 0, /* in_previous_session_id */
1088 &state->smb2_blob);
1089 if (subreq == NULL) {
1090 return false;
1092 *psubreq = subreq;
1093 return true;
1096 SCVAL(state->vwv+0, 0, 0xFF);
1097 SCVAL(state->vwv+0, 1, 0);
1098 SSVAL(state->vwv+1, 0, 0);
1099 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1100 SSVAL(state->vwv+3, 0, 2);
1101 SSVAL(state->vwv+4, 0, 1);
1102 SIVAL(state->vwv+5, 0, 0);
1104 SSVAL(state->vwv+7, 0, thistime);
1106 SSVAL(state->vwv+8, 0, 0);
1107 SSVAL(state->vwv+9, 0, 0);
1108 SIVAL(state->vwv+10, 0,
1109 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1111 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1112 thistime);
1113 if (state->buf == NULL) {
1114 return false;
1116 state->blob.data += thistime;
1117 state->blob.length -= thistime;
1119 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1120 "Unix", 5, NULL);
1121 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1122 "Samba", 6, NULL);
1123 if (state->buf == NULL) {
1124 return false;
1126 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1127 12, state->vwv,
1128 talloc_get_size(state->buf), state->buf);
1129 if (subreq == NULL) {
1130 return false;
1132 *psubreq = subreq;
1133 return true;
1136 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1138 struct tevent_req *req = tevent_req_callback_data(
1139 subreq, struct tevent_req);
1140 struct cli_sesssetup_blob_state *state = tevent_req_data(
1141 req, struct cli_sesssetup_blob_state);
1142 struct cli_state *cli = state->cli;
1143 uint8_t wct;
1144 uint16_t *vwv;
1145 uint32_t num_bytes;
1146 uint8_t *bytes;
1147 NTSTATUS status;
1148 uint8_t *p;
1149 uint16_t blob_length;
1150 uint8_t *in;
1151 uint8_t *inhdr;
1152 ssize_t ret;
1154 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1155 status = smb2cli_session_setup_recv(subreq, state,
1156 &state->recv_iov,
1157 &state->ret_blob);
1158 } else {
1159 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1160 &num_bytes, &bytes);
1161 TALLOC_FREE(state->buf);
1163 TALLOC_FREE(subreq);
1164 if (!NT_STATUS_IS_OK(status)
1165 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1166 tevent_req_nterror(req, status);
1167 return;
1170 state->status = status;
1172 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1173 goto next;
1176 state->inbuf = in;
1177 inhdr = in + NBT_HDR_SIZE;
1178 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1180 blob_length = SVAL(vwv+3, 0);
1181 if (blob_length > num_bytes) {
1182 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1183 return;
1185 state->ret_blob = data_blob_const(bytes, blob_length);
1187 p = bytes + blob_length;
1189 status = smb_bytes_talloc_string(cli,
1190 inhdr,
1191 &cli->server_os,
1193 bytes+num_bytes-p,
1194 &ret);
1196 if (!NT_STATUS_IS_OK(status)) {
1197 tevent_req_nterror(req, status);
1198 return;
1200 p += ret;
1202 status = smb_bytes_talloc_string(cli,
1203 inhdr,
1204 &cli->server_type,
1206 bytes+num_bytes-p,
1207 &ret);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 tevent_req_nterror(req, status);
1211 return;
1213 p += ret;
1215 status = smb_bytes_talloc_string(cli,
1216 inhdr,
1217 &cli->server_domain,
1219 bytes+num_bytes-p,
1220 &ret);
1222 if (!NT_STATUS_IS_OK(status)) {
1223 tevent_req_nterror(req, status);
1224 return;
1226 p += ret;
1228 next:
1229 if (state->blob.length != 0) {
1231 * More to send
1233 if (!cli_sesssetup_blob_next(state, &subreq)) {
1234 tevent_req_oom(req);
1235 return;
1237 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1238 return;
1240 tevent_req_done(req);
1243 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1244 TALLOC_CTX *mem_ctx,
1245 DATA_BLOB *pblob,
1246 uint8_t **pinbuf,
1247 struct iovec **precv_iov)
1249 struct cli_sesssetup_blob_state *state = tevent_req_data(
1250 req, struct cli_sesssetup_blob_state);
1251 NTSTATUS status;
1252 uint8_t *inbuf;
1253 struct iovec *recv_iov;
1255 if (tevent_req_is_nterror(req, &status)) {
1256 TALLOC_FREE(state->cli->smb2.session);
1257 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1258 return status;
1261 inbuf = talloc_move(mem_ctx, &state->inbuf);
1262 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1263 if (pblob != NULL) {
1264 *pblob = state->ret_blob;
1266 if (pinbuf != NULL) {
1267 *pinbuf = inbuf;
1269 if (precv_iov != NULL) {
1270 *precv_iov = recv_iov;
1272 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1273 return state->status;
1276 #ifdef HAVE_KRB5
1278 /****************************************************************************
1279 Use in-memory credentials cache
1280 ****************************************************************************/
1282 static void use_in_memory_ccache(void) {
1283 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1286 /****************************************************************************
1287 Do a spnego/kerberos encrypted session setup.
1288 ****************************************************************************/
1290 struct cli_session_setup_kerberos_state {
1291 struct cli_state *cli;
1292 DATA_BLOB negTokenTarg;
1293 DATA_BLOB session_key_krb5;
1294 ADS_STATUS ads_status;
1297 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1299 static struct tevent_req *cli_session_setup_kerberos_send(
1300 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1301 const char *principal)
1303 struct tevent_req *req, *subreq;
1304 struct cli_session_setup_kerberos_state *state;
1305 int rc;
1307 DEBUG(2,("Doing kerberos session setup\n"));
1309 req = tevent_req_create(mem_ctx, &state,
1310 struct cli_session_setup_kerberos_state);
1311 if (req == NULL) {
1312 return NULL;
1314 state->cli = cli;
1315 state->ads_status = ADS_SUCCESS;
1318 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1319 * we have to acquire a ticket. To be fixed later :-)
1321 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1322 &state->session_key_krb5, 0, NULL, NULL);
1323 if (rc) {
1324 DEBUG(1, ("cli_session_setup_kerberos: "
1325 "spnego_gen_krb5_negTokenInit failed: %s\n",
1326 error_message(rc)));
1327 state->ads_status = ADS_ERROR_KRB5(rc);
1328 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1329 return tevent_req_post(req, ev);
1332 #if 0
1333 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1334 state->negTokenTarg.length);
1335 #endif
1337 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1338 state->cli->smb2.session = smbXcli_session_create(cli,
1339 cli->conn);
1340 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1341 return tevent_req_post(req, ev);
1345 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1346 if (tevent_req_nomem(subreq, req)) {
1347 return tevent_req_post(req, ev);
1349 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1350 return req;
1353 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1355 struct tevent_req *req = tevent_req_callback_data(
1356 subreq, struct tevent_req);
1357 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1358 req, struct cli_session_setup_kerberos_state);
1359 uint8_t *inbuf = NULL;
1360 struct iovec *recv_iov = NULL;
1361 NTSTATUS status;
1363 status = cli_sesssetup_blob_recv(subreq, state,
1364 NULL, &inbuf, &recv_iov);
1365 TALLOC_FREE(subreq);
1366 if (!NT_STATUS_IS_OK(status)) {
1367 tevent_req_nterror(req, status);
1368 return;
1371 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1372 struct smbXcli_session *session = state->cli->smb2.session;
1373 status = smb2cli_session_set_session_key(session,
1374 state->session_key_krb5,
1375 recv_iov);
1376 if (tevent_req_nterror(req, status)) {
1377 return;
1379 } else {
1380 struct smbXcli_session *session = state->cli->smb1.session;
1382 status = smb1cli_session_set_session_key(session,
1383 state->session_key_krb5);
1384 if (tevent_req_nterror(req, status)) {
1385 return;
1388 if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5,
1389 data_blob_null)
1390 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1391 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1392 return;
1396 tevent_req_done(req);
1399 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1401 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1402 req, struct cli_session_setup_kerberos_state);
1403 NTSTATUS status;
1405 if (tevent_req_is_nterror(req, &status)) {
1406 return ADS_ERROR_NT(status);
1408 return state->ads_status;
1411 #endif /* HAVE_KRB5 */
1413 /****************************************************************************
1414 Do a spnego/NTLMSSP encrypted session setup.
1415 ****************************************************************************/
1417 struct cli_session_setup_ntlmssp_state {
1418 struct tevent_context *ev;
1419 struct cli_state *cli;
1420 struct ntlmssp_state *ntlmssp_state;
1421 int turn;
1422 DATA_BLOB blob_out;
1425 static int cli_session_setup_ntlmssp_state_destructor(
1426 struct cli_session_setup_ntlmssp_state *state)
1428 if (state->ntlmssp_state != NULL) {
1429 TALLOC_FREE(state->ntlmssp_state);
1431 return 0;
1434 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1436 static struct tevent_req *cli_session_setup_ntlmssp_send(
1437 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1438 const char *user, const char *pass, const char *domain)
1440 struct tevent_req *req, *subreq;
1441 struct cli_session_setup_ntlmssp_state *state;
1442 NTSTATUS status;
1443 DATA_BLOB blob_out;
1444 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1446 req = tevent_req_create(mem_ctx, &state,
1447 struct cli_session_setup_ntlmssp_state);
1448 if (req == NULL) {
1449 return NULL;
1451 state->ev = ev;
1452 state->cli = cli;
1453 state->turn = 1;
1455 state->ntlmssp_state = NULL;
1456 talloc_set_destructor(
1457 state, cli_session_setup_ntlmssp_state_destructor);
1459 status = ntlmssp_client_start(state,
1460 lp_netbios_name(),
1461 lp_workgroup(),
1462 lp_client_ntlmv2_auth(),
1463 &state->ntlmssp_state);
1464 if (!NT_STATUS_IS_OK(status)) {
1465 goto fail;
1467 ntlmssp_want_feature(state->ntlmssp_state,
1468 NTLMSSP_FEATURE_SESSION_KEY);
1469 if (cli->use_ccache) {
1470 ntlmssp_want_feature(state->ntlmssp_state,
1471 NTLMSSP_FEATURE_CCACHE);
1473 status = ntlmssp_set_username(state->ntlmssp_state, user);
1474 if (!NT_STATUS_IS_OK(status)) {
1475 goto fail;
1477 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1478 if (!NT_STATUS_IS_OK(status)) {
1479 goto fail;
1481 if (cli->pw_nt_hash) {
1482 status = ntlmssp_set_password_hash(state->ntlmssp_state, pass);
1483 } else {
1484 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1486 if (!NT_STATUS_IS_OK(status)) {
1487 goto fail;
1489 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1490 &blob_out);
1491 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1492 goto fail;
1495 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1496 data_blob_free(&blob_out);
1498 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1499 state->cli->smb2.session = smbXcli_session_create(cli,
1500 cli->conn);
1501 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1502 return tevent_req_post(req, ev);
1506 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1507 if (tevent_req_nomem(subreq, req)) {
1508 return tevent_req_post(req, ev);
1510 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1511 return req;
1512 fail:
1513 tevent_req_nterror(req, status);
1514 return tevent_req_post(req, ev);
1517 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1519 struct tevent_req *req = tevent_req_callback_data(
1520 subreq, struct tevent_req);
1521 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1522 req, struct cli_session_setup_ntlmssp_state);
1523 DATA_BLOB blob_in, msg_in, blob_out;
1524 uint8_t *inbuf = NULL;
1525 struct iovec *recv_iov = NULL;
1526 bool parse_ret;
1527 NTSTATUS status;
1529 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1530 &inbuf, &recv_iov);
1531 TALLOC_FREE(subreq);
1532 data_blob_free(&state->blob_out);
1534 if (NT_STATUS_IS_OK(status)) {
1535 if (state->cli->server_domain[0] == '\0') {
1536 TALLOC_FREE(state->cli->server_domain);
1537 state->cli->server_domain = talloc_strdup(state->cli,
1538 state->ntlmssp_state->server.netbios_domain);
1539 if (state->cli->server_domain == NULL) {
1540 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1541 return;
1545 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1546 struct smbXcli_session *session = state->cli->smb2.session;
1548 if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
1550 * Windows server does not set the
1551 * SMB2_SESSION_FLAG_IS_GUEST nor
1552 * SMB2_SESSION_FLAG_IS_NULL flag.
1554 * This fix makes sure we do not try
1555 * to verify a signature on the final
1556 * session setup response.
1558 TALLOC_FREE(state->ntlmssp_state);
1559 tevent_req_done(req);
1560 return;
1563 status = smb2cli_session_set_session_key(session,
1564 state->ntlmssp_state->session_key,
1565 recv_iov);
1566 if (tevent_req_nterror(req, status)) {
1567 return;
1569 } else {
1570 struct smbXcli_session *session = state->cli->smb1.session;
1572 status = smb1cli_session_set_session_key(session,
1573 state->ntlmssp_state->session_key);
1574 if (tevent_req_nterror(req, status)) {
1575 return;
1578 if (smb1cli_conn_activate_signing(
1579 state->cli->conn, state->ntlmssp_state->session_key,
1580 data_blob_null)
1581 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1582 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1583 return;
1586 TALLOC_FREE(state->ntlmssp_state);
1587 tevent_req_done(req);
1588 return;
1590 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1591 tevent_req_nterror(req, status);
1592 return;
1595 if (blob_in.length == 0) {
1596 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1597 return;
1600 if ((state->turn == 1)
1601 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1602 DATA_BLOB tmp_blob = data_blob_null;
1603 /* the server might give us back two challenges */
1604 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1605 &tmp_blob);
1606 data_blob_free(&tmp_blob);
1607 } else {
1608 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1609 OID_NTLMSSP, &msg_in);
1611 state->turn += 1;
1613 if (!parse_ret) {
1614 DEBUG(3,("Failed to parse auth response\n"));
1615 if (NT_STATUS_IS_OK(status)
1616 || NT_STATUS_EQUAL(status,
1617 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1618 tevent_req_nterror(
1619 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1620 return;
1624 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1626 if (!NT_STATUS_IS_OK(status)
1627 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1628 TALLOC_FREE(state->ntlmssp_state);
1629 tevent_req_nterror(req, status);
1630 return;
1633 state->blob_out = spnego_gen_auth(state, blob_out);
1634 if (tevent_req_nomem(state->blob_out.data, req)) {
1635 return;
1638 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1639 state->blob_out);
1640 if (tevent_req_nomem(subreq, req)) {
1641 return;
1643 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1646 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1648 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1649 req, struct cli_session_setup_ntlmssp_state);
1650 NTSTATUS status;
1652 if (tevent_req_is_nterror(req, &status)) {
1653 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1654 return status;
1656 return NT_STATUS_OK;
1659 #ifdef HAVE_KRB5
1661 static char *cli_session_setup_get_principal(
1662 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1663 const char *remote_name, const char *dest_realm)
1665 char *principal = NULL;
1667 if (!lp_client_use_spnego_principal() ||
1668 strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1669 spnego_principal = NULL;
1671 if (spnego_principal != NULL) {
1672 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1673 "principal %s\n", spnego_principal));
1674 return talloc_strdup(mem_ctx, spnego_principal);
1676 if (is_ipaddress(remote_name) ||
1677 strequal(remote_name, STAR_SMBSERVER)) {
1678 return NULL;
1681 DEBUG(3, ("cli_session_setup_spnego: using target "
1682 "hostname not SPNEGO principal\n"));
1684 if (dest_realm) {
1685 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1686 if (realm == NULL) {
1687 return NULL;
1689 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1690 remote_name, realm);
1691 TALLOC_FREE(realm);
1692 } else {
1693 principal = kerberos_get_principal_from_service_hostname(
1694 talloc_tos(), "cifs", remote_name, lp_realm());
1696 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1697 principal ? principal : "<null>"));
1699 return principal;
1701 #endif
1703 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1704 const char *principal)
1706 char *account, *p;
1708 account = talloc_strdup(mem_ctx, principal);
1709 if (account == NULL) {
1710 return NULL;
1712 p = strchr_m(account, '@');
1713 if (p != NULL) {
1714 *p = '\0';
1716 return account;
1719 /****************************************************************************
1720 Do a spnego encrypted session setup.
1722 user_domain: The shortname of the domain the user/machine is a member of.
1723 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1724 ****************************************************************************/
1726 struct cli_session_setup_spnego_state {
1727 struct tevent_context *ev;
1728 struct cli_state *cli;
1729 const char *user;
1730 const char *account;
1731 const char *pass;
1732 const char *user_domain;
1733 const char *dest_realm;
1734 ADS_STATUS result;
1737 #ifdef HAVE_KRB5
1738 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1739 #endif
1741 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1743 static struct tevent_req *cli_session_setup_spnego_send(
1744 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1745 const char *user, const char *pass, const char *user_domain,
1746 const char *dest_realm)
1748 struct tevent_req *req, *subreq;
1749 struct cli_session_setup_spnego_state *state;
1750 char *principal = NULL;
1751 char *OIDs[ASN1_MAX_OIDS];
1752 int i;
1753 const DATA_BLOB *server_blob;
1754 NTSTATUS status;
1756 req = tevent_req_create(mem_ctx, &state,
1757 struct cli_session_setup_spnego_state);
1758 if (req == NULL) {
1759 return NULL;
1761 state->ev = ev;
1762 state->cli = cli;
1763 state->user = user;
1764 state->pass = pass;
1765 state->user_domain = user_domain;
1766 state->dest_realm = dest_realm;
1768 state->account = cli_session_setup_get_account(state, user);
1769 if (tevent_req_nomem(state->account, req)) {
1770 return tevent_req_post(req, ev);
1773 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1775 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1776 (unsigned long)server_blob->length));
1778 /* the server might not even do spnego */
1779 if (server_blob->length == 0) {
1780 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1781 goto ntlmssp;
1784 #if 0
1785 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1786 #endif
1788 /* The server sent us the first part of the SPNEGO exchange in the
1789 * negprot reply. It is WRONG to depend on the principal sent in the
1790 * negprot reply, but right now we do it. If we don't receive one,
1791 * we try to best guess, then fall back to NTLM. */
1792 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1793 &principal, NULL) ||
1794 OIDs[0] == NULL) {
1795 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1796 tevent_req_done(req);
1797 return tevent_req_post(req, ev);
1800 /* make sure the server understands kerberos */
1801 for (i=0;OIDs[i];i++) {
1802 if (i == 0)
1803 DEBUG(3,("got OID=%s\n", OIDs[i]));
1804 else
1805 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1806 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1807 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1808 cli->got_kerberos_mechanism = True;
1810 talloc_free(OIDs[i]);
1813 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1815 status = cli_set_username(cli, user);
1816 if (!NT_STATUS_IS_OK(status)) {
1817 state->result = ADS_ERROR_NT(status);
1818 tevent_req_done(req);
1819 return tevent_req_post(req, ev);
1822 #ifdef HAVE_KRB5
1823 /* If password is set we reauthenticate to kerberos server
1824 * and do not store results */
1826 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1827 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
1828 char *tmp;
1830 if (pass && *pass) {
1831 int ret;
1833 use_in_memory_ccache();
1834 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1836 if (ret){
1837 TALLOC_FREE(principal);
1838 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1839 if (cli->fallback_after_kerberos)
1840 goto ntlmssp;
1841 state->result = ADS_ERROR_KRB5(ret);
1842 tevent_req_done(req);
1843 return tevent_req_post(req, ev);
1847 tmp = cli_session_setup_get_principal(
1848 talloc_tos(), principal, remote_name, dest_realm);
1849 TALLOC_FREE(principal);
1850 principal = tmp;
1852 if (principal) {
1853 subreq = cli_session_setup_kerberos_send(
1854 state, ev, cli, principal);
1855 if (tevent_req_nomem(subreq, req)) {
1856 return tevent_req_post(req, ev);
1858 tevent_req_set_callback(
1859 subreq, cli_session_setup_spnego_done_krb,
1860 req);
1861 return req;
1864 #endif
1866 ntlmssp:
1867 subreq = cli_session_setup_ntlmssp_send(
1868 state, ev, cli, state->account, pass, user_domain);
1869 if (tevent_req_nomem(subreq, req)) {
1870 return tevent_req_post(req, ev);
1872 tevent_req_set_callback(
1873 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1874 return req;
1877 #ifdef HAVE_KRB5
1878 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1880 struct tevent_req *req = tevent_req_callback_data(
1881 subreq, struct tevent_req);
1882 struct cli_session_setup_spnego_state *state = tevent_req_data(
1883 req, struct cli_session_setup_spnego_state);
1885 state->result = cli_session_setup_kerberos_recv(subreq);
1886 TALLOC_FREE(subreq);
1888 if (ADS_ERR_OK(state->result) ||
1889 !state->cli->fallback_after_kerberos) {
1890 tevent_req_done(req);
1891 return;
1894 subreq = cli_session_setup_ntlmssp_send(
1895 state, state->ev, state->cli, state->account, state->pass,
1896 state->user_domain);
1897 if (tevent_req_nomem(subreq, req)) {
1898 return;
1900 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1901 req);
1903 #endif
1905 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1907 struct tevent_req *req = tevent_req_callback_data(
1908 subreq, struct tevent_req);
1909 struct cli_session_setup_spnego_state *state = tevent_req_data(
1910 req, struct cli_session_setup_spnego_state);
1911 NTSTATUS status;
1913 status = cli_session_setup_ntlmssp_recv(subreq);
1914 TALLOC_FREE(subreq);
1915 state->result = ADS_ERROR_NT(status);
1916 tevent_req_done(req);
1919 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1921 struct cli_session_setup_spnego_state *state = tevent_req_data(
1922 req, struct cli_session_setup_spnego_state);
1924 return state->result;
1927 struct cli_session_setup_state {
1928 uint8_t dummy;
1931 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1932 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1933 static void cli_session_setup_done_guest(struct tevent_req *subreq);
1934 static void cli_session_setup_done_plain(struct tevent_req *subreq);
1935 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1937 /****************************************************************************
1938 Send a session setup. The username and workgroup is in UNIX character
1939 format and must be converted to DOS codepage format before sending. If the
1940 password is in plaintext, the same should be done.
1941 ****************************************************************************/
1943 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1944 struct tevent_context *ev,
1945 struct cli_state *cli,
1946 const char *user,
1947 const char *pass, int passlen,
1948 const char *ntpass, int ntpasslen,
1949 const char *workgroup)
1951 struct tevent_req *req, *subreq;
1952 struct cli_session_setup_state *state;
1953 char *p;
1954 char *user2;
1955 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1957 req = tevent_req_create(mem_ctx, &state,
1958 struct cli_session_setup_state);
1959 if (req == NULL) {
1960 return NULL;
1963 if (user) {
1964 user2 = talloc_strdup(state, user);
1965 } else {
1966 user2 = talloc_strdup(state, "");
1968 if (user2 == NULL) {
1969 tevent_req_oom(req);
1970 return tevent_req_post(req, ev);
1973 if (!workgroup) {
1974 workgroup = "";
1977 /* allow for workgroups as part of the username */
1978 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1979 (p=strchr_m(user2,*lp_winbind_separator()))) {
1980 *p = 0;
1981 user = p+1;
1982 if (!strupper_m(user2)) {
1983 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1984 return tevent_req_post(req, ev);
1986 workgroup = user2;
1989 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1990 tevent_req_done(req);
1991 return tevent_req_post(req, ev);
1994 /* now work out what sort of session setup we are going to
1995 do. I have split this into separate functions to make the
1996 flow a bit easier to understand (tridge) */
1998 /* if its an older server then we have to use the older request format */
2000 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2001 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2002 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2003 " or 'client ntlmv2 auth = yes'\n"));
2004 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2005 return tevent_req_post(req, ev);
2008 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2009 !lp_client_plaintext_auth() && (*pass)) {
2010 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2011 " or 'client ntlmv2 auth = yes'\n"));
2012 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2013 return tevent_req_post(req, ev);
2016 subreq = cli_session_setup_lanman2_send(
2017 state, ev, cli, user, pass, passlen, workgroup);
2018 if (tevent_req_nomem(subreq, req)) {
2019 return tevent_req_post(req, ev);
2021 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2022 req);
2023 return req;
2026 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2027 const char *remote_realm = cli_state_remote_realm(cli);
2029 subreq = cli_session_setup_spnego_send(
2030 state, ev, cli, user, pass, workgroup, remote_realm);
2031 if (tevent_req_nomem(subreq, req)) {
2032 return tevent_req_post(req, ev);
2034 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2035 req);
2036 return req;
2039 /* if no user is supplied then we have to do an anonymous connection.
2040 passwords are ignored */
2042 if (!user || !*user) {
2043 subreq = cli_session_setup_guest_send(state, ev, cli);
2044 if (tevent_req_nomem(subreq, req)) {
2045 return tevent_req_post(req, ev);
2047 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2048 req);
2049 return req;
2052 /* if the server is share level then send a plaintext null
2053 password at this point. The password is sent in the tree
2054 connect */
2056 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2057 subreq = cli_session_setup_plain_send(
2058 state, ev, cli, user, "", workgroup);
2059 if (tevent_req_nomem(subreq, req)) {
2060 return tevent_req_post(req, ev);
2062 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2063 req);
2064 return req;
2067 /* if the server doesn't support encryption then we have to use
2068 plaintext. The second password is ignored */
2070 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2071 if (!lp_client_plaintext_auth() && (*pass)) {
2072 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2073 " or 'client ntlmv2 auth = yes'\n"));
2074 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2075 return tevent_req_post(req, ev);
2077 subreq = cli_session_setup_plain_send(
2078 state, ev, cli, user, pass, workgroup);
2079 if (tevent_req_nomem(subreq, req)) {
2080 return tevent_req_post(req, ev);
2082 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2083 req);
2084 return req;
2087 /* if the server supports extended security then use SPNEGO */
2089 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2090 const char *remote_realm = cli_state_remote_realm(cli);
2092 subreq = cli_session_setup_spnego_send(
2093 state, ev, cli, user, pass, workgroup, remote_realm);
2094 if (tevent_req_nomem(subreq, req)) {
2095 return tevent_req_post(req, ev);
2097 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2098 req);
2099 return req;
2100 } else {
2101 /* otherwise do a NT1 style session setup */
2103 subreq = cli_session_setup_nt1_send(
2104 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2105 workgroup);
2106 if (tevent_req_nomem(subreq, req)) {
2107 return tevent_req_post(req, ev);
2109 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2110 req);
2111 return req;
2114 tevent_req_done(req);
2115 return tevent_req_post(req, ev);
2118 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2120 struct tevent_req *req = tevent_req_callback_data(
2121 subreq, struct tevent_req);
2122 NTSTATUS status;
2124 status = cli_session_setup_lanman2_recv(subreq);
2125 TALLOC_FREE(subreq);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 tevent_req_nterror(req, status);
2128 return;
2130 tevent_req_done(req);
2133 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2135 struct tevent_req *req = tevent_req_callback_data(
2136 subreq, struct tevent_req);
2137 ADS_STATUS status;
2139 status = cli_session_setup_spnego_recv(subreq);
2140 TALLOC_FREE(subreq);
2141 if (!ADS_ERR_OK(status)) {
2142 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2143 tevent_req_nterror(req, ads_ntstatus(status));
2144 return;
2146 tevent_req_done(req);
2149 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2151 struct tevent_req *req = tevent_req_callback_data(
2152 subreq, struct tevent_req);
2153 NTSTATUS status;
2155 status = cli_session_setup_guest_recv(subreq);
2156 TALLOC_FREE(subreq);
2157 if (!NT_STATUS_IS_OK(status)) {
2158 tevent_req_nterror(req, status);
2159 return;
2161 tevent_req_done(req);
2164 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2166 struct tevent_req *req = tevent_req_callback_data(
2167 subreq, struct tevent_req);
2168 NTSTATUS status;
2170 status = cli_session_setup_plain_recv(subreq);
2171 TALLOC_FREE(subreq);
2172 if (!NT_STATUS_IS_OK(status)) {
2173 tevent_req_nterror(req, status);
2174 return;
2176 tevent_req_done(req);
2179 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2181 struct tevent_req *req = tevent_req_callback_data(
2182 subreq, struct tevent_req);
2183 NTSTATUS status;
2185 status = cli_session_setup_nt1_recv(subreq);
2186 TALLOC_FREE(subreq);
2187 if (!NT_STATUS_IS_OK(status)) {
2188 DEBUG(3, ("cli_session_setup: NT1 session setup "
2189 "failed: %s\n", nt_errstr(status)));
2190 tevent_req_nterror(req, status);
2191 return;
2193 tevent_req_done(req);
2196 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2198 return tevent_req_simple_recv_ntstatus(req);
2201 NTSTATUS cli_session_setup(struct cli_state *cli,
2202 const char *user,
2203 const char *pass, int passlen,
2204 const char *ntpass, int ntpasslen,
2205 const char *workgroup)
2207 struct tevent_context *ev;
2208 struct tevent_req *req;
2209 NTSTATUS status = NT_STATUS_NO_MEMORY;
2211 if (smbXcli_conn_has_async_calls(cli->conn)) {
2212 return NT_STATUS_INVALID_PARAMETER;
2214 ev = samba_tevent_context_init(talloc_tos());
2215 if (ev == NULL) {
2216 goto fail;
2218 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2219 ntpass, ntpasslen, workgroup);
2220 if (req == NULL) {
2221 goto fail;
2223 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2224 goto fail;
2226 status = cli_session_setup_recv(req);
2227 fail:
2228 TALLOC_FREE(ev);
2229 return status;
2232 /****************************************************************************
2233 Send a uloggoff.
2234 *****************************************************************************/
2236 struct cli_ulogoff_state {
2237 struct cli_state *cli;
2238 uint16_t vwv[3];
2241 static void cli_ulogoff_done(struct tevent_req *subreq);
2243 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2244 struct tevent_context *ev,
2245 struct cli_state *cli)
2247 struct tevent_req *req, *subreq;
2248 struct cli_ulogoff_state *state;
2250 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2251 if (req == NULL) {
2252 return NULL;
2254 state->cli = cli;
2256 SCVAL(state->vwv+0, 0, 0xFF);
2257 SCVAL(state->vwv+1, 0, 0);
2258 SSVAL(state->vwv+2, 0, 0);
2260 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2261 0, NULL);
2262 if (tevent_req_nomem(subreq, req)) {
2263 return tevent_req_post(req, ev);
2265 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2266 return req;
2269 static void cli_ulogoff_done(struct tevent_req *subreq)
2271 struct tevent_req *req = tevent_req_callback_data(
2272 subreq, struct tevent_req);
2273 struct cli_ulogoff_state *state = tevent_req_data(
2274 req, struct cli_ulogoff_state);
2275 NTSTATUS status;
2277 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2278 if (!NT_STATUS_IS_OK(status)) {
2279 tevent_req_nterror(req, status);
2280 return;
2282 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2283 tevent_req_done(req);
2286 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2288 return tevent_req_simple_recv_ntstatus(req);
2291 NTSTATUS cli_ulogoff(struct cli_state *cli)
2293 struct tevent_context *ev;
2294 struct tevent_req *req;
2295 NTSTATUS status = NT_STATUS_NO_MEMORY;
2297 if (smbXcli_conn_has_async_calls(cli->conn)) {
2298 return NT_STATUS_INVALID_PARAMETER;
2300 ev = samba_tevent_context_init(talloc_tos());
2301 if (ev == NULL) {
2302 goto fail;
2304 req = cli_ulogoff_send(ev, ev, cli);
2305 if (req == NULL) {
2306 goto fail;
2308 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2309 goto fail;
2311 status = cli_ulogoff_recv(req);
2312 fail:
2313 TALLOC_FREE(ev);
2314 return status;
2317 /****************************************************************************
2318 Send a tconX.
2319 ****************************************************************************/
2321 struct cli_tcon_andx_state {
2322 struct cli_state *cli;
2323 uint16_t vwv[4];
2324 struct iovec bytes;
2327 static void cli_tcon_andx_done(struct tevent_req *subreq);
2329 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2330 struct tevent_context *ev,
2331 struct cli_state *cli,
2332 const char *share, const char *dev,
2333 const char *pass, int passlen,
2334 struct tevent_req **psmbreq)
2336 struct tevent_req *req, *subreq;
2337 struct cli_tcon_andx_state *state;
2338 uint8_t p24[24];
2339 uint16_t *vwv;
2340 char *tmp = NULL;
2341 uint8_t *bytes;
2342 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2343 uint16_t tcon_flags = 0;
2345 *psmbreq = NULL;
2347 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2348 if (req == NULL) {
2349 return NULL;
2351 state->cli = cli;
2352 vwv = state->vwv;
2354 cli->share = talloc_strdup(cli, share);
2355 if (!cli->share) {
2356 return NULL;
2359 /* in user level security don't send a password now */
2360 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2361 passlen = 1;
2362 pass = "";
2363 } else if (pass == NULL) {
2364 DEBUG(1, ("Server not using user level security and no "
2365 "password supplied.\n"));
2366 goto access_denied;
2369 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2370 *pass && passlen != 24) {
2371 if (!lp_client_lanman_auth()) {
2372 DEBUG(1, ("Server requested LANMAN password "
2373 "(share-level security) but "
2374 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2375 goto access_denied;
2379 * Non-encrypted passwords - convert to DOS codepage before
2380 * encryption.
2382 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2383 passlen = 24;
2384 pass = (const char *)p24;
2385 } else {
2386 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2387 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2388 == 0) {
2389 uint8_t *tmp_pass;
2391 if (!lp_client_plaintext_auth() && (*pass)) {
2392 DEBUG(1, ("Server requested PLAINTEXT "
2393 "password but "
2394 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2395 goto access_denied;
2399 * Non-encrypted passwords - convert to DOS codepage
2400 * before using.
2402 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2403 if (tevent_req_nomem(tmp_pass, req)) {
2404 return tevent_req_post(req, ev);
2406 tmp_pass = trans2_bytes_push_str(tmp_pass,
2407 false, /* always DOS */
2408 pass,
2409 passlen,
2410 NULL);
2411 if (tevent_req_nomem(tmp_pass, req)) {
2412 return tevent_req_post(req, ev);
2414 pass = (const char *)tmp_pass;
2415 passlen = talloc_get_size(tmp_pass);
2419 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2420 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2422 SCVAL(vwv+0, 0, 0xFF);
2423 SCVAL(vwv+0, 1, 0);
2424 SSVAL(vwv+1, 0, 0);
2425 SSVAL(vwv+2, 0, tcon_flags);
2426 SSVAL(vwv+3, 0, passlen);
2428 if (passlen && pass) {
2429 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2430 } else {
2431 bytes = talloc_array(state, uint8_t, 0);
2435 * Add the sharename
2437 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2438 smbXcli_conn_remote_name(cli->conn), share);
2439 if (tmp == NULL) {
2440 TALLOC_FREE(req);
2441 return NULL;
2443 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2444 NULL);
2445 TALLOC_FREE(tmp);
2448 * Add the devicetype
2450 tmp = talloc_strdup_upper(talloc_tos(), dev);
2451 if (tmp == NULL) {
2452 TALLOC_FREE(req);
2453 return NULL;
2455 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2456 TALLOC_FREE(tmp);
2458 if (bytes == NULL) {
2459 TALLOC_FREE(req);
2460 return NULL;
2463 state->bytes.iov_base = (void *)bytes;
2464 state->bytes.iov_len = talloc_get_size(bytes);
2466 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2467 1, &state->bytes);
2468 if (subreq == NULL) {
2469 TALLOC_FREE(req);
2470 return NULL;
2472 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2473 *psmbreq = subreq;
2474 return req;
2476 access_denied:
2477 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2478 return tevent_req_post(req, ev);
2481 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2482 struct tevent_context *ev,
2483 struct cli_state *cli,
2484 const char *share, const char *dev,
2485 const char *pass, int passlen)
2487 struct tevent_req *req, *subreq;
2488 NTSTATUS status;
2490 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2491 &subreq);
2492 if (req == NULL) {
2493 return NULL;
2495 if (subreq == NULL) {
2496 return req;
2498 status = smb1cli_req_chain_submit(&subreq, 1);
2499 if (!NT_STATUS_IS_OK(status)) {
2500 tevent_req_nterror(req, status);
2501 return tevent_req_post(req, ev);
2503 return req;
2506 static void cli_tcon_andx_done(struct tevent_req *subreq)
2508 struct tevent_req *req = tevent_req_callback_data(
2509 subreq, struct tevent_req);
2510 struct cli_tcon_andx_state *state = tevent_req_data(
2511 req, struct cli_tcon_andx_state);
2512 struct cli_state *cli = state->cli;
2513 uint8_t *in;
2514 uint8_t *inhdr;
2515 uint8_t wct;
2516 uint16_t *vwv;
2517 uint32_t num_bytes;
2518 uint8_t *bytes;
2519 NTSTATUS status;
2520 uint16_t optional_support = 0;
2522 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2523 &num_bytes, &bytes);
2524 TALLOC_FREE(subreq);
2525 if (!NT_STATUS_IS_OK(status)) {
2526 tevent_req_nterror(req, status);
2527 return;
2530 inhdr = in + NBT_HDR_SIZE;
2532 if (num_bytes) {
2533 if (clistr_pull_talloc(cli,
2534 (const char *)inhdr,
2535 SVAL(inhdr, HDR_FLG2),
2536 &cli->dev,
2537 bytes,
2538 num_bytes,
2539 STR_TERMINATE|STR_ASCII) == -1) {
2540 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2541 return;
2543 } else {
2544 cli->dev = talloc_strdup(cli, "");
2545 if (cli->dev == NULL) {
2546 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2547 return;
2551 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2552 /* almost certainly win95 - enable bug fixes */
2553 cli->win95 = True;
2557 * Make sure that we have the optional support 16-bit field. WCT > 2.
2558 * Avoids issues when connecting to Win9x boxes sharing files
2561 cli->dfsroot = false;
2563 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2564 optional_support = SVAL(vwv+2, 0);
2567 if (optional_support & SMB_SHARE_IN_DFS) {
2568 cli->dfsroot = true;
2571 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2572 smb1cli_session_protect_session_key(cli->smb1.session);
2575 cli_state_set_tid(cli, SVAL(inhdr, HDR_TID));
2576 tevent_req_done(req);
2579 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2581 return tevent_req_simple_recv_ntstatus(req);
2584 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2585 const char *dev, const char *pass, int passlen)
2587 TALLOC_CTX *frame = talloc_stackframe();
2588 struct tevent_context *ev;
2589 struct tevent_req *req;
2590 NTSTATUS status = NT_STATUS_NO_MEMORY;
2592 if (smbXcli_conn_has_async_calls(cli->conn)) {
2594 * Can't use sync call while an async call is in flight
2596 status = NT_STATUS_INVALID_PARAMETER;
2597 goto fail;
2600 ev = samba_tevent_context_init(frame);
2601 if (ev == NULL) {
2602 goto fail;
2605 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2606 if (req == NULL) {
2607 goto fail;
2610 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2611 goto fail;
2614 status = cli_tcon_andx_recv(req);
2615 fail:
2616 TALLOC_FREE(frame);
2617 return status;
2620 struct cli_tree_connect_state {
2621 struct cli_state *cli;
2624 static struct tevent_req *cli_raw_tcon_send(
2625 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2626 const char *service, const char *pass, const char *dev);
2627 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2628 uint16 *max_xmit, uint16 *tid);
2630 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2631 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2632 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2634 static struct tevent_req *cli_tree_connect_send(
2635 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2636 const char *share, const char *dev, const char *pass, int passlen)
2638 struct tevent_req *req, *subreq;
2639 struct cli_tree_connect_state *state;
2641 req = tevent_req_create(mem_ctx, &state,
2642 struct cli_tree_connect_state);
2643 if (req == NULL) {
2644 return NULL;
2646 state->cli = cli;
2648 cli->share = talloc_strdup(cli, share);
2649 if (tevent_req_nomem(cli->share, req)) {
2650 return tevent_req_post(req, ev);
2653 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2654 subreq = smb2cli_tcon_send(state, ev, cli, share);
2655 if (tevent_req_nomem(subreq, req)) {
2656 return tevent_req_post(req, ev);
2658 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2659 req);
2660 return req;
2663 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2664 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2665 pass, passlen);
2666 if (tevent_req_nomem(subreq, req)) {
2667 return tevent_req_post(req, ev);
2669 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2670 req);
2671 return req;
2674 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2675 if (tevent_req_nomem(subreq, req)) {
2676 return tevent_req_post(req, ev);
2678 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2680 return req;
2683 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2685 tevent_req_simple_finish_ntstatus(
2686 subreq, smb2cli_tcon_recv(subreq));
2689 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2691 tevent_req_simple_finish_ntstatus(
2692 subreq, cli_tcon_andx_recv(subreq));
2695 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2697 struct tevent_req *req = tevent_req_callback_data(
2698 subreq, struct tevent_req);
2699 struct cli_tree_connect_state *state = tevent_req_data(
2700 req, struct cli_tree_connect_state);
2701 NTSTATUS status;
2702 uint16_t max_xmit = 0;
2703 uint16_t tid = 0;
2705 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2706 if (tevent_req_nterror(req, status)) {
2707 return;
2709 cli_state_set_tid(state->cli, tid);
2710 tevent_req_done(req);
2713 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2715 return tevent_req_simple_recv_ntstatus(req);
2718 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2719 const char *dev, const char *pass, int passlen)
2721 struct tevent_context *ev;
2722 struct tevent_req *req;
2723 NTSTATUS status = NT_STATUS_NO_MEMORY;
2725 if (smbXcli_conn_has_async_calls(cli->conn)) {
2726 return NT_STATUS_INVALID_PARAMETER;
2728 ev = samba_tevent_context_init(talloc_tos());
2729 if (ev == NULL) {
2730 goto fail;
2732 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2733 if (req == NULL) {
2734 goto fail;
2736 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2737 goto fail;
2739 status = cli_tree_connect_recv(req);
2740 fail:
2741 TALLOC_FREE(ev);
2742 return status;
2745 /****************************************************************************
2746 Send a tree disconnect.
2747 ****************************************************************************/
2749 struct cli_tdis_state {
2750 struct cli_state *cli;
2753 static void cli_tdis_done(struct tevent_req *subreq);
2755 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2756 struct tevent_context *ev,
2757 struct cli_state *cli)
2759 struct tevent_req *req, *subreq;
2760 struct cli_tdis_state *state;
2762 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2763 if (req == NULL) {
2764 return NULL;
2766 state->cli = cli;
2768 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2769 if (tevent_req_nomem(subreq, req)) {
2770 return tevent_req_post(req, ev);
2772 tevent_req_set_callback(subreq, cli_tdis_done, req);
2773 return req;
2776 static void cli_tdis_done(struct tevent_req *subreq)
2778 struct tevent_req *req = tevent_req_callback_data(
2779 subreq, struct tevent_req);
2780 struct cli_tdis_state *state = tevent_req_data(
2781 req, struct cli_tdis_state);
2782 NTSTATUS status;
2784 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2785 TALLOC_FREE(subreq);
2786 if (!NT_STATUS_IS_OK(status)) {
2787 tevent_req_nterror(req, status);
2788 return;
2790 cli_state_set_tid(state->cli, UINT16_MAX);
2791 tevent_req_done(req);
2794 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2796 return tevent_req_simple_recv_ntstatus(req);
2799 NTSTATUS cli_tdis(struct cli_state *cli)
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_tdis_send(ev, ev, cli);
2813 if (req == NULL) {
2814 goto fail;
2816 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2817 goto fail;
2819 status = cli_tdis_recv(req);
2820 fail:
2821 TALLOC_FREE(ev);
2822 return status;
2825 struct cli_connect_sock_state {
2826 const char **called_names;
2827 const char **calling_names;
2828 int *called_types;
2829 int fd;
2830 uint16_t port;
2833 static void cli_connect_sock_done(struct tevent_req *subreq);
2836 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2837 * nonzero address.
2840 static struct tevent_req *cli_connect_sock_send(
2841 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2842 const char *host, int name_type, const struct sockaddr_storage *pss,
2843 const char *myname, uint16_t port)
2845 struct tevent_req *req, *subreq;
2846 struct cli_connect_sock_state *state;
2847 const char *prog;
2848 unsigned i, num_addrs;
2849 NTSTATUS status;
2851 req = tevent_req_create(mem_ctx, &state,
2852 struct cli_connect_sock_state);
2853 if (req == NULL) {
2854 return NULL;
2857 prog = getenv("LIBSMB_PROG");
2858 if (prog != NULL) {
2859 state->fd = sock_exec(prog);
2860 if (state->fd == -1) {
2861 status = map_nt_error_from_unix(errno);
2862 tevent_req_nterror(req, status);
2863 } else {
2864 state->port = 0;
2865 tevent_req_done(req);
2867 return tevent_req_post(req, ev);
2870 if ((pss == NULL) || is_zero_addr(pss)) {
2871 struct sockaddr_storage *addrs;
2874 * Here we cheat. resolve_name_list is not async at all. So
2875 * this call will only be really async if the name lookup has
2876 * been done externally.
2879 status = resolve_name_list(state, host, name_type,
2880 &addrs, &num_addrs);
2881 if (!NT_STATUS_IS_OK(status)) {
2882 tevent_req_nterror(req, status);
2883 return tevent_req_post(req, ev);
2885 pss = addrs;
2886 } else {
2887 num_addrs = 1;
2890 state->called_names = talloc_array(state, const char *, num_addrs);
2891 if (tevent_req_nomem(state->called_names, req)) {
2892 return tevent_req_post(req, ev);
2894 state->called_types = talloc_array(state, int, num_addrs);
2895 if (tevent_req_nomem(state->called_types, req)) {
2896 return tevent_req_post(req, ev);
2898 state->calling_names = talloc_array(state, const char *, num_addrs);
2899 if (tevent_req_nomem(state->calling_names, req)) {
2900 return tevent_req_post(req, ev);
2902 for (i=0; i<num_addrs; i++) {
2903 state->called_names[i] = host;
2904 state->called_types[i] = name_type;
2905 state->calling_names[i] = myname;
2908 subreq = smbsock_any_connect_send(
2909 state, ev, pss, state->called_names, state->called_types,
2910 state->calling_names, NULL, num_addrs, port);
2911 if (tevent_req_nomem(subreq, req)) {
2912 return tevent_req_post(req, ev);
2914 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2915 return req;
2918 static void cli_connect_sock_done(struct tevent_req *subreq)
2920 struct tevent_req *req = tevent_req_callback_data(
2921 subreq, struct tevent_req);
2922 struct cli_connect_sock_state *state = tevent_req_data(
2923 req, struct cli_connect_sock_state);
2924 NTSTATUS status;
2926 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2927 &state->port);
2928 TALLOC_FREE(subreq);
2929 if (tevent_req_nterror(req, status)) {
2930 return;
2932 set_socket_options(state->fd, lp_socket_options());
2933 tevent_req_done(req);
2936 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2937 int *pfd, uint16_t *pport)
2939 struct cli_connect_sock_state *state = tevent_req_data(
2940 req, struct cli_connect_sock_state);
2941 NTSTATUS status;
2943 if (tevent_req_is_nterror(req, &status)) {
2944 return status;
2946 *pfd = state->fd;
2947 *pport = state->port;
2948 return NT_STATUS_OK;
2951 struct cli_connect_nb_state {
2952 const char *desthost;
2953 int signing_state;
2954 int flags;
2955 struct cli_state *cli;
2958 static void cli_connect_nb_done(struct tevent_req *subreq);
2960 static struct tevent_req *cli_connect_nb_send(
2961 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2962 const char *host, const struct sockaddr_storage *dest_ss,
2963 uint16_t port, int name_type, const char *myname,
2964 int signing_state, int flags)
2966 struct tevent_req *req, *subreq;
2967 struct cli_connect_nb_state *state;
2968 char *p;
2970 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2971 if (req == NULL) {
2972 return NULL;
2974 state->desthost = host;
2975 state->signing_state = signing_state;
2976 state->flags = flags;
2978 p = strchr(host, '#');
2979 if (p != NULL) {
2980 name_type = strtol(p+1, NULL, 16);
2981 host = talloc_strndup(state, host, p - host);
2982 if (tevent_req_nomem(host, req)) {
2983 return tevent_req_post(req, ev);
2987 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2988 myname, port);
2989 if (tevent_req_nomem(subreq, req)) {
2990 return tevent_req_post(req, ev);
2992 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2993 return req;
2996 static void cli_connect_nb_done(struct tevent_req *subreq)
2998 struct tevent_req *req = tevent_req_callback_data(
2999 subreq, struct tevent_req);
3000 struct cli_connect_nb_state *state = tevent_req_data(
3001 req, struct cli_connect_nb_state);
3002 NTSTATUS status;
3003 int fd;
3004 uint16_t port;
3006 status = cli_connect_sock_recv(subreq, &fd, &port);
3007 TALLOC_FREE(subreq);
3008 if (tevent_req_nterror(req, status)) {
3009 return;
3012 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3013 state->signing_state, state->flags);
3014 if (tevent_req_nomem(state->cli, req)) {
3015 close(fd);
3016 return;
3018 tevent_req_done(req);
3021 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3022 struct cli_state **pcli)
3024 struct cli_connect_nb_state *state = tevent_req_data(
3025 req, struct cli_connect_nb_state);
3026 NTSTATUS status;
3028 if (tevent_req_is_nterror(req, &status)) {
3029 return status;
3031 *pcli = talloc_move(NULL, &state->cli);
3032 return NT_STATUS_OK;
3035 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3036 uint16_t port, int name_type, const char *myname,
3037 int signing_state, int flags, struct cli_state **pcli)
3039 struct tevent_context *ev;
3040 struct tevent_req *req;
3041 NTSTATUS status = NT_STATUS_NO_MEMORY;
3043 ev = samba_tevent_context_init(talloc_tos());
3044 if (ev == NULL) {
3045 goto fail;
3047 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3048 myname, signing_state, flags);
3049 if (req == NULL) {
3050 goto fail;
3052 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3053 goto fail;
3055 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3056 goto fail;
3058 status = cli_connect_nb_recv(req, pcli);
3059 fail:
3060 TALLOC_FREE(ev);
3061 return status;
3064 struct cli_start_connection_state {
3065 struct tevent_context *ev;
3066 struct cli_state *cli;
3069 static void cli_start_connection_connected(struct tevent_req *subreq);
3070 static void cli_start_connection_done(struct tevent_req *subreq);
3073 establishes a connection to after the negprot.
3074 @param output_cli A fully initialised cli structure, non-null only on success
3075 @param dest_host The netbios name of the remote host
3076 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3077 @param port (optional) The destination port (0 for default)
3080 static struct tevent_req *cli_start_connection_send(
3081 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3082 const char *my_name, const char *dest_host,
3083 const struct sockaddr_storage *dest_ss, int port,
3084 int signing_state, int flags)
3086 struct tevent_req *req, *subreq;
3087 struct cli_start_connection_state *state;
3089 req = tevent_req_create(mem_ctx, &state,
3090 struct cli_start_connection_state);
3091 if (req == NULL) {
3092 return NULL;
3094 state->ev = ev;
3096 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3097 0x20, my_name, signing_state, flags);
3098 if (tevent_req_nomem(subreq, req)) {
3099 return tevent_req_post(req, ev);
3101 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3102 return req;
3105 static void cli_start_connection_connected(struct tevent_req *subreq)
3107 struct tevent_req *req = tevent_req_callback_data(
3108 subreq, struct tevent_req);
3109 struct cli_start_connection_state *state = tevent_req_data(
3110 req, struct cli_start_connection_state);
3111 NTSTATUS status;
3113 status = cli_connect_nb_recv(subreq, &state->cli);
3114 TALLOC_FREE(subreq);
3115 if (tevent_req_nterror(req, status)) {
3116 return;
3119 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3120 state->cli->timeout,
3121 lp_cli_minprotocol(),
3122 lp_cli_maxprotocol());
3123 if (tevent_req_nomem(subreq, req)) {
3124 return;
3126 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3129 static void cli_start_connection_done(struct tevent_req *subreq)
3131 struct tevent_req *req = tevent_req_callback_data(
3132 subreq, struct tevent_req);
3133 struct cli_start_connection_state *state = tevent_req_data(
3134 req, struct cli_start_connection_state);
3135 NTSTATUS status;
3137 status = smbXcli_negprot_recv(subreq);
3138 TALLOC_FREE(subreq);
3139 if (tevent_req_nterror(req, status)) {
3140 return;
3143 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3144 /* Ensure we ask for some initial credits. */
3145 smb2cli_conn_set_max_credits(state->cli->conn,
3146 DEFAULT_SMB2_MAX_CREDITS);
3149 tevent_req_done(req);
3152 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3153 struct cli_state **output_cli)
3155 struct cli_start_connection_state *state = tevent_req_data(
3156 req, struct cli_start_connection_state);
3157 NTSTATUS status;
3159 if (tevent_req_is_nterror(req, &status)) {
3160 return status;
3162 *output_cli = state->cli;
3164 return NT_STATUS_OK;
3167 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3168 const char *my_name,
3169 const char *dest_host,
3170 const struct sockaddr_storage *dest_ss, int port,
3171 int signing_state, int flags)
3173 struct tevent_context *ev;
3174 struct tevent_req *req;
3175 NTSTATUS status = NT_STATUS_NO_MEMORY;
3177 ev = samba_tevent_context_init(talloc_tos());
3178 if (ev == NULL) {
3179 goto fail;
3181 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3182 port, signing_state, flags);
3183 if (req == NULL) {
3184 goto fail;
3186 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3187 goto fail;
3189 status = cli_start_connection_recv(req, output_cli);
3190 fail:
3191 TALLOC_FREE(ev);
3192 return status;
3196 establishes a connection right up to doing tconX, password specified.
3197 @param output_cli A fully initialised cli structure, non-null only on success
3198 @param dest_host The netbios name of the remote host
3199 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3200 @param port (optional) The destination port (0 for default)
3201 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3202 @param service_type The 'type' of serivice.
3203 @param user Username, unix string
3204 @param domain User's domain
3205 @param password User's password, unencrypted unix string.
3208 struct cli_full_connection_state {
3209 struct tevent_context *ev;
3210 const char *service;
3211 const char *service_type;
3212 const char *user;
3213 const char *domain;
3214 const char *password;
3215 int pw_len;
3216 int flags;
3217 struct cli_state *cli;
3220 static int cli_full_connection_state_destructor(
3221 struct cli_full_connection_state *s);
3222 static void cli_full_connection_started(struct tevent_req *subreq);
3223 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3224 static void cli_full_connection_done(struct tevent_req *subreq);
3226 struct tevent_req *cli_full_connection_send(
3227 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3228 const char *my_name, const char *dest_host,
3229 const struct sockaddr_storage *dest_ss, int port,
3230 const char *service, const char *service_type,
3231 const char *user, const char *domain,
3232 const char *password, int flags, int signing_state)
3234 struct tevent_req *req, *subreq;
3235 struct cli_full_connection_state *state;
3237 req = tevent_req_create(mem_ctx, &state,
3238 struct cli_full_connection_state);
3239 if (req == NULL) {
3240 return NULL;
3242 talloc_set_destructor(state, cli_full_connection_state_destructor);
3244 state->ev = ev;
3245 state->service = service;
3246 state->service_type = service_type;
3247 state->user = user;
3248 state->domain = domain;
3249 state->password = password;
3250 state->flags = flags;
3252 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3253 if (state->password == NULL) {
3254 state->password = "";
3257 subreq = cli_start_connection_send(
3258 state, ev, my_name, dest_host, dest_ss, port,
3259 signing_state, flags);
3260 if (tevent_req_nomem(subreq, req)) {
3261 return tevent_req_post(req, ev);
3263 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3264 return req;
3267 static int cli_full_connection_state_destructor(
3268 struct cli_full_connection_state *s)
3270 if (s->cli != NULL) {
3271 cli_shutdown(s->cli);
3272 s->cli = NULL;
3274 return 0;
3277 static void cli_full_connection_started(struct tevent_req *subreq)
3279 struct tevent_req *req = tevent_req_callback_data(
3280 subreq, struct tevent_req);
3281 struct cli_full_connection_state *state = tevent_req_data(
3282 req, struct cli_full_connection_state);
3283 NTSTATUS status;
3285 status = cli_start_connection_recv(subreq, &state->cli);
3286 TALLOC_FREE(subreq);
3287 if (tevent_req_nterror(req, status)) {
3288 return;
3290 subreq = cli_session_setup_send(
3291 state, state->ev, state->cli, state->user,
3292 state->password, state->pw_len, state->password, state->pw_len,
3293 state->domain);
3294 if (tevent_req_nomem(subreq, req)) {
3295 return;
3297 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3300 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3302 struct tevent_req *req = tevent_req_callback_data(
3303 subreq, struct tevent_req);
3304 struct cli_full_connection_state *state = tevent_req_data(
3305 req, struct cli_full_connection_state);
3306 NTSTATUS status;
3308 status = cli_session_setup_recv(subreq);
3309 TALLOC_FREE(subreq);
3311 if (!NT_STATUS_IS_OK(status) &&
3312 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3314 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3316 subreq = cli_session_setup_send(
3317 state, state->ev, state->cli, "", "", 0, "", 0,
3318 state->domain);
3319 if (tevent_req_nomem(subreq, req)) {
3320 return;
3322 tevent_req_set_callback(
3323 subreq, cli_full_connection_sess_set_up, req);
3324 return;
3327 if (tevent_req_nterror(req, status)) {
3328 return;
3331 if (state->service != NULL) {
3332 subreq = cli_tree_connect_send(
3333 state, state->ev, state->cli,
3334 state->service, state->service_type,
3335 state->password, state->pw_len);
3336 if (tevent_req_nomem(subreq, req)) {
3337 return;
3339 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3340 return;
3343 status = cli_init_creds(state->cli, state->user, state->domain,
3344 state->password);
3345 if (tevent_req_nterror(req, status)) {
3346 return;
3348 tevent_req_done(req);
3351 static void cli_full_connection_done(struct tevent_req *subreq)
3353 struct tevent_req *req = tevent_req_callback_data(
3354 subreq, struct tevent_req);
3355 struct cli_full_connection_state *state = tevent_req_data(
3356 req, struct cli_full_connection_state);
3357 NTSTATUS status;
3359 status = cli_tree_connect_recv(subreq);
3360 TALLOC_FREE(subreq);
3361 if (tevent_req_nterror(req, status)) {
3362 return;
3364 status = cli_init_creds(state->cli, state->user, state->domain,
3365 state->password);
3366 if (tevent_req_nterror(req, status)) {
3367 return;
3369 tevent_req_done(req);
3372 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3373 struct cli_state **output_cli)
3375 struct cli_full_connection_state *state = tevent_req_data(
3376 req, struct cli_full_connection_state);
3377 NTSTATUS status;
3379 if (tevent_req_is_nterror(req, &status)) {
3380 return status;
3382 *output_cli = state->cli;
3383 talloc_set_destructor(state, NULL);
3384 return NT_STATUS_OK;
3387 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3388 const char *my_name,
3389 const char *dest_host,
3390 const struct sockaddr_storage *dest_ss, int port,
3391 const char *service, const char *service_type,
3392 const char *user, const char *domain,
3393 const char *password, int flags,
3394 int signing_state)
3396 struct tevent_context *ev;
3397 struct tevent_req *req;
3398 NTSTATUS status = NT_STATUS_NO_MEMORY;
3400 ev = samba_tevent_context_init(talloc_tos());
3401 if (ev == NULL) {
3402 goto fail;
3404 req = cli_full_connection_send(
3405 ev, ev, my_name, dest_host, dest_ss, port, service,
3406 service_type, user, domain, password, flags, signing_state);
3407 if (req == NULL) {
3408 goto fail;
3410 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3411 goto fail;
3413 status = cli_full_connection_recv(req, output_cli);
3414 fail:
3415 TALLOC_FREE(ev);
3416 return status;
3419 /****************************************************************************
3420 Send an old style tcon.
3421 ****************************************************************************/
3422 struct cli_raw_tcon_state {
3423 uint16_t *ret_vwv;
3426 static void cli_raw_tcon_done(struct tevent_req *subreq);
3428 static struct tevent_req *cli_raw_tcon_send(
3429 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3430 const char *service, const char *pass, const char *dev)
3432 struct tevent_req *req, *subreq;
3433 struct cli_raw_tcon_state *state;
3434 uint8_t *bytes;
3436 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3437 if (req == NULL) {
3438 return NULL;
3441 if (!lp_client_plaintext_auth() && (*pass)) {
3442 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3443 " or 'client ntlmv2 auth = yes'\n"));
3444 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3445 return tevent_req_post(req, ev);
3448 bytes = talloc_array(state, uint8_t, 0);
3449 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3450 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3451 service, strlen(service)+1, NULL);
3452 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3453 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3454 pass, strlen(pass)+1, NULL);
3455 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3456 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3457 dev, strlen(dev)+1, NULL);
3459 if (tevent_req_nomem(bytes, req)) {
3460 return tevent_req_post(req, ev);
3463 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3464 talloc_get_size(bytes), bytes);
3465 if (tevent_req_nomem(subreq, req)) {
3466 return tevent_req_post(req, ev);
3468 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3469 return req;
3472 static void cli_raw_tcon_done(struct tevent_req *subreq)
3474 struct tevent_req *req = tevent_req_callback_data(
3475 subreq, struct tevent_req);
3476 struct cli_raw_tcon_state *state = tevent_req_data(
3477 req, struct cli_raw_tcon_state);
3478 NTSTATUS status;
3480 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3481 NULL, NULL);
3482 TALLOC_FREE(subreq);
3483 if (tevent_req_nterror(req, status)) {
3484 return;
3486 tevent_req_done(req);
3489 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3490 uint16 *max_xmit, uint16 *tid)
3492 struct cli_raw_tcon_state *state = tevent_req_data(
3493 req, struct cli_raw_tcon_state);
3494 NTSTATUS status;
3496 if (tevent_req_is_nterror(req, &status)) {
3497 return status;
3499 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3500 *tid = SVAL(state->ret_vwv + 1, 0);
3501 return NT_STATUS_OK;
3504 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3505 const char *service, const char *pass, const char *dev,
3506 uint16 *max_xmit, uint16 *tid)
3508 struct tevent_context *ev;
3509 struct tevent_req *req;
3510 NTSTATUS status = NT_STATUS_NO_MEMORY;
3512 ev = samba_tevent_context_init(talloc_tos());
3513 if (ev == NULL) {
3514 goto fail;
3516 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3517 if (req == NULL) {
3518 goto fail;
3520 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3521 goto fail;
3523 status = cli_raw_tcon_recv(req, max_xmit, tid);
3524 fail:
3525 TALLOC_FREE(ev);
3526 return status;
3529 /* Return a cli_state pointing at the IPC$ share for the given server */
3531 struct cli_state *get_ipc_connect(char *server,
3532 struct sockaddr_storage *server_ss,
3533 const struct user_auth_info *user_info)
3535 struct cli_state *cli;
3536 NTSTATUS nt_status;
3537 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3539 if (user_info->use_kerberos) {
3540 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3543 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3544 user_info->username ? user_info->username : "",
3545 lp_workgroup(),
3546 user_info->password ? user_info->password : "",
3547 flags,
3548 SMB_SIGNING_DEFAULT);
3550 if (NT_STATUS_IS_OK(nt_status)) {
3551 return cli;
3552 } else if (is_ipaddress(server)) {
3553 /* windows 9* needs a correct NMB name for connections */
3554 fstring remote_name;
3556 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3557 cli = get_ipc_connect(remote_name, server_ss, user_info);
3558 if (cli)
3559 return cli;
3562 return NULL;
3566 * Given the IP address of a master browser on the network, return its
3567 * workgroup and connect to it.
3569 * This function is provided to allow additional processing beyond what
3570 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3571 * browsers and obtain each master browsers' list of domains (in case the
3572 * first master browser is recently on the network and has not yet
3573 * synchronized with other master browsers and therefore does not yet have the
3574 * entire network browse list)
3577 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3578 struct sockaddr_storage *mb_ip,
3579 const struct user_auth_info *user_info,
3580 char **pp_workgroup_out)
3582 char addr[INET6_ADDRSTRLEN];
3583 fstring name;
3584 struct cli_state *cli;
3585 struct sockaddr_storage server_ss;
3587 *pp_workgroup_out = NULL;
3589 print_sockaddr(addr, sizeof(addr), mb_ip);
3590 DEBUG(99, ("Looking up name of master browser %s\n",
3591 addr));
3594 * Do a name status query to find out the name of the master browser.
3595 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3596 * master browser will not respond to a wildcard query (or, at least,
3597 * an NT4 server acting as the domain master browser will not).
3599 * We might be able to use ONLY the query on MSBROWSE, but that's not
3600 * yet been tested with all Windows versions, so until it is, leave
3601 * the original wildcard query as the first choice and fall back to
3602 * MSBROWSE if the wildcard query fails.
3604 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3605 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3607 DEBUG(99, ("Could not retrieve name status for %s\n",
3608 addr));
3609 return NULL;
3612 if (!find_master_ip(name, &server_ss)) {
3613 DEBUG(99, ("Could not find master ip for %s\n", name));
3614 return NULL;
3617 *pp_workgroup_out = talloc_strdup(ctx, name);
3619 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3621 print_sockaddr(addr, sizeof(addr), &server_ss);
3622 cli = get_ipc_connect(addr, &server_ss, user_info);
3624 return cli;
3628 * Return the IP address and workgroup of a master browser on the network, and
3629 * connect to it.
3632 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3633 const struct user_auth_info *user_info,
3634 char **pp_workgroup_out)
3636 struct sockaddr_storage *ip_list;
3637 struct cli_state *cli;
3638 int i, count;
3639 NTSTATUS status;
3641 *pp_workgroup_out = NULL;
3643 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3645 /* Go looking for workgroups by broadcasting on the local network */
3647 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3648 &ip_list, &count);
3649 if (!NT_STATUS_IS_OK(status)) {
3650 DEBUG(99, ("No master browsers responded: %s\n",
3651 nt_errstr(status)));
3652 return NULL;
3655 for (i = 0; i < count; i++) {
3656 char addr[INET6_ADDRSTRLEN];
3657 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3658 DEBUG(99, ("Found master browser %s\n", addr));
3660 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3661 user_info, pp_workgroup_out);
3662 if (cli)
3663 return(cli);
3666 return NULL;