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