source3/lib: include config.h before any glibc headers
[Samba.git] / source3 / libsmb / cliconnect.c
blob530f5c36b1bdbf33926e84eea2ec073a74d7c9c3
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"
38 #define STAR_SMBSERVER "*SMBSERVER"
40 /********************************************************
41 Utility function to ensure we always return at least
42 a valid char * pointer to an empty string for the
43 cli->server_os, cli->server_type and cli->server_domain
44 strings.
45 *******************************************************/
47 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
48 const uint8_t *hdr,
49 char **dest,
50 uint8_t *src,
51 size_t srclen,
52 ssize_t *destlen)
54 *destlen = clistr_pull_talloc(mem_ctx,
55 (const char *)hdr,
56 SVAL(hdr, HDR_FLG2),
57 dest,
58 (char *)src,
59 srclen,
60 STR_TERMINATE);
61 if (*destlen == -1) {
62 return NT_STATUS_NO_MEMORY;
65 if (*dest == NULL) {
66 *dest = talloc_strdup(mem_ctx, "");
67 if (*dest == NULL) {
68 return NT_STATUS_NO_MEMORY;
71 return NT_STATUS_OK;
74 /****************************************************************************
75 Do an old lanman2 style session setup.
76 ****************************************************************************/
78 struct cli_session_setup_lanman2_state {
79 struct cli_state *cli;
80 uint16_t vwv[10];
81 const char *user;
84 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
86 static struct tevent_req *cli_session_setup_lanman2_send(
87 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
88 struct cli_state *cli, const char *user,
89 const char *pass, size_t passlen,
90 const char *workgroup)
92 struct tevent_req *req, *subreq;
93 struct cli_session_setup_lanman2_state *state;
94 DATA_BLOB lm_response = data_blob_null;
95 uint16_t *vwv;
96 uint8_t *bytes;
97 char *tmp;
98 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
100 req = tevent_req_create(mem_ctx, &state,
101 struct cli_session_setup_lanman2_state);
102 if (req == NULL) {
103 return NULL;
105 state->cli = cli;
106 state->user = user;
107 vwv = state->vwv;
110 * if in share level security then don't send a password now
112 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
113 passlen = 0;
116 if (passlen > 0
117 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
118 && passlen != 24) {
120 * Encrypted mode needed, and non encrypted password
121 * supplied.
123 lm_response = data_blob(NULL, 24);
124 if (tevent_req_nomem(lm_response.data, req)) {
125 return tevent_req_post(req, ev);
128 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
129 (uint8_t *)lm_response.data)) {
130 DEBUG(1, ("Password is > 14 chars in length, and is "
131 "therefore incompatible with Lanman "
132 "authentication\n"));
133 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
134 return tevent_req_post(req, ev);
136 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
137 && passlen == 24) {
139 * Encrypted mode needed, and encrypted password
140 * supplied.
142 lm_response = data_blob(pass, passlen);
143 if (tevent_req_nomem(lm_response.data, req)) {
144 return tevent_req_post(req, ev);
146 } else if (passlen > 0) {
147 uint8_t *buf;
148 size_t converted_size;
150 * Plaintext mode needed, assume plaintext supplied.
152 buf = talloc_array(talloc_tos(), uint8_t, 0);
153 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
154 &converted_size);
155 if (tevent_req_nomem(buf, req)) {
156 return tevent_req_post(req, ev);
158 lm_response = data_blob(pass, passlen);
159 TALLOC_FREE(buf);
160 if (tevent_req_nomem(lm_response.data, req)) {
161 return tevent_req_post(req, ev);
165 SCVAL(vwv+0, 0, 0xff);
166 SCVAL(vwv+0, 1, 0);
167 SSVAL(vwv+1, 0, 0);
168 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
169 SSVAL(vwv+3, 0, 2);
170 SSVAL(vwv+4, 0, 1);
171 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
172 SSVAL(vwv+7, 0, lm_response.length);
174 bytes = talloc_array(state, uint8_t, lm_response.length);
175 if (tevent_req_nomem(bytes, req)) {
176 return tevent_req_post(req, ev);
178 if (lm_response.length != 0) {
179 memcpy(bytes, lm_response.data, lm_response.length);
181 data_blob_free(&lm_response);
183 tmp = talloc_strdup_upper(talloc_tos(), user);
184 if (tevent_req_nomem(tmp, req)) {
185 return tevent_req_post(req, ev);
187 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
188 NULL);
189 TALLOC_FREE(tmp);
191 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
192 if (tevent_req_nomem(tmp, req)) {
193 return tevent_req_post(req, ev);
195 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
196 NULL);
197 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
198 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
200 if (tevent_req_nomem(bytes, req)) {
201 return tevent_req_post(req, ev);
204 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
205 talloc_get_size(bytes), bytes);
206 if (tevent_req_nomem(subreq, req)) {
207 return tevent_req_post(req, ev);
209 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
210 return req;
213 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
215 struct tevent_req *req = tevent_req_callback_data(
216 subreq, struct tevent_req);
217 struct cli_session_setup_lanman2_state *state = tevent_req_data(
218 req, struct cli_session_setup_lanman2_state);
219 struct cli_state *cli = state->cli;
220 uint32_t num_bytes;
221 uint8_t *in;
222 uint8_t *inhdr;
223 uint8_t *bytes;
224 uint8_t *p;
225 NTSTATUS status;
226 ssize_t ret;
227 uint8_t wct;
228 uint16_t *vwv;
230 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
231 &num_bytes, &bytes);
232 TALLOC_FREE(subreq);
233 if (!NT_STATUS_IS_OK(status)) {
234 tevent_req_nterror(req, status);
235 return;
238 inhdr = in + NBT_HDR_SIZE;
239 p = bytes;
241 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
243 status = smb_bytes_talloc_string(cli,
244 inhdr,
245 &cli->server_os,
247 bytes+num_bytes-p,
248 &ret);
250 if (!NT_STATUS_IS_OK(status)) {
251 tevent_req_nterror(req, status);
252 return;
254 p += ret;
256 status = smb_bytes_talloc_string(cli,
257 inhdr,
258 &cli->server_type,
260 bytes+num_bytes-p,
261 &ret);
263 if (!NT_STATUS_IS_OK(status)) {
264 tevent_req_nterror(req, status);
265 return;
267 p += ret;
269 status = smb_bytes_talloc_string(cli,
270 inhdr,
271 &cli->server_domain,
273 bytes+num_bytes-p,
274 &ret);
276 if (!NT_STATUS_IS_OK(status)) {
277 tevent_req_nterror(req, status);
278 return;
280 p += ret;
282 tevent_req_done(req);
285 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
287 return tevent_req_simple_recv_ntstatus(req);
290 /****************************************************************************
291 Work out suitable capabilities to offer the server.
292 ****************************************************************************/
294 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
295 uint32_t sesssetup_capabilities)
297 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
300 * We only send capabilities based on the mask for:
301 * - client only flags
302 * - flags used in both directions
304 * We do not echo the server only flags, except some legacy flags.
306 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
307 * CAP_LARGE_WRITEX in order to allow us to do large reads
308 * against old Samba releases (<= 3.6.x).
310 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
313 * Session Setup specific flags CAP_DYNAMIC_REAUTH
314 * and CAP_EXTENDED_SECURITY are passed by the caller.
315 * We need that in order to do guest logins even if
316 * CAP_EXTENDED_SECURITY is negotiated.
318 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
319 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
320 client_capabilities |= sesssetup_capabilities;
322 return client_capabilities;
325 /****************************************************************************
326 Do a NT1 guest session setup.
327 ****************************************************************************/
329 struct cli_session_setup_guest_state {
330 struct cli_state *cli;
331 uint16_t vwv[13];
332 struct iovec bytes;
335 static void cli_session_setup_guest_done(struct tevent_req *subreq);
337 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
338 struct tevent_context *ev,
339 struct cli_state *cli,
340 struct tevent_req **psmbreq)
342 struct tevent_req *req, *subreq;
343 struct cli_session_setup_guest_state *state;
344 uint16_t *vwv;
345 uint8_t *bytes;
347 req = tevent_req_create(mem_ctx, &state,
348 struct cli_session_setup_guest_state);
349 if (req == NULL) {
350 return NULL;
352 state->cli = cli;
353 vwv = state->vwv;
355 SCVAL(vwv+0, 0, 0xFF);
356 SCVAL(vwv+0, 1, 0);
357 SSVAL(vwv+1, 0, 0);
358 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
359 SSVAL(vwv+3, 0, 2);
360 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
361 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
362 SSVAL(vwv+7, 0, 0);
363 SSVAL(vwv+8, 0, 0);
364 SSVAL(vwv+9, 0, 0);
365 SSVAL(vwv+10, 0, 0);
366 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
368 bytes = talloc_array(state, uint8_t, 0);
370 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
371 NULL);
372 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
373 NULL);
374 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
375 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
377 if (bytes == NULL) {
378 TALLOC_FREE(req);
379 return NULL;
382 state->bytes.iov_base = (void *)bytes;
383 state->bytes.iov_len = talloc_get_size(bytes);
385 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
386 1, &state->bytes);
387 if (subreq == NULL) {
388 TALLOC_FREE(req);
389 return NULL;
391 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
392 *psmbreq = subreq;
393 return req;
396 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
397 struct tevent_context *ev,
398 struct cli_state *cli)
400 struct tevent_req *req, *subreq;
401 NTSTATUS status;
403 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
404 if (req == NULL) {
405 return NULL;
408 status = smb1cli_req_chain_submit(&subreq, 1);
409 if (!NT_STATUS_IS_OK(status)) {
410 tevent_req_nterror(req, status);
411 return tevent_req_post(req, ev);
413 return req;
416 static void cli_session_setup_guest_done(struct tevent_req *subreq)
418 struct tevent_req *req = tevent_req_callback_data(
419 subreq, struct tevent_req);
420 struct cli_session_setup_guest_state *state = tevent_req_data(
421 req, struct cli_session_setup_guest_state);
422 struct cli_state *cli = state->cli;
423 uint32_t num_bytes;
424 uint8_t *in;
425 uint8_t *inhdr;
426 uint8_t *bytes;
427 uint8_t *p;
428 NTSTATUS status;
429 ssize_t ret;
430 uint8_t wct;
431 uint16_t *vwv;
433 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
434 &num_bytes, &bytes);
435 TALLOC_FREE(subreq);
436 if (!NT_STATUS_IS_OK(status)) {
437 tevent_req_nterror(req, status);
438 return;
441 inhdr = in + NBT_HDR_SIZE;
442 p = bytes;
444 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
446 status = smb_bytes_talloc_string(cli,
447 inhdr,
448 &cli->server_os,
450 bytes+num_bytes-p,
451 &ret);
453 if (!NT_STATUS_IS_OK(status)) {
454 tevent_req_nterror(req, status);
455 return;
457 p += ret;
459 status = smb_bytes_talloc_string(cli,
460 inhdr,
461 &cli->server_type,
463 bytes+num_bytes-p,
464 &ret);
466 if (!NT_STATUS_IS_OK(status)) {
467 tevent_req_nterror(req, status);
468 return;
470 p += ret;
472 status = smb_bytes_talloc_string(cli,
473 inhdr,
474 &cli->server_domain,
476 bytes+num_bytes-p,
477 &ret);
479 if (!NT_STATUS_IS_OK(status)) {
480 tevent_req_nterror(req, status);
481 return;
483 p += ret;
485 tevent_req_done(req);
488 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
490 return tevent_req_simple_recv_ntstatus(req);
493 /****************************************************************************
494 Do a NT1 plaintext session setup.
495 ****************************************************************************/
497 struct cli_session_setup_plain_state {
498 struct cli_state *cli;
499 uint16_t vwv[13];
500 const char *user;
503 static void cli_session_setup_plain_done(struct tevent_req *subreq);
505 static struct tevent_req *cli_session_setup_plain_send(
506 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
507 struct cli_state *cli,
508 const char *user, const char *pass, const char *workgroup)
510 struct tevent_req *req, *subreq;
511 struct cli_session_setup_plain_state *state;
512 uint16_t *vwv;
513 uint8_t *bytes;
514 size_t passlen;
515 char *version;
517 req = tevent_req_create(mem_ctx, &state,
518 struct cli_session_setup_plain_state);
519 if (req == NULL) {
520 return NULL;
522 state->cli = cli;
523 state->user = user;
524 vwv = state->vwv;
526 SCVAL(vwv+0, 0, 0xff);
527 SCVAL(vwv+0, 1, 0);
528 SSVAL(vwv+1, 0, 0);
529 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
530 SSVAL(vwv+3, 0, 2);
531 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
532 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
533 SSVAL(vwv+7, 0, 0);
534 SSVAL(vwv+8, 0, 0);
535 SSVAL(vwv+9, 0, 0);
536 SSVAL(vwv+10, 0, 0);
537 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
539 bytes = talloc_array(state, uint8_t, 0);
540 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
541 &passlen);
542 if (tevent_req_nomem(bytes, req)) {
543 return tevent_req_post(req, ev);
545 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
547 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
548 user, strlen(user)+1, NULL);
549 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
550 workgroup, strlen(workgroup)+1, NULL);
551 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
552 "Unix", 5, NULL);
554 version = talloc_asprintf(talloc_tos(), "Samba %s",
555 samba_version_string());
556 if (tevent_req_nomem(version, req)){
557 return tevent_req_post(req, ev);
559 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
560 version, strlen(version)+1, NULL);
561 TALLOC_FREE(version);
563 if (tevent_req_nomem(bytes, req)) {
564 return tevent_req_post(req, ev);
567 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
568 talloc_get_size(bytes), bytes);
569 if (tevent_req_nomem(subreq, req)) {
570 return tevent_req_post(req, ev);
572 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
573 return req;
576 static void cli_session_setup_plain_done(struct tevent_req *subreq)
578 struct tevent_req *req = tevent_req_callback_data(
579 subreq, struct tevent_req);
580 struct cli_session_setup_plain_state *state = tevent_req_data(
581 req, struct cli_session_setup_plain_state);
582 struct cli_state *cli = state->cli;
583 uint32_t num_bytes;
584 uint8_t *in;
585 uint8_t *inhdr;
586 uint8_t *bytes;
587 uint8_t *p;
588 NTSTATUS status;
589 ssize_t ret;
590 uint8_t wct;
591 uint16_t *vwv;
593 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
594 &num_bytes, &bytes);
595 TALLOC_FREE(subreq);
596 if (tevent_req_nterror(req, status)) {
597 return;
600 inhdr = in + NBT_HDR_SIZE;
601 p = bytes;
603 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
605 status = smb_bytes_talloc_string(cli,
606 inhdr,
607 &cli->server_os,
609 bytes+num_bytes-p,
610 &ret);
612 if (!NT_STATUS_IS_OK(status)) {
613 tevent_req_nterror(req, status);
614 return;
616 p += ret;
618 status = smb_bytes_talloc_string(cli,
619 inhdr,
620 &cli->server_type,
622 bytes+num_bytes-p,
623 &ret);
625 if (!NT_STATUS_IS_OK(status)) {
626 tevent_req_nterror(req, status);
627 return;
629 p += ret;
631 status = smb_bytes_talloc_string(cli,
632 inhdr,
633 &cli->server_domain,
635 bytes+num_bytes-p,
636 &ret);
638 if (!NT_STATUS_IS_OK(status)) {
639 tevent_req_nterror(req, status);
640 return;
642 p += ret;
644 tevent_req_done(req);
647 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
649 return tevent_req_simple_recv_ntstatus(req);
652 /****************************************************************************
653 do a NT1 NTLM/LM encrypted session setup - for when extended security
654 is not negotiated.
655 @param cli client state to create do session setup on
656 @param user username
657 @param pass *either* cleartext password (passlen !=24) or LM response.
658 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
659 @param workgroup The user's domain.
660 ****************************************************************************/
662 struct cli_session_setup_nt1_state {
663 struct cli_state *cli;
664 uint16_t vwv[13];
665 DATA_BLOB response;
666 DATA_BLOB session_key;
667 const char *user;
670 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
672 static struct tevent_req *cli_session_setup_nt1_send(
673 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
674 struct cli_state *cli, const char *user,
675 const char *pass, size_t passlen,
676 const char *ntpass, size_t ntpasslen,
677 const char *workgroup)
679 struct tevent_req *req, *subreq;
680 struct cli_session_setup_nt1_state *state;
681 DATA_BLOB lm_response = data_blob_null;
682 DATA_BLOB nt_response = data_blob_null;
683 DATA_BLOB session_key = data_blob_null;
684 uint16_t *vwv;
685 uint8_t *bytes;
686 char *workgroup_upper;
688 req = tevent_req_create(mem_ctx, &state,
689 struct cli_session_setup_nt1_state);
690 if (req == NULL) {
691 return NULL;
693 state->cli = cli;
694 state->user = user;
695 vwv = state->vwv;
697 if (passlen == 0) {
698 /* do nothing - guest login */
699 } else if (passlen != 24) {
700 if (lp_client_ntlmv2_auth()) {
701 DATA_BLOB server_chal;
702 DATA_BLOB names_blob;
704 server_chal =
705 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
709 * note that the 'workgroup' here is a best
710 * guess - we don't know the server's domain
711 * at this point. Windows clients also don't
712 * use hostname...
714 names_blob = NTLMv2_generate_names_blob(
715 NULL, NULL, workgroup);
717 if (tevent_req_nomem(names_blob.data, req)) {
718 return tevent_req_post(req, ev);
721 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
722 &server_chal, &names_blob,
723 &lm_response, &nt_response,
724 NULL, &session_key)) {
725 data_blob_free(&names_blob);
726 tevent_req_nterror(
727 req, NT_STATUS_ACCESS_DENIED);
728 return tevent_req_post(req, ev);
730 data_blob_free(&names_blob);
732 } else {
733 uchar nt_hash[16];
734 E_md4hash(pass, nt_hash);
736 #ifdef LANMAN_ONLY
737 nt_response = data_blob_null;
738 #else
739 nt_response = data_blob(NULL, 24);
740 if (tevent_req_nomem(nt_response.data, req)) {
741 return tevent_req_post(req, ev);
744 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
745 nt_response.data);
746 #endif
747 /* non encrypted password supplied. Ignore ntpass. */
748 if (lp_client_lanman_auth()) {
750 lm_response = data_blob(NULL, 24);
751 if (tevent_req_nomem(lm_response.data, req)) {
752 return tevent_req_post(req, ev);
755 if (!SMBencrypt(pass,
756 smb1cli_conn_server_challenge(cli->conn),
757 lm_response.data)) {
759 * Oops, the LM response is
760 * invalid, just put the NT
761 * response there instead
763 data_blob_free(&lm_response);
764 lm_response = data_blob(
765 nt_response.data,
766 nt_response.length);
768 } else {
770 * LM disabled, place NT# in LM field
771 * instead
773 lm_response = data_blob(
774 nt_response.data, nt_response.length);
777 if (tevent_req_nomem(lm_response.data, req)) {
778 return tevent_req_post(req, ev);
781 session_key = data_blob(NULL, 16);
782 if (tevent_req_nomem(session_key.data, req)) {
783 return tevent_req_post(req, ev);
785 #ifdef LANMAN_ONLY
786 E_deshash(pass, session_key.data);
787 memset(&session_key.data[8], '\0', 8);
788 #else
789 SMBsesskeygen_ntv1(nt_hash, session_key.data);
790 #endif
792 } else {
793 /* pre-encrypted password supplied. Only used for
794 security=server, can't do
795 signing because we don't have original key */
797 lm_response = data_blob(pass, passlen);
798 if (tevent_req_nomem(lm_response.data, req)) {
799 return tevent_req_post(req, ev);
802 nt_response = data_blob(ntpass, ntpasslen);
803 if (tevent_req_nomem(nt_response.data, req)) {
804 return tevent_req_post(req, ev);
808 #ifdef LANMAN_ONLY
809 state->response = data_blob_talloc(
810 state, lm_response.data, lm_response.length);
811 #else
812 state->response = data_blob_talloc(
813 state, nt_response.data, nt_response.length);
814 #endif
815 if (tevent_req_nomem(state->response.data, req)) {
816 return tevent_req_post(req, ev);
819 if (session_key.data) {
820 state->session_key = data_blob_talloc(
821 state, session_key.data, session_key.length);
822 if (tevent_req_nomem(state->session_key.data, req)) {
823 return tevent_req_post(req, ev);
826 data_blob_free(&session_key);
828 SCVAL(vwv+0, 0, 0xff);
829 SCVAL(vwv+0, 1, 0);
830 SSVAL(vwv+1, 0, 0);
831 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
832 SSVAL(vwv+3, 0, 2);
833 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
834 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
835 SSVAL(vwv+7, 0, lm_response.length);
836 SSVAL(vwv+8, 0, nt_response.length);
837 SSVAL(vwv+9, 0, 0);
838 SSVAL(vwv+10, 0, 0);
839 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
841 bytes = talloc_array(state, uint8_t,
842 lm_response.length + nt_response.length);
843 if (tevent_req_nomem(bytes, req)) {
844 return tevent_req_post(req, ev);
846 if (lm_response.length != 0) {
847 memcpy(bytes, lm_response.data, lm_response.length);
849 if (nt_response.length != 0) {
850 memcpy(bytes + lm_response.length,
851 nt_response.data, nt_response.length);
853 data_blob_free(&lm_response);
854 data_blob_free(&nt_response);
856 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
857 user, strlen(user)+1, NULL);
860 * Upper case here might help some NTLMv2 implementations
862 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
863 if (tevent_req_nomem(workgroup_upper, req)) {
864 return tevent_req_post(req, ev);
866 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
867 workgroup_upper, strlen(workgroup_upper)+1,
868 NULL);
869 TALLOC_FREE(workgroup_upper);
871 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
872 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
873 if (tevent_req_nomem(bytes, req)) {
874 return tevent_req_post(req, ev);
877 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
878 talloc_get_size(bytes), bytes);
879 if (tevent_req_nomem(subreq, req)) {
880 return tevent_req_post(req, ev);
882 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
883 return req;
886 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
888 struct tevent_req *req = tevent_req_callback_data(
889 subreq, struct tevent_req);
890 struct cli_session_setup_nt1_state *state = tevent_req_data(
891 req, struct cli_session_setup_nt1_state);
892 struct cli_state *cli = state->cli;
893 uint32_t num_bytes;
894 uint8_t *in;
895 uint8_t *inhdr;
896 uint8_t *bytes;
897 uint8_t *p;
898 NTSTATUS status;
899 ssize_t ret;
900 uint8_t wct;
901 uint16_t *vwv;
903 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
904 &num_bytes, &bytes);
905 TALLOC_FREE(subreq);
906 if (!NT_STATUS_IS_OK(status)) {
907 tevent_req_nterror(req, status);
908 return;
911 inhdr = in + NBT_HDR_SIZE;
912 p = bytes;
914 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
916 status = smb_bytes_talloc_string(cli,
917 inhdr,
918 &cli->server_os,
920 bytes+num_bytes-p,
921 &ret);
922 if (!NT_STATUS_IS_OK(status)) {
923 tevent_req_nterror(req, status);
924 return;
926 p += ret;
928 status = smb_bytes_talloc_string(cli,
929 inhdr,
930 &cli->server_type,
932 bytes+num_bytes-p,
933 &ret);
934 if (!NT_STATUS_IS_OK(status)) {
935 tevent_req_nterror(req, status);
936 return;
938 p += ret;
940 status = smb_bytes_talloc_string(cli,
941 inhdr,
942 &cli->server_domain,
944 bytes+num_bytes-p,
945 &ret);
946 if (!NT_STATUS_IS_OK(status)) {
947 tevent_req_nterror(req, status);
948 return;
950 p += ret;
952 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
953 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
954 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
955 return;
957 if (state->session_key.data) {
958 struct smbXcli_session *session = state->cli->smb1.session;
960 status = smb1cli_session_set_session_key(session,
961 state->session_key);
962 if (tevent_req_nterror(req, status)) {
963 return;
966 tevent_req_done(req);
969 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
971 return tevent_req_simple_recv_ntstatus(req);
974 /* The following is calculated from :
975 * (smb_size-4) = 35
976 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
977 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
978 * end of packet.
981 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
983 struct cli_sesssetup_blob_state {
984 struct tevent_context *ev;
985 struct cli_state *cli;
986 DATA_BLOB blob;
987 uint16_t max_blob_size;
988 uint16_t vwv[12];
989 uint8_t *buf;
991 DATA_BLOB smb2_blob;
992 struct iovec *recv_iov;
994 NTSTATUS status;
995 uint8_t *inbuf;
996 DATA_BLOB ret_blob;
999 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1000 struct tevent_req **psubreq);
1001 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1003 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1004 struct tevent_context *ev,
1005 struct cli_state *cli,
1006 DATA_BLOB blob)
1008 struct tevent_req *req, *subreq;
1009 struct cli_sesssetup_blob_state *state;
1010 uint32_t usable_space;
1012 req = tevent_req_create(mem_ctx, &state,
1013 struct cli_sesssetup_blob_state);
1014 if (req == NULL) {
1015 return NULL;
1017 state->ev = ev;
1018 state->blob = blob;
1019 state->cli = cli;
1021 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1022 usable_space = UINT16_MAX;
1023 } else {
1024 usable_space = cli_state_available_size(cli,
1025 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1028 if (usable_space == 0) {
1029 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1030 "(not possible to send %u bytes)\n",
1031 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1032 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1033 return tevent_req_post(req, ev);
1035 state->max_blob_size = MIN(usable_space, 0xFFFF);
1037 if (!cli_sesssetup_blob_next(state, &subreq)) {
1038 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1039 return tevent_req_post(req, ev);
1041 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1042 return req;
1045 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1046 struct tevent_req **psubreq)
1048 struct tevent_req *subreq;
1049 uint16_t thistime;
1051 thistime = MIN(state->blob.length, state->max_blob_size);
1053 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1055 state->smb2_blob.data = state->blob.data;
1056 state->smb2_blob.length = thistime;
1058 state->blob.data += thistime;
1059 state->blob.length -= thistime;
1061 subreq = smb2cli_session_setup_send(state, state->ev,
1062 state->cli->conn,
1063 state->cli->timeout,
1064 state->cli->smb2.session,
1065 0, /* in_flags */
1066 SMB2_CAP_DFS, /* in_capabilities */
1067 0, /* in_channel */
1068 0, /* in_previous_session_id */
1069 &state->smb2_blob);
1070 if (subreq == NULL) {
1071 return false;
1073 *psubreq = subreq;
1074 return true;
1077 SCVAL(state->vwv+0, 0, 0xFF);
1078 SCVAL(state->vwv+0, 1, 0);
1079 SSVAL(state->vwv+1, 0, 0);
1080 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1081 SSVAL(state->vwv+3, 0, 2);
1082 SSVAL(state->vwv+4, 0, 1);
1083 SIVAL(state->vwv+5, 0, 0);
1085 SSVAL(state->vwv+7, 0, thistime);
1087 SSVAL(state->vwv+8, 0, 0);
1088 SSVAL(state->vwv+9, 0, 0);
1089 SIVAL(state->vwv+10, 0,
1090 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1092 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1093 thistime);
1094 if (state->buf == NULL) {
1095 return false;
1097 state->blob.data += thistime;
1098 state->blob.length -= thistime;
1100 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1101 "Unix", 5, NULL);
1102 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1103 "Samba", 6, NULL);
1104 if (state->buf == NULL) {
1105 return false;
1107 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1108 12, state->vwv,
1109 talloc_get_size(state->buf), state->buf);
1110 if (subreq == NULL) {
1111 return false;
1113 *psubreq = subreq;
1114 return true;
1117 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1119 struct tevent_req *req = tevent_req_callback_data(
1120 subreq, struct tevent_req);
1121 struct cli_sesssetup_blob_state *state = tevent_req_data(
1122 req, struct cli_sesssetup_blob_state);
1123 struct cli_state *cli = state->cli;
1124 uint8_t wct;
1125 uint16_t *vwv;
1126 uint32_t num_bytes;
1127 uint8_t *bytes;
1128 NTSTATUS status;
1129 uint8_t *p;
1130 uint16_t blob_length;
1131 uint8_t *in;
1132 uint8_t *inhdr;
1133 ssize_t ret;
1135 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1136 status = smb2cli_session_setup_recv(subreq, state,
1137 &state->recv_iov,
1138 &state->ret_blob);
1139 } else {
1140 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1141 &num_bytes, &bytes);
1142 TALLOC_FREE(state->buf);
1144 TALLOC_FREE(subreq);
1145 if (!NT_STATUS_IS_OK(status)
1146 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1147 tevent_req_nterror(req, status);
1148 return;
1151 state->status = status;
1153 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1154 goto next;
1157 state->inbuf = in;
1158 inhdr = in + NBT_HDR_SIZE;
1159 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1161 blob_length = SVAL(vwv+3, 0);
1162 if (blob_length > num_bytes) {
1163 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1164 return;
1166 state->ret_blob = data_blob_const(bytes, blob_length);
1168 p = bytes + blob_length;
1170 status = smb_bytes_talloc_string(cli,
1171 inhdr,
1172 &cli->server_os,
1174 bytes+num_bytes-p,
1175 &ret);
1177 if (!NT_STATUS_IS_OK(status)) {
1178 tevent_req_nterror(req, status);
1179 return;
1181 p += ret;
1183 status = smb_bytes_talloc_string(cli,
1184 inhdr,
1185 &cli->server_type,
1187 bytes+num_bytes-p,
1188 &ret);
1190 if (!NT_STATUS_IS_OK(status)) {
1191 tevent_req_nterror(req, status);
1192 return;
1194 p += ret;
1196 status = smb_bytes_talloc_string(cli,
1197 inhdr,
1198 &cli->server_domain,
1200 bytes+num_bytes-p,
1201 &ret);
1203 if (!NT_STATUS_IS_OK(status)) {
1204 tevent_req_nterror(req, status);
1205 return;
1207 p += ret;
1209 next:
1210 if (state->blob.length != 0) {
1212 * More to send
1214 if (!cli_sesssetup_blob_next(state, &subreq)) {
1215 tevent_req_oom(req);
1216 return;
1218 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1219 return;
1221 tevent_req_done(req);
1224 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1225 TALLOC_CTX *mem_ctx,
1226 DATA_BLOB *pblob,
1227 uint8_t **pinbuf,
1228 struct iovec **precv_iov)
1230 struct cli_sesssetup_blob_state *state = tevent_req_data(
1231 req, struct cli_sesssetup_blob_state);
1232 NTSTATUS status;
1233 uint8_t *inbuf;
1234 struct iovec *recv_iov;
1236 if (tevent_req_is_nterror(req, &status)) {
1237 TALLOC_FREE(state->cli->smb2.session);
1238 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1239 return status;
1242 inbuf = talloc_move(mem_ctx, &state->inbuf);
1243 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1244 if (pblob != NULL) {
1245 *pblob = state->ret_blob;
1247 if (pinbuf != NULL) {
1248 *pinbuf = inbuf;
1250 if (precv_iov != NULL) {
1251 *precv_iov = recv_iov;
1253 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1254 return state->status;
1257 #ifdef HAVE_KRB5
1259 /****************************************************************************
1260 Use in-memory credentials cache
1261 ****************************************************************************/
1263 static void use_in_memory_ccache(void) {
1264 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1267 /****************************************************************************
1268 Do a spnego/kerberos encrypted session setup.
1269 ****************************************************************************/
1271 struct cli_session_setup_kerberos_state {
1272 struct cli_state *cli;
1273 DATA_BLOB negTokenTarg;
1274 DATA_BLOB session_key_krb5;
1275 ADS_STATUS ads_status;
1278 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1280 static struct tevent_req *cli_session_setup_kerberos_send(
1281 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1282 const char *principal)
1284 struct tevent_req *req, *subreq;
1285 struct cli_session_setup_kerberos_state *state;
1286 int rc;
1288 DEBUG(2,("Doing kerberos session setup\n"));
1290 req = tevent_req_create(mem_ctx, &state,
1291 struct cli_session_setup_kerberos_state);
1292 if (req == NULL) {
1293 return NULL;
1295 state->cli = cli;
1296 state->ads_status = ADS_SUCCESS;
1299 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1300 * we have to acquire a ticket. To be fixed later :-)
1302 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1303 &state->session_key_krb5, 0, NULL, NULL);
1304 if (rc) {
1305 NTSTATUS status;
1307 state->ads_status = ADS_ERROR_KRB5(rc);
1308 status = ads_ntstatus(state->ads_status);
1309 if (NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL)) {
1310 status = NT_STATUS_LOGON_FAILURE;
1311 state->ads_status = ADS_ERROR_NT(status);
1313 DEBUG(1, ("cli_session_setup_kerberos: "
1314 "spnego_gen_krb5_negTokenInit failed: %s - %s\n",
1315 error_message(rc), nt_errstr(status)));
1316 tevent_req_nterror(req, status);
1317 return tevent_req_post(req, ev);
1320 #if 0
1321 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1322 state->negTokenTarg.length);
1323 #endif
1325 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1326 state->cli->smb2.session = smbXcli_session_create(cli,
1327 cli->conn);
1328 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1329 return tevent_req_post(req, ev);
1333 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1334 if (tevent_req_nomem(subreq, req)) {
1335 return tevent_req_post(req, ev);
1337 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1338 return req;
1341 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1343 struct tevent_req *req = tevent_req_callback_data(
1344 subreq, struct tevent_req);
1345 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1346 req, struct cli_session_setup_kerberos_state);
1347 uint8_t *inbuf = NULL;
1348 struct iovec *recv_iov = NULL;
1349 NTSTATUS status;
1351 status = cli_sesssetup_blob_recv(subreq, state,
1352 NULL, &inbuf, &recv_iov);
1353 TALLOC_FREE(subreq);
1354 if (!NT_STATUS_IS_OK(status)) {
1355 tevent_req_nterror(req, status);
1356 return;
1359 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1360 struct smbXcli_session *session = state->cli->smb2.session;
1361 status = smb2cli_session_set_session_key(session,
1362 state->session_key_krb5,
1363 recv_iov);
1364 if (tevent_req_nterror(req, status)) {
1365 return;
1367 } else {
1368 struct smbXcli_session *session = state->cli->smb1.session;
1370 status = smb1cli_session_set_session_key(session,
1371 state->session_key_krb5);
1372 if (tevent_req_nterror(req, status)) {
1373 return;
1376 if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5,
1377 data_blob_null)
1378 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1379 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1380 return;
1384 tevent_req_done(req);
1387 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1389 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1390 req, struct cli_session_setup_kerberos_state);
1391 NTSTATUS status;
1393 if (tevent_req_is_nterror(req, &status)) {
1394 ADS_STATUS ads = state->ads_status;
1396 if (!ADS_ERR_OK(state->ads_status)) {
1397 ads = state->ads_status;
1398 } else {
1399 ads = ADS_ERROR_NT(status);
1401 tevent_req_received(req);
1402 return ads;
1404 tevent_req_received(req);
1405 return ADS_SUCCESS;
1408 #endif /* HAVE_KRB5 */
1410 /****************************************************************************
1411 Do a spnego/NTLMSSP encrypted session setup.
1412 ****************************************************************************/
1414 struct cli_session_setup_ntlmssp_state {
1415 struct tevent_context *ev;
1416 struct cli_state *cli;
1417 struct ntlmssp_state *ntlmssp_state;
1418 int turn;
1419 DATA_BLOB blob_out;
1422 static int cli_session_setup_ntlmssp_state_destructor(
1423 struct cli_session_setup_ntlmssp_state *state)
1425 if (state->ntlmssp_state != NULL) {
1426 TALLOC_FREE(state->ntlmssp_state);
1428 return 0;
1431 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1433 static struct tevent_req *cli_session_setup_ntlmssp_send(
1434 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1435 const char *user, const char *pass, const char *domain)
1437 struct tevent_req *req, *subreq;
1438 struct cli_session_setup_ntlmssp_state *state;
1439 NTSTATUS status;
1440 DATA_BLOB blob_out;
1441 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1443 req = tevent_req_create(mem_ctx, &state,
1444 struct cli_session_setup_ntlmssp_state);
1445 if (req == NULL) {
1446 return NULL;
1448 state->ev = ev;
1449 state->cli = cli;
1450 state->turn = 1;
1452 state->ntlmssp_state = NULL;
1453 talloc_set_destructor(
1454 state, cli_session_setup_ntlmssp_state_destructor);
1456 status = ntlmssp_client_start(state,
1457 lp_netbios_name(),
1458 lp_workgroup(),
1459 lp_client_ntlmv2_auth(),
1460 &state->ntlmssp_state);
1461 if (!NT_STATUS_IS_OK(status)) {
1462 goto fail;
1464 ntlmssp_want_feature(state->ntlmssp_state,
1465 NTLMSSP_FEATURE_SESSION_KEY);
1466 if (cli->use_ccache) {
1467 ntlmssp_want_feature(state->ntlmssp_state,
1468 NTLMSSP_FEATURE_CCACHE);
1470 status = ntlmssp_set_username(state->ntlmssp_state, user);
1471 if (!NT_STATUS_IS_OK(status)) {
1472 goto fail;
1474 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1475 if (!NT_STATUS_IS_OK(status)) {
1476 goto fail;
1478 if (cli->pw_nt_hash) {
1479 status = ntlmssp_set_password_hash(state->ntlmssp_state, pass);
1480 } else {
1481 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1483 if (!NT_STATUS_IS_OK(status)) {
1484 goto fail;
1486 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1487 &blob_out);
1488 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1489 goto fail;
1492 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1493 data_blob_free(&blob_out);
1495 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1496 state->cli->smb2.session = smbXcli_session_create(cli,
1497 cli->conn);
1498 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1499 return tevent_req_post(req, ev);
1503 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1504 if (tevent_req_nomem(subreq, req)) {
1505 return tevent_req_post(req, ev);
1507 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1508 return req;
1509 fail:
1510 tevent_req_nterror(req, status);
1511 return tevent_req_post(req, ev);
1514 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1516 struct tevent_req *req = tevent_req_callback_data(
1517 subreq, struct tevent_req);
1518 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1519 req, struct cli_session_setup_ntlmssp_state);
1520 DATA_BLOB blob_in, msg_in, blob_out;
1521 uint8_t *inbuf = NULL;
1522 struct iovec *recv_iov = NULL;
1523 bool parse_ret;
1524 NTSTATUS status;
1526 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1527 &inbuf, &recv_iov);
1528 TALLOC_FREE(subreq);
1529 data_blob_free(&state->blob_out);
1531 if (NT_STATUS_IS_OK(status)) {
1532 if (state->cli->server_domain[0] == '\0') {
1533 TALLOC_FREE(state->cli->server_domain);
1534 state->cli->server_domain = talloc_strdup(state->cli,
1535 state->ntlmssp_state->server.netbios_domain);
1536 if (state->cli->server_domain == NULL) {
1537 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1538 return;
1542 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1543 struct smbXcli_session *session = state->cli->smb2.session;
1545 if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
1547 * Windows server does not set the
1548 * SMB2_SESSION_FLAG_IS_GUEST nor
1549 * SMB2_SESSION_FLAG_IS_NULL flag.
1551 * This fix makes sure we do not try
1552 * to verify a signature on the final
1553 * session setup response.
1555 TALLOC_FREE(state->ntlmssp_state);
1556 tevent_req_done(req);
1557 return;
1560 status = smb2cli_session_set_session_key(session,
1561 state->ntlmssp_state->session_key,
1562 recv_iov);
1563 if (tevent_req_nterror(req, status)) {
1564 return;
1566 } else {
1567 struct smbXcli_session *session = state->cli->smb1.session;
1569 status = smb1cli_session_set_session_key(session,
1570 state->ntlmssp_state->session_key);
1571 if (tevent_req_nterror(req, status)) {
1572 return;
1575 if (smb1cli_conn_activate_signing(
1576 state->cli->conn, state->ntlmssp_state->session_key,
1577 data_blob_null)
1578 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1579 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1580 return;
1583 TALLOC_FREE(state->ntlmssp_state);
1584 tevent_req_done(req);
1585 return;
1587 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1588 tevent_req_nterror(req, status);
1589 return;
1592 if (blob_in.length == 0) {
1593 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1594 return;
1597 if ((state->turn == 1)
1598 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1599 DATA_BLOB tmp_blob = data_blob_null;
1600 /* the server might give us back two challenges */
1601 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1602 &tmp_blob);
1603 data_blob_free(&tmp_blob);
1604 } else {
1605 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1606 OID_NTLMSSP, &msg_in);
1608 state->turn += 1;
1610 if (!parse_ret) {
1611 DEBUG(3,("Failed to parse auth response\n"));
1612 if (NT_STATUS_IS_OK(status)
1613 || NT_STATUS_EQUAL(status,
1614 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1615 tevent_req_nterror(
1616 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1617 return;
1621 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1623 if (!NT_STATUS_IS_OK(status)
1624 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1625 TALLOC_FREE(state->ntlmssp_state);
1626 tevent_req_nterror(req, status);
1627 return;
1630 state->blob_out = spnego_gen_auth(state, blob_out);
1631 if (tevent_req_nomem(state->blob_out.data, req)) {
1632 return;
1635 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1636 state->blob_out);
1637 if (tevent_req_nomem(subreq, req)) {
1638 return;
1640 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1643 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1645 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1646 req, struct cli_session_setup_ntlmssp_state);
1647 NTSTATUS status;
1649 if (tevent_req_is_nterror(req, &status)) {
1650 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1651 return status;
1653 return NT_STATUS_OK;
1656 #ifdef HAVE_KRB5
1658 static char *cli_session_setup_get_principal(
1659 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1660 const char *remote_name, const char *dest_realm)
1662 char *principal = NULL;
1664 if (!lp_client_use_spnego_principal() ||
1665 strequal(spnego_principal, ADS_IGNORE_PRINCIPAL)) {
1666 spnego_principal = NULL;
1668 if (spnego_principal != NULL) {
1669 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1670 "principal %s\n", spnego_principal));
1671 return talloc_strdup(mem_ctx, spnego_principal);
1673 if (is_ipaddress(remote_name) ||
1674 strequal(remote_name, STAR_SMBSERVER)) {
1675 return NULL;
1678 DEBUG(3, ("cli_session_setup_spnego: using target "
1679 "hostname not SPNEGO principal\n"));
1681 if (dest_realm) {
1682 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1683 if (realm == NULL) {
1684 return NULL;
1686 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1687 remote_name, realm);
1688 TALLOC_FREE(realm);
1689 } else {
1690 principal = kerberos_get_principal_from_service_hostname(
1691 talloc_tos(), "cifs", remote_name, lp_realm());
1693 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1694 principal ? principal : "<null>"));
1696 return principal;
1698 #endif
1700 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1701 const char *principal)
1703 char *account, *p;
1705 account = talloc_strdup(mem_ctx, principal);
1706 if (account == NULL) {
1707 return NULL;
1709 p = strchr_m(account, '@');
1710 if (p != NULL) {
1711 *p = '\0';
1713 return account;
1716 /****************************************************************************
1717 Do a spnego encrypted session setup.
1719 user_domain: The shortname of the domain the user/machine is a member of.
1720 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1721 ****************************************************************************/
1723 struct cli_session_setup_spnego_state {
1724 struct tevent_context *ev;
1725 struct cli_state *cli;
1726 const char *user;
1727 const char *account;
1728 const char *pass;
1729 const char *user_domain;
1730 const char *dest_realm;
1731 ADS_STATUS result;
1734 #ifdef HAVE_KRB5
1735 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1736 #endif
1738 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1740 static struct tevent_req *cli_session_setup_spnego_send(
1741 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1742 const char *user, const char *pass, const char *user_domain,
1743 const char *dest_realm)
1745 struct tevent_req *req, *subreq;
1746 struct cli_session_setup_spnego_state *state;
1747 char *principal = NULL;
1748 char *OIDs[ASN1_MAX_OIDS];
1749 int i;
1750 const DATA_BLOB *server_blob;
1752 req = tevent_req_create(mem_ctx, &state,
1753 struct cli_session_setup_spnego_state);
1754 if (req == NULL) {
1755 return NULL;
1757 state->ev = ev;
1758 state->cli = cli;
1759 state->user = user;
1760 state->pass = pass;
1761 state->user_domain = user_domain;
1762 state->dest_realm = dest_realm;
1764 state->account = cli_session_setup_get_account(state, user);
1765 if (tevent_req_nomem(state->account, req)) {
1766 return tevent_req_post(req, ev);
1769 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1771 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1772 (unsigned long)server_blob->length));
1774 /* the server might not even do spnego */
1775 if (server_blob->length == 0) {
1776 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1777 goto ntlmssp;
1780 #if 0
1781 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1782 #endif
1784 /* The server sent us the first part of the SPNEGO exchange in the
1785 * negprot reply. It is WRONG to depend on the principal sent in the
1786 * negprot reply, but right now we do it. If we don't receive one,
1787 * we try to best guess, then fall back to NTLM. */
1788 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1789 &principal, NULL) ||
1790 OIDs[0] == NULL) {
1791 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1792 tevent_req_done(req);
1793 return tevent_req_post(req, ev);
1796 /* make sure the server understands kerberos */
1797 for (i=0;OIDs[i];i++) {
1798 if (i == 0)
1799 DEBUG(3,("got OID=%s\n", OIDs[i]));
1800 else
1801 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1802 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1803 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1804 cli->got_kerberos_mechanism = True;
1806 talloc_free(OIDs[i]);
1809 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1811 #ifdef HAVE_KRB5
1812 /* If password is set we reauthenticate to kerberos server
1813 * and do not store results */
1815 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1816 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
1817 char *tmp;
1820 tmp = cli_session_setup_get_principal(
1821 talloc_tos(), principal, remote_name, dest_realm);
1822 TALLOC_FREE(principal);
1823 principal = tmp;
1825 if (pass && *pass) {
1826 int ret;
1828 use_in_memory_ccache();
1829 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1831 if (ret){
1832 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1833 TALLOC_FREE(principal);
1834 if (cli->fallback_after_kerberos)
1835 goto ntlmssp;
1836 state->result = ADS_ERROR_KRB5(ret);
1837 tevent_req_done(req);
1838 return tevent_req_post(req, ev);
1842 if (principal) {
1843 subreq = cli_session_setup_kerberos_send(
1844 state, ev, cli, principal);
1845 if (tevent_req_nomem(subreq, req)) {
1846 return tevent_req_post(req, ev);
1848 tevent_req_set_callback(
1849 subreq, cli_session_setup_spnego_done_krb,
1850 req);
1851 return req;
1854 #endif
1856 ntlmssp:
1857 subreq = cli_session_setup_ntlmssp_send(
1858 state, ev, cli, state->account, pass, user_domain);
1859 if (tevent_req_nomem(subreq, req)) {
1860 return tevent_req_post(req, ev);
1862 tevent_req_set_callback(
1863 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1864 return req;
1867 #ifdef HAVE_KRB5
1868 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1870 struct tevent_req *req = tevent_req_callback_data(
1871 subreq, struct tevent_req);
1872 struct cli_session_setup_spnego_state *state = tevent_req_data(
1873 req, struct cli_session_setup_spnego_state);
1875 state->result = cli_session_setup_kerberos_recv(subreq);
1876 TALLOC_FREE(subreq);
1878 if (ADS_ERR_OK(state->result) ||
1879 !state->cli->fallback_after_kerberos) {
1880 tevent_req_done(req);
1881 return;
1884 subreq = cli_session_setup_ntlmssp_send(
1885 state, state->ev, state->cli, state->account, state->pass,
1886 state->user_domain);
1887 if (tevent_req_nomem(subreq, req)) {
1888 return;
1890 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1891 req);
1893 #endif
1895 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1897 struct tevent_req *req = tevent_req_callback_data(
1898 subreq, struct tevent_req);
1899 struct cli_session_setup_spnego_state *state = tevent_req_data(
1900 req, struct cli_session_setup_spnego_state);
1901 NTSTATUS status;
1903 status = cli_session_setup_ntlmssp_recv(subreq);
1904 TALLOC_FREE(subreq);
1905 state->result = ADS_ERROR_NT(status);
1906 tevent_req_done(req);
1909 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1911 struct cli_session_setup_spnego_state *state = tevent_req_data(
1912 req, struct cli_session_setup_spnego_state);
1914 return state->result;
1917 struct cli_session_setup_state {
1918 uint8_t dummy;
1921 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1922 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1923 static void cli_session_setup_done_guest(struct tevent_req *subreq);
1924 static void cli_session_setup_done_plain(struct tevent_req *subreq);
1925 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1927 /****************************************************************************
1928 Send a session setup. The username and workgroup is in UNIX character
1929 format and must be converted to DOS codepage format before sending. If the
1930 password is in plaintext, the same should be done.
1931 ****************************************************************************/
1933 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1934 struct tevent_context *ev,
1935 struct cli_state *cli,
1936 const char *user,
1937 const char *pass, int passlen,
1938 const char *ntpass, int ntpasslen,
1939 const char *workgroup)
1941 struct tevent_req *req, *subreq;
1942 struct cli_session_setup_state *state;
1943 char *p;
1944 char *user2;
1945 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1947 req = tevent_req_create(mem_ctx, &state,
1948 struct cli_session_setup_state);
1949 if (req == NULL) {
1950 return NULL;
1953 if (user) {
1954 user2 = talloc_strdup(state, user);
1955 } else {
1956 user2 = talloc_strdup(state, "");
1958 if (user2 == NULL) {
1959 tevent_req_oom(req);
1960 return tevent_req_post(req, ev);
1963 if (!workgroup) {
1964 workgroup = "";
1967 /* allow for workgroups as part of the username */
1968 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1969 (p=strchr_m(user2,*lp_winbind_separator()))) {
1970 *p = 0;
1971 user = p+1;
1972 if (!strupper_m(user2)) {
1973 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1974 return tevent_req_post(req, ev);
1976 workgroup = user2;
1979 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1980 tevent_req_done(req);
1981 return tevent_req_post(req, ev);
1984 /* now work out what sort of session setup we are going to
1985 do. I have split this into separate functions to make the
1986 flow a bit easier to understand (tridge) */
1988 /* if its an older server then we have to use the older request format */
1990 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1991 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1992 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
1993 " or 'client ntlmv2 auth = yes'\n"));
1994 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1995 return tevent_req_post(req, ev);
1998 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1999 !lp_client_plaintext_auth() && (*pass)) {
2000 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2001 " or 'client ntlmv2 auth = yes'\n"));
2002 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2003 return tevent_req_post(req, ev);
2006 subreq = cli_session_setup_lanman2_send(
2007 state, ev, cli, user, pass, passlen, workgroup);
2008 if (tevent_req_nomem(subreq, req)) {
2009 return tevent_req_post(req, ev);
2011 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2012 req);
2013 return req;
2016 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2017 const char *remote_realm = cli_state_remote_realm(cli);
2019 subreq = cli_session_setup_spnego_send(
2020 state, ev, cli, user, pass, workgroup, remote_realm);
2021 if (tevent_req_nomem(subreq, req)) {
2022 return tevent_req_post(req, ev);
2024 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2025 req);
2026 return req;
2029 /* if no user is supplied then we have to do an anonymous connection.
2030 passwords are ignored */
2032 if (!user || !*user) {
2033 subreq = cli_session_setup_guest_send(state, ev, cli);
2034 if (tevent_req_nomem(subreq, req)) {
2035 return tevent_req_post(req, ev);
2037 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2038 req);
2039 return req;
2042 /* if the server is share level then send a plaintext null
2043 password at this point. The password is sent in the tree
2044 connect */
2046 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2047 subreq = cli_session_setup_plain_send(
2048 state, ev, cli, user, "", workgroup);
2049 if (tevent_req_nomem(subreq, req)) {
2050 return tevent_req_post(req, ev);
2052 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2053 req);
2054 return req;
2057 /* if the server doesn't support encryption then we have to use
2058 plaintext. The second password is ignored */
2060 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2061 if (!lp_client_plaintext_auth() && (*pass)) {
2062 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2063 " or 'client ntlmv2 auth = yes'\n"));
2064 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2065 return tevent_req_post(req, ev);
2067 subreq = cli_session_setup_plain_send(
2068 state, ev, cli, user, pass, workgroup);
2069 if (tevent_req_nomem(subreq, req)) {
2070 return tevent_req_post(req, ev);
2072 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2073 req);
2074 return req;
2077 /* if the server supports extended security then use SPNEGO */
2079 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2080 const char *remote_realm = cli_state_remote_realm(cli);
2082 subreq = cli_session_setup_spnego_send(
2083 state, ev, cli, user, pass, workgroup, remote_realm);
2084 if (tevent_req_nomem(subreq, req)) {
2085 return tevent_req_post(req, ev);
2087 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2088 req);
2089 return req;
2090 } else {
2091 /* otherwise do a NT1 style session setup */
2093 subreq = cli_session_setup_nt1_send(
2094 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2095 workgroup);
2096 if (tevent_req_nomem(subreq, req)) {
2097 return tevent_req_post(req, ev);
2099 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2100 req);
2101 return req;
2104 tevent_req_done(req);
2105 return tevent_req_post(req, ev);
2108 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2110 struct tevent_req *req = tevent_req_callback_data(
2111 subreq, struct tevent_req);
2112 NTSTATUS status;
2114 status = cli_session_setup_lanman2_recv(subreq);
2115 TALLOC_FREE(subreq);
2116 if (!NT_STATUS_IS_OK(status)) {
2117 tevent_req_nterror(req, status);
2118 return;
2120 tevent_req_done(req);
2123 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2125 struct tevent_req *req = tevent_req_callback_data(
2126 subreq, struct tevent_req);
2127 ADS_STATUS status;
2129 status = cli_session_setup_spnego_recv(subreq);
2130 TALLOC_FREE(subreq);
2131 if (!ADS_ERR_OK(status)) {
2132 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2133 tevent_req_nterror(req, ads_ntstatus(status));
2134 return;
2136 tevent_req_done(req);
2139 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2141 struct tevent_req *req = tevent_req_callback_data(
2142 subreq, struct tevent_req);
2143 NTSTATUS status;
2145 status = cli_session_setup_guest_recv(subreq);
2146 TALLOC_FREE(subreq);
2147 if (!NT_STATUS_IS_OK(status)) {
2148 tevent_req_nterror(req, status);
2149 return;
2151 tevent_req_done(req);
2154 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2156 struct tevent_req *req = tevent_req_callback_data(
2157 subreq, struct tevent_req);
2158 NTSTATUS status;
2160 status = cli_session_setup_plain_recv(subreq);
2161 TALLOC_FREE(subreq);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 tevent_req_nterror(req, status);
2164 return;
2166 tevent_req_done(req);
2169 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2171 struct tevent_req *req = tevent_req_callback_data(
2172 subreq, struct tevent_req);
2173 NTSTATUS status;
2175 status = cli_session_setup_nt1_recv(subreq);
2176 TALLOC_FREE(subreq);
2177 if (!NT_STATUS_IS_OK(status)) {
2178 DEBUG(3, ("cli_session_setup: NT1 session setup "
2179 "failed: %s\n", nt_errstr(status)));
2180 tevent_req_nterror(req, status);
2181 return;
2183 tevent_req_done(req);
2186 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2188 return tevent_req_simple_recv_ntstatus(req);
2191 NTSTATUS cli_session_setup(struct cli_state *cli,
2192 const char *user,
2193 const char *pass, int passlen,
2194 const char *ntpass, int ntpasslen,
2195 const char *workgroup)
2197 struct tevent_context *ev;
2198 struct tevent_req *req;
2199 NTSTATUS status = NT_STATUS_NO_MEMORY;
2201 if (smbXcli_conn_has_async_calls(cli->conn)) {
2202 return NT_STATUS_INVALID_PARAMETER;
2204 ev = samba_tevent_context_init(talloc_tos());
2205 if (ev == NULL) {
2206 goto fail;
2208 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2209 ntpass, ntpasslen, workgroup);
2210 if (req == NULL) {
2211 goto fail;
2213 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2214 goto fail;
2216 status = cli_session_setup_recv(req);
2217 fail:
2218 TALLOC_FREE(ev);
2219 return status;
2222 /****************************************************************************
2223 Send a uloggoff.
2224 *****************************************************************************/
2226 struct cli_ulogoff_state {
2227 struct cli_state *cli;
2228 uint16_t vwv[3];
2231 static void cli_ulogoff_done(struct tevent_req *subreq);
2233 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2234 struct tevent_context *ev,
2235 struct cli_state *cli)
2237 struct tevent_req *req, *subreq;
2238 struct cli_ulogoff_state *state;
2240 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2241 if (req == NULL) {
2242 return NULL;
2244 state->cli = cli;
2246 SCVAL(state->vwv+0, 0, 0xFF);
2247 SCVAL(state->vwv+1, 0, 0);
2248 SSVAL(state->vwv+2, 0, 0);
2250 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2251 0, NULL);
2252 if (tevent_req_nomem(subreq, req)) {
2253 return tevent_req_post(req, ev);
2255 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2256 return req;
2259 static void cli_ulogoff_done(struct tevent_req *subreq)
2261 struct tevent_req *req = tevent_req_callback_data(
2262 subreq, struct tevent_req);
2263 struct cli_ulogoff_state *state = tevent_req_data(
2264 req, struct cli_ulogoff_state);
2265 NTSTATUS status;
2267 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2268 if (!NT_STATUS_IS_OK(status)) {
2269 tevent_req_nterror(req, status);
2270 return;
2272 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2273 tevent_req_done(req);
2276 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2278 return tevent_req_simple_recv_ntstatus(req);
2281 NTSTATUS cli_ulogoff(struct cli_state *cli)
2283 struct tevent_context *ev;
2284 struct tevent_req *req;
2285 NTSTATUS status = NT_STATUS_NO_MEMORY;
2287 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2288 status = smb2cli_logoff(cli->conn,
2289 cli->timeout,
2290 cli->smb2.session);
2291 if (!NT_STATUS_IS_OK(status)) {
2292 return status;
2294 smb2cli_session_set_id_and_flags(cli->smb2.session,
2295 UINT64_MAX, 0);
2296 return NT_STATUS_OK;
2299 if (smbXcli_conn_has_async_calls(cli->conn)) {
2300 return NT_STATUS_INVALID_PARAMETER;
2302 ev = samba_tevent_context_init(talloc_tos());
2303 if (ev == NULL) {
2304 goto fail;
2306 req = cli_ulogoff_send(ev, ev, cli);
2307 if (req == NULL) {
2308 goto fail;
2310 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2311 goto fail;
2313 status = cli_ulogoff_recv(req);
2314 fail:
2315 TALLOC_FREE(ev);
2316 return status;
2319 /****************************************************************************
2320 Send a tconX.
2321 ****************************************************************************/
2323 struct cli_tcon_andx_state {
2324 struct cli_state *cli;
2325 uint16_t vwv[4];
2326 struct iovec bytes;
2329 static void cli_tcon_andx_done(struct tevent_req *subreq);
2331 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2332 struct tevent_context *ev,
2333 struct cli_state *cli,
2334 const char *share, const char *dev,
2335 const char *pass, int passlen,
2336 struct tevent_req **psmbreq)
2338 struct tevent_req *req, *subreq;
2339 struct cli_tcon_andx_state *state;
2340 uint8_t p24[24];
2341 uint16_t *vwv;
2342 char *tmp = NULL;
2343 uint8_t *bytes;
2344 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2345 uint16_t tcon_flags = 0;
2347 *psmbreq = NULL;
2349 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2350 if (req == NULL) {
2351 return NULL;
2353 state->cli = cli;
2354 vwv = state->vwv;
2356 cli->share = talloc_strdup(cli, share);
2357 if (!cli->share) {
2358 return NULL;
2361 /* in user level security don't send a password now */
2362 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2363 passlen = 1;
2364 pass = "";
2365 } else if (pass == NULL) {
2366 DEBUG(1, ("Server not using user level security and no "
2367 "password supplied.\n"));
2368 goto access_denied;
2371 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2372 *pass && passlen != 24) {
2373 if (!lp_client_lanman_auth()) {
2374 DEBUG(1, ("Server requested LANMAN password "
2375 "(share-level security) but "
2376 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2377 goto access_denied;
2381 * Non-encrypted passwords - convert to DOS codepage before
2382 * encryption.
2384 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2385 passlen = 24;
2386 pass = (const char *)p24;
2387 } else {
2388 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2389 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2390 == 0) {
2391 uint8_t *tmp_pass;
2393 if (!lp_client_plaintext_auth() && (*pass)) {
2394 DEBUG(1, ("Server requested PLAINTEXT "
2395 "password but "
2396 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2397 goto access_denied;
2401 * Non-encrypted passwords - convert to DOS codepage
2402 * before using.
2404 tmp_pass = talloc_array(talloc_tos(), uint8_t, 0);
2405 if (tevent_req_nomem(tmp_pass, req)) {
2406 return tevent_req_post(req, ev);
2408 tmp_pass = trans2_bytes_push_str(tmp_pass,
2409 false, /* always DOS */
2410 pass,
2411 passlen,
2412 NULL);
2413 if (tevent_req_nomem(tmp_pass, req)) {
2414 return tevent_req_post(req, ev);
2416 pass = (const char *)tmp_pass;
2417 passlen = talloc_get_size(tmp_pass);
2421 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2422 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2424 SCVAL(vwv+0, 0, 0xFF);
2425 SCVAL(vwv+0, 1, 0);
2426 SSVAL(vwv+1, 0, 0);
2427 SSVAL(vwv+2, 0, tcon_flags);
2428 SSVAL(vwv+3, 0, passlen);
2430 if (passlen && pass) {
2431 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2432 } else {
2433 bytes = talloc_array(state, uint8_t, 0);
2437 * Add the sharename
2439 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2440 smbXcli_conn_remote_name(cli->conn), share);
2441 if (tmp == NULL) {
2442 TALLOC_FREE(req);
2443 return NULL;
2445 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2446 NULL);
2447 TALLOC_FREE(tmp);
2450 * Add the devicetype
2452 tmp = talloc_strdup_upper(talloc_tos(), dev);
2453 if (tmp == NULL) {
2454 TALLOC_FREE(req);
2455 return NULL;
2457 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2458 TALLOC_FREE(tmp);
2460 if (bytes == NULL) {
2461 TALLOC_FREE(req);
2462 return NULL;
2465 state->bytes.iov_base = (void *)bytes;
2466 state->bytes.iov_len = talloc_get_size(bytes);
2468 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2469 1, &state->bytes);
2470 if (subreq == NULL) {
2471 TALLOC_FREE(req);
2472 return NULL;
2474 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2475 *psmbreq = subreq;
2476 return req;
2478 access_denied:
2479 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2480 return tevent_req_post(req, ev);
2483 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2484 struct tevent_context *ev,
2485 struct cli_state *cli,
2486 const char *share, const char *dev,
2487 const char *pass, int passlen)
2489 struct tevent_req *req, *subreq;
2490 NTSTATUS status;
2492 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2493 &subreq);
2494 if (req == NULL) {
2495 return NULL;
2497 if (subreq == NULL) {
2498 return req;
2500 status = smb1cli_req_chain_submit(&subreq, 1);
2501 if (!NT_STATUS_IS_OK(status)) {
2502 tevent_req_nterror(req, status);
2503 return tevent_req_post(req, ev);
2505 return req;
2508 static void cli_tcon_andx_done(struct tevent_req *subreq)
2510 struct tevent_req *req = tevent_req_callback_data(
2511 subreq, struct tevent_req);
2512 struct cli_tcon_andx_state *state = tevent_req_data(
2513 req, struct cli_tcon_andx_state);
2514 struct cli_state *cli = state->cli;
2515 uint8_t *in;
2516 uint8_t *inhdr;
2517 uint8_t wct;
2518 uint16_t *vwv;
2519 uint32_t num_bytes;
2520 uint8_t *bytes;
2521 NTSTATUS status;
2522 uint16_t optional_support = 0;
2524 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2525 &num_bytes, &bytes);
2526 TALLOC_FREE(subreq);
2527 if (!NT_STATUS_IS_OK(status)) {
2528 tevent_req_nterror(req, status);
2529 return;
2532 inhdr = in + NBT_HDR_SIZE;
2534 if (num_bytes) {
2535 if (clistr_pull_talloc(cli,
2536 (const char *)inhdr,
2537 SVAL(inhdr, HDR_FLG2),
2538 &cli->dev,
2539 bytes,
2540 num_bytes,
2541 STR_TERMINATE|STR_ASCII) == -1) {
2542 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2543 return;
2545 } else {
2546 cli->dev = talloc_strdup(cli, "");
2547 if (cli->dev == NULL) {
2548 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2549 return;
2553 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2554 /* almost certainly win95 - enable bug fixes */
2555 cli->win95 = True;
2559 * Make sure that we have the optional support 16-bit field. WCT > 2.
2560 * Avoids issues when connecting to Win9x boxes sharing files
2563 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2564 optional_support = SVAL(vwv+2, 0);
2567 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2568 smb1cli_session_protect_session_key(cli->smb1.session);
2571 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2572 SVAL(inhdr, HDR_TID),
2573 optional_support,
2574 0, /* maximal_access */
2575 0, /* guest_maximal_access */
2576 NULL, /* service */
2577 NULL); /* fs_type */
2579 tevent_req_done(req);
2582 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2584 return tevent_req_simple_recv_ntstatus(req);
2587 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2588 const char *dev, const char *pass, int passlen)
2590 TALLOC_CTX *frame = talloc_stackframe();
2591 struct tevent_context *ev;
2592 struct tevent_req *req;
2593 NTSTATUS status = NT_STATUS_NO_MEMORY;
2595 if (smbXcli_conn_has_async_calls(cli->conn)) {
2597 * Can't use sync call while an async call is in flight
2599 status = NT_STATUS_INVALID_PARAMETER;
2600 goto fail;
2603 ev = samba_tevent_context_init(frame);
2604 if (ev == NULL) {
2605 goto fail;
2608 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2609 if (req == NULL) {
2610 goto fail;
2613 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2614 goto fail;
2617 status = cli_tcon_andx_recv(req);
2618 fail:
2619 TALLOC_FREE(frame);
2620 return status;
2623 struct cli_tree_connect_state {
2624 struct cli_state *cli;
2627 static struct tevent_req *cli_raw_tcon_send(
2628 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2629 const char *service, const char *pass, const char *dev);
2630 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2631 uint16_t *max_xmit, uint16_t *tid);
2633 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2634 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2635 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2637 static struct tevent_req *cli_tree_connect_send(
2638 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2639 const char *share, const char *dev, const char *pass, int passlen)
2641 struct tevent_req *req, *subreq;
2642 struct cli_tree_connect_state *state;
2644 req = tevent_req_create(mem_ctx, &state,
2645 struct cli_tree_connect_state);
2646 if (req == NULL) {
2647 return NULL;
2649 state->cli = cli;
2651 cli->share = talloc_strdup(cli, share);
2652 if (tevent_req_nomem(cli->share, req)) {
2653 return tevent_req_post(req, ev);
2656 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2657 char *unc;
2659 cli->smb2.tcon = smbXcli_tcon_create(cli);
2660 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2661 return tevent_req_post(req, ev);
2664 unc = talloc_asprintf(state, "\\\\%s\\%s",
2665 smbXcli_conn_remote_name(cli->conn),
2666 share);
2667 if (tevent_req_nomem(unc, req)) {
2668 return tevent_req_post(req, ev);
2671 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2672 cli->smb2.session, cli->smb2.tcon,
2673 0, /* flags */
2674 unc);
2675 if (tevent_req_nomem(subreq, req)) {
2676 return tevent_req_post(req, ev);
2678 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2679 req);
2680 return req;
2683 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2684 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2685 pass, passlen);
2686 if (tevent_req_nomem(subreq, req)) {
2687 return tevent_req_post(req, ev);
2689 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2690 req);
2691 return req;
2694 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2695 if (tevent_req_nomem(subreq, req)) {
2696 return tevent_req_post(req, ev);
2698 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2700 return req;
2703 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2705 tevent_req_simple_finish_ntstatus(
2706 subreq, smb2cli_tcon_recv(subreq));
2709 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2711 tevent_req_simple_finish_ntstatus(
2712 subreq, cli_tcon_andx_recv(subreq));
2715 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2717 struct tevent_req *req = tevent_req_callback_data(
2718 subreq, struct tevent_req);
2719 struct cli_tree_connect_state *state = tevent_req_data(
2720 req, struct cli_tree_connect_state);
2721 NTSTATUS status;
2722 uint16_t max_xmit = 0;
2723 uint16_t tid = 0;
2725 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2726 if (tevent_req_nterror(req, status)) {
2727 return;
2730 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2731 tid,
2732 0, /* optional_support */
2733 0, /* maximal_access */
2734 0, /* guest_maximal_access */
2735 NULL, /* service */
2736 NULL); /* fs_type */
2738 tevent_req_done(req);
2741 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2743 return tevent_req_simple_recv_ntstatus(req);
2746 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2747 const char *dev, const char *pass, int passlen)
2749 struct tevent_context *ev;
2750 struct tevent_req *req;
2751 NTSTATUS status = NT_STATUS_NO_MEMORY;
2753 if (smbXcli_conn_has_async_calls(cli->conn)) {
2754 return NT_STATUS_INVALID_PARAMETER;
2756 ev = samba_tevent_context_init(talloc_tos());
2757 if (ev == NULL) {
2758 goto fail;
2760 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2761 if (req == NULL) {
2762 goto fail;
2764 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2765 goto fail;
2767 status = cli_tree_connect_recv(req);
2768 fail:
2769 TALLOC_FREE(ev);
2770 return status;
2773 /****************************************************************************
2774 Send a tree disconnect.
2775 ****************************************************************************/
2777 struct cli_tdis_state {
2778 struct cli_state *cli;
2781 static void cli_tdis_done(struct tevent_req *subreq);
2783 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2784 struct tevent_context *ev,
2785 struct cli_state *cli)
2787 struct tevent_req *req, *subreq;
2788 struct cli_tdis_state *state;
2790 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2791 if (req == NULL) {
2792 return NULL;
2794 state->cli = cli;
2796 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2797 if (tevent_req_nomem(subreq, req)) {
2798 return tevent_req_post(req, ev);
2800 tevent_req_set_callback(subreq, cli_tdis_done, req);
2801 return req;
2804 static void cli_tdis_done(struct tevent_req *subreq)
2806 struct tevent_req *req = tevent_req_callback_data(
2807 subreq, struct tevent_req);
2808 struct cli_tdis_state *state = tevent_req_data(
2809 req, struct cli_tdis_state);
2810 NTSTATUS status;
2812 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2813 TALLOC_FREE(subreq);
2814 if (!NT_STATUS_IS_OK(status)) {
2815 tevent_req_nterror(req, status);
2816 return;
2818 cli_state_set_tid(state->cli, UINT16_MAX);
2819 tevent_req_done(req);
2822 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2824 return tevent_req_simple_recv_ntstatus(req);
2827 NTSTATUS cli_tdis(struct cli_state *cli)
2829 struct tevent_context *ev;
2830 struct tevent_req *req;
2831 NTSTATUS status = NT_STATUS_NO_MEMORY;
2833 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2834 return smb2cli_tdis(cli->conn,
2835 cli->timeout,
2836 cli->smb2.session,
2837 cli->smb2.tcon);
2840 if (smbXcli_conn_has_async_calls(cli->conn)) {
2841 return NT_STATUS_INVALID_PARAMETER;
2843 ev = samba_tevent_context_init(talloc_tos());
2844 if (ev == NULL) {
2845 goto fail;
2847 req = cli_tdis_send(ev, ev, cli);
2848 if (req == NULL) {
2849 goto fail;
2851 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2852 goto fail;
2854 status = cli_tdis_recv(req);
2855 fail:
2856 TALLOC_FREE(ev);
2857 return status;
2860 struct cli_connect_sock_state {
2861 const char **called_names;
2862 const char **calling_names;
2863 int *called_types;
2864 int fd;
2865 uint16_t port;
2868 static void cli_connect_sock_done(struct tevent_req *subreq);
2871 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2872 * nonzero address.
2875 static struct tevent_req *cli_connect_sock_send(
2876 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2877 const char *host, int name_type, const struct sockaddr_storage *pss,
2878 const char *myname, uint16_t port)
2880 struct tevent_req *req, *subreq;
2881 struct cli_connect_sock_state *state;
2882 const char *prog;
2883 struct sockaddr_storage *addrs;
2884 unsigned i, num_addrs;
2885 NTSTATUS status;
2887 req = tevent_req_create(mem_ctx, &state,
2888 struct cli_connect_sock_state);
2889 if (req == NULL) {
2890 return NULL;
2893 prog = getenv("LIBSMB_PROG");
2894 if (prog != NULL) {
2895 state->fd = sock_exec(prog);
2896 if (state->fd == -1) {
2897 status = map_nt_error_from_unix(errno);
2898 tevent_req_nterror(req, status);
2899 } else {
2900 state->port = 0;
2901 tevent_req_done(req);
2903 return tevent_req_post(req, ev);
2906 if ((pss == NULL) || is_zero_addr(pss)) {
2909 * Here we cheat. resolve_name_list is not async at all. So
2910 * this call will only be really async if the name lookup has
2911 * been done externally.
2914 status = resolve_name_list(state, host, name_type,
2915 &addrs, &num_addrs);
2916 if (!NT_STATUS_IS_OK(status)) {
2917 tevent_req_nterror(req, status);
2918 return tevent_req_post(req, ev);
2920 } else {
2921 addrs = talloc_array(state, struct sockaddr_storage, 1);
2922 if (tevent_req_nomem(addrs, req)) {
2923 return tevent_req_post(req, ev);
2925 addrs[0] = *pss;
2926 num_addrs = 1;
2929 state->called_names = talloc_array(state, const char *, num_addrs);
2930 if (tevent_req_nomem(state->called_names, req)) {
2931 return tevent_req_post(req, ev);
2933 state->called_types = talloc_array(state, int, num_addrs);
2934 if (tevent_req_nomem(state->called_types, req)) {
2935 return tevent_req_post(req, ev);
2937 state->calling_names = talloc_array(state, const char *, num_addrs);
2938 if (tevent_req_nomem(state->calling_names, req)) {
2939 return tevent_req_post(req, ev);
2941 for (i=0; i<num_addrs; i++) {
2942 state->called_names[i] = host;
2943 state->called_types[i] = name_type;
2944 state->calling_names[i] = myname;
2947 subreq = smbsock_any_connect_send(
2948 state, ev, addrs, state->called_names, state->called_types,
2949 state->calling_names, NULL, num_addrs, port);
2950 if (tevent_req_nomem(subreq, req)) {
2951 return tevent_req_post(req, ev);
2953 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2954 return req;
2957 static void cli_connect_sock_done(struct tevent_req *subreq)
2959 struct tevent_req *req = tevent_req_callback_data(
2960 subreq, struct tevent_req);
2961 struct cli_connect_sock_state *state = tevent_req_data(
2962 req, struct cli_connect_sock_state);
2963 NTSTATUS status;
2965 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2966 &state->port);
2967 TALLOC_FREE(subreq);
2968 if (tevent_req_nterror(req, status)) {
2969 return;
2971 set_socket_options(state->fd, lp_socket_options());
2972 tevent_req_done(req);
2975 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2976 int *pfd, uint16_t *pport)
2978 struct cli_connect_sock_state *state = tevent_req_data(
2979 req, struct cli_connect_sock_state);
2980 NTSTATUS status;
2982 if (tevent_req_is_nterror(req, &status)) {
2983 return status;
2985 *pfd = state->fd;
2986 *pport = state->port;
2987 return NT_STATUS_OK;
2990 struct cli_connect_nb_state {
2991 const char *desthost;
2992 int signing_state;
2993 int flags;
2994 struct cli_state *cli;
2997 static void cli_connect_nb_done(struct tevent_req *subreq);
2999 static struct tevent_req *cli_connect_nb_send(
3000 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3001 const char *host, const struct sockaddr_storage *dest_ss,
3002 uint16_t port, int name_type, const char *myname,
3003 int signing_state, int flags)
3005 struct tevent_req *req, *subreq;
3006 struct cli_connect_nb_state *state;
3008 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3009 if (req == NULL) {
3010 return NULL;
3012 state->signing_state = signing_state;
3013 state->flags = flags;
3015 if (host != NULL) {
3016 char *p = strchr(host, '#');
3018 if (p != NULL) {
3019 name_type = strtol(p+1, NULL, 16);
3020 host = talloc_strndup(state, host, p - host);
3021 if (tevent_req_nomem(host, req)) {
3022 return tevent_req_post(req, ev);
3026 state->desthost = host;
3027 } else {
3028 state->desthost = print_canonical_sockaddr(state, dest_ss);
3029 if (tevent_req_nomem(state->desthost, req)) {
3030 return tevent_req_post(req, ev);
3034 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3035 myname, port);
3036 if (tevent_req_nomem(subreq, req)) {
3037 return tevent_req_post(req, ev);
3039 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3040 return req;
3043 static void cli_connect_nb_done(struct tevent_req *subreq)
3045 struct tevent_req *req = tevent_req_callback_data(
3046 subreq, struct tevent_req);
3047 struct cli_connect_nb_state *state = tevent_req_data(
3048 req, struct cli_connect_nb_state);
3049 NTSTATUS status;
3050 int fd = 0;
3051 uint16_t port;
3053 status = cli_connect_sock_recv(subreq, &fd, &port);
3054 TALLOC_FREE(subreq);
3055 if (tevent_req_nterror(req, status)) {
3056 return;
3059 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3060 state->signing_state, state->flags);
3061 if (tevent_req_nomem(state->cli, req)) {
3062 close(fd);
3063 return;
3065 tevent_req_done(req);
3068 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3069 struct cli_state **pcli)
3071 struct cli_connect_nb_state *state = tevent_req_data(
3072 req, struct cli_connect_nb_state);
3073 NTSTATUS status;
3075 if (tevent_req_is_nterror(req, &status)) {
3076 return status;
3078 *pcli = talloc_move(NULL, &state->cli);
3079 return NT_STATUS_OK;
3082 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3083 uint16_t port, int name_type, const char *myname,
3084 int signing_state, int flags, struct cli_state **pcli)
3086 struct tevent_context *ev;
3087 struct tevent_req *req;
3088 NTSTATUS status = NT_STATUS_NO_MEMORY;
3090 ev = samba_tevent_context_init(talloc_tos());
3091 if (ev == NULL) {
3092 goto fail;
3094 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3095 myname, signing_state, flags);
3096 if (req == NULL) {
3097 goto fail;
3099 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3100 goto fail;
3102 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3103 goto fail;
3105 status = cli_connect_nb_recv(req, pcli);
3106 fail:
3107 TALLOC_FREE(ev);
3108 return status;
3111 struct cli_start_connection_state {
3112 struct tevent_context *ev;
3113 struct cli_state *cli;
3116 static void cli_start_connection_connected(struct tevent_req *subreq);
3117 static void cli_start_connection_done(struct tevent_req *subreq);
3120 establishes a connection to after the negprot.
3121 @param output_cli A fully initialised cli structure, non-null only on success
3122 @param dest_host The netbios name of the remote host
3123 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3124 @param port (optional) The destination port (0 for default)
3127 static struct tevent_req *cli_start_connection_send(
3128 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3129 const char *my_name, const char *dest_host,
3130 const struct sockaddr_storage *dest_ss, int port,
3131 int signing_state, int flags)
3133 struct tevent_req *req, *subreq;
3134 struct cli_start_connection_state *state;
3136 req = tevent_req_create(mem_ctx, &state,
3137 struct cli_start_connection_state);
3138 if (req == NULL) {
3139 return NULL;
3141 state->ev = ev;
3143 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3144 0x20, my_name, signing_state, flags);
3145 if (tevent_req_nomem(subreq, req)) {
3146 return tevent_req_post(req, ev);
3148 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3149 return req;
3152 static void cli_start_connection_connected(struct tevent_req *subreq)
3154 struct tevent_req *req = tevent_req_callback_data(
3155 subreq, struct tevent_req);
3156 struct cli_start_connection_state *state = tevent_req_data(
3157 req, struct cli_start_connection_state);
3158 NTSTATUS status;
3160 status = cli_connect_nb_recv(subreq, &state->cli);
3161 TALLOC_FREE(subreq);
3162 if (tevent_req_nterror(req, status)) {
3163 return;
3166 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3167 state->cli->timeout,
3168 lp_client_min_protocol(),
3169 lp_client_max_protocol());
3170 if (tevent_req_nomem(subreq, req)) {
3171 return;
3173 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3176 static void cli_start_connection_done(struct tevent_req *subreq)
3178 struct tevent_req *req = tevent_req_callback_data(
3179 subreq, struct tevent_req);
3180 struct cli_start_connection_state *state = tevent_req_data(
3181 req, struct cli_start_connection_state);
3182 NTSTATUS status;
3184 status = smbXcli_negprot_recv(subreq);
3185 TALLOC_FREE(subreq);
3186 if (tevent_req_nterror(req, status)) {
3187 return;
3190 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3191 /* Ensure we ask for some initial credits. */
3192 smb2cli_conn_set_max_credits(state->cli->conn,
3193 DEFAULT_SMB2_MAX_CREDITS);
3196 tevent_req_done(req);
3199 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3200 struct cli_state **output_cli)
3202 struct cli_start_connection_state *state = tevent_req_data(
3203 req, struct cli_start_connection_state);
3204 NTSTATUS status;
3206 if (tevent_req_is_nterror(req, &status)) {
3207 return status;
3209 *output_cli = state->cli;
3211 return NT_STATUS_OK;
3214 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3215 const char *my_name,
3216 const char *dest_host,
3217 const struct sockaddr_storage *dest_ss, int port,
3218 int signing_state, int flags)
3220 struct tevent_context *ev;
3221 struct tevent_req *req;
3222 NTSTATUS status = NT_STATUS_NO_MEMORY;
3224 ev = samba_tevent_context_init(talloc_tos());
3225 if (ev == NULL) {
3226 goto fail;
3228 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3229 port, signing_state, flags);
3230 if (req == NULL) {
3231 goto fail;
3233 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3234 goto fail;
3236 status = cli_start_connection_recv(req, output_cli);
3237 fail:
3238 TALLOC_FREE(ev);
3239 return status;
3243 establishes a connection right up to doing tconX, password specified.
3244 @param output_cli A fully initialised cli structure, non-null only on success
3245 @param dest_host The netbios name of the remote host
3246 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3247 @param port (optional) The destination port (0 for default)
3248 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3249 @param service_type The 'type' of serivice.
3250 @param user Username, unix string
3251 @param domain User's domain
3252 @param password User's password, unencrypted unix string.
3255 struct cli_full_connection_state {
3256 struct tevent_context *ev;
3257 const char *service;
3258 const char *service_type;
3259 const char *user;
3260 const char *domain;
3261 const char *password;
3262 int pw_len;
3263 int flags;
3264 struct cli_state *cli;
3267 static int cli_full_connection_state_destructor(
3268 struct cli_full_connection_state *s);
3269 static void cli_full_connection_started(struct tevent_req *subreq);
3270 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3271 static void cli_full_connection_done(struct tevent_req *subreq);
3273 struct tevent_req *cli_full_connection_send(
3274 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3275 const char *my_name, const char *dest_host,
3276 const struct sockaddr_storage *dest_ss, int port,
3277 const char *service, const char *service_type,
3278 const char *user, const char *domain,
3279 const char *password, int flags, int signing_state)
3281 struct tevent_req *req, *subreq;
3282 struct cli_full_connection_state *state;
3284 req = tevent_req_create(mem_ctx, &state,
3285 struct cli_full_connection_state);
3286 if (req == NULL) {
3287 return NULL;
3289 talloc_set_destructor(state, cli_full_connection_state_destructor);
3291 state->ev = ev;
3292 state->service = service;
3293 state->service_type = service_type;
3294 state->user = user;
3295 state->domain = domain;
3296 state->password = password;
3297 state->flags = flags;
3299 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3300 if (state->password == NULL) {
3301 state->password = "";
3304 subreq = cli_start_connection_send(
3305 state, ev, my_name, dest_host, dest_ss, port,
3306 signing_state, flags);
3307 if (tevent_req_nomem(subreq, req)) {
3308 return tevent_req_post(req, ev);
3310 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3311 return req;
3314 static int cli_full_connection_state_destructor(
3315 struct cli_full_connection_state *s)
3317 if (s->cli != NULL) {
3318 cli_shutdown(s->cli);
3319 s->cli = NULL;
3321 return 0;
3324 static void cli_full_connection_started(struct tevent_req *subreq)
3326 struct tevent_req *req = tevent_req_callback_data(
3327 subreq, struct tevent_req);
3328 struct cli_full_connection_state *state = tevent_req_data(
3329 req, struct cli_full_connection_state);
3330 NTSTATUS status;
3332 status = cli_start_connection_recv(subreq, &state->cli);
3333 TALLOC_FREE(subreq);
3334 if (tevent_req_nterror(req, status)) {
3335 return;
3337 subreq = cli_session_setup_send(
3338 state, state->ev, state->cli, state->user,
3339 state->password, state->pw_len, state->password, state->pw_len,
3340 state->domain);
3341 if (tevent_req_nomem(subreq, req)) {
3342 return;
3344 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3347 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3349 struct tevent_req *req = tevent_req_callback_data(
3350 subreq, struct tevent_req);
3351 struct cli_full_connection_state *state = tevent_req_data(
3352 req, struct cli_full_connection_state);
3353 NTSTATUS status;
3355 status = cli_session_setup_recv(subreq);
3356 TALLOC_FREE(subreq);
3358 if (!NT_STATUS_IS_OK(status) &&
3359 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3361 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3363 subreq = cli_session_setup_send(
3364 state, state->ev, state->cli, "", "", 0, "", 0,
3365 state->domain);
3366 if (tevent_req_nomem(subreq, req)) {
3367 return;
3369 tevent_req_set_callback(
3370 subreq, cli_full_connection_sess_set_up, req);
3371 return;
3374 if (tevent_req_nterror(req, status)) {
3375 return;
3378 if (state->service != NULL) {
3379 subreq = cli_tree_connect_send(
3380 state, state->ev, state->cli,
3381 state->service, state->service_type,
3382 state->password, state->pw_len);
3383 if (tevent_req_nomem(subreq, req)) {
3384 return;
3386 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3387 return;
3390 tevent_req_done(req);
3393 static void cli_full_connection_done(struct tevent_req *subreq)
3395 struct tevent_req *req = tevent_req_callback_data(
3396 subreq, struct tevent_req);
3397 NTSTATUS status;
3399 status = cli_tree_connect_recv(subreq);
3400 TALLOC_FREE(subreq);
3401 if (tevent_req_nterror(req, status)) {
3402 return;
3405 tevent_req_done(req);
3408 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3409 struct cli_state **output_cli)
3411 struct cli_full_connection_state *state = tevent_req_data(
3412 req, struct cli_full_connection_state);
3413 NTSTATUS status;
3415 if (tevent_req_is_nterror(req, &status)) {
3416 return status;
3418 *output_cli = state->cli;
3419 talloc_set_destructor(state, NULL);
3420 return NT_STATUS_OK;
3423 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3424 const char *my_name,
3425 const char *dest_host,
3426 const struct sockaddr_storage *dest_ss, int port,
3427 const char *service, const char *service_type,
3428 const char *user, const char *domain,
3429 const char *password, int flags,
3430 int signing_state)
3432 struct tevent_context *ev;
3433 struct tevent_req *req;
3434 NTSTATUS status = NT_STATUS_NO_MEMORY;
3436 ev = samba_tevent_context_init(talloc_tos());
3437 if (ev == NULL) {
3438 goto fail;
3440 req = cli_full_connection_send(
3441 ev, ev, my_name, dest_host, dest_ss, port, service,
3442 service_type, user, domain, password, flags, signing_state);
3443 if (req == NULL) {
3444 goto fail;
3446 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3447 goto fail;
3449 status = cli_full_connection_recv(req, output_cli);
3450 fail:
3451 TALLOC_FREE(ev);
3452 return status;
3455 /****************************************************************************
3456 Send an old style tcon.
3457 ****************************************************************************/
3458 struct cli_raw_tcon_state {
3459 uint16_t *ret_vwv;
3462 static void cli_raw_tcon_done(struct tevent_req *subreq);
3464 static struct tevent_req *cli_raw_tcon_send(
3465 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3466 const char *service, const char *pass, const char *dev)
3468 struct tevent_req *req, *subreq;
3469 struct cli_raw_tcon_state *state;
3470 uint8_t *bytes;
3472 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3473 if (req == NULL) {
3474 return NULL;
3477 if (!lp_client_plaintext_auth() && (*pass)) {
3478 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3479 " or 'client ntlmv2 auth = yes'\n"));
3480 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3481 return tevent_req_post(req, ev);
3484 bytes = talloc_array(state, uint8_t, 0);
3485 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3486 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3487 service, strlen(service)+1, NULL);
3488 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3489 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3490 pass, strlen(pass)+1, NULL);
3491 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3492 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3493 dev, strlen(dev)+1, NULL);
3495 if (tevent_req_nomem(bytes, req)) {
3496 return tevent_req_post(req, ev);
3499 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3500 talloc_get_size(bytes), bytes);
3501 if (tevent_req_nomem(subreq, req)) {
3502 return tevent_req_post(req, ev);
3504 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3505 return req;
3508 static void cli_raw_tcon_done(struct tevent_req *subreq)
3510 struct tevent_req *req = tevent_req_callback_data(
3511 subreq, struct tevent_req);
3512 struct cli_raw_tcon_state *state = tevent_req_data(
3513 req, struct cli_raw_tcon_state);
3514 NTSTATUS status;
3516 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3517 NULL, NULL);
3518 TALLOC_FREE(subreq);
3519 if (tevent_req_nterror(req, status)) {
3520 return;
3522 tevent_req_done(req);
3525 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3526 uint16_t *max_xmit, uint16_t *tid)
3528 struct cli_raw_tcon_state *state = tevent_req_data(
3529 req, struct cli_raw_tcon_state);
3530 NTSTATUS status;
3532 if (tevent_req_is_nterror(req, &status)) {
3533 return status;
3535 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3536 *tid = SVAL(state->ret_vwv + 1, 0);
3537 return NT_STATUS_OK;
3540 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3541 const char *service, const char *pass, const char *dev,
3542 uint16_t *max_xmit, uint16_t *tid)
3544 struct tevent_context *ev;
3545 struct tevent_req *req;
3546 NTSTATUS status = NT_STATUS_NO_MEMORY;
3548 ev = samba_tevent_context_init(talloc_tos());
3549 if (ev == NULL) {
3550 goto fail;
3552 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3553 if (req == NULL) {
3554 goto fail;
3556 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3557 goto fail;
3559 status = cli_raw_tcon_recv(req, max_xmit, tid);
3560 fail:
3561 TALLOC_FREE(ev);
3562 return status;
3565 /* Return a cli_state pointing at the IPC$ share for the given server */
3567 struct cli_state *get_ipc_connect(char *server,
3568 struct sockaddr_storage *server_ss,
3569 const struct user_auth_info *user_info)
3571 struct cli_state *cli;
3572 NTSTATUS nt_status;
3573 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3575 if (user_info->use_kerberos) {
3576 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3579 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3580 user_info->username ? user_info->username : "",
3581 lp_workgroup(),
3582 user_info->password ? user_info->password : "",
3583 flags,
3584 SMB_SIGNING_DEFAULT);
3586 if (NT_STATUS_IS_OK(nt_status)) {
3587 return cli;
3588 } else if (is_ipaddress(server)) {
3589 /* windows 9* needs a correct NMB name for connections */
3590 fstring remote_name;
3592 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3593 cli = get_ipc_connect(remote_name, server_ss, user_info);
3594 if (cli)
3595 return cli;
3598 return NULL;
3602 * Given the IP address of a master browser on the network, return its
3603 * workgroup and connect to it.
3605 * This function is provided to allow additional processing beyond what
3606 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3607 * browsers and obtain each master browsers' list of domains (in case the
3608 * first master browser is recently on the network and has not yet
3609 * synchronized with other master browsers and therefore does not yet have the
3610 * entire network browse list)
3613 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3614 struct sockaddr_storage *mb_ip,
3615 const struct user_auth_info *user_info,
3616 char **pp_workgroup_out)
3618 char addr[INET6_ADDRSTRLEN];
3619 fstring name;
3620 struct cli_state *cli;
3621 struct sockaddr_storage server_ss;
3623 *pp_workgroup_out = NULL;
3625 print_sockaddr(addr, sizeof(addr), mb_ip);
3626 DEBUG(99, ("Looking up name of master browser %s\n",
3627 addr));
3630 * Do a name status query to find out the name of the master browser.
3631 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3632 * master browser will not respond to a wildcard query (or, at least,
3633 * an NT4 server acting as the domain master browser will not).
3635 * We might be able to use ONLY the query on MSBROWSE, but that's not
3636 * yet been tested with all Windows versions, so until it is, leave
3637 * the original wildcard query as the first choice and fall back to
3638 * MSBROWSE if the wildcard query fails.
3640 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3641 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3643 DEBUG(99, ("Could not retrieve name status for %s\n",
3644 addr));
3645 return NULL;
3648 if (!find_master_ip(name, &server_ss)) {
3649 DEBUG(99, ("Could not find master ip for %s\n", name));
3650 return NULL;
3653 *pp_workgroup_out = talloc_strdup(ctx, name);
3655 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3657 print_sockaddr(addr, sizeof(addr), &server_ss);
3658 cli = get_ipc_connect(addr, &server_ss, user_info);
3660 return cli;
3664 * Return the IP address and workgroup of a master browser on the network, and
3665 * connect to it.
3668 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3669 const struct user_auth_info *user_info,
3670 char **pp_workgroup_out)
3672 struct sockaddr_storage *ip_list;
3673 struct cli_state *cli;
3674 int i, count;
3675 NTSTATUS status;
3677 *pp_workgroup_out = NULL;
3679 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3681 /* Go looking for workgroups by broadcasting on the local network */
3683 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3684 &ip_list, &count);
3685 if (!NT_STATUS_IS_OK(status)) {
3686 DEBUG(99, ("No master browsers responded: %s\n",
3687 nt_errstr(status)));
3688 return NULL;
3691 for (i = 0; i < count; i++) {
3692 char addr[INET6_ADDRSTRLEN];
3693 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3694 DEBUG(99, ("Found master browser %s\n", addr));
3696 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3697 user_info, pp_workgroup_out);
3698 if (cli)
3699 return(cli);
3702 return NULL;