s3:libsmb: avoid calling cli_set_username() cliconnect.c
[Samba.git] / source3 / libsmb / cliconnect.c
blob789a85d5e9df7bed2f8af6b372f2560c599167a9
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 DEBUG(1, ("cli_session_setup_kerberos: "
1306 "spnego_gen_krb5_negTokenInit failed: %s\n",
1307 error_message(rc)));
1308 state->ads_status = ADS_ERROR_KRB5(rc);
1309 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1310 return tevent_req_post(req, ev);
1313 #if 0
1314 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1315 state->negTokenTarg.length);
1316 #endif
1318 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1319 state->cli->smb2.session = smbXcli_session_create(cli,
1320 cli->conn);
1321 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1322 return tevent_req_post(req, ev);
1326 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1327 if (tevent_req_nomem(subreq, req)) {
1328 return tevent_req_post(req, ev);
1330 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1331 return req;
1334 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1336 struct tevent_req *req = tevent_req_callback_data(
1337 subreq, struct tevent_req);
1338 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1339 req, struct cli_session_setup_kerberos_state);
1340 uint8_t *inbuf = NULL;
1341 struct iovec *recv_iov = NULL;
1342 NTSTATUS status;
1344 status = cli_sesssetup_blob_recv(subreq, state,
1345 NULL, &inbuf, &recv_iov);
1346 TALLOC_FREE(subreq);
1347 if (!NT_STATUS_IS_OK(status)) {
1348 tevent_req_nterror(req, status);
1349 return;
1352 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1353 struct smbXcli_session *session = state->cli->smb2.session;
1354 status = smb2cli_session_set_session_key(session,
1355 state->session_key_krb5,
1356 recv_iov);
1357 if (tevent_req_nterror(req, status)) {
1358 return;
1360 } else {
1361 struct smbXcli_session *session = state->cli->smb1.session;
1363 status = smb1cli_session_set_session_key(session,
1364 state->session_key_krb5);
1365 if (tevent_req_nterror(req, status)) {
1366 return;
1369 if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5,
1370 data_blob_null)
1371 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1372 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1373 return;
1377 tevent_req_done(req);
1380 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1382 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1383 req, struct cli_session_setup_kerberos_state);
1384 NTSTATUS status;
1386 if (tevent_req_is_nterror(req, &status)) {
1387 return ADS_ERROR_NT(status);
1389 return state->ads_status;
1392 #endif /* HAVE_KRB5 */
1394 /****************************************************************************
1395 Do a spnego/NTLMSSP encrypted session setup.
1396 ****************************************************************************/
1398 struct cli_session_setup_ntlmssp_state {
1399 struct tevent_context *ev;
1400 struct cli_state *cli;
1401 struct ntlmssp_state *ntlmssp_state;
1402 int turn;
1403 DATA_BLOB blob_out;
1406 static int cli_session_setup_ntlmssp_state_destructor(
1407 struct cli_session_setup_ntlmssp_state *state)
1409 if (state->ntlmssp_state != NULL) {
1410 TALLOC_FREE(state->ntlmssp_state);
1412 return 0;
1415 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1417 static struct tevent_req *cli_session_setup_ntlmssp_send(
1418 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1419 const char *user, const char *pass, const char *domain)
1421 struct tevent_req *req, *subreq;
1422 struct cli_session_setup_ntlmssp_state *state;
1423 NTSTATUS status;
1424 DATA_BLOB blob_out;
1425 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1427 req = tevent_req_create(mem_ctx, &state,
1428 struct cli_session_setup_ntlmssp_state);
1429 if (req == NULL) {
1430 return NULL;
1432 state->ev = ev;
1433 state->cli = cli;
1434 state->turn = 1;
1436 state->ntlmssp_state = NULL;
1437 talloc_set_destructor(
1438 state, cli_session_setup_ntlmssp_state_destructor);
1440 status = ntlmssp_client_start(state,
1441 lp_netbios_name(),
1442 lp_workgroup(),
1443 lp_client_ntlmv2_auth(),
1444 &state->ntlmssp_state);
1445 if (!NT_STATUS_IS_OK(status)) {
1446 goto fail;
1448 ntlmssp_want_feature(state->ntlmssp_state,
1449 NTLMSSP_FEATURE_SESSION_KEY);
1450 if (cli->use_ccache) {
1451 ntlmssp_want_feature(state->ntlmssp_state,
1452 NTLMSSP_FEATURE_CCACHE);
1454 status = ntlmssp_set_username(state->ntlmssp_state, user);
1455 if (!NT_STATUS_IS_OK(status)) {
1456 goto fail;
1458 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1459 if (!NT_STATUS_IS_OK(status)) {
1460 goto fail;
1462 if (cli->pw_nt_hash) {
1463 status = ntlmssp_set_password_hash(state->ntlmssp_state, pass);
1464 } else {
1465 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1467 if (!NT_STATUS_IS_OK(status)) {
1468 goto fail;
1470 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1471 &blob_out);
1472 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1473 goto fail;
1476 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1477 data_blob_free(&blob_out);
1479 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1480 state->cli->smb2.session = smbXcli_session_create(cli,
1481 cli->conn);
1482 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1483 return tevent_req_post(req, ev);
1487 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1488 if (tevent_req_nomem(subreq, req)) {
1489 return tevent_req_post(req, ev);
1491 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1492 return req;
1493 fail:
1494 tevent_req_nterror(req, status);
1495 return tevent_req_post(req, ev);
1498 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1500 struct tevent_req *req = tevent_req_callback_data(
1501 subreq, struct tevent_req);
1502 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1503 req, struct cli_session_setup_ntlmssp_state);
1504 DATA_BLOB blob_in, msg_in, blob_out;
1505 uint8_t *inbuf = NULL;
1506 struct iovec *recv_iov = NULL;
1507 bool parse_ret;
1508 NTSTATUS status;
1510 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1511 &inbuf, &recv_iov);
1512 TALLOC_FREE(subreq);
1513 data_blob_free(&state->blob_out);
1515 if (NT_STATUS_IS_OK(status)) {
1516 if (state->cli->server_domain[0] == '\0') {
1517 TALLOC_FREE(state->cli->server_domain);
1518 state->cli->server_domain = talloc_strdup(state->cli,
1519 state->ntlmssp_state->server.netbios_domain);
1520 if (state->cli->server_domain == NULL) {
1521 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1522 return;
1526 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1527 struct smbXcli_session *session = state->cli->smb2.session;
1529 if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
1531 * Windows server does not set the
1532 * SMB2_SESSION_FLAG_IS_GUEST nor
1533 * SMB2_SESSION_FLAG_IS_NULL flag.
1535 * This fix makes sure we do not try
1536 * to verify a signature on the final
1537 * session setup response.
1539 TALLOC_FREE(state->ntlmssp_state);
1540 tevent_req_done(req);
1541 return;
1544 status = smb2cli_session_set_session_key(session,
1545 state->ntlmssp_state->session_key,
1546 recv_iov);
1547 if (tevent_req_nterror(req, status)) {
1548 return;
1550 } else {
1551 struct smbXcli_session *session = state->cli->smb1.session;
1553 status = smb1cli_session_set_session_key(session,
1554 state->ntlmssp_state->session_key);
1555 if (tevent_req_nterror(req, status)) {
1556 return;
1559 if (smb1cli_conn_activate_signing(
1560 state->cli->conn, state->ntlmssp_state->session_key,
1561 data_blob_null)
1562 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1563 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1564 return;
1567 TALLOC_FREE(state->ntlmssp_state);
1568 tevent_req_done(req);
1569 return;
1571 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1572 tevent_req_nterror(req, status);
1573 return;
1576 if (blob_in.length == 0) {
1577 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1578 return;
1581 if ((state->turn == 1)
1582 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1583 DATA_BLOB tmp_blob = data_blob_null;
1584 /* the server might give us back two challenges */
1585 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1586 &tmp_blob);
1587 data_blob_free(&tmp_blob);
1588 } else {
1589 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1590 OID_NTLMSSP, &msg_in);
1592 state->turn += 1;
1594 if (!parse_ret) {
1595 DEBUG(3,("Failed to parse auth response\n"));
1596 if (NT_STATUS_IS_OK(status)
1597 || NT_STATUS_EQUAL(status,
1598 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1599 tevent_req_nterror(
1600 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1601 return;
1605 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1607 if (!NT_STATUS_IS_OK(status)
1608 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1609 TALLOC_FREE(state->ntlmssp_state);
1610 tevent_req_nterror(req, status);
1611 return;
1614 state->blob_out = spnego_gen_auth(state, blob_out);
1615 if (tevent_req_nomem(state->blob_out.data, req)) {
1616 return;
1619 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1620 state->blob_out);
1621 if (tevent_req_nomem(subreq, req)) {
1622 return;
1624 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1627 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1629 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1630 req, struct cli_session_setup_ntlmssp_state);
1631 NTSTATUS status;
1633 if (tevent_req_is_nterror(req, &status)) {
1634 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1635 return status;
1637 return NT_STATUS_OK;
1640 #ifdef HAVE_KRB5
1642 static char *cli_session_setup_get_principal(
1643 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1644 const char *remote_name, const char *dest_realm)
1646 char *principal = NULL;
1648 if (!lp_client_use_spnego_principal() ||
1649 strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1650 spnego_principal = NULL;
1652 if (spnego_principal != NULL) {
1653 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1654 "principal %s\n", spnego_principal));
1655 return talloc_strdup(mem_ctx, spnego_principal);
1657 if (is_ipaddress(remote_name) ||
1658 strequal(remote_name, STAR_SMBSERVER)) {
1659 return NULL;
1662 DEBUG(3, ("cli_session_setup_spnego: using target "
1663 "hostname not SPNEGO principal\n"));
1665 if (dest_realm) {
1666 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1667 if (realm == NULL) {
1668 return NULL;
1670 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1671 remote_name, realm);
1672 TALLOC_FREE(realm);
1673 } else {
1674 principal = kerberos_get_principal_from_service_hostname(
1675 talloc_tos(), "cifs", remote_name, lp_realm());
1677 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1678 principal ? principal : "<null>"));
1680 return principal;
1682 #endif
1684 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1685 const char *principal)
1687 char *account, *p;
1689 account = talloc_strdup(mem_ctx, principal);
1690 if (account == NULL) {
1691 return NULL;
1693 p = strchr_m(account, '@');
1694 if (p != NULL) {
1695 *p = '\0';
1697 return account;
1700 /****************************************************************************
1701 Do a spnego encrypted session setup.
1703 user_domain: The shortname of the domain the user/machine is a member of.
1704 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1705 ****************************************************************************/
1707 struct cli_session_setup_spnego_state {
1708 struct tevent_context *ev;
1709 struct cli_state *cli;
1710 const char *user;
1711 const char *account;
1712 const char *pass;
1713 const char *user_domain;
1714 const char *dest_realm;
1715 ADS_STATUS result;
1718 #ifdef HAVE_KRB5
1719 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1720 #endif
1722 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1724 static struct tevent_req *cli_session_setup_spnego_send(
1725 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1726 const char *user, const char *pass, const char *user_domain,
1727 const char *dest_realm)
1729 struct tevent_req *req, *subreq;
1730 struct cli_session_setup_spnego_state *state;
1731 char *principal = NULL;
1732 char *OIDs[ASN1_MAX_OIDS];
1733 int i;
1734 const DATA_BLOB *server_blob;
1735 NTSTATUS status;
1737 req = tevent_req_create(mem_ctx, &state,
1738 struct cli_session_setup_spnego_state);
1739 if (req == NULL) {
1740 return NULL;
1742 state->ev = ev;
1743 state->cli = cli;
1744 state->user = user;
1745 state->pass = pass;
1746 state->user_domain = user_domain;
1747 state->dest_realm = dest_realm;
1749 state->account = cli_session_setup_get_account(state, user);
1750 if (tevent_req_nomem(state->account, req)) {
1751 return tevent_req_post(req, ev);
1754 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1756 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1757 (unsigned long)server_blob->length));
1759 /* the server might not even do spnego */
1760 if (server_blob->length == 0) {
1761 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1762 goto ntlmssp;
1765 #if 0
1766 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1767 #endif
1769 /* The server sent us the first part of the SPNEGO exchange in the
1770 * negprot reply. It is WRONG to depend on the principal sent in the
1771 * negprot reply, but right now we do it. If we don't receive one,
1772 * we try to best guess, then fall back to NTLM. */
1773 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1774 &principal, NULL) ||
1775 OIDs[0] == NULL) {
1776 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1777 tevent_req_done(req);
1778 return tevent_req_post(req, ev);
1781 /* make sure the server understands kerberos */
1782 for (i=0;OIDs[i];i++) {
1783 if (i == 0)
1784 DEBUG(3,("got OID=%s\n", OIDs[i]));
1785 else
1786 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1787 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1788 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1789 cli->got_kerberos_mechanism = True;
1791 talloc_free(OIDs[i]);
1794 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1796 #ifdef HAVE_KRB5
1797 /* If password is set we reauthenticate to kerberos server
1798 * and do not store results */
1800 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1801 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
1802 char *tmp;
1805 tmp = cli_session_setup_get_principal(
1806 talloc_tos(), principal, remote_name, dest_realm);
1807 TALLOC_FREE(principal);
1808 principal = tmp;
1810 if (pass && *pass) {
1811 int ret;
1813 use_in_memory_ccache();
1814 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1816 if (ret){
1817 DEBUG(0, ("Kinit for %s to access %s failed: %s\n", user, principal, error_message(ret)));
1818 TALLOC_FREE(principal);
1819 if (cli->fallback_after_kerberos)
1820 goto ntlmssp;
1821 state->result = ADS_ERROR_KRB5(ret);
1822 tevent_req_done(req);
1823 return tevent_req_post(req, ev);
1827 if (principal) {
1828 subreq = cli_session_setup_kerberos_send(
1829 state, ev, cli, principal);
1830 if (tevent_req_nomem(subreq, req)) {
1831 return tevent_req_post(req, ev);
1833 tevent_req_set_callback(
1834 subreq, cli_session_setup_spnego_done_krb,
1835 req);
1836 return req;
1839 #endif
1841 ntlmssp:
1842 subreq = cli_session_setup_ntlmssp_send(
1843 state, ev, cli, state->account, pass, user_domain);
1844 if (tevent_req_nomem(subreq, req)) {
1845 return tevent_req_post(req, ev);
1847 tevent_req_set_callback(
1848 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1849 return req;
1852 #ifdef HAVE_KRB5
1853 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1855 struct tevent_req *req = tevent_req_callback_data(
1856 subreq, struct tevent_req);
1857 struct cli_session_setup_spnego_state *state = tevent_req_data(
1858 req, struct cli_session_setup_spnego_state);
1860 state->result = cli_session_setup_kerberos_recv(subreq);
1861 TALLOC_FREE(subreq);
1863 if (ADS_ERR_OK(state->result) ||
1864 !state->cli->fallback_after_kerberos) {
1865 tevent_req_done(req);
1866 return;
1869 subreq = cli_session_setup_ntlmssp_send(
1870 state, state->ev, state->cli, state->account, state->pass,
1871 state->user_domain);
1872 if (tevent_req_nomem(subreq, req)) {
1873 return;
1875 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1876 req);
1878 #endif
1880 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1882 struct tevent_req *req = tevent_req_callback_data(
1883 subreq, struct tevent_req);
1884 struct cli_session_setup_spnego_state *state = tevent_req_data(
1885 req, struct cli_session_setup_spnego_state);
1886 NTSTATUS status;
1888 status = cli_session_setup_ntlmssp_recv(subreq);
1889 TALLOC_FREE(subreq);
1890 state->result = ADS_ERROR_NT(status);
1891 tevent_req_done(req);
1894 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1896 struct cli_session_setup_spnego_state *state = tevent_req_data(
1897 req, struct cli_session_setup_spnego_state);
1899 return state->result;
1902 struct cli_session_setup_state {
1903 uint8_t dummy;
1906 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1907 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1908 static void cli_session_setup_done_guest(struct tevent_req *subreq);
1909 static void cli_session_setup_done_plain(struct tevent_req *subreq);
1910 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1912 /****************************************************************************
1913 Send a session setup. The username and workgroup is in UNIX character
1914 format and must be converted to DOS codepage format before sending. If the
1915 password is in plaintext, the same should be done.
1916 ****************************************************************************/
1918 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1919 struct tevent_context *ev,
1920 struct cli_state *cli,
1921 const char *user,
1922 const char *pass, int passlen,
1923 const char *ntpass, int ntpasslen,
1924 const char *workgroup)
1926 struct tevent_req *req, *subreq;
1927 struct cli_session_setup_state *state;
1928 char *p;
1929 char *user2;
1930 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1932 req = tevent_req_create(mem_ctx, &state,
1933 struct cli_session_setup_state);
1934 if (req == NULL) {
1935 return NULL;
1938 if (user) {
1939 user2 = talloc_strdup(state, user);
1940 } else {
1941 user2 = talloc_strdup(state, "");
1943 if (user2 == NULL) {
1944 tevent_req_oom(req);
1945 return tevent_req_post(req, ev);
1948 if (!workgroup) {
1949 workgroup = "";
1952 /* allow for workgroups as part of the username */
1953 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1954 (p=strchr_m(user2,*lp_winbind_separator()))) {
1955 *p = 0;
1956 user = p+1;
1957 if (!strupper_m(user2)) {
1958 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1959 return tevent_req_post(req, ev);
1961 workgroup = user2;
1964 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1965 tevent_req_done(req);
1966 return tevent_req_post(req, ev);
1969 /* now work out what sort of session setup we are going to
1970 do. I have split this into separate functions to make the
1971 flow a bit easier to understand (tridge) */
1973 /* if its an older server then we have to use the older request format */
1975 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
1976 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1977 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
1978 " or 'client ntlmv2 auth = yes'\n"));
1979 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1980 return tevent_req_post(req, ev);
1983 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1984 !lp_client_plaintext_auth() && (*pass)) {
1985 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
1986 " or 'client ntlmv2 auth = yes'\n"));
1987 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1988 return tevent_req_post(req, ev);
1991 subreq = cli_session_setup_lanman2_send(
1992 state, ev, cli, user, pass, passlen, workgroup);
1993 if (tevent_req_nomem(subreq, req)) {
1994 return tevent_req_post(req, ev);
1996 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
1997 req);
1998 return req;
2001 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2002 const char *remote_realm = cli_state_remote_realm(cli);
2004 subreq = cli_session_setup_spnego_send(
2005 state, ev, cli, user, pass, workgroup, remote_realm);
2006 if (tevent_req_nomem(subreq, req)) {
2007 return tevent_req_post(req, ev);
2009 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2010 req);
2011 return req;
2014 /* if no user is supplied then we have to do an anonymous connection.
2015 passwords are ignored */
2017 if (!user || !*user) {
2018 subreq = cli_session_setup_guest_send(state, ev, cli);
2019 if (tevent_req_nomem(subreq, req)) {
2020 return tevent_req_post(req, ev);
2022 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2023 req);
2024 return req;
2027 /* if the server is share level then send a plaintext null
2028 password at this point. The password is sent in the tree
2029 connect */
2031 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2032 subreq = cli_session_setup_plain_send(
2033 state, ev, cli, user, "", workgroup);
2034 if (tevent_req_nomem(subreq, req)) {
2035 return tevent_req_post(req, ev);
2037 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2038 req);
2039 return req;
2042 /* if the server doesn't support encryption then we have to use
2043 plaintext. The second password is ignored */
2045 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2046 if (!lp_client_plaintext_auth() && (*pass)) {
2047 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2048 " or 'client ntlmv2 auth = yes'\n"));
2049 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2050 return tevent_req_post(req, ev);
2052 subreq = cli_session_setup_plain_send(
2053 state, ev, cli, user, pass, workgroup);
2054 if (tevent_req_nomem(subreq, req)) {
2055 return tevent_req_post(req, ev);
2057 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2058 req);
2059 return req;
2062 /* if the server supports extended security then use SPNEGO */
2064 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2065 const char *remote_realm = cli_state_remote_realm(cli);
2067 subreq = cli_session_setup_spnego_send(
2068 state, ev, cli, user, pass, workgroup, remote_realm);
2069 if (tevent_req_nomem(subreq, req)) {
2070 return tevent_req_post(req, ev);
2072 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2073 req);
2074 return req;
2075 } else {
2076 /* otherwise do a NT1 style session setup */
2078 subreq = cli_session_setup_nt1_send(
2079 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2080 workgroup);
2081 if (tevent_req_nomem(subreq, req)) {
2082 return tevent_req_post(req, ev);
2084 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2085 req);
2086 return req;
2089 tevent_req_done(req);
2090 return tevent_req_post(req, ev);
2093 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2095 struct tevent_req *req = tevent_req_callback_data(
2096 subreq, struct tevent_req);
2097 NTSTATUS status;
2099 status = cli_session_setup_lanman2_recv(subreq);
2100 TALLOC_FREE(subreq);
2101 if (!NT_STATUS_IS_OK(status)) {
2102 tevent_req_nterror(req, status);
2103 return;
2105 tevent_req_done(req);
2108 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2110 struct tevent_req *req = tevent_req_callback_data(
2111 subreq, struct tevent_req);
2112 ADS_STATUS status;
2114 status = cli_session_setup_spnego_recv(subreq);
2115 TALLOC_FREE(subreq);
2116 if (!ADS_ERR_OK(status)) {
2117 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2118 tevent_req_nterror(req, ads_ntstatus(status));
2119 return;
2121 tevent_req_done(req);
2124 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2126 struct tevent_req *req = tevent_req_callback_data(
2127 subreq, struct tevent_req);
2128 NTSTATUS status;
2130 status = cli_session_setup_guest_recv(subreq);
2131 TALLOC_FREE(subreq);
2132 if (!NT_STATUS_IS_OK(status)) {
2133 tevent_req_nterror(req, status);
2134 return;
2136 tevent_req_done(req);
2139 static void cli_session_setup_done_plain(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_plain_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_nt1(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_nt1_recv(subreq);
2161 TALLOC_FREE(subreq);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 DEBUG(3, ("cli_session_setup: NT1 session setup "
2164 "failed: %s\n", nt_errstr(status)));
2165 tevent_req_nterror(req, status);
2166 return;
2168 tevent_req_done(req);
2171 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2173 return tevent_req_simple_recv_ntstatus(req);
2176 NTSTATUS cli_session_setup(struct cli_state *cli,
2177 const char *user,
2178 const char *pass, int passlen,
2179 const char *ntpass, int ntpasslen,
2180 const char *workgroup)
2182 struct tevent_context *ev;
2183 struct tevent_req *req;
2184 NTSTATUS status = NT_STATUS_NO_MEMORY;
2186 if (smbXcli_conn_has_async_calls(cli->conn)) {
2187 return NT_STATUS_INVALID_PARAMETER;
2189 ev = samba_tevent_context_init(talloc_tos());
2190 if (ev == NULL) {
2191 goto fail;
2193 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2194 ntpass, ntpasslen, workgroup);
2195 if (req == NULL) {
2196 goto fail;
2198 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2199 goto fail;
2201 status = cli_session_setup_recv(req);
2202 fail:
2203 TALLOC_FREE(ev);
2204 return status;
2207 /****************************************************************************
2208 Send a uloggoff.
2209 *****************************************************************************/
2211 struct cli_ulogoff_state {
2212 struct cli_state *cli;
2213 uint16_t vwv[3];
2216 static void cli_ulogoff_done(struct tevent_req *subreq);
2218 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2219 struct tevent_context *ev,
2220 struct cli_state *cli)
2222 struct tevent_req *req, *subreq;
2223 struct cli_ulogoff_state *state;
2225 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2226 if (req == NULL) {
2227 return NULL;
2229 state->cli = cli;
2231 SCVAL(state->vwv+0, 0, 0xFF);
2232 SCVAL(state->vwv+1, 0, 0);
2233 SSVAL(state->vwv+2, 0, 0);
2235 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2236 0, NULL);
2237 if (tevent_req_nomem(subreq, req)) {
2238 return tevent_req_post(req, ev);
2240 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2241 return req;
2244 static void cli_ulogoff_done(struct tevent_req *subreq)
2246 struct tevent_req *req = tevent_req_callback_data(
2247 subreq, struct tevent_req);
2248 struct cli_ulogoff_state *state = tevent_req_data(
2249 req, struct cli_ulogoff_state);
2250 NTSTATUS status;
2252 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2253 if (!NT_STATUS_IS_OK(status)) {
2254 tevent_req_nterror(req, status);
2255 return;
2257 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2258 tevent_req_done(req);
2261 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2263 return tevent_req_simple_recv_ntstatus(req);
2266 NTSTATUS cli_ulogoff(struct cli_state *cli)
2268 struct tevent_context *ev;
2269 struct tevent_req *req;
2270 NTSTATUS status = NT_STATUS_NO_MEMORY;
2272 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2273 status = smb2cli_logoff(cli->conn,
2274 cli->timeout,
2275 cli->smb2.session);
2276 if (!NT_STATUS_IS_OK(status)) {
2277 return status;
2279 smb2cli_session_set_id_and_flags(cli->smb2.session,
2280 UINT64_MAX, 0);
2281 return NT_STATUS_OK;
2284 if (smbXcli_conn_has_async_calls(cli->conn)) {
2285 return NT_STATUS_INVALID_PARAMETER;
2287 ev = samba_tevent_context_init(talloc_tos());
2288 if (ev == NULL) {
2289 goto fail;
2291 req = cli_ulogoff_send(ev, ev, cli);
2292 if (req == NULL) {
2293 goto fail;
2295 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2296 goto fail;
2298 status = cli_ulogoff_recv(req);
2299 fail:
2300 TALLOC_FREE(ev);
2301 return status;
2304 /****************************************************************************
2305 Send a tconX.
2306 ****************************************************************************/
2308 struct cli_tcon_andx_state {
2309 struct cli_state *cli;
2310 uint16_t vwv[4];
2311 struct iovec bytes;
2314 static void cli_tcon_andx_done(struct tevent_req *subreq);
2316 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2317 struct tevent_context *ev,
2318 struct cli_state *cli,
2319 const char *share, const char *dev,
2320 const char *pass, int passlen,
2321 struct tevent_req **psmbreq)
2323 struct tevent_req *req, *subreq;
2324 struct cli_tcon_andx_state *state;
2325 uint8_t p24[24];
2326 uint16_t *vwv;
2327 char *tmp = NULL;
2328 uint8_t *bytes;
2329 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2330 uint16_t tcon_flags = 0;
2332 *psmbreq = NULL;
2334 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2335 if (req == NULL) {
2336 return NULL;
2338 state->cli = cli;
2339 vwv = state->vwv;
2341 cli->share = talloc_strdup(cli, share);
2342 if (!cli->share) {
2343 return NULL;
2346 /* in user level security don't send a password now */
2347 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2348 passlen = 1;
2349 pass = "";
2350 } else if (pass == NULL) {
2351 DEBUG(1, ("Server not using user level security and no "
2352 "password supplied.\n"));
2353 goto access_denied;
2356 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2357 *pass && passlen != 24) {
2358 if (!lp_client_lanman_auth()) {
2359 DEBUG(1, ("Server requested LANMAN password "
2360 "(share-level security) but "
2361 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2362 goto access_denied;
2366 * Non-encrypted passwords - convert to DOS codepage before
2367 * encryption.
2369 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2370 passlen = 24;
2371 pass = (const char *)p24;
2372 } else {
2373 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2374 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2375 == 0) {
2376 uint8_t *tmp_pass;
2378 if (!lp_client_plaintext_auth() && (*pass)) {
2379 DEBUG(1, ("Server requested PLAINTEXT "
2380 "password but "
2381 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2382 goto access_denied;
2386 * Non-encrypted passwords - convert to DOS codepage
2387 * before using.
2389 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2390 if (tevent_req_nomem(tmp_pass, req)) {
2391 return tevent_req_post(req, ev);
2393 tmp_pass = trans2_bytes_push_str(tmp_pass,
2394 false, /* always DOS */
2395 pass,
2396 passlen,
2397 NULL);
2398 if (tevent_req_nomem(tmp_pass, req)) {
2399 return tevent_req_post(req, ev);
2401 pass = (const char *)tmp_pass;
2402 passlen = talloc_get_size(tmp_pass);
2406 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2407 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2409 SCVAL(vwv+0, 0, 0xFF);
2410 SCVAL(vwv+0, 1, 0);
2411 SSVAL(vwv+1, 0, 0);
2412 SSVAL(vwv+2, 0, tcon_flags);
2413 SSVAL(vwv+3, 0, passlen);
2415 if (passlen && pass) {
2416 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2417 } else {
2418 bytes = talloc_array(state, uint8_t, 0);
2422 * Add the sharename
2424 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2425 smbXcli_conn_remote_name(cli->conn), share);
2426 if (tmp == NULL) {
2427 TALLOC_FREE(req);
2428 return NULL;
2430 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2431 NULL);
2432 TALLOC_FREE(tmp);
2435 * Add the devicetype
2437 tmp = talloc_strdup_upper(talloc_tos(), dev);
2438 if (tmp == NULL) {
2439 TALLOC_FREE(req);
2440 return NULL;
2442 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2443 TALLOC_FREE(tmp);
2445 if (bytes == NULL) {
2446 TALLOC_FREE(req);
2447 return NULL;
2450 state->bytes.iov_base = (void *)bytes;
2451 state->bytes.iov_len = talloc_get_size(bytes);
2453 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2454 1, &state->bytes);
2455 if (subreq == NULL) {
2456 TALLOC_FREE(req);
2457 return NULL;
2459 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2460 *psmbreq = subreq;
2461 return req;
2463 access_denied:
2464 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2465 return tevent_req_post(req, ev);
2468 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2469 struct tevent_context *ev,
2470 struct cli_state *cli,
2471 const char *share, const char *dev,
2472 const char *pass, int passlen)
2474 struct tevent_req *req, *subreq;
2475 NTSTATUS status;
2477 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2478 &subreq);
2479 if (req == NULL) {
2480 return NULL;
2482 if (subreq == NULL) {
2483 return req;
2485 status = smb1cli_req_chain_submit(&subreq, 1);
2486 if (!NT_STATUS_IS_OK(status)) {
2487 tevent_req_nterror(req, status);
2488 return tevent_req_post(req, ev);
2490 return req;
2493 static void cli_tcon_andx_done(struct tevent_req *subreq)
2495 struct tevent_req *req = tevent_req_callback_data(
2496 subreq, struct tevent_req);
2497 struct cli_tcon_andx_state *state = tevent_req_data(
2498 req, struct cli_tcon_andx_state);
2499 struct cli_state *cli = state->cli;
2500 uint8_t *in;
2501 uint8_t *inhdr;
2502 uint8_t wct;
2503 uint16_t *vwv;
2504 uint32_t num_bytes;
2505 uint8_t *bytes;
2506 NTSTATUS status;
2507 uint16_t optional_support = 0;
2509 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2510 &num_bytes, &bytes);
2511 TALLOC_FREE(subreq);
2512 if (!NT_STATUS_IS_OK(status)) {
2513 tevent_req_nterror(req, status);
2514 return;
2517 inhdr = in + NBT_HDR_SIZE;
2519 if (num_bytes) {
2520 if (clistr_pull_talloc(cli,
2521 (const char *)inhdr,
2522 SVAL(inhdr, HDR_FLG2),
2523 &cli->dev,
2524 bytes,
2525 num_bytes,
2526 STR_TERMINATE|STR_ASCII) == -1) {
2527 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2528 return;
2530 } else {
2531 cli->dev = talloc_strdup(cli, "");
2532 if (cli->dev == NULL) {
2533 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2534 return;
2538 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2539 /* almost certainly win95 - enable bug fixes */
2540 cli->win95 = True;
2544 * Make sure that we have the optional support 16-bit field. WCT > 2.
2545 * Avoids issues when connecting to Win9x boxes sharing files
2548 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2549 optional_support = SVAL(vwv+2, 0);
2552 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2553 smb1cli_session_protect_session_key(cli->smb1.session);
2556 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2557 SVAL(inhdr, HDR_TID),
2558 optional_support,
2559 0, /* maximal_access */
2560 0, /* guest_maximal_access */
2561 NULL, /* service */
2562 NULL); /* fs_type */
2564 tevent_req_done(req);
2567 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2569 return tevent_req_simple_recv_ntstatus(req);
2572 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2573 const char *dev, const char *pass, int passlen)
2575 TALLOC_CTX *frame = talloc_stackframe();
2576 struct tevent_context *ev;
2577 struct tevent_req *req;
2578 NTSTATUS status = NT_STATUS_NO_MEMORY;
2580 if (smbXcli_conn_has_async_calls(cli->conn)) {
2582 * Can't use sync call while an async call is in flight
2584 status = NT_STATUS_INVALID_PARAMETER;
2585 goto fail;
2588 ev = samba_tevent_context_init(frame);
2589 if (ev == NULL) {
2590 goto fail;
2593 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2594 if (req == NULL) {
2595 goto fail;
2598 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2599 goto fail;
2602 status = cli_tcon_andx_recv(req);
2603 fail:
2604 TALLOC_FREE(frame);
2605 return status;
2608 struct cli_tree_connect_state {
2609 struct cli_state *cli;
2612 static struct tevent_req *cli_raw_tcon_send(
2613 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2614 const char *service, const char *pass, const char *dev);
2615 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2616 uint16 *max_xmit, uint16 *tid);
2618 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2619 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2620 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2622 static struct tevent_req *cli_tree_connect_send(
2623 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2624 const char *share, const char *dev, const char *pass, int passlen)
2626 struct tevent_req *req, *subreq;
2627 struct cli_tree_connect_state *state;
2629 req = tevent_req_create(mem_ctx, &state,
2630 struct cli_tree_connect_state);
2631 if (req == NULL) {
2632 return NULL;
2634 state->cli = cli;
2636 cli->share = talloc_strdup(cli, share);
2637 if (tevent_req_nomem(cli->share, req)) {
2638 return tevent_req_post(req, ev);
2641 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2642 char *unc;
2644 cli->smb2.tcon = smbXcli_tcon_create(cli);
2645 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2646 return tevent_req_post(req, ev);
2649 unc = talloc_asprintf(state, "\\\\%s\\%s",
2650 smbXcli_conn_remote_name(cli->conn),
2651 share);
2652 if (tevent_req_nomem(unc, req)) {
2653 return tevent_req_post(req, ev);
2656 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2657 cli->smb2.session, cli->smb2.tcon,
2658 0, /* flags */
2659 unc);
2660 if (tevent_req_nomem(subreq, req)) {
2661 return tevent_req_post(req, ev);
2663 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2664 req);
2665 return req;
2668 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2669 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2670 pass, passlen);
2671 if (tevent_req_nomem(subreq, req)) {
2672 return tevent_req_post(req, ev);
2674 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2675 req);
2676 return req;
2679 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2680 if (tevent_req_nomem(subreq, req)) {
2681 return tevent_req_post(req, ev);
2683 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2685 return req;
2688 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2690 tevent_req_simple_finish_ntstatus(
2691 subreq, smb2cli_tcon_recv(subreq));
2694 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2696 tevent_req_simple_finish_ntstatus(
2697 subreq, cli_tcon_andx_recv(subreq));
2700 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2702 struct tevent_req *req = tevent_req_callback_data(
2703 subreq, struct tevent_req);
2704 struct cli_tree_connect_state *state = tevent_req_data(
2705 req, struct cli_tree_connect_state);
2706 NTSTATUS status;
2707 uint16_t max_xmit = 0;
2708 uint16_t tid = 0;
2710 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2711 if (tevent_req_nterror(req, status)) {
2712 return;
2715 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2716 tid,
2717 0, /* optional_support */
2718 0, /* maximal_access */
2719 0, /* guest_maximal_access */
2720 NULL, /* service */
2721 NULL); /* fs_type */
2723 tevent_req_done(req);
2726 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2728 return tevent_req_simple_recv_ntstatus(req);
2731 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2732 const char *dev, const char *pass, int passlen)
2734 struct tevent_context *ev;
2735 struct tevent_req *req;
2736 NTSTATUS status = NT_STATUS_NO_MEMORY;
2738 if (smbXcli_conn_has_async_calls(cli->conn)) {
2739 return NT_STATUS_INVALID_PARAMETER;
2741 ev = samba_tevent_context_init(talloc_tos());
2742 if (ev == NULL) {
2743 goto fail;
2745 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2746 if (req == NULL) {
2747 goto fail;
2749 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2750 goto fail;
2752 status = cli_tree_connect_recv(req);
2753 fail:
2754 TALLOC_FREE(ev);
2755 return status;
2758 /****************************************************************************
2759 Send a tree disconnect.
2760 ****************************************************************************/
2762 struct cli_tdis_state {
2763 struct cli_state *cli;
2766 static void cli_tdis_done(struct tevent_req *subreq);
2768 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2769 struct tevent_context *ev,
2770 struct cli_state *cli)
2772 struct tevent_req *req, *subreq;
2773 struct cli_tdis_state *state;
2775 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2776 if (req == NULL) {
2777 return NULL;
2779 state->cli = cli;
2781 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2782 if (tevent_req_nomem(subreq, req)) {
2783 return tevent_req_post(req, ev);
2785 tevent_req_set_callback(subreq, cli_tdis_done, req);
2786 return req;
2789 static void cli_tdis_done(struct tevent_req *subreq)
2791 struct tevent_req *req = tevent_req_callback_data(
2792 subreq, struct tevent_req);
2793 struct cli_tdis_state *state = tevent_req_data(
2794 req, struct cli_tdis_state);
2795 NTSTATUS status;
2797 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2798 TALLOC_FREE(subreq);
2799 if (!NT_STATUS_IS_OK(status)) {
2800 tevent_req_nterror(req, status);
2801 return;
2803 cli_state_set_tid(state->cli, UINT16_MAX);
2804 tevent_req_done(req);
2807 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2809 return tevent_req_simple_recv_ntstatus(req);
2812 NTSTATUS cli_tdis(struct cli_state *cli)
2814 struct tevent_context *ev;
2815 struct tevent_req *req;
2816 NTSTATUS status = NT_STATUS_NO_MEMORY;
2818 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2819 return smb2cli_tdis(cli->conn,
2820 cli->timeout,
2821 cli->smb2.session,
2822 cli->smb2.tcon);
2825 if (smbXcli_conn_has_async_calls(cli->conn)) {
2826 return NT_STATUS_INVALID_PARAMETER;
2828 ev = samba_tevent_context_init(talloc_tos());
2829 if (ev == NULL) {
2830 goto fail;
2832 req = cli_tdis_send(ev, ev, cli);
2833 if (req == NULL) {
2834 goto fail;
2836 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2837 goto fail;
2839 status = cli_tdis_recv(req);
2840 fail:
2841 TALLOC_FREE(ev);
2842 return status;
2845 struct cli_connect_sock_state {
2846 const char **called_names;
2847 const char **calling_names;
2848 int *called_types;
2849 int fd;
2850 uint16_t port;
2853 static void cli_connect_sock_done(struct tevent_req *subreq);
2856 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2857 * nonzero address.
2860 static struct tevent_req *cli_connect_sock_send(
2861 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2862 const char *host, int name_type, const struct sockaddr_storage *pss,
2863 const char *myname, uint16_t port)
2865 struct tevent_req *req, *subreq;
2866 struct cli_connect_sock_state *state;
2867 const char *prog;
2868 struct sockaddr_storage *addrs;
2869 unsigned i, num_addrs;
2870 NTSTATUS status;
2872 req = tevent_req_create(mem_ctx, &state,
2873 struct cli_connect_sock_state);
2874 if (req == NULL) {
2875 return NULL;
2878 prog = getenv("LIBSMB_PROG");
2879 if (prog != NULL) {
2880 state->fd = sock_exec(prog);
2881 if (state->fd == -1) {
2882 status = map_nt_error_from_unix(errno);
2883 tevent_req_nterror(req, status);
2884 } else {
2885 state->port = 0;
2886 tevent_req_done(req);
2888 return tevent_req_post(req, ev);
2891 if ((pss == NULL) || is_zero_addr(pss)) {
2894 * Here we cheat. resolve_name_list is not async at all. So
2895 * this call will only be really async if the name lookup has
2896 * been done externally.
2899 status = resolve_name_list(state, host, name_type,
2900 &addrs, &num_addrs);
2901 if (!NT_STATUS_IS_OK(status)) {
2902 tevent_req_nterror(req, status);
2903 return tevent_req_post(req, ev);
2905 } else {
2906 addrs = talloc_array(state, struct sockaddr_storage, 1);
2907 if (tevent_req_nomem(addrs, req)) {
2908 return tevent_req_post(req, ev);
2910 addrs[0] = *pss;
2911 num_addrs = 1;
2914 state->called_names = talloc_array(state, const char *, num_addrs);
2915 if (tevent_req_nomem(state->called_names, req)) {
2916 return tevent_req_post(req, ev);
2918 state->called_types = talloc_array(state, int, num_addrs);
2919 if (tevent_req_nomem(state->called_types, req)) {
2920 return tevent_req_post(req, ev);
2922 state->calling_names = talloc_array(state, const char *, num_addrs);
2923 if (tevent_req_nomem(state->calling_names, req)) {
2924 return tevent_req_post(req, ev);
2926 for (i=0; i<num_addrs; i++) {
2927 state->called_names[i] = host;
2928 state->called_types[i] = name_type;
2929 state->calling_names[i] = myname;
2932 subreq = smbsock_any_connect_send(
2933 state, ev, addrs, state->called_names, state->called_types,
2934 state->calling_names, NULL, num_addrs, port);
2935 if (tevent_req_nomem(subreq, req)) {
2936 return tevent_req_post(req, ev);
2938 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2939 return req;
2942 static void cli_connect_sock_done(struct tevent_req *subreq)
2944 struct tevent_req *req = tevent_req_callback_data(
2945 subreq, struct tevent_req);
2946 struct cli_connect_sock_state *state = tevent_req_data(
2947 req, struct cli_connect_sock_state);
2948 NTSTATUS status;
2950 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2951 &state->port);
2952 TALLOC_FREE(subreq);
2953 if (tevent_req_nterror(req, status)) {
2954 return;
2956 set_socket_options(state->fd, lp_socket_options());
2957 tevent_req_done(req);
2960 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2961 int *pfd, uint16_t *pport)
2963 struct cli_connect_sock_state *state = tevent_req_data(
2964 req, struct cli_connect_sock_state);
2965 NTSTATUS status;
2967 if (tevent_req_is_nterror(req, &status)) {
2968 return status;
2970 *pfd = state->fd;
2971 *pport = state->port;
2972 return NT_STATUS_OK;
2975 struct cli_connect_nb_state {
2976 const char *desthost;
2977 int signing_state;
2978 int flags;
2979 struct cli_state *cli;
2982 static void cli_connect_nb_done(struct tevent_req *subreq);
2984 static struct tevent_req *cli_connect_nb_send(
2985 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2986 const char *host, const struct sockaddr_storage *dest_ss,
2987 uint16_t port, int name_type, const char *myname,
2988 int signing_state, int flags)
2990 struct tevent_req *req, *subreq;
2991 struct cli_connect_nb_state *state;
2992 char *p;
2994 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2995 if (req == NULL) {
2996 return NULL;
2998 state->desthost = host;
2999 state->signing_state = signing_state;
3000 state->flags = flags;
3002 p = strchr(host, '#');
3003 if (p != NULL) {
3004 name_type = strtol(p+1, NULL, 16);
3005 host = talloc_strndup(state, host, p - host);
3006 if (tevent_req_nomem(host, req)) {
3007 return tevent_req_post(req, ev);
3011 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3012 myname, port);
3013 if (tevent_req_nomem(subreq, req)) {
3014 return tevent_req_post(req, ev);
3016 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3017 return req;
3020 static void cli_connect_nb_done(struct tevent_req *subreq)
3022 struct tevent_req *req = tevent_req_callback_data(
3023 subreq, struct tevent_req);
3024 struct cli_connect_nb_state *state = tevent_req_data(
3025 req, struct cli_connect_nb_state);
3026 NTSTATUS status;
3027 int fd = 0;
3028 uint16_t port;
3030 status = cli_connect_sock_recv(subreq, &fd, &port);
3031 TALLOC_FREE(subreq);
3032 if (tevent_req_nterror(req, status)) {
3033 return;
3036 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3037 state->signing_state, state->flags);
3038 if (tevent_req_nomem(state->cli, req)) {
3039 close(fd);
3040 return;
3042 tevent_req_done(req);
3045 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3046 struct cli_state **pcli)
3048 struct cli_connect_nb_state *state = tevent_req_data(
3049 req, struct cli_connect_nb_state);
3050 NTSTATUS status;
3052 if (tevent_req_is_nterror(req, &status)) {
3053 return status;
3055 *pcli = talloc_move(NULL, &state->cli);
3056 return NT_STATUS_OK;
3059 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3060 uint16_t port, int name_type, const char *myname,
3061 int signing_state, int flags, struct cli_state **pcli)
3063 struct tevent_context *ev;
3064 struct tevent_req *req;
3065 NTSTATUS status = NT_STATUS_NO_MEMORY;
3067 ev = samba_tevent_context_init(talloc_tos());
3068 if (ev == NULL) {
3069 goto fail;
3071 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3072 myname, signing_state, flags);
3073 if (req == NULL) {
3074 goto fail;
3076 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3077 goto fail;
3079 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3080 goto fail;
3082 status = cli_connect_nb_recv(req, pcli);
3083 fail:
3084 TALLOC_FREE(ev);
3085 return status;
3088 struct cli_start_connection_state {
3089 struct tevent_context *ev;
3090 struct cli_state *cli;
3093 static void cli_start_connection_connected(struct tevent_req *subreq);
3094 static void cli_start_connection_done(struct tevent_req *subreq);
3097 establishes a connection to after the negprot.
3098 @param output_cli A fully initialised cli structure, non-null only on success
3099 @param dest_host The netbios name of the remote host
3100 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3101 @param port (optional) The destination port (0 for default)
3104 static struct tevent_req *cli_start_connection_send(
3105 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3106 const char *my_name, const char *dest_host,
3107 const struct sockaddr_storage *dest_ss, int port,
3108 int signing_state, int flags)
3110 struct tevent_req *req, *subreq;
3111 struct cli_start_connection_state *state;
3113 req = tevent_req_create(mem_ctx, &state,
3114 struct cli_start_connection_state);
3115 if (req == NULL) {
3116 return NULL;
3118 state->ev = ev;
3120 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3121 0x20, my_name, signing_state, flags);
3122 if (tevent_req_nomem(subreq, req)) {
3123 return tevent_req_post(req, ev);
3125 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3126 return req;
3129 static void cli_start_connection_connected(struct tevent_req *subreq)
3131 struct tevent_req *req = tevent_req_callback_data(
3132 subreq, struct tevent_req);
3133 struct cli_start_connection_state *state = tevent_req_data(
3134 req, struct cli_start_connection_state);
3135 NTSTATUS status;
3137 status = cli_connect_nb_recv(subreq, &state->cli);
3138 TALLOC_FREE(subreq);
3139 if (tevent_req_nterror(req, status)) {
3140 return;
3143 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3144 state->cli->timeout,
3145 lp_client_min_protocol(),
3146 lp_client_max_protocol());
3147 if (tevent_req_nomem(subreq, req)) {
3148 return;
3150 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3153 static void cli_start_connection_done(struct tevent_req *subreq)
3155 struct tevent_req *req = tevent_req_callback_data(
3156 subreq, struct tevent_req);
3157 struct cli_start_connection_state *state = tevent_req_data(
3158 req, struct cli_start_connection_state);
3159 NTSTATUS status;
3161 status = smbXcli_negprot_recv(subreq);
3162 TALLOC_FREE(subreq);
3163 if (tevent_req_nterror(req, status)) {
3164 return;
3167 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3168 /* Ensure we ask for some initial credits. */
3169 smb2cli_conn_set_max_credits(state->cli->conn,
3170 DEFAULT_SMB2_MAX_CREDITS);
3173 tevent_req_done(req);
3176 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3177 struct cli_state **output_cli)
3179 struct cli_start_connection_state *state = tevent_req_data(
3180 req, struct cli_start_connection_state);
3181 NTSTATUS status;
3183 if (tevent_req_is_nterror(req, &status)) {
3184 return status;
3186 *output_cli = state->cli;
3188 return NT_STATUS_OK;
3191 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3192 const char *my_name,
3193 const char *dest_host,
3194 const struct sockaddr_storage *dest_ss, int port,
3195 int signing_state, int flags)
3197 struct tevent_context *ev;
3198 struct tevent_req *req;
3199 NTSTATUS status = NT_STATUS_NO_MEMORY;
3201 ev = samba_tevent_context_init(talloc_tos());
3202 if (ev == NULL) {
3203 goto fail;
3205 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3206 port, signing_state, flags);
3207 if (req == NULL) {
3208 goto fail;
3210 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3211 goto fail;
3213 status = cli_start_connection_recv(req, output_cli);
3214 fail:
3215 TALLOC_FREE(ev);
3216 return status;
3220 establishes a connection right up to doing tconX, password specified.
3221 @param output_cli A fully initialised cli structure, non-null only on success
3222 @param dest_host The netbios name of the remote host
3223 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3224 @param port (optional) The destination port (0 for default)
3225 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3226 @param service_type The 'type' of serivice.
3227 @param user Username, unix string
3228 @param domain User's domain
3229 @param password User's password, unencrypted unix string.
3232 struct cli_full_connection_state {
3233 struct tevent_context *ev;
3234 const char *service;
3235 const char *service_type;
3236 const char *user;
3237 const char *domain;
3238 const char *password;
3239 int pw_len;
3240 int flags;
3241 struct cli_state *cli;
3244 static int cli_full_connection_state_destructor(
3245 struct cli_full_connection_state *s);
3246 static void cli_full_connection_started(struct tevent_req *subreq);
3247 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3248 static void cli_full_connection_done(struct tevent_req *subreq);
3250 struct tevent_req *cli_full_connection_send(
3251 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3252 const char *my_name, const char *dest_host,
3253 const struct sockaddr_storage *dest_ss, int port,
3254 const char *service, const char *service_type,
3255 const char *user, const char *domain,
3256 const char *password, int flags, int signing_state)
3258 struct tevent_req *req, *subreq;
3259 struct cli_full_connection_state *state;
3261 req = tevent_req_create(mem_ctx, &state,
3262 struct cli_full_connection_state);
3263 if (req == NULL) {
3264 return NULL;
3266 talloc_set_destructor(state, cli_full_connection_state_destructor);
3268 state->ev = ev;
3269 state->service = service;
3270 state->service_type = service_type;
3271 state->user = user;
3272 state->domain = domain;
3273 state->password = password;
3274 state->flags = flags;
3276 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3277 if (state->password == NULL) {
3278 state->password = "";
3281 subreq = cli_start_connection_send(
3282 state, ev, my_name, dest_host, dest_ss, port,
3283 signing_state, flags);
3284 if (tevent_req_nomem(subreq, req)) {
3285 return tevent_req_post(req, ev);
3287 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3288 return req;
3291 static int cli_full_connection_state_destructor(
3292 struct cli_full_connection_state *s)
3294 if (s->cli != NULL) {
3295 cli_shutdown(s->cli);
3296 s->cli = NULL;
3298 return 0;
3301 static void cli_full_connection_started(struct tevent_req *subreq)
3303 struct tevent_req *req = tevent_req_callback_data(
3304 subreq, struct tevent_req);
3305 struct cli_full_connection_state *state = tevent_req_data(
3306 req, struct cli_full_connection_state);
3307 NTSTATUS status;
3309 status = cli_start_connection_recv(subreq, &state->cli);
3310 TALLOC_FREE(subreq);
3311 if (tevent_req_nterror(req, status)) {
3312 return;
3314 subreq = cli_session_setup_send(
3315 state, state->ev, state->cli, state->user,
3316 state->password, state->pw_len, state->password, state->pw_len,
3317 state->domain);
3318 if (tevent_req_nomem(subreq, req)) {
3319 return;
3321 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3324 static void cli_full_connection_sess_set_up(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_session_setup_recv(subreq);
3333 TALLOC_FREE(subreq);
3335 if (!NT_STATUS_IS_OK(status) &&
3336 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3338 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3340 subreq = cli_session_setup_send(
3341 state, state->ev, state->cli, "", "", 0, "", 0,
3342 state->domain);
3343 if (tevent_req_nomem(subreq, req)) {
3344 return;
3346 tevent_req_set_callback(
3347 subreq, cli_full_connection_sess_set_up, req);
3348 return;
3351 if (tevent_req_nterror(req, status)) {
3352 return;
3355 if (state->service != NULL) {
3356 subreq = cli_tree_connect_send(
3357 state, state->ev, state->cli,
3358 state->service, state->service_type,
3359 state->password, state->pw_len);
3360 if (tevent_req_nomem(subreq, req)) {
3361 return;
3363 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3364 return;
3367 tevent_req_done(req);
3370 static void cli_full_connection_done(struct tevent_req *subreq)
3372 struct tevent_req *req = tevent_req_callback_data(
3373 subreq, struct tevent_req);
3374 struct cli_full_connection_state *state = tevent_req_data(
3375 req, struct cli_full_connection_state);
3376 NTSTATUS status;
3378 status = cli_tree_connect_recv(subreq);
3379 TALLOC_FREE(subreq);
3380 if (tevent_req_nterror(req, status)) {
3381 return;
3384 tevent_req_done(req);
3387 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3388 struct cli_state **output_cli)
3390 struct cli_full_connection_state *state = tevent_req_data(
3391 req, struct cli_full_connection_state);
3392 NTSTATUS status;
3394 if (tevent_req_is_nterror(req, &status)) {
3395 return status;
3397 *output_cli = state->cli;
3398 talloc_set_destructor(state, NULL);
3399 return NT_STATUS_OK;
3402 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3403 const char *my_name,
3404 const char *dest_host,
3405 const struct sockaddr_storage *dest_ss, int port,
3406 const char *service, const char *service_type,
3407 const char *user, const char *domain,
3408 const char *password, int flags,
3409 int signing_state)
3411 struct tevent_context *ev;
3412 struct tevent_req *req;
3413 NTSTATUS status = NT_STATUS_NO_MEMORY;
3415 ev = samba_tevent_context_init(talloc_tos());
3416 if (ev == NULL) {
3417 goto fail;
3419 req = cli_full_connection_send(
3420 ev, ev, my_name, dest_host, dest_ss, port, service,
3421 service_type, user, domain, password, flags, signing_state);
3422 if (req == NULL) {
3423 goto fail;
3425 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3426 goto fail;
3428 status = cli_full_connection_recv(req, output_cli);
3429 fail:
3430 TALLOC_FREE(ev);
3431 return status;
3434 /****************************************************************************
3435 Send an old style tcon.
3436 ****************************************************************************/
3437 struct cli_raw_tcon_state {
3438 uint16_t *ret_vwv;
3441 static void cli_raw_tcon_done(struct tevent_req *subreq);
3443 static struct tevent_req *cli_raw_tcon_send(
3444 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3445 const char *service, const char *pass, const char *dev)
3447 struct tevent_req *req, *subreq;
3448 struct cli_raw_tcon_state *state;
3449 uint8_t *bytes;
3451 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3452 if (req == NULL) {
3453 return NULL;
3456 if (!lp_client_plaintext_auth() && (*pass)) {
3457 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3458 " or 'client ntlmv2 auth = yes'\n"));
3459 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3460 return tevent_req_post(req, ev);
3463 bytes = talloc_array(state, uint8_t, 0);
3464 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3465 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3466 service, strlen(service)+1, NULL);
3467 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3468 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3469 pass, strlen(pass)+1, NULL);
3470 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3471 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3472 dev, strlen(dev)+1, NULL);
3474 if (tevent_req_nomem(bytes, req)) {
3475 return tevent_req_post(req, ev);
3478 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3479 talloc_get_size(bytes), bytes);
3480 if (tevent_req_nomem(subreq, req)) {
3481 return tevent_req_post(req, ev);
3483 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3484 return req;
3487 static void cli_raw_tcon_done(struct tevent_req *subreq)
3489 struct tevent_req *req = tevent_req_callback_data(
3490 subreq, struct tevent_req);
3491 struct cli_raw_tcon_state *state = tevent_req_data(
3492 req, struct cli_raw_tcon_state);
3493 NTSTATUS status;
3495 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3496 NULL, NULL);
3497 TALLOC_FREE(subreq);
3498 if (tevent_req_nterror(req, status)) {
3499 return;
3501 tevent_req_done(req);
3504 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3505 uint16 *max_xmit, uint16 *tid)
3507 struct cli_raw_tcon_state *state = tevent_req_data(
3508 req, struct cli_raw_tcon_state);
3509 NTSTATUS status;
3511 if (tevent_req_is_nterror(req, &status)) {
3512 return status;
3514 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3515 *tid = SVAL(state->ret_vwv + 1, 0);
3516 return NT_STATUS_OK;
3519 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3520 const char *service, const char *pass, const char *dev,
3521 uint16 *max_xmit, uint16 *tid)
3523 struct tevent_context *ev;
3524 struct tevent_req *req;
3525 NTSTATUS status = NT_STATUS_NO_MEMORY;
3527 ev = samba_tevent_context_init(talloc_tos());
3528 if (ev == NULL) {
3529 goto fail;
3531 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3532 if (req == NULL) {
3533 goto fail;
3535 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3536 goto fail;
3538 status = cli_raw_tcon_recv(req, max_xmit, tid);
3539 fail:
3540 TALLOC_FREE(ev);
3541 return status;
3544 /* Return a cli_state pointing at the IPC$ share for the given server */
3546 struct cli_state *get_ipc_connect(char *server,
3547 struct sockaddr_storage *server_ss,
3548 const struct user_auth_info *user_info)
3550 struct cli_state *cli;
3551 NTSTATUS nt_status;
3552 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3554 if (user_info->use_kerberos) {
3555 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3558 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3559 user_info->username ? user_info->username : "",
3560 lp_workgroup(),
3561 user_info->password ? user_info->password : "",
3562 flags,
3563 SMB_SIGNING_DEFAULT);
3565 if (NT_STATUS_IS_OK(nt_status)) {
3566 return cli;
3567 } else if (is_ipaddress(server)) {
3568 /* windows 9* needs a correct NMB name for connections */
3569 fstring remote_name;
3571 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3572 cli = get_ipc_connect(remote_name, server_ss, user_info);
3573 if (cli)
3574 return cli;
3577 return NULL;
3581 * Given the IP address of a master browser on the network, return its
3582 * workgroup and connect to it.
3584 * This function is provided to allow additional processing beyond what
3585 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3586 * browsers and obtain each master browsers' list of domains (in case the
3587 * first master browser is recently on the network and has not yet
3588 * synchronized with other master browsers and therefore does not yet have the
3589 * entire network browse list)
3592 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3593 struct sockaddr_storage *mb_ip,
3594 const struct user_auth_info *user_info,
3595 char **pp_workgroup_out)
3597 char addr[INET6_ADDRSTRLEN];
3598 fstring name;
3599 struct cli_state *cli;
3600 struct sockaddr_storage server_ss;
3602 *pp_workgroup_out = NULL;
3604 print_sockaddr(addr, sizeof(addr), mb_ip);
3605 DEBUG(99, ("Looking up name of master browser %s\n",
3606 addr));
3609 * Do a name status query to find out the name of the master browser.
3610 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3611 * master browser will not respond to a wildcard query (or, at least,
3612 * an NT4 server acting as the domain master browser will not).
3614 * We might be able to use ONLY the query on MSBROWSE, but that's not
3615 * yet been tested with all Windows versions, so until it is, leave
3616 * the original wildcard query as the first choice and fall back to
3617 * MSBROWSE if the wildcard query fails.
3619 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3620 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3622 DEBUG(99, ("Could not retrieve name status for %s\n",
3623 addr));
3624 return NULL;
3627 if (!find_master_ip(name, &server_ss)) {
3628 DEBUG(99, ("Could not find master ip for %s\n", name));
3629 return NULL;
3632 *pp_workgroup_out = talloc_strdup(ctx, name);
3634 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3636 print_sockaddr(addr, sizeof(addr), &server_ss);
3637 cli = get_ipc_connect(addr, &server_ss, user_info);
3639 return cli;
3643 * Return the IP address and workgroup of a master browser on the network, and
3644 * connect to it.
3647 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3648 const struct user_auth_info *user_info,
3649 char **pp_workgroup_out)
3651 struct sockaddr_storage *ip_list;
3652 struct cli_state *cli;
3653 int i, count;
3654 NTSTATUS status;
3656 *pp_workgroup_out = NULL;
3658 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3660 /* Go looking for workgroups by broadcasting on the local network */
3662 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3663 &ip_list, &count);
3664 if (!NT_STATUS_IS_OK(status)) {
3665 DEBUG(99, ("No master browsers responded: %s\n",
3666 nt_errstr(status)));
3667 return NULL;
3670 for (i = 0; i < count; i++) {
3671 char addr[INET6_ADDRSTRLEN];
3672 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3673 DEBUG(99, ("Found master browser %s\n", addr));
3675 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3676 user_info, pp_workgroup_out);
3677 if (cli)
3678 return(cli);
3681 return NULL;