s3:libsmb: remove unused smb2cli.h
[Samba.git] / source3 / libsmb / cliconnect.c
blob950865167d15a9ecd42fe34f987fe3a87f5e9aeb
1 /*
2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
6 Copyright (C) Volker Lendecke 2011
7 Copyright (C) Jeremy Allison 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "libsmb/libsmb.h"
25 #include "auth_info.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
28 #include "smb_krb5.h"
29 #include "../auth/ntlmssp/ntlmssp.h"
30 #include "libads/kerberos_proto.h"
31 #include "krb5_env.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "async_smb.h"
34 #include "libsmb/nmblib.h"
35 #include "librpc/ndr/libndr.h"
36 #include "../libcli/smb/smbXcli_base.h"
38 #define STAR_SMBSERVER "*SMBSERVER"
40 /********************************************************
41 Utility function to ensure we always return at least
42 a valid char * pointer to an empty string for the
43 cli->server_os, cli->server_type and cli->server_domain
44 strings.
45 *******************************************************/
47 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
48 const uint8_t *hdr,
49 char **dest,
50 uint8_t *src,
51 size_t srclen,
52 ssize_t *destlen)
54 *destlen = clistr_pull_talloc(mem_ctx,
55 (const char *)hdr,
56 SVAL(hdr, HDR_FLG2),
57 dest,
58 (char *)src,
59 srclen,
60 STR_TERMINATE);
61 if (*destlen == -1) {
62 return NT_STATUS_NO_MEMORY;
65 if (*dest == NULL) {
66 *dest = talloc_strdup(mem_ctx, "");
67 if (*dest == NULL) {
68 return NT_STATUS_NO_MEMORY;
71 return NT_STATUS_OK;
74 /****************************************************************************
75 Do an old lanman2 style session setup.
76 ****************************************************************************/
78 struct cli_session_setup_lanman2_state {
79 struct cli_state *cli;
80 uint16_t vwv[10];
81 const char *user;
84 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
86 static struct tevent_req *cli_session_setup_lanman2_send(
87 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
88 struct cli_state *cli, const char *user,
89 const char *pass, size_t passlen,
90 const char *workgroup)
92 struct tevent_req *req, *subreq;
93 struct cli_session_setup_lanman2_state *state;
94 DATA_BLOB lm_response = data_blob_null;
95 uint16_t *vwv;
96 uint8_t *bytes;
97 char *tmp;
98 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
100 req = tevent_req_create(mem_ctx, &state,
101 struct cli_session_setup_lanman2_state);
102 if (req == NULL) {
103 return NULL;
105 state->cli = cli;
106 state->user = user;
107 vwv = state->vwv;
110 * if in share level security then don't send a password now
112 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
113 passlen = 0;
116 if (passlen > 0
117 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
118 && passlen != 24) {
120 * Encrypted mode needed, and non encrypted password
121 * supplied.
123 lm_response = data_blob(NULL, 24);
124 if (tevent_req_nomem(lm_response.data, req)) {
125 return tevent_req_post(req, ev);
128 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
129 (uint8_t *)lm_response.data)) {
130 DEBUG(1, ("Password is > 14 chars in length, and is "
131 "therefore incompatible with Lanman "
132 "authentication\n"));
133 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
134 return tevent_req_post(req, ev);
136 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
137 && passlen == 24) {
139 * Encrypted mode needed, and encrypted password
140 * supplied.
142 lm_response = data_blob(pass, passlen);
143 if (tevent_req_nomem(lm_response.data, req)) {
144 return tevent_req_post(req, ev);
146 } else if (passlen > 0) {
147 uint8_t *buf;
148 size_t converted_size;
150 * Plaintext mode needed, assume plaintext supplied.
152 buf = talloc_array(talloc_tos(), uint8_t, 0);
153 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
154 &converted_size);
155 if (tevent_req_nomem(buf, req)) {
156 return tevent_req_post(req, ev);
158 lm_response = data_blob(pass, passlen);
159 TALLOC_FREE(buf);
160 if (tevent_req_nomem(lm_response.data, req)) {
161 return tevent_req_post(req, ev);
165 SCVAL(vwv+0, 0, 0xff);
166 SCVAL(vwv+0, 1, 0);
167 SSVAL(vwv+1, 0, 0);
168 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
169 SSVAL(vwv+3, 0, 2);
170 SSVAL(vwv+4, 0, 1);
171 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
172 SSVAL(vwv+7, 0, lm_response.length);
174 bytes = talloc_array(state, uint8_t, lm_response.length);
175 if (tevent_req_nomem(bytes, req)) {
176 return tevent_req_post(req, ev);
178 if (lm_response.length != 0) {
179 memcpy(bytes, lm_response.data, lm_response.length);
181 data_blob_free(&lm_response);
183 tmp = talloc_strdup_upper(talloc_tos(), user);
184 if (tevent_req_nomem(tmp, req)) {
185 return tevent_req_post(req, ev);
187 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
188 NULL);
189 TALLOC_FREE(tmp);
191 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
192 if (tevent_req_nomem(tmp, req)) {
193 return tevent_req_post(req, ev);
195 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
196 NULL);
197 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
198 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
200 if (tevent_req_nomem(bytes, req)) {
201 return tevent_req_post(req, ev);
204 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
205 talloc_get_size(bytes), bytes);
206 if (tevent_req_nomem(subreq, req)) {
207 return tevent_req_post(req, ev);
209 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
210 return req;
213 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
215 struct tevent_req *req = tevent_req_callback_data(
216 subreq, struct tevent_req);
217 struct cli_session_setup_lanman2_state *state = tevent_req_data(
218 req, struct cli_session_setup_lanman2_state);
219 struct cli_state *cli = state->cli;
220 uint32_t num_bytes;
221 uint8_t *in;
222 uint8_t *inhdr;
223 uint8_t *bytes;
224 uint8_t *p;
225 NTSTATUS status;
226 ssize_t ret;
227 uint8_t wct;
228 uint16_t *vwv;
230 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
231 &num_bytes, &bytes);
232 TALLOC_FREE(subreq);
233 if (!NT_STATUS_IS_OK(status)) {
234 tevent_req_nterror(req, status);
235 return;
238 inhdr = in + NBT_HDR_SIZE;
239 p = bytes;
241 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
243 status = smb_bytes_talloc_string(cli,
244 inhdr,
245 &cli->server_os,
247 bytes+num_bytes-p,
248 &ret);
250 if (!NT_STATUS_IS_OK(status)) {
251 tevent_req_nterror(req, status);
252 return;
254 p += ret;
256 status = smb_bytes_talloc_string(cli,
257 inhdr,
258 &cli->server_type,
260 bytes+num_bytes-p,
261 &ret);
263 if (!NT_STATUS_IS_OK(status)) {
264 tevent_req_nterror(req, status);
265 return;
267 p += ret;
269 status = smb_bytes_talloc_string(cli,
270 inhdr,
271 &cli->server_domain,
273 bytes+num_bytes-p,
274 &ret);
276 if (!NT_STATUS_IS_OK(status)) {
277 tevent_req_nterror(req, status);
278 return;
280 p += ret;
282 status = cli_set_username(cli, state->user);
283 if (tevent_req_nterror(req, status)) {
284 return;
286 tevent_req_done(req);
289 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
291 return tevent_req_simple_recv_ntstatus(req);
294 /****************************************************************************
295 Work out suitable capabilities to offer the server.
296 ****************************************************************************/
298 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
299 uint32_t sesssetup_capabilities)
301 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
304 * We only send capabilities based on the mask for:
305 * - client only flags
306 * - flags used in both directions
308 * We do not echo the server only flags, except some legacy flags.
310 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
311 * CAP_LARGE_WRITEX in order to allow us to do large reads
312 * against old Samba releases (<= 3.6.x).
314 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
317 * Session Setup specific flags CAP_DYNAMIC_REAUTH
318 * and CAP_EXTENDED_SECURITY are passed by the caller.
319 * We need that in order to do guest logins even if
320 * CAP_EXTENDED_SECURITY is negotiated.
322 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
323 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
324 client_capabilities |= sesssetup_capabilities;
326 return client_capabilities;
329 /****************************************************************************
330 Do a NT1 guest session setup.
331 ****************************************************************************/
333 struct cli_session_setup_guest_state {
334 struct cli_state *cli;
335 uint16_t vwv[13];
336 struct iovec bytes;
339 static void cli_session_setup_guest_done(struct tevent_req *subreq);
341 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
342 struct tevent_context *ev,
343 struct cli_state *cli,
344 struct tevent_req **psmbreq)
346 struct tevent_req *req, *subreq;
347 struct cli_session_setup_guest_state *state;
348 uint16_t *vwv;
349 uint8_t *bytes;
351 req = tevent_req_create(mem_ctx, &state,
352 struct cli_session_setup_guest_state);
353 if (req == NULL) {
354 return NULL;
356 state->cli = cli;
357 vwv = state->vwv;
359 SCVAL(vwv+0, 0, 0xFF);
360 SCVAL(vwv+0, 1, 0);
361 SSVAL(vwv+1, 0, 0);
362 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
363 SSVAL(vwv+3, 0, 2);
364 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
365 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
366 SSVAL(vwv+7, 0, 0);
367 SSVAL(vwv+8, 0, 0);
368 SSVAL(vwv+9, 0, 0);
369 SSVAL(vwv+10, 0, 0);
370 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
372 bytes = talloc_array(state, uint8_t, 0);
374 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
375 NULL);
376 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
377 NULL);
378 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
379 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
381 if (bytes == NULL) {
382 TALLOC_FREE(req);
383 return NULL;
386 state->bytes.iov_base = (void *)bytes;
387 state->bytes.iov_len = talloc_get_size(bytes);
389 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
390 1, &state->bytes);
391 if (subreq == NULL) {
392 TALLOC_FREE(req);
393 return NULL;
395 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
396 *psmbreq = subreq;
397 return req;
400 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
401 struct tevent_context *ev,
402 struct cli_state *cli)
404 struct tevent_req *req, *subreq;
405 NTSTATUS status;
407 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
408 if (req == NULL) {
409 return NULL;
412 status = smb1cli_req_chain_submit(&subreq, 1);
413 if (!NT_STATUS_IS_OK(status)) {
414 tevent_req_nterror(req, status);
415 return tevent_req_post(req, ev);
417 return req;
420 static void cli_session_setup_guest_done(struct tevent_req *subreq)
422 struct tevent_req *req = tevent_req_callback_data(
423 subreq, struct tevent_req);
424 struct cli_session_setup_guest_state *state = tevent_req_data(
425 req, struct cli_session_setup_guest_state);
426 struct cli_state *cli = state->cli;
427 uint32_t num_bytes;
428 uint8_t *in;
429 uint8_t *inhdr;
430 uint8_t *bytes;
431 uint8_t *p;
432 NTSTATUS status;
433 ssize_t ret;
434 uint8_t wct;
435 uint16_t *vwv;
437 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
438 &num_bytes, &bytes);
439 TALLOC_FREE(subreq);
440 if (!NT_STATUS_IS_OK(status)) {
441 tevent_req_nterror(req, status);
442 return;
445 inhdr = in + NBT_HDR_SIZE;
446 p = bytes;
448 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
450 status = smb_bytes_talloc_string(cli,
451 inhdr,
452 &cli->server_os,
454 bytes+num_bytes-p,
455 &ret);
457 if (!NT_STATUS_IS_OK(status)) {
458 tevent_req_nterror(req, status);
459 return;
461 p += ret;
463 status = smb_bytes_talloc_string(cli,
464 inhdr,
465 &cli->server_type,
467 bytes+num_bytes-p,
468 &ret);
470 if (!NT_STATUS_IS_OK(status)) {
471 tevent_req_nterror(req, status);
472 return;
474 p += ret;
476 status = smb_bytes_talloc_string(cli,
477 inhdr,
478 &cli->server_domain,
480 bytes+num_bytes-p,
481 &ret);
483 if (!NT_STATUS_IS_OK(status)) {
484 tevent_req_nterror(req, status);
485 return;
487 p += ret;
489 status = cli_set_username(cli, "");
490 if (!NT_STATUS_IS_OK(status)) {
491 tevent_req_nterror(req, status);
492 return;
494 tevent_req_done(req);
497 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
499 return tevent_req_simple_recv_ntstatus(req);
502 /****************************************************************************
503 Do a NT1 plaintext session setup.
504 ****************************************************************************/
506 struct cli_session_setup_plain_state {
507 struct cli_state *cli;
508 uint16_t vwv[13];
509 const char *user;
512 static void cli_session_setup_plain_done(struct tevent_req *subreq);
514 static struct tevent_req *cli_session_setup_plain_send(
515 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
516 struct cli_state *cli,
517 const char *user, const char *pass, const char *workgroup)
519 struct tevent_req *req, *subreq;
520 struct cli_session_setup_plain_state *state;
521 uint16_t *vwv;
522 uint8_t *bytes;
523 size_t passlen;
524 char *version;
526 req = tevent_req_create(mem_ctx, &state,
527 struct cli_session_setup_plain_state);
528 if (req == NULL) {
529 return NULL;
531 state->cli = cli;
532 state->user = user;
533 vwv = state->vwv;
535 SCVAL(vwv+0, 0, 0xff);
536 SCVAL(vwv+0, 1, 0);
537 SSVAL(vwv+1, 0, 0);
538 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
539 SSVAL(vwv+3, 0, 2);
540 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
541 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
542 SSVAL(vwv+7, 0, 0);
543 SSVAL(vwv+8, 0, 0);
544 SSVAL(vwv+9, 0, 0);
545 SSVAL(vwv+10, 0, 0);
546 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
548 bytes = talloc_array(state, uint8_t, 0);
549 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
550 &passlen);
551 if (tevent_req_nomem(bytes, req)) {
552 return tevent_req_post(req, ev);
554 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
556 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
557 user, strlen(user)+1, NULL);
558 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
559 workgroup, strlen(workgroup)+1, NULL);
560 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
561 "Unix", 5, NULL);
563 version = talloc_asprintf(talloc_tos(), "Samba %s",
564 samba_version_string());
565 if (tevent_req_nomem(version, req)){
566 return tevent_req_post(req, ev);
568 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
569 version, strlen(version)+1, NULL);
570 TALLOC_FREE(version);
572 if (tevent_req_nomem(bytes, req)) {
573 return tevent_req_post(req, ev);
576 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
577 talloc_get_size(bytes), bytes);
578 if (tevent_req_nomem(subreq, req)) {
579 return tevent_req_post(req, ev);
581 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
582 return req;
585 static void cli_session_setup_plain_done(struct tevent_req *subreq)
587 struct tevent_req *req = tevent_req_callback_data(
588 subreq, struct tevent_req);
589 struct cli_session_setup_plain_state *state = tevent_req_data(
590 req, struct cli_session_setup_plain_state);
591 struct cli_state *cli = state->cli;
592 uint32_t num_bytes;
593 uint8_t *in;
594 uint8_t *inhdr;
595 uint8_t *bytes;
596 uint8_t *p;
597 NTSTATUS status;
598 ssize_t ret;
599 uint8_t wct;
600 uint16_t *vwv;
602 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
603 &num_bytes, &bytes);
604 TALLOC_FREE(subreq);
605 if (tevent_req_nterror(req, status)) {
606 return;
609 inhdr = in + NBT_HDR_SIZE;
610 p = bytes;
612 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
614 status = smb_bytes_talloc_string(cli,
615 inhdr,
616 &cli->server_os,
618 bytes+num_bytes-p,
619 &ret);
621 if (!NT_STATUS_IS_OK(status)) {
622 tevent_req_nterror(req, status);
623 return;
625 p += ret;
627 status = smb_bytes_talloc_string(cli,
628 inhdr,
629 &cli->server_type,
631 bytes+num_bytes-p,
632 &ret);
634 if (!NT_STATUS_IS_OK(status)) {
635 tevent_req_nterror(req, status);
636 return;
638 p += ret;
640 status = smb_bytes_talloc_string(cli,
641 inhdr,
642 &cli->server_domain,
644 bytes+num_bytes-p,
645 &ret);
647 if (!NT_STATUS_IS_OK(status)) {
648 tevent_req_nterror(req, status);
649 return;
651 p += ret;
653 status = cli_set_username(cli, state->user);
654 if (tevent_req_nterror(req, status)) {
655 return;
658 tevent_req_done(req);
661 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
663 return tevent_req_simple_recv_ntstatus(req);
666 /****************************************************************************
667 do a NT1 NTLM/LM encrypted session setup - for when extended security
668 is not negotiated.
669 @param cli client state to create do session setup on
670 @param user username
671 @param pass *either* cleartext password (passlen !=24) or LM response.
672 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
673 @param workgroup The user's domain.
674 ****************************************************************************/
676 struct cli_session_setup_nt1_state {
677 struct cli_state *cli;
678 uint16_t vwv[13];
679 DATA_BLOB response;
680 DATA_BLOB session_key;
681 const char *user;
684 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
686 static struct tevent_req *cli_session_setup_nt1_send(
687 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
688 struct cli_state *cli, const char *user,
689 const char *pass, size_t passlen,
690 const char *ntpass, size_t ntpasslen,
691 const char *workgroup)
693 struct tevent_req *req, *subreq;
694 struct cli_session_setup_nt1_state *state;
695 DATA_BLOB lm_response = data_blob_null;
696 DATA_BLOB nt_response = data_blob_null;
697 DATA_BLOB session_key = data_blob_null;
698 uint16_t *vwv;
699 uint8_t *bytes;
700 char *workgroup_upper;
702 req = tevent_req_create(mem_ctx, &state,
703 struct cli_session_setup_nt1_state);
704 if (req == NULL) {
705 return NULL;
707 state->cli = cli;
708 state->user = user;
709 vwv = state->vwv;
711 if (passlen == 0) {
712 /* do nothing - guest login */
713 } else if (passlen != 24) {
714 if (lp_client_ntlmv2_auth()) {
715 DATA_BLOB server_chal;
716 DATA_BLOB names_blob;
718 server_chal =
719 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
723 * note that the 'workgroup' here is a best
724 * guess - we don't know the server's domain
725 * at this point. Windows clients also don't
726 * use hostname...
728 names_blob = NTLMv2_generate_names_blob(
729 NULL, NULL, workgroup);
731 if (tevent_req_nomem(names_blob.data, req)) {
732 return tevent_req_post(req, ev);
735 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
736 &server_chal, &names_blob,
737 &lm_response, &nt_response,
738 NULL, &session_key)) {
739 data_blob_free(&names_blob);
740 tevent_req_nterror(
741 req, NT_STATUS_ACCESS_DENIED);
742 return tevent_req_post(req, ev);
744 data_blob_free(&names_blob);
746 } else {
747 uchar nt_hash[16];
748 E_md4hash(pass, nt_hash);
750 #ifdef LANMAN_ONLY
751 nt_response = data_blob_null;
752 #else
753 nt_response = data_blob(NULL, 24);
754 if (tevent_req_nomem(nt_response.data, req)) {
755 return tevent_req_post(req, ev);
758 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
759 nt_response.data);
760 #endif
761 /* non encrypted password supplied. Ignore ntpass. */
762 if (lp_client_lanman_auth()) {
764 lm_response = data_blob(NULL, 24);
765 if (tevent_req_nomem(lm_response.data, req)) {
766 return tevent_req_post(req, ev);
769 if (!SMBencrypt(pass,
770 smb1cli_conn_server_challenge(cli->conn),
771 lm_response.data)) {
773 * Oops, the LM response is
774 * invalid, just put the NT
775 * response there instead
777 data_blob_free(&lm_response);
778 lm_response = data_blob(
779 nt_response.data,
780 nt_response.length);
782 } else {
784 * LM disabled, place NT# in LM field
785 * instead
787 lm_response = data_blob(
788 nt_response.data, nt_response.length);
791 if (tevent_req_nomem(lm_response.data, req)) {
792 return tevent_req_post(req, ev);
795 session_key = data_blob(NULL, 16);
796 if (tevent_req_nomem(session_key.data, req)) {
797 return tevent_req_post(req, ev);
799 #ifdef LANMAN_ONLY
800 E_deshash(pass, session_key.data);
801 memset(&session_key.data[8], '\0', 8);
802 #else
803 SMBsesskeygen_ntv1(nt_hash, session_key.data);
804 #endif
806 } else {
807 /* pre-encrypted password supplied. Only used for
808 security=server, can't do
809 signing because we don't have original key */
811 lm_response = data_blob(pass, passlen);
812 if (tevent_req_nomem(lm_response.data, req)) {
813 return tevent_req_post(req, ev);
816 nt_response = data_blob(ntpass, ntpasslen);
817 if (tevent_req_nomem(nt_response.data, req)) {
818 return tevent_req_post(req, ev);
822 #ifdef LANMAN_ONLY
823 state->response = data_blob_talloc(
824 state, lm_response.data, lm_response.length);
825 #else
826 state->response = data_blob_talloc(
827 state, nt_response.data, nt_response.length);
828 #endif
829 if (tevent_req_nomem(state->response.data, req)) {
830 return tevent_req_post(req, ev);
833 if (session_key.data) {
834 state->session_key = data_blob_talloc(
835 state, session_key.data, session_key.length);
836 if (tevent_req_nomem(state->session_key.data, req)) {
837 return tevent_req_post(req, ev);
840 data_blob_free(&session_key);
842 SCVAL(vwv+0, 0, 0xff);
843 SCVAL(vwv+0, 1, 0);
844 SSVAL(vwv+1, 0, 0);
845 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
846 SSVAL(vwv+3, 0, 2);
847 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
848 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
849 SSVAL(vwv+7, 0, lm_response.length);
850 SSVAL(vwv+8, 0, nt_response.length);
851 SSVAL(vwv+9, 0, 0);
852 SSVAL(vwv+10, 0, 0);
853 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
855 bytes = talloc_array(state, uint8_t,
856 lm_response.length + nt_response.length);
857 if (tevent_req_nomem(bytes, req)) {
858 return tevent_req_post(req, ev);
860 if (lm_response.length != 0) {
861 memcpy(bytes, lm_response.data, lm_response.length);
863 if (nt_response.length != 0) {
864 memcpy(bytes + lm_response.length,
865 nt_response.data, nt_response.length);
867 data_blob_free(&lm_response);
868 data_blob_free(&nt_response);
870 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
871 user, strlen(user)+1, NULL);
874 * Upper case here might help some NTLMv2 implementations
876 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
877 if (tevent_req_nomem(workgroup_upper, req)) {
878 return tevent_req_post(req, ev);
880 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
881 workgroup_upper, strlen(workgroup_upper)+1,
882 NULL);
883 TALLOC_FREE(workgroup_upper);
885 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
886 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
887 if (tevent_req_nomem(bytes, req)) {
888 return tevent_req_post(req, ev);
891 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
892 talloc_get_size(bytes), bytes);
893 if (tevent_req_nomem(subreq, req)) {
894 return tevent_req_post(req, ev);
896 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
897 return req;
900 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
902 struct tevent_req *req = tevent_req_callback_data(
903 subreq, struct tevent_req);
904 struct cli_session_setup_nt1_state *state = tevent_req_data(
905 req, struct cli_session_setup_nt1_state);
906 struct cli_state *cli = state->cli;
907 uint32_t num_bytes;
908 uint8_t *in;
909 uint8_t *inhdr;
910 uint8_t *bytes;
911 uint8_t *p;
912 NTSTATUS status;
913 ssize_t ret;
914 uint8_t wct;
915 uint16_t *vwv;
917 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
918 &num_bytes, &bytes);
919 TALLOC_FREE(subreq);
920 if (!NT_STATUS_IS_OK(status)) {
921 tevent_req_nterror(req, status);
922 return;
925 inhdr = in + NBT_HDR_SIZE;
926 p = bytes;
928 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
930 status = smb_bytes_talloc_string(cli,
931 inhdr,
932 &cli->server_os,
934 bytes+num_bytes-p,
935 &ret);
936 if (!NT_STATUS_IS_OK(status)) {
937 tevent_req_nterror(req, status);
938 return;
940 p += ret;
942 status = smb_bytes_talloc_string(cli,
943 inhdr,
944 &cli->server_type,
946 bytes+num_bytes-p,
947 &ret);
948 if (!NT_STATUS_IS_OK(status)) {
949 tevent_req_nterror(req, status);
950 return;
952 p += ret;
954 status = smb_bytes_talloc_string(cli,
955 inhdr,
956 &cli->server_domain,
958 bytes+num_bytes-p,
959 &ret);
960 if (!NT_STATUS_IS_OK(status)) {
961 tevent_req_nterror(req, status);
962 return;
964 p += ret;
966 status = cli_set_username(cli, state->user);
967 if (tevent_req_nterror(req, status)) {
968 return;
970 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
971 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
972 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
973 return;
975 if (state->session_key.data) {
976 struct smbXcli_session *session = state->cli->smb1.session;
978 status = smb1cli_session_set_session_key(session,
979 state->session_key);
980 if (tevent_req_nterror(req, status)) {
981 return;
984 tevent_req_done(req);
987 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
989 return tevent_req_simple_recv_ntstatus(req);
992 /* The following is calculated from :
993 * (smb_size-4) = 35
994 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
995 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
996 * end of packet.
999 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1001 struct cli_sesssetup_blob_state {
1002 struct tevent_context *ev;
1003 struct cli_state *cli;
1004 DATA_BLOB blob;
1005 uint16_t max_blob_size;
1006 uint16_t vwv[12];
1007 uint8_t *buf;
1009 DATA_BLOB smb2_blob;
1010 struct iovec *recv_iov;
1012 NTSTATUS status;
1013 uint8_t *inbuf;
1014 DATA_BLOB ret_blob;
1017 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1018 struct tevent_req **psubreq);
1019 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1021 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1022 struct tevent_context *ev,
1023 struct cli_state *cli,
1024 DATA_BLOB blob)
1026 struct tevent_req *req, *subreq;
1027 struct cli_sesssetup_blob_state *state;
1028 uint32_t usable_space;
1030 req = tevent_req_create(mem_ctx, &state,
1031 struct cli_sesssetup_blob_state);
1032 if (req == NULL) {
1033 return NULL;
1035 state->ev = ev;
1036 state->blob = blob;
1037 state->cli = cli;
1039 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1040 usable_space = UINT16_MAX;
1041 } else {
1042 usable_space = cli_state_available_size(cli,
1043 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1046 if (usable_space == 0) {
1047 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1048 "(not possible to send %u bytes)\n",
1049 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1050 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1051 return tevent_req_post(req, ev);
1053 state->max_blob_size = MIN(usable_space, 0xFFFF);
1055 if (!cli_sesssetup_blob_next(state, &subreq)) {
1056 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1057 return tevent_req_post(req, ev);
1059 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1060 return req;
1063 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1064 struct tevent_req **psubreq)
1066 struct tevent_req *subreq;
1067 uint16_t thistime;
1069 thistime = MIN(state->blob.length, state->max_blob_size);
1071 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1073 state->smb2_blob.data = state->blob.data;
1074 state->smb2_blob.length = thistime;
1076 state->blob.data += thistime;
1077 state->blob.length -= thistime;
1079 subreq = smb2cli_session_setup_send(state, state->ev,
1080 state->cli->conn,
1081 state->cli->timeout,
1082 state->cli->smb2.session,
1083 0, /* in_flags */
1084 SMB2_CAP_DFS, /* in_capabilities */
1085 0, /* in_channel */
1086 0, /* in_previous_session_id */
1087 &state->smb2_blob);
1088 if (subreq == NULL) {
1089 return false;
1091 *psubreq = subreq;
1092 return true;
1095 SCVAL(state->vwv+0, 0, 0xFF);
1096 SCVAL(state->vwv+0, 1, 0);
1097 SSVAL(state->vwv+1, 0, 0);
1098 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1099 SSVAL(state->vwv+3, 0, 2);
1100 SSVAL(state->vwv+4, 0, 1);
1101 SIVAL(state->vwv+5, 0, 0);
1103 SSVAL(state->vwv+7, 0, thistime);
1105 SSVAL(state->vwv+8, 0, 0);
1106 SSVAL(state->vwv+9, 0, 0);
1107 SIVAL(state->vwv+10, 0,
1108 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1110 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1111 thistime);
1112 if (state->buf == NULL) {
1113 return false;
1115 state->blob.data += thistime;
1116 state->blob.length -= thistime;
1118 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1119 "Unix", 5, NULL);
1120 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1121 "Samba", 6, NULL);
1122 if (state->buf == NULL) {
1123 return false;
1125 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1126 12, state->vwv,
1127 talloc_get_size(state->buf), state->buf);
1128 if (subreq == NULL) {
1129 return false;
1131 *psubreq = subreq;
1132 return true;
1135 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1137 struct tevent_req *req = tevent_req_callback_data(
1138 subreq, struct tevent_req);
1139 struct cli_sesssetup_blob_state *state = tevent_req_data(
1140 req, struct cli_sesssetup_blob_state);
1141 struct cli_state *cli = state->cli;
1142 uint8_t wct;
1143 uint16_t *vwv;
1144 uint32_t num_bytes;
1145 uint8_t *bytes;
1146 NTSTATUS status;
1147 uint8_t *p;
1148 uint16_t blob_length;
1149 uint8_t *in;
1150 uint8_t *inhdr;
1151 ssize_t ret;
1153 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1154 status = smb2cli_session_setup_recv(subreq, state,
1155 &state->recv_iov,
1156 &state->ret_blob);
1157 } else {
1158 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1159 &num_bytes, &bytes);
1160 TALLOC_FREE(state->buf);
1162 TALLOC_FREE(subreq);
1163 if (!NT_STATUS_IS_OK(status)
1164 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1165 tevent_req_nterror(req, status);
1166 return;
1169 state->status = status;
1171 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1172 goto next;
1175 state->inbuf = in;
1176 inhdr = in + NBT_HDR_SIZE;
1177 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1179 blob_length = SVAL(vwv+3, 0);
1180 if (blob_length > num_bytes) {
1181 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1182 return;
1184 state->ret_blob = data_blob_const(bytes, blob_length);
1186 p = bytes + blob_length;
1188 status = smb_bytes_talloc_string(cli,
1189 inhdr,
1190 &cli->server_os,
1192 bytes+num_bytes-p,
1193 &ret);
1195 if (!NT_STATUS_IS_OK(status)) {
1196 tevent_req_nterror(req, status);
1197 return;
1199 p += ret;
1201 status = smb_bytes_talloc_string(cli,
1202 inhdr,
1203 &cli->server_type,
1205 bytes+num_bytes-p,
1206 &ret);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 tevent_req_nterror(req, status);
1210 return;
1212 p += ret;
1214 status = smb_bytes_talloc_string(cli,
1215 inhdr,
1216 &cli->server_domain,
1218 bytes+num_bytes-p,
1219 &ret);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 tevent_req_nterror(req, status);
1223 return;
1225 p += ret;
1227 next:
1228 if (state->blob.length != 0) {
1230 * More to send
1232 if (!cli_sesssetup_blob_next(state, &subreq)) {
1233 tevent_req_oom(req);
1234 return;
1236 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1237 return;
1239 tevent_req_done(req);
1242 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1243 TALLOC_CTX *mem_ctx,
1244 DATA_BLOB *pblob,
1245 uint8_t **pinbuf,
1246 struct iovec **precv_iov)
1248 struct cli_sesssetup_blob_state *state = tevent_req_data(
1249 req, struct cli_sesssetup_blob_state);
1250 NTSTATUS status;
1251 uint8_t *inbuf;
1252 struct iovec *recv_iov;
1254 if (tevent_req_is_nterror(req, &status)) {
1255 TALLOC_FREE(state->cli->smb2.session);
1256 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1257 return status;
1260 inbuf = talloc_move(mem_ctx, &state->inbuf);
1261 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1262 if (pblob != NULL) {
1263 *pblob = state->ret_blob;
1265 if (pinbuf != NULL) {
1266 *pinbuf = inbuf;
1268 if (precv_iov != NULL) {
1269 *precv_iov = recv_iov;
1271 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1272 return state->status;
1275 #ifdef HAVE_KRB5
1277 /****************************************************************************
1278 Use in-memory credentials cache
1279 ****************************************************************************/
1281 static void use_in_memory_ccache(void) {
1282 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1285 /****************************************************************************
1286 Do a spnego/kerberos encrypted session setup.
1287 ****************************************************************************/
1289 struct cli_session_setup_kerberos_state {
1290 struct cli_state *cli;
1291 DATA_BLOB negTokenTarg;
1292 DATA_BLOB session_key_krb5;
1293 ADS_STATUS ads_status;
1296 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1298 static struct tevent_req *cli_session_setup_kerberos_send(
1299 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1300 const char *principal)
1302 struct tevent_req *req, *subreq;
1303 struct cli_session_setup_kerberos_state *state;
1304 int rc;
1306 DEBUG(2,("Doing kerberos session setup\n"));
1308 req = tevent_req_create(mem_ctx, &state,
1309 struct cli_session_setup_kerberos_state);
1310 if (req == NULL) {
1311 return NULL;
1313 state->cli = cli;
1314 state->ads_status = ADS_SUCCESS;
1317 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1318 * we have to acquire a ticket. To be fixed later :-)
1320 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1321 &state->session_key_krb5, 0, NULL, NULL);
1322 if (rc) {
1323 DEBUG(1, ("cli_session_setup_kerberos: "
1324 "spnego_gen_krb5_negTokenInit failed: %s\n",
1325 error_message(rc)));
1326 state->ads_status = ADS_ERROR_KRB5(rc);
1327 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1328 return tevent_req_post(req, ev);
1331 #if 0
1332 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1333 state->negTokenTarg.length);
1334 #endif
1336 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1337 state->cli->smb2.session = smbXcli_session_create(cli,
1338 cli->conn);
1339 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1340 return tevent_req_post(req, ev);
1344 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1345 if (tevent_req_nomem(subreq, req)) {
1346 return tevent_req_post(req, ev);
1348 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1349 return req;
1352 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1354 struct tevent_req *req = tevent_req_callback_data(
1355 subreq, struct tevent_req);
1356 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1357 req, struct cli_session_setup_kerberos_state);
1358 uint8_t *inbuf = NULL;
1359 struct iovec *recv_iov = NULL;
1360 NTSTATUS status;
1362 status = cli_sesssetup_blob_recv(subreq, state,
1363 NULL, &inbuf, &recv_iov);
1364 TALLOC_FREE(subreq);
1365 if (!NT_STATUS_IS_OK(status)) {
1366 tevent_req_nterror(req, status);
1367 return;
1370 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1371 struct smbXcli_session *session = state->cli->smb2.session;
1372 status = smb2cli_session_set_session_key(session,
1373 state->session_key_krb5,
1374 recv_iov);
1375 if (tevent_req_nterror(req, status)) {
1376 return;
1378 } else {
1379 struct smbXcli_session *session = state->cli->smb1.session;
1381 status = smb1cli_session_set_session_key(session,
1382 state->session_key_krb5);
1383 if (tevent_req_nterror(req, status)) {
1384 return;
1387 if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5,
1388 data_blob_null)
1389 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1390 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1391 return;
1395 tevent_req_done(req);
1398 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1400 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1401 req, struct cli_session_setup_kerberos_state);
1402 NTSTATUS status;
1404 if (tevent_req_is_nterror(req, &status)) {
1405 return ADS_ERROR_NT(status);
1407 return state->ads_status;
1410 #endif /* HAVE_KRB5 */
1412 /****************************************************************************
1413 Do a spnego/NTLMSSP encrypted session setup.
1414 ****************************************************************************/
1416 struct cli_session_setup_ntlmssp_state {
1417 struct tevent_context *ev;
1418 struct cli_state *cli;
1419 struct ntlmssp_state *ntlmssp_state;
1420 int turn;
1421 DATA_BLOB blob_out;
1424 static int cli_session_setup_ntlmssp_state_destructor(
1425 struct cli_session_setup_ntlmssp_state *state)
1427 if (state->ntlmssp_state != NULL) {
1428 TALLOC_FREE(state->ntlmssp_state);
1430 return 0;
1433 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1435 static struct tevent_req *cli_session_setup_ntlmssp_send(
1436 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1437 const char *user, const char *pass, const char *domain)
1439 struct tevent_req *req, *subreq;
1440 struct cli_session_setup_ntlmssp_state *state;
1441 NTSTATUS status;
1442 DATA_BLOB blob_out;
1443 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1445 req = tevent_req_create(mem_ctx, &state,
1446 struct cli_session_setup_ntlmssp_state);
1447 if (req == NULL) {
1448 return NULL;
1450 state->ev = ev;
1451 state->cli = cli;
1452 state->turn = 1;
1454 state->ntlmssp_state = NULL;
1455 talloc_set_destructor(
1456 state, cli_session_setup_ntlmssp_state_destructor);
1458 status = ntlmssp_client_start(state,
1459 lp_netbios_name(),
1460 lp_workgroup(),
1461 lp_client_ntlmv2_auth(),
1462 &state->ntlmssp_state);
1463 if (!NT_STATUS_IS_OK(status)) {
1464 goto fail;
1466 ntlmssp_want_feature(state->ntlmssp_state,
1467 NTLMSSP_FEATURE_SESSION_KEY);
1468 if (cli->use_ccache) {
1469 ntlmssp_want_feature(state->ntlmssp_state,
1470 NTLMSSP_FEATURE_CCACHE);
1472 status = ntlmssp_set_username(state->ntlmssp_state, user);
1473 if (!NT_STATUS_IS_OK(status)) {
1474 goto fail;
1476 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1477 if (!NT_STATUS_IS_OK(status)) {
1478 goto fail;
1480 if (cli->pw_nt_hash) {
1481 status = ntlmssp_set_password_hash(state->ntlmssp_state, pass);
1482 } else {
1483 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1485 if (!NT_STATUS_IS_OK(status)) {
1486 goto fail;
1488 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1489 &blob_out);
1490 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1491 goto fail;
1494 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1495 data_blob_free(&blob_out);
1497 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1498 state->cli->smb2.session = smbXcli_session_create(cli,
1499 cli->conn);
1500 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1501 return tevent_req_post(req, ev);
1505 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1506 if (tevent_req_nomem(subreq, req)) {
1507 return tevent_req_post(req, ev);
1509 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1510 return req;
1511 fail:
1512 tevent_req_nterror(req, status);
1513 return tevent_req_post(req, ev);
1516 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1518 struct tevent_req *req = tevent_req_callback_data(
1519 subreq, struct tevent_req);
1520 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1521 req, struct cli_session_setup_ntlmssp_state);
1522 DATA_BLOB blob_in, msg_in, blob_out;
1523 uint8_t *inbuf = NULL;
1524 struct iovec *recv_iov = NULL;
1525 bool parse_ret;
1526 NTSTATUS status;
1528 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1529 &inbuf, &recv_iov);
1530 TALLOC_FREE(subreq);
1531 data_blob_free(&state->blob_out);
1533 if (NT_STATUS_IS_OK(status)) {
1534 if (state->cli->server_domain[0] == '\0') {
1535 TALLOC_FREE(state->cli->server_domain);
1536 state->cli->server_domain = talloc_strdup(state->cli,
1537 state->ntlmssp_state->server.netbios_domain);
1538 if (state->cli->server_domain == NULL) {
1539 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1540 return;
1544 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1545 struct smbXcli_session *session = state->cli->smb2.session;
1547 if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
1549 * Windows server does not set the
1550 * SMB2_SESSION_FLAG_IS_GUEST nor
1551 * SMB2_SESSION_FLAG_IS_NULL flag.
1553 * This fix makes sure we do not try
1554 * to verify a signature on the final
1555 * session setup response.
1557 TALLOC_FREE(state->ntlmssp_state);
1558 tevent_req_done(req);
1559 return;
1562 status = smb2cli_session_set_session_key(session,
1563 state->ntlmssp_state->session_key,
1564 recv_iov);
1565 if (tevent_req_nterror(req, status)) {
1566 return;
1568 } else {
1569 struct smbXcli_session *session = state->cli->smb1.session;
1571 status = smb1cli_session_set_session_key(session,
1572 state->ntlmssp_state->session_key);
1573 if (tevent_req_nterror(req, status)) {
1574 return;
1577 if (smb1cli_conn_activate_signing(
1578 state->cli->conn, state->ntlmssp_state->session_key,
1579 data_blob_null)
1580 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1581 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1582 return;
1585 TALLOC_FREE(state->ntlmssp_state);
1586 tevent_req_done(req);
1587 return;
1589 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1590 tevent_req_nterror(req, status);
1591 return;
1594 if (blob_in.length == 0) {
1595 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1596 return;
1599 if ((state->turn == 1)
1600 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1601 DATA_BLOB tmp_blob = data_blob_null;
1602 /* the server might give us back two challenges */
1603 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1604 &tmp_blob);
1605 data_blob_free(&tmp_blob);
1606 } else {
1607 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1608 OID_NTLMSSP, &msg_in);
1610 state->turn += 1;
1612 if (!parse_ret) {
1613 DEBUG(3,("Failed to parse auth response\n"));
1614 if (NT_STATUS_IS_OK(status)
1615 || NT_STATUS_EQUAL(status,
1616 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1617 tevent_req_nterror(
1618 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1619 return;
1623 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1625 if (!NT_STATUS_IS_OK(status)
1626 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1627 TALLOC_FREE(state->ntlmssp_state);
1628 tevent_req_nterror(req, status);
1629 return;
1632 state->blob_out = spnego_gen_auth(state, blob_out);
1633 if (tevent_req_nomem(state->blob_out.data, req)) {
1634 return;
1637 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1638 state->blob_out);
1639 if (tevent_req_nomem(subreq, req)) {
1640 return;
1642 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1645 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1647 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1648 req, struct cli_session_setup_ntlmssp_state);
1649 NTSTATUS status;
1651 if (tevent_req_is_nterror(req, &status)) {
1652 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1653 return status;
1655 return NT_STATUS_OK;
1658 #ifdef HAVE_KRB5
1660 static char *cli_session_setup_get_principal(
1661 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1662 const char *remote_name, const char *dest_realm)
1664 char *principal = NULL;
1666 if (!lp_client_use_spnego_principal() ||
1667 strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1668 spnego_principal = NULL;
1670 if (spnego_principal != NULL) {
1671 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1672 "principal %s\n", spnego_principal));
1673 return talloc_strdup(mem_ctx, spnego_principal);
1675 if (is_ipaddress(remote_name) ||
1676 strequal(remote_name, STAR_SMBSERVER)) {
1677 return NULL;
1680 DEBUG(3, ("cli_session_setup_spnego: using target "
1681 "hostname not SPNEGO principal\n"));
1683 if (dest_realm) {
1684 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1685 if (realm == NULL) {
1686 return NULL;
1688 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1689 remote_name, realm);
1690 TALLOC_FREE(realm);
1691 } else {
1692 principal = kerberos_get_principal_from_service_hostname(
1693 talloc_tos(), "cifs", remote_name, lp_realm());
1695 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1696 principal ? principal : "<null>"));
1698 return principal;
1700 #endif
1702 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1703 const char *principal)
1705 char *account, *p;
1707 account = talloc_strdup(mem_ctx, principal);
1708 if (account == NULL) {
1709 return NULL;
1711 p = strchr_m(account, '@');
1712 if (p != NULL) {
1713 *p = '\0';
1715 return account;
1718 /****************************************************************************
1719 Do a spnego encrypted session setup.
1721 user_domain: The shortname of the domain the user/machine is a member of.
1722 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1723 ****************************************************************************/
1725 struct cli_session_setup_spnego_state {
1726 struct tevent_context *ev;
1727 struct cli_state *cli;
1728 const char *user;
1729 const char *account;
1730 const char *pass;
1731 const char *user_domain;
1732 const char *dest_realm;
1733 ADS_STATUS result;
1736 #ifdef HAVE_KRB5
1737 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1738 #endif
1740 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1742 static struct tevent_req *cli_session_setup_spnego_send(
1743 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1744 const char *user, const char *pass, const char *user_domain,
1745 const char *dest_realm)
1747 struct tevent_req *req, *subreq;
1748 struct cli_session_setup_spnego_state *state;
1749 char *principal = NULL;
1750 char *OIDs[ASN1_MAX_OIDS];
1751 int i;
1752 const DATA_BLOB *server_blob;
1753 NTSTATUS status;
1755 req = tevent_req_create(mem_ctx, &state,
1756 struct cli_session_setup_spnego_state);
1757 if (req == NULL) {
1758 return NULL;
1760 state->ev = ev;
1761 state->cli = cli;
1762 state->user = user;
1763 state->pass = pass;
1764 state->user_domain = user_domain;
1765 state->dest_realm = dest_realm;
1767 state->account = cli_session_setup_get_account(state, user);
1768 if (tevent_req_nomem(state->account, req)) {
1769 return tevent_req_post(req, ev);
1772 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1774 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1775 (unsigned long)server_blob->length));
1777 /* the server might not even do spnego */
1778 if (server_blob->length == 0) {
1779 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1780 goto ntlmssp;
1783 #if 0
1784 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1785 #endif
1787 /* The server sent us the first part of the SPNEGO exchange in the
1788 * negprot reply. It is WRONG to depend on the principal sent in the
1789 * negprot reply, but right now we do it. If we don't receive one,
1790 * we try to best guess, then fall back to NTLM. */
1791 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1792 &principal, NULL) ||
1793 OIDs[0] == NULL) {
1794 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1795 tevent_req_done(req);
1796 return tevent_req_post(req, ev);
1799 /* make sure the server understands kerberos */
1800 for (i=0;OIDs[i];i++) {
1801 if (i == 0)
1802 DEBUG(3,("got OID=%s\n", OIDs[i]));
1803 else
1804 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1805 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1806 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1807 cli->got_kerberos_mechanism = True;
1809 talloc_free(OIDs[i]);
1812 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1814 status = cli_set_username(cli, user);
1815 if (!NT_STATUS_IS_OK(status)) {
1816 state->result = ADS_ERROR_NT(status);
1817 tevent_req_done(req);
1818 return tevent_req_post(req, ev);
1821 #ifdef HAVE_KRB5
1822 /* If password is set we reauthenticate to kerberos server
1823 * and do not store results */
1825 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1826 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
1827 char *tmp;
1829 if (pass && *pass) {
1830 int ret;
1832 use_in_memory_ccache();
1833 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1835 if (ret){
1836 TALLOC_FREE(principal);
1837 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1838 if (cli->fallback_after_kerberos)
1839 goto ntlmssp;
1840 state->result = ADS_ERROR_KRB5(ret);
1841 tevent_req_done(req);
1842 return tevent_req_post(req, ev);
1846 tmp = cli_session_setup_get_principal(
1847 talloc_tos(), principal, remote_name, dest_realm);
1848 TALLOC_FREE(principal);
1849 principal = tmp;
1851 if (principal) {
1852 subreq = cli_session_setup_kerberos_send(
1853 state, ev, cli, principal);
1854 if (tevent_req_nomem(subreq, req)) {
1855 return tevent_req_post(req, ev);
1857 tevent_req_set_callback(
1858 subreq, cli_session_setup_spnego_done_krb,
1859 req);
1860 return req;
1863 #endif
1865 ntlmssp:
1866 subreq = cli_session_setup_ntlmssp_send(
1867 state, ev, cli, state->account, pass, user_domain);
1868 if (tevent_req_nomem(subreq, req)) {
1869 return tevent_req_post(req, ev);
1871 tevent_req_set_callback(
1872 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1873 return req;
1876 #ifdef HAVE_KRB5
1877 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1879 struct tevent_req *req = tevent_req_callback_data(
1880 subreq, struct tevent_req);
1881 struct cli_session_setup_spnego_state *state = tevent_req_data(
1882 req, struct cli_session_setup_spnego_state);
1884 state->result = cli_session_setup_kerberos_recv(subreq);
1885 TALLOC_FREE(subreq);
1887 if (ADS_ERR_OK(state->result) ||
1888 !state->cli->fallback_after_kerberos) {
1889 tevent_req_done(req);
1890 return;
1893 subreq = cli_session_setup_ntlmssp_send(
1894 state, state->ev, state->cli, state->account, state->pass,
1895 state->user_domain);
1896 if (tevent_req_nomem(subreq, req)) {
1897 return;
1899 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1900 req);
1902 #endif
1904 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1906 struct tevent_req *req = tevent_req_callback_data(
1907 subreq, struct tevent_req);
1908 struct cli_session_setup_spnego_state *state = tevent_req_data(
1909 req, struct cli_session_setup_spnego_state);
1910 NTSTATUS status;
1912 status = cli_session_setup_ntlmssp_recv(subreq);
1913 TALLOC_FREE(subreq);
1914 state->result = ADS_ERROR_NT(status);
1915 tevent_req_done(req);
1918 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1920 struct cli_session_setup_spnego_state *state = tevent_req_data(
1921 req, struct cli_session_setup_spnego_state);
1923 return state->result;
1926 struct cli_session_setup_state {
1927 uint8_t dummy;
1930 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1931 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1932 static void cli_session_setup_done_guest(struct tevent_req *subreq);
1933 static void cli_session_setup_done_plain(struct tevent_req *subreq);
1934 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1936 /****************************************************************************
1937 Send a session setup. The username and workgroup is in UNIX character
1938 format and must be converted to DOS codepage format before sending. If the
1939 password is in plaintext, the same should be done.
1940 ****************************************************************************/
1942 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1943 struct tevent_context *ev,
1944 struct cli_state *cli,
1945 const char *user,
1946 const char *pass, int passlen,
1947 const char *ntpass, int ntpasslen,
1948 const char *workgroup)
1950 struct tevent_req *req, *subreq;
1951 struct cli_session_setup_state *state;
1952 char *p;
1953 char *user2;
1954 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1956 req = tevent_req_create(mem_ctx, &state,
1957 struct cli_session_setup_state);
1958 if (req == NULL) {
1959 return NULL;
1962 if (user) {
1963 user2 = talloc_strdup(state, user);
1964 } else {
1965 user2 = talloc_strdup(state, "");
1967 if (user2 == NULL) {
1968 tevent_req_oom(req);
1969 return tevent_req_post(req, ev);
1972 if (!workgroup) {
1973 workgroup = "";
1976 /* allow for workgroups as part of the username */
1977 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1978 (p=strchr_m(user2,*lp_winbind_separator()))) {
1979 *p = 0;
1980 user = p+1;
1981 if (!strupper_m(user2)) {
1982 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1983 return tevent_req_post(req, ev);
1985 workgroup = user2;
1988 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1989 tevent_req_done(req);
1990 return tevent_req_post(req, ev);
1993 /* now work out what sort of session setup we are going to
1994 do. I have split this into separate functions to make the
1995 flow a bit easier to understand (tridge) */
1997 /* if its an older server then we have to use the older request format */
1999 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2000 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2001 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2002 " or 'client ntlmv2 auth = yes'\n"));
2003 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2004 return tevent_req_post(req, ev);
2007 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2008 !lp_client_plaintext_auth() && (*pass)) {
2009 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2010 " or 'client ntlmv2 auth = yes'\n"));
2011 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2012 return tevent_req_post(req, ev);
2015 subreq = cli_session_setup_lanman2_send(
2016 state, ev, cli, user, pass, passlen, workgroup);
2017 if (tevent_req_nomem(subreq, req)) {
2018 return tevent_req_post(req, ev);
2020 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2021 req);
2022 return req;
2025 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2026 const char *remote_realm = cli_state_remote_realm(cli);
2028 subreq = cli_session_setup_spnego_send(
2029 state, ev, cli, user, pass, workgroup, remote_realm);
2030 if (tevent_req_nomem(subreq, req)) {
2031 return tevent_req_post(req, ev);
2033 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2034 req);
2035 return req;
2038 /* if no user is supplied then we have to do an anonymous connection.
2039 passwords are ignored */
2041 if (!user || !*user) {
2042 subreq = cli_session_setup_guest_send(state, ev, cli);
2043 if (tevent_req_nomem(subreq, req)) {
2044 return tevent_req_post(req, ev);
2046 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2047 req);
2048 return req;
2051 /* if the server is share level then send a plaintext null
2052 password at this point. The password is sent in the tree
2053 connect */
2055 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2056 subreq = cli_session_setup_plain_send(
2057 state, ev, cli, user, "", workgroup);
2058 if (tevent_req_nomem(subreq, req)) {
2059 return tevent_req_post(req, ev);
2061 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2062 req);
2063 return req;
2066 /* if the server doesn't support encryption then we have to use
2067 plaintext. The second password is ignored */
2069 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2070 if (!lp_client_plaintext_auth() && (*pass)) {
2071 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2072 " or 'client ntlmv2 auth = yes'\n"));
2073 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2074 return tevent_req_post(req, ev);
2076 subreq = cli_session_setup_plain_send(
2077 state, ev, cli, user, pass, workgroup);
2078 if (tevent_req_nomem(subreq, req)) {
2079 return tevent_req_post(req, ev);
2081 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2082 req);
2083 return req;
2086 /* if the server supports extended security then use SPNEGO */
2088 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2089 const char *remote_realm = cli_state_remote_realm(cli);
2091 subreq = cli_session_setup_spnego_send(
2092 state, ev, cli, user, pass, workgroup, remote_realm);
2093 if (tevent_req_nomem(subreq, req)) {
2094 return tevent_req_post(req, ev);
2096 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2097 req);
2098 return req;
2099 } else {
2100 /* otherwise do a NT1 style session setup */
2102 subreq = cli_session_setup_nt1_send(
2103 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2104 workgroup);
2105 if (tevent_req_nomem(subreq, req)) {
2106 return tevent_req_post(req, ev);
2108 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2109 req);
2110 return req;
2113 tevent_req_done(req);
2114 return tevent_req_post(req, ev);
2117 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2119 struct tevent_req *req = tevent_req_callback_data(
2120 subreq, struct tevent_req);
2121 NTSTATUS status;
2123 status = cli_session_setup_lanman2_recv(subreq);
2124 TALLOC_FREE(subreq);
2125 if (!NT_STATUS_IS_OK(status)) {
2126 tevent_req_nterror(req, status);
2127 return;
2129 tevent_req_done(req);
2132 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2134 struct tevent_req *req = tevent_req_callback_data(
2135 subreq, struct tevent_req);
2136 ADS_STATUS status;
2138 status = cli_session_setup_spnego_recv(subreq);
2139 TALLOC_FREE(subreq);
2140 if (!ADS_ERR_OK(status)) {
2141 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2142 tevent_req_nterror(req, ads_ntstatus(status));
2143 return;
2145 tevent_req_done(req);
2148 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2150 struct tevent_req *req = tevent_req_callback_data(
2151 subreq, struct tevent_req);
2152 NTSTATUS status;
2154 status = cli_session_setup_guest_recv(subreq);
2155 TALLOC_FREE(subreq);
2156 if (!NT_STATUS_IS_OK(status)) {
2157 tevent_req_nterror(req, status);
2158 return;
2160 tevent_req_done(req);
2163 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2165 struct tevent_req *req = tevent_req_callback_data(
2166 subreq, struct tevent_req);
2167 NTSTATUS status;
2169 status = cli_session_setup_plain_recv(subreq);
2170 TALLOC_FREE(subreq);
2171 if (!NT_STATUS_IS_OK(status)) {
2172 tevent_req_nterror(req, status);
2173 return;
2175 tevent_req_done(req);
2178 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2180 struct tevent_req *req = tevent_req_callback_data(
2181 subreq, struct tevent_req);
2182 NTSTATUS status;
2184 status = cli_session_setup_nt1_recv(subreq);
2185 TALLOC_FREE(subreq);
2186 if (!NT_STATUS_IS_OK(status)) {
2187 DEBUG(3, ("cli_session_setup: NT1 session setup "
2188 "failed: %s\n", nt_errstr(status)));
2189 tevent_req_nterror(req, status);
2190 return;
2192 tevent_req_done(req);
2195 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2197 return tevent_req_simple_recv_ntstatus(req);
2200 NTSTATUS cli_session_setup(struct cli_state *cli,
2201 const char *user,
2202 const char *pass, int passlen,
2203 const char *ntpass, int ntpasslen,
2204 const char *workgroup)
2206 struct tevent_context *ev;
2207 struct tevent_req *req;
2208 NTSTATUS status = NT_STATUS_NO_MEMORY;
2210 if (smbXcli_conn_has_async_calls(cli->conn)) {
2211 return NT_STATUS_INVALID_PARAMETER;
2213 ev = samba_tevent_context_init(talloc_tos());
2214 if (ev == NULL) {
2215 goto fail;
2217 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2218 ntpass, ntpasslen, workgroup);
2219 if (req == NULL) {
2220 goto fail;
2222 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2223 goto fail;
2225 status = cli_session_setup_recv(req);
2226 fail:
2227 TALLOC_FREE(ev);
2228 return status;
2231 /****************************************************************************
2232 Send a uloggoff.
2233 *****************************************************************************/
2235 struct cli_ulogoff_state {
2236 struct cli_state *cli;
2237 uint16_t vwv[3];
2240 static void cli_ulogoff_done(struct tevent_req *subreq);
2242 static struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2243 struct tevent_context *ev,
2244 struct cli_state *cli)
2246 struct tevent_req *req, *subreq;
2247 struct cli_ulogoff_state *state;
2249 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2250 if (req == NULL) {
2251 return NULL;
2253 state->cli = cli;
2255 SCVAL(state->vwv+0, 0, 0xFF);
2256 SCVAL(state->vwv+1, 0, 0);
2257 SSVAL(state->vwv+2, 0, 0);
2259 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2260 0, NULL);
2261 if (tevent_req_nomem(subreq, req)) {
2262 return tevent_req_post(req, ev);
2264 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2265 return req;
2268 static void cli_ulogoff_done(struct tevent_req *subreq)
2270 struct tevent_req *req = tevent_req_callback_data(
2271 subreq, struct tevent_req);
2272 struct cli_ulogoff_state *state = tevent_req_data(
2273 req, struct cli_ulogoff_state);
2274 NTSTATUS status;
2276 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2277 if (!NT_STATUS_IS_OK(status)) {
2278 tevent_req_nterror(req, status);
2279 return;
2281 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2282 tevent_req_done(req);
2285 static NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2287 return tevent_req_simple_recv_ntstatus(req);
2290 NTSTATUS cli_ulogoff(struct cli_state *cli)
2292 struct tevent_context *ev;
2293 struct tevent_req *req;
2294 NTSTATUS status = NT_STATUS_NO_MEMORY;
2296 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2297 status = smb2cli_logoff(cli->conn,
2298 cli->timeout,
2299 cli->smb2.session);
2300 if (!NT_STATUS_IS_OK(status)) {
2301 return status;
2303 smb2cli_session_set_id_and_flags(cli->smb2.session,
2304 UINT64_MAX, 0);
2305 return NT_STATUS_OK;
2308 if (smbXcli_conn_has_async_calls(cli->conn)) {
2309 return NT_STATUS_INVALID_PARAMETER;
2311 ev = samba_tevent_context_init(talloc_tos());
2312 if (ev == NULL) {
2313 goto fail;
2315 req = cli_ulogoff_send(ev, ev, cli);
2316 if (req == NULL) {
2317 goto fail;
2319 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2320 goto fail;
2322 status = cli_ulogoff_recv(req);
2323 fail:
2324 TALLOC_FREE(ev);
2325 return status;
2328 /****************************************************************************
2329 Send a tconX.
2330 ****************************************************************************/
2332 struct cli_tcon_andx_state {
2333 struct cli_state *cli;
2334 uint16_t vwv[4];
2335 struct iovec bytes;
2338 static void cli_tcon_andx_done(struct tevent_req *subreq);
2340 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2341 struct tevent_context *ev,
2342 struct cli_state *cli,
2343 const char *share, const char *dev,
2344 const char *pass, int passlen,
2345 struct tevent_req **psmbreq)
2347 struct tevent_req *req, *subreq;
2348 struct cli_tcon_andx_state *state;
2349 uint8_t p24[24];
2350 uint16_t *vwv;
2351 char *tmp = NULL;
2352 uint8_t *bytes;
2353 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2354 uint16_t tcon_flags = 0;
2356 *psmbreq = NULL;
2358 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2359 if (req == NULL) {
2360 return NULL;
2362 state->cli = cli;
2363 vwv = state->vwv;
2365 cli->share = talloc_strdup(cli, share);
2366 if (!cli->share) {
2367 return NULL;
2370 /* in user level security don't send a password now */
2371 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2372 passlen = 1;
2373 pass = "";
2374 } else if (pass == NULL) {
2375 DEBUG(1, ("Server not using user level security and no "
2376 "password supplied.\n"));
2377 goto access_denied;
2380 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2381 *pass && passlen != 24) {
2382 if (!lp_client_lanman_auth()) {
2383 DEBUG(1, ("Server requested LANMAN password "
2384 "(share-level security) but "
2385 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2386 goto access_denied;
2390 * Non-encrypted passwords - convert to DOS codepage before
2391 * encryption.
2393 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2394 passlen = 24;
2395 pass = (const char *)p24;
2396 } else {
2397 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2398 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2399 == 0) {
2400 uint8_t *tmp_pass;
2402 if (!lp_client_plaintext_auth() && (*pass)) {
2403 DEBUG(1, ("Server requested PLAINTEXT "
2404 "password but "
2405 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2406 goto access_denied;
2410 * Non-encrypted passwords - convert to DOS codepage
2411 * before using.
2413 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2414 if (tevent_req_nomem(tmp_pass, req)) {
2415 return tevent_req_post(req, ev);
2417 tmp_pass = trans2_bytes_push_str(tmp_pass,
2418 false, /* always DOS */
2419 pass,
2420 passlen,
2421 NULL);
2422 if (tevent_req_nomem(tmp_pass, req)) {
2423 return tevent_req_post(req, ev);
2425 pass = (const char *)tmp_pass;
2426 passlen = talloc_get_size(tmp_pass);
2430 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2431 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2433 SCVAL(vwv+0, 0, 0xFF);
2434 SCVAL(vwv+0, 1, 0);
2435 SSVAL(vwv+1, 0, 0);
2436 SSVAL(vwv+2, 0, tcon_flags);
2437 SSVAL(vwv+3, 0, passlen);
2439 if (passlen && pass) {
2440 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2441 } else {
2442 bytes = talloc_array(state, uint8_t, 0);
2446 * Add the sharename
2448 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2449 smbXcli_conn_remote_name(cli->conn), share);
2450 if (tmp == NULL) {
2451 TALLOC_FREE(req);
2452 return NULL;
2454 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2455 NULL);
2456 TALLOC_FREE(tmp);
2459 * Add the devicetype
2461 tmp = talloc_strdup_upper(talloc_tos(), dev);
2462 if (tmp == NULL) {
2463 TALLOC_FREE(req);
2464 return NULL;
2466 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2467 TALLOC_FREE(tmp);
2469 if (bytes == NULL) {
2470 TALLOC_FREE(req);
2471 return NULL;
2474 state->bytes.iov_base = (void *)bytes;
2475 state->bytes.iov_len = talloc_get_size(bytes);
2477 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2478 1, &state->bytes);
2479 if (subreq == NULL) {
2480 TALLOC_FREE(req);
2481 return NULL;
2483 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2484 *psmbreq = subreq;
2485 return req;
2487 access_denied:
2488 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2489 return tevent_req_post(req, ev);
2492 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2493 struct tevent_context *ev,
2494 struct cli_state *cli,
2495 const char *share, const char *dev,
2496 const char *pass, int passlen)
2498 struct tevent_req *req, *subreq;
2499 NTSTATUS status;
2501 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2502 &subreq);
2503 if (req == NULL) {
2504 return NULL;
2506 if (subreq == NULL) {
2507 return req;
2509 status = smb1cli_req_chain_submit(&subreq, 1);
2510 if (!NT_STATUS_IS_OK(status)) {
2511 tevent_req_nterror(req, status);
2512 return tevent_req_post(req, ev);
2514 return req;
2517 static void cli_tcon_andx_done(struct tevent_req *subreq)
2519 struct tevent_req *req = tevent_req_callback_data(
2520 subreq, struct tevent_req);
2521 struct cli_tcon_andx_state *state = tevent_req_data(
2522 req, struct cli_tcon_andx_state);
2523 struct cli_state *cli = state->cli;
2524 uint8_t *in;
2525 uint8_t *inhdr;
2526 uint8_t wct;
2527 uint16_t *vwv;
2528 uint32_t num_bytes;
2529 uint8_t *bytes;
2530 NTSTATUS status;
2531 uint16_t optional_support = 0;
2533 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2534 &num_bytes, &bytes);
2535 TALLOC_FREE(subreq);
2536 if (!NT_STATUS_IS_OK(status)) {
2537 tevent_req_nterror(req, status);
2538 return;
2541 inhdr = in + NBT_HDR_SIZE;
2543 if (num_bytes) {
2544 if (clistr_pull_talloc(cli,
2545 (const char *)inhdr,
2546 SVAL(inhdr, HDR_FLG2),
2547 &cli->dev,
2548 bytes,
2549 num_bytes,
2550 STR_TERMINATE|STR_ASCII) == -1) {
2551 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2552 return;
2554 } else {
2555 cli->dev = talloc_strdup(cli, "");
2556 if (cli->dev == NULL) {
2557 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2558 return;
2562 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2563 /* almost certainly win95 - enable bug fixes */
2564 cli->win95 = True;
2568 * Make sure that we have the optional support 16-bit field. WCT > 2.
2569 * Avoids issues when connecting to Win9x boxes sharing files
2572 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2573 optional_support = SVAL(vwv+2, 0);
2576 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2577 smb1cli_session_protect_session_key(cli->smb1.session);
2580 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2581 SVAL(inhdr, HDR_TID),
2582 optional_support,
2583 0, /* maximal_access */
2584 0, /* guest_maximal_access */
2585 NULL, /* service */
2586 NULL); /* fs_type */
2588 tevent_req_done(req);
2591 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2593 return tevent_req_simple_recv_ntstatus(req);
2596 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2597 const char *dev, const char *pass, int passlen)
2599 TALLOC_CTX *frame = talloc_stackframe();
2600 struct tevent_context *ev;
2601 struct tevent_req *req;
2602 NTSTATUS status = NT_STATUS_NO_MEMORY;
2604 if (smbXcli_conn_has_async_calls(cli->conn)) {
2606 * Can't use sync call while an async call is in flight
2608 status = NT_STATUS_INVALID_PARAMETER;
2609 goto fail;
2612 ev = samba_tevent_context_init(frame);
2613 if (ev == NULL) {
2614 goto fail;
2617 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2618 if (req == NULL) {
2619 goto fail;
2622 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2623 goto fail;
2626 status = cli_tcon_andx_recv(req);
2627 fail:
2628 TALLOC_FREE(frame);
2629 return status;
2632 struct cli_tree_connect_state {
2633 struct cli_state *cli;
2636 static struct tevent_req *cli_raw_tcon_send(
2637 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2638 const char *service, const char *pass, const char *dev);
2639 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2640 uint16 *max_xmit, uint16 *tid);
2642 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2643 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2644 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2646 static struct tevent_req *cli_tree_connect_send(
2647 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2648 const char *share, const char *dev, const char *pass, int passlen)
2650 struct tevent_req *req, *subreq;
2651 struct cli_tree_connect_state *state;
2653 req = tevent_req_create(mem_ctx, &state,
2654 struct cli_tree_connect_state);
2655 if (req == NULL) {
2656 return NULL;
2658 state->cli = cli;
2660 cli->share = talloc_strdup(cli, share);
2661 if (tevent_req_nomem(cli->share, req)) {
2662 return tevent_req_post(req, ev);
2665 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2666 char *unc;
2668 cli->smb2.tcon = smbXcli_tcon_create(cli);
2669 if (tevent_req_nomem(cli->smb2.tcon, req)) {
2670 return tevent_req_post(req, ev);
2673 unc = talloc_asprintf(state, "\\\\%s\\%s",
2674 smbXcli_conn_remote_name(cli->conn),
2675 share);
2676 if (tevent_req_nomem(unc, req)) {
2677 return tevent_req_post(req, ev);
2680 subreq = smb2cli_tcon_send(state, ev, cli->conn, cli->timeout,
2681 cli->smb2.session, cli->smb2.tcon,
2682 0, /* flags */
2683 unc);
2684 if (tevent_req_nomem(subreq, req)) {
2685 return tevent_req_post(req, ev);
2687 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2688 req);
2689 return req;
2692 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2693 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2694 pass, passlen);
2695 if (tevent_req_nomem(subreq, req)) {
2696 return tevent_req_post(req, ev);
2698 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2699 req);
2700 return req;
2703 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2704 if (tevent_req_nomem(subreq, req)) {
2705 return tevent_req_post(req, ev);
2707 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2709 return req;
2712 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2714 tevent_req_simple_finish_ntstatus(
2715 subreq, smb2cli_tcon_recv(subreq));
2718 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2720 tevent_req_simple_finish_ntstatus(
2721 subreq, cli_tcon_andx_recv(subreq));
2724 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2726 struct tevent_req *req = tevent_req_callback_data(
2727 subreq, struct tevent_req);
2728 struct cli_tree_connect_state *state = tevent_req_data(
2729 req, struct cli_tree_connect_state);
2730 NTSTATUS status;
2731 uint16_t max_xmit = 0;
2732 uint16_t tid = 0;
2734 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2735 if (tevent_req_nterror(req, status)) {
2736 return;
2739 smb1cli_tcon_set_values(state->cli->smb1.tcon,
2740 tid,
2741 0, /* optional_support */
2742 0, /* maximal_access */
2743 0, /* guest_maximal_access */
2744 NULL, /* service */
2745 NULL); /* fs_type */
2747 tevent_req_done(req);
2750 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2752 return tevent_req_simple_recv_ntstatus(req);
2755 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2756 const char *dev, const char *pass, int passlen)
2758 struct tevent_context *ev;
2759 struct tevent_req *req;
2760 NTSTATUS status = NT_STATUS_NO_MEMORY;
2762 if (smbXcli_conn_has_async_calls(cli->conn)) {
2763 return NT_STATUS_INVALID_PARAMETER;
2765 ev = samba_tevent_context_init(talloc_tos());
2766 if (ev == NULL) {
2767 goto fail;
2769 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2770 if (req == NULL) {
2771 goto fail;
2773 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2774 goto fail;
2776 status = cli_tree_connect_recv(req);
2777 fail:
2778 TALLOC_FREE(ev);
2779 return status;
2782 /****************************************************************************
2783 Send a tree disconnect.
2784 ****************************************************************************/
2786 struct cli_tdis_state {
2787 struct cli_state *cli;
2790 static void cli_tdis_done(struct tevent_req *subreq);
2792 static struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2793 struct tevent_context *ev,
2794 struct cli_state *cli)
2796 struct tevent_req *req, *subreq;
2797 struct cli_tdis_state *state;
2799 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2800 if (req == NULL) {
2801 return NULL;
2803 state->cli = cli;
2805 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2806 if (tevent_req_nomem(subreq, req)) {
2807 return tevent_req_post(req, ev);
2809 tevent_req_set_callback(subreq, cli_tdis_done, req);
2810 return req;
2813 static void cli_tdis_done(struct tevent_req *subreq)
2815 struct tevent_req *req = tevent_req_callback_data(
2816 subreq, struct tevent_req);
2817 struct cli_tdis_state *state = tevent_req_data(
2818 req, struct cli_tdis_state);
2819 NTSTATUS status;
2821 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2822 TALLOC_FREE(subreq);
2823 if (!NT_STATUS_IS_OK(status)) {
2824 tevent_req_nterror(req, status);
2825 return;
2827 cli_state_set_tid(state->cli, UINT16_MAX);
2828 tevent_req_done(req);
2831 static NTSTATUS cli_tdis_recv(struct tevent_req *req)
2833 return tevent_req_simple_recv_ntstatus(req);
2836 NTSTATUS cli_tdis(struct cli_state *cli)
2838 struct tevent_context *ev;
2839 struct tevent_req *req;
2840 NTSTATUS status = NT_STATUS_NO_MEMORY;
2842 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2843 return smb2cli_tdis(cli->conn,
2844 cli->timeout,
2845 cli->smb2.session,
2846 cli->smb2.tcon);
2849 if (smbXcli_conn_has_async_calls(cli->conn)) {
2850 return NT_STATUS_INVALID_PARAMETER;
2852 ev = samba_tevent_context_init(talloc_tos());
2853 if (ev == NULL) {
2854 goto fail;
2856 req = cli_tdis_send(ev, ev, cli);
2857 if (req == NULL) {
2858 goto fail;
2860 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2861 goto fail;
2863 status = cli_tdis_recv(req);
2864 fail:
2865 TALLOC_FREE(ev);
2866 return status;
2869 struct cli_connect_sock_state {
2870 const char **called_names;
2871 const char **calling_names;
2872 int *called_types;
2873 int fd;
2874 uint16_t port;
2877 static void cli_connect_sock_done(struct tevent_req *subreq);
2880 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2881 * nonzero address.
2884 static struct tevent_req *cli_connect_sock_send(
2885 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2886 const char *host, int name_type, const struct sockaddr_storage *pss,
2887 const char *myname, uint16_t port)
2889 struct tevent_req *req, *subreq;
2890 struct cli_connect_sock_state *state;
2891 const char *prog;
2892 struct sockaddr_storage *addrs;
2893 unsigned i, num_addrs;
2894 NTSTATUS status;
2896 req = tevent_req_create(mem_ctx, &state,
2897 struct cli_connect_sock_state);
2898 if (req == NULL) {
2899 return NULL;
2902 prog = getenv("LIBSMB_PROG");
2903 if (prog != NULL) {
2904 state->fd = sock_exec(prog);
2905 if (state->fd == -1) {
2906 status = map_nt_error_from_unix(errno);
2907 tevent_req_nterror(req, status);
2908 } else {
2909 state->port = 0;
2910 tevent_req_done(req);
2912 return tevent_req_post(req, ev);
2915 if ((pss == NULL) || is_zero_addr(pss)) {
2918 * Here we cheat. resolve_name_list is not async at all. So
2919 * this call will only be really async if the name lookup has
2920 * been done externally.
2923 status = resolve_name_list(state, host, name_type,
2924 &addrs, &num_addrs);
2925 if (!NT_STATUS_IS_OK(status)) {
2926 tevent_req_nterror(req, status);
2927 return tevent_req_post(req, ev);
2929 } else {
2930 addrs = talloc_array(state, struct sockaddr_storage, 1);
2931 if (tevent_req_nomem(addrs, req)) {
2932 return tevent_req_post(req, ev);
2934 addrs[0] = *pss;
2935 num_addrs = 1;
2938 state->called_names = talloc_array(state, const char *, num_addrs);
2939 if (tevent_req_nomem(state->called_names, req)) {
2940 return tevent_req_post(req, ev);
2942 state->called_types = talloc_array(state, int, num_addrs);
2943 if (tevent_req_nomem(state->called_types, req)) {
2944 return tevent_req_post(req, ev);
2946 state->calling_names = talloc_array(state, const char *, num_addrs);
2947 if (tevent_req_nomem(state->calling_names, req)) {
2948 return tevent_req_post(req, ev);
2950 for (i=0; i<num_addrs; i++) {
2951 state->called_names[i] = host;
2952 state->called_types[i] = name_type;
2953 state->calling_names[i] = myname;
2956 subreq = smbsock_any_connect_send(
2957 state, ev, addrs, state->called_names, state->called_types,
2958 state->calling_names, NULL, num_addrs, port);
2959 if (tevent_req_nomem(subreq, req)) {
2960 return tevent_req_post(req, ev);
2962 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2963 return req;
2966 static void cli_connect_sock_done(struct tevent_req *subreq)
2968 struct tevent_req *req = tevent_req_callback_data(
2969 subreq, struct tevent_req);
2970 struct cli_connect_sock_state *state = tevent_req_data(
2971 req, struct cli_connect_sock_state);
2972 NTSTATUS status;
2974 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2975 &state->port);
2976 TALLOC_FREE(subreq);
2977 if (tevent_req_nterror(req, status)) {
2978 return;
2980 set_socket_options(state->fd, lp_socket_options());
2981 tevent_req_done(req);
2984 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2985 int *pfd, uint16_t *pport)
2987 struct cli_connect_sock_state *state = tevent_req_data(
2988 req, struct cli_connect_sock_state);
2989 NTSTATUS status;
2991 if (tevent_req_is_nterror(req, &status)) {
2992 return status;
2994 *pfd = state->fd;
2995 *pport = state->port;
2996 return NT_STATUS_OK;
2999 struct cli_connect_nb_state {
3000 const char *desthost;
3001 int signing_state;
3002 int flags;
3003 struct cli_state *cli;
3006 static void cli_connect_nb_done(struct tevent_req *subreq);
3008 static struct tevent_req *cli_connect_nb_send(
3009 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3010 const char *host, const struct sockaddr_storage *dest_ss,
3011 uint16_t port, int name_type, const char *myname,
3012 int signing_state, int flags)
3014 struct tevent_req *req, *subreq;
3015 struct cli_connect_nb_state *state;
3016 char *p;
3018 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
3019 if (req == NULL) {
3020 return NULL;
3022 state->desthost = host;
3023 state->signing_state = signing_state;
3024 state->flags = flags;
3026 p = strchr(host, '#');
3027 if (p != NULL) {
3028 name_type = strtol(p+1, NULL, 16);
3029 host = talloc_strndup(state, host, p - host);
3030 if (tevent_req_nomem(host, req)) {
3031 return tevent_req_post(req, ev);
3035 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
3036 myname, port);
3037 if (tevent_req_nomem(subreq, req)) {
3038 return tevent_req_post(req, ev);
3040 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
3041 return req;
3044 static void cli_connect_nb_done(struct tevent_req *subreq)
3046 struct tevent_req *req = tevent_req_callback_data(
3047 subreq, struct tevent_req);
3048 struct cli_connect_nb_state *state = tevent_req_data(
3049 req, struct cli_connect_nb_state);
3050 NTSTATUS status;
3051 int fd = 0;
3052 uint16_t port;
3054 status = cli_connect_sock_recv(subreq, &fd, &port);
3055 TALLOC_FREE(subreq);
3056 if (tevent_req_nterror(req, status)) {
3057 return;
3060 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3061 state->signing_state, state->flags);
3062 if (tevent_req_nomem(state->cli, req)) {
3063 close(fd);
3064 return;
3066 tevent_req_done(req);
3069 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3070 struct cli_state **pcli)
3072 struct cli_connect_nb_state *state = tevent_req_data(
3073 req, struct cli_connect_nb_state);
3074 NTSTATUS status;
3076 if (tevent_req_is_nterror(req, &status)) {
3077 return status;
3079 *pcli = talloc_move(NULL, &state->cli);
3080 return NT_STATUS_OK;
3083 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3084 uint16_t port, int name_type, const char *myname,
3085 int signing_state, int flags, struct cli_state **pcli)
3087 struct tevent_context *ev;
3088 struct tevent_req *req;
3089 NTSTATUS status = NT_STATUS_NO_MEMORY;
3091 ev = samba_tevent_context_init(talloc_tos());
3092 if (ev == NULL) {
3093 goto fail;
3095 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3096 myname, signing_state, flags);
3097 if (req == NULL) {
3098 goto fail;
3100 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3101 goto fail;
3103 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3104 goto fail;
3106 status = cli_connect_nb_recv(req, pcli);
3107 fail:
3108 TALLOC_FREE(ev);
3109 return status;
3112 struct cli_start_connection_state {
3113 struct tevent_context *ev;
3114 struct cli_state *cli;
3117 static void cli_start_connection_connected(struct tevent_req *subreq);
3118 static void cli_start_connection_done(struct tevent_req *subreq);
3121 establishes a connection to after the negprot.
3122 @param output_cli A fully initialised cli structure, non-null only on success
3123 @param dest_host The netbios name of the remote host
3124 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3125 @param port (optional) The destination port (0 for default)
3128 static struct tevent_req *cli_start_connection_send(
3129 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3130 const char *my_name, const char *dest_host,
3131 const struct sockaddr_storage *dest_ss, int port,
3132 int signing_state, int flags)
3134 struct tevent_req *req, *subreq;
3135 struct cli_start_connection_state *state;
3137 req = tevent_req_create(mem_ctx, &state,
3138 struct cli_start_connection_state);
3139 if (req == NULL) {
3140 return NULL;
3142 state->ev = ev;
3144 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3145 0x20, my_name, signing_state, flags);
3146 if (tevent_req_nomem(subreq, req)) {
3147 return tevent_req_post(req, ev);
3149 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3150 return req;
3153 static void cli_start_connection_connected(struct tevent_req *subreq)
3155 struct tevent_req *req = tevent_req_callback_data(
3156 subreq, struct tevent_req);
3157 struct cli_start_connection_state *state = tevent_req_data(
3158 req, struct cli_start_connection_state);
3159 NTSTATUS status;
3161 status = cli_connect_nb_recv(subreq, &state->cli);
3162 TALLOC_FREE(subreq);
3163 if (tevent_req_nterror(req, status)) {
3164 return;
3167 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3168 state->cli->timeout,
3169 lp_client_min_protocol(),
3170 lp_client_max_protocol());
3171 if (tevent_req_nomem(subreq, req)) {
3172 return;
3174 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3177 static void cli_start_connection_done(struct tevent_req *subreq)
3179 struct tevent_req *req = tevent_req_callback_data(
3180 subreq, struct tevent_req);
3181 struct cli_start_connection_state *state = tevent_req_data(
3182 req, struct cli_start_connection_state);
3183 NTSTATUS status;
3185 status = smbXcli_negprot_recv(subreq);
3186 TALLOC_FREE(subreq);
3187 if (tevent_req_nterror(req, status)) {
3188 return;
3191 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
3192 /* Ensure we ask for some initial credits. */
3193 smb2cli_conn_set_max_credits(state->cli->conn,
3194 DEFAULT_SMB2_MAX_CREDITS);
3197 tevent_req_done(req);
3200 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3201 struct cli_state **output_cli)
3203 struct cli_start_connection_state *state = tevent_req_data(
3204 req, struct cli_start_connection_state);
3205 NTSTATUS status;
3207 if (tevent_req_is_nterror(req, &status)) {
3208 return status;
3210 *output_cli = state->cli;
3212 return NT_STATUS_OK;
3215 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3216 const char *my_name,
3217 const char *dest_host,
3218 const struct sockaddr_storage *dest_ss, int port,
3219 int signing_state, int flags)
3221 struct tevent_context *ev;
3222 struct tevent_req *req;
3223 NTSTATUS status = NT_STATUS_NO_MEMORY;
3225 ev = samba_tevent_context_init(talloc_tos());
3226 if (ev == NULL) {
3227 goto fail;
3229 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3230 port, signing_state, flags);
3231 if (req == NULL) {
3232 goto fail;
3234 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3235 goto fail;
3237 status = cli_start_connection_recv(req, output_cli);
3238 fail:
3239 TALLOC_FREE(ev);
3240 return status;
3244 establishes a connection right up to doing tconX, password specified.
3245 @param output_cli A fully initialised cli structure, non-null only on success
3246 @param dest_host The netbios name of the remote host
3247 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3248 @param port (optional) The destination port (0 for default)
3249 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3250 @param service_type The 'type' of serivice.
3251 @param user Username, unix string
3252 @param domain User's domain
3253 @param password User's password, unencrypted unix string.
3256 struct cli_full_connection_state {
3257 struct tevent_context *ev;
3258 const char *service;
3259 const char *service_type;
3260 const char *user;
3261 const char *domain;
3262 const char *password;
3263 int pw_len;
3264 int flags;
3265 struct cli_state *cli;
3268 static int cli_full_connection_state_destructor(
3269 struct cli_full_connection_state *s);
3270 static void cli_full_connection_started(struct tevent_req *subreq);
3271 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3272 static void cli_full_connection_done(struct tevent_req *subreq);
3274 struct tevent_req *cli_full_connection_send(
3275 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3276 const char *my_name, const char *dest_host,
3277 const struct sockaddr_storage *dest_ss, int port,
3278 const char *service, const char *service_type,
3279 const char *user, const char *domain,
3280 const char *password, int flags, int signing_state)
3282 struct tevent_req *req, *subreq;
3283 struct cli_full_connection_state *state;
3285 req = tevent_req_create(mem_ctx, &state,
3286 struct cli_full_connection_state);
3287 if (req == NULL) {
3288 return NULL;
3290 talloc_set_destructor(state, cli_full_connection_state_destructor);
3292 state->ev = ev;
3293 state->service = service;
3294 state->service_type = service_type;
3295 state->user = user;
3296 state->domain = domain;
3297 state->password = password;
3298 state->flags = flags;
3300 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3301 if (state->password == NULL) {
3302 state->password = "";
3305 subreq = cli_start_connection_send(
3306 state, ev, my_name, dest_host, dest_ss, port,
3307 signing_state, flags);
3308 if (tevent_req_nomem(subreq, req)) {
3309 return tevent_req_post(req, ev);
3311 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3312 return req;
3315 static int cli_full_connection_state_destructor(
3316 struct cli_full_connection_state *s)
3318 if (s->cli != NULL) {
3319 cli_shutdown(s->cli);
3320 s->cli = NULL;
3322 return 0;
3325 static void cli_full_connection_started(struct tevent_req *subreq)
3327 struct tevent_req *req = tevent_req_callback_data(
3328 subreq, struct tevent_req);
3329 struct cli_full_connection_state *state = tevent_req_data(
3330 req, struct cli_full_connection_state);
3331 NTSTATUS status;
3333 status = cli_start_connection_recv(subreq, &state->cli);
3334 TALLOC_FREE(subreq);
3335 if (tevent_req_nterror(req, status)) {
3336 return;
3338 subreq = cli_session_setup_send(
3339 state, state->ev, state->cli, state->user,
3340 state->password, state->pw_len, state->password, state->pw_len,
3341 state->domain);
3342 if (tevent_req_nomem(subreq, req)) {
3343 return;
3345 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3348 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3350 struct tevent_req *req = tevent_req_callback_data(
3351 subreq, struct tevent_req);
3352 struct cli_full_connection_state *state = tevent_req_data(
3353 req, struct cli_full_connection_state);
3354 NTSTATUS status;
3356 status = cli_session_setup_recv(subreq);
3357 TALLOC_FREE(subreq);
3359 if (!NT_STATUS_IS_OK(status) &&
3360 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3362 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3364 subreq = cli_session_setup_send(
3365 state, state->ev, state->cli, "", "", 0, "", 0,
3366 state->domain);
3367 if (tevent_req_nomem(subreq, req)) {
3368 return;
3370 tevent_req_set_callback(
3371 subreq, cli_full_connection_sess_set_up, req);
3372 return;
3375 if (tevent_req_nterror(req, status)) {
3376 return;
3379 if (state->service != NULL) {
3380 subreq = cli_tree_connect_send(
3381 state, state->ev, state->cli,
3382 state->service, state->service_type,
3383 state->password, state->pw_len);
3384 if (tevent_req_nomem(subreq, req)) {
3385 return;
3387 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3388 return;
3391 status = cli_init_creds(state->cli, state->user, state->domain,
3392 state->password);
3393 if (tevent_req_nterror(req, status)) {
3394 return;
3396 tevent_req_done(req);
3399 static void cli_full_connection_done(struct tevent_req *subreq)
3401 struct tevent_req *req = tevent_req_callback_data(
3402 subreq, struct tevent_req);
3403 struct cli_full_connection_state *state = tevent_req_data(
3404 req, struct cli_full_connection_state);
3405 NTSTATUS status;
3407 status = cli_tree_connect_recv(subreq);
3408 TALLOC_FREE(subreq);
3409 if (tevent_req_nterror(req, status)) {
3410 return;
3412 status = cli_init_creds(state->cli, state->user, state->domain,
3413 state->password);
3414 if (tevent_req_nterror(req, status)) {
3415 return;
3417 tevent_req_done(req);
3420 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3421 struct cli_state **output_cli)
3423 struct cli_full_connection_state *state = tevent_req_data(
3424 req, struct cli_full_connection_state);
3425 NTSTATUS status;
3427 if (tevent_req_is_nterror(req, &status)) {
3428 return status;
3430 *output_cli = state->cli;
3431 talloc_set_destructor(state, NULL);
3432 return NT_STATUS_OK;
3435 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3436 const char *my_name,
3437 const char *dest_host,
3438 const struct sockaddr_storage *dest_ss, int port,
3439 const char *service, const char *service_type,
3440 const char *user, const char *domain,
3441 const char *password, int flags,
3442 int signing_state)
3444 struct tevent_context *ev;
3445 struct tevent_req *req;
3446 NTSTATUS status = NT_STATUS_NO_MEMORY;
3448 ev = samba_tevent_context_init(talloc_tos());
3449 if (ev == NULL) {
3450 goto fail;
3452 req = cli_full_connection_send(
3453 ev, ev, my_name, dest_host, dest_ss, port, service,
3454 service_type, user, domain, password, flags, signing_state);
3455 if (req == NULL) {
3456 goto fail;
3458 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3459 goto fail;
3461 status = cli_full_connection_recv(req, output_cli);
3462 fail:
3463 TALLOC_FREE(ev);
3464 return status;
3467 /****************************************************************************
3468 Send an old style tcon.
3469 ****************************************************************************/
3470 struct cli_raw_tcon_state {
3471 uint16_t *ret_vwv;
3474 static void cli_raw_tcon_done(struct tevent_req *subreq);
3476 static struct tevent_req *cli_raw_tcon_send(
3477 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3478 const char *service, const char *pass, const char *dev)
3480 struct tevent_req *req, *subreq;
3481 struct cli_raw_tcon_state *state;
3482 uint8_t *bytes;
3484 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3485 if (req == NULL) {
3486 return NULL;
3489 if (!lp_client_plaintext_auth() && (*pass)) {
3490 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3491 " or 'client ntlmv2 auth = yes'\n"));
3492 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3493 return tevent_req_post(req, ev);
3496 bytes = talloc_array(state, uint8_t, 0);
3497 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3498 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3499 service, strlen(service)+1, NULL);
3500 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3501 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3502 pass, strlen(pass)+1, NULL);
3503 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3504 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3505 dev, strlen(dev)+1, NULL);
3507 if (tevent_req_nomem(bytes, req)) {
3508 return tevent_req_post(req, ev);
3511 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3512 talloc_get_size(bytes), bytes);
3513 if (tevent_req_nomem(subreq, req)) {
3514 return tevent_req_post(req, ev);
3516 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3517 return req;
3520 static void cli_raw_tcon_done(struct tevent_req *subreq)
3522 struct tevent_req *req = tevent_req_callback_data(
3523 subreq, struct tevent_req);
3524 struct cli_raw_tcon_state *state = tevent_req_data(
3525 req, struct cli_raw_tcon_state);
3526 NTSTATUS status;
3528 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3529 NULL, NULL);
3530 TALLOC_FREE(subreq);
3531 if (tevent_req_nterror(req, status)) {
3532 return;
3534 tevent_req_done(req);
3537 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3538 uint16 *max_xmit, uint16 *tid)
3540 struct cli_raw_tcon_state *state = tevent_req_data(
3541 req, struct cli_raw_tcon_state);
3542 NTSTATUS status;
3544 if (tevent_req_is_nterror(req, &status)) {
3545 return status;
3547 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3548 *tid = SVAL(state->ret_vwv + 1, 0);
3549 return NT_STATUS_OK;
3552 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3553 const char *service, const char *pass, const char *dev,
3554 uint16 *max_xmit, uint16 *tid)
3556 struct tevent_context *ev;
3557 struct tevent_req *req;
3558 NTSTATUS status = NT_STATUS_NO_MEMORY;
3560 ev = samba_tevent_context_init(talloc_tos());
3561 if (ev == NULL) {
3562 goto fail;
3564 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3565 if (req == NULL) {
3566 goto fail;
3568 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3569 goto fail;
3571 status = cli_raw_tcon_recv(req, max_xmit, tid);
3572 fail:
3573 TALLOC_FREE(ev);
3574 return status;
3577 /* Return a cli_state pointing at the IPC$ share for the given server */
3579 struct cli_state *get_ipc_connect(char *server,
3580 struct sockaddr_storage *server_ss,
3581 const struct user_auth_info *user_info)
3583 struct cli_state *cli;
3584 NTSTATUS nt_status;
3585 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3587 if (user_info->use_kerberos) {
3588 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3591 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3592 user_info->username ? user_info->username : "",
3593 lp_workgroup(),
3594 user_info->password ? user_info->password : "",
3595 flags,
3596 SMB_SIGNING_DEFAULT);
3598 if (NT_STATUS_IS_OK(nt_status)) {
3599 return cli;
3600 } else if (is_ipaddress(server)) {
3601 /* windows 9* needs a correct NMB name for connections */
3602 fstring remote_name;
3604 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3605 cli = get_ipc_connect(remote_name, server_ss, user_info);
3606 if (cli)
3607 return cli;
3610 return NULL;
3614 * Given the IP address of a master browser on the network, return its
3615 * workgroup and connect to it.
3617 * This function is provided to allow additional processing beyond what
3618 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3619 * browsers and obtain each master browsers' list of domains (in case the
3620 * first master browser is recently on the network and has not yet
3621 * synchronized with other master browsers and therefore does not yet have the
3622 * entire network browse list)
3625 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3626 struct sockaddr_storage *mb_ip,
3627 const struct user_auth_info *user_info,
3628 char **pp_workgroup_out)
3630 char addr[INET6_ADDRSTRLEN];
3631 fstring name;
3632 struct cli_state *cli;
3633 struct sockaddr_storage server_ss;
3635 *pp_workgroup_out = NULL;
3637 print_sockaddr(addr, sizeof(addr), mb_ip);
3638 DEBUG(99, ("Looking up name of master browser %s\n",
3639 addr));
3642 * Do a name status query to find out the name of the master browser.
3643 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3644 * master browser will not respond to a wildcard query (or, at least,
3645 * an NT4 server acting as the domain master browser will not).
3647 * We might be able to use ONLY the query on MSBROWSE, but that's not
3648 * yet been tested with all Windows versions, so until it is, leave
3649 * the original wildcard query as the first choice and fall back to
3650 * MSBROWSE if the wildcard query fails.
3652 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3653 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3655 DEBUG(99, ("Could not retrieve name status for %s\n",
3656 addr));
3657 return NULL;
3660 if (!find_master_ip(name, &server_ss)) {
3661 DEBUG(99, ("Could not find master ip for %s\n", name));
3662 return NULL;
3665 *pp_workgroup_out = talloc_strdup(ctx, name);
3667 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3669 print_sockaddr(addr, sizeof(addr), &server_ss);
3670 cli = get_ipc_connect(addr, &server_ss, user_info);
3672 return cli;
3676 * Return the IP address and workgroup of a master browser on the network, and
3677 * connect to it.
3680 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3681 const struct user_auth_info *user_info,
3682 char **pp_workgroup_out)
3684 struct sockaddr_storage *ip_list;
3685 struct cli_state *cli;
3686 int i, count;
3687 NTSTATUS status;
3689 *pp_workgroup_out = NULL;
3691 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3693 /* Go looking for workgroups by broadcasting on the local network */
3695 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3696 &ip_list, &count);
3697 if (!NT_STATUS_IS_OK(status)) {
3698 DEBUG(99, ("No master browsers responded: %s\n",
3699 nt_errstr(status)));
3700 return NULL;
3703 for (i = 0; i < count; i++) {
3704 char addr[INET6_ADDRSTRLEN];
3705 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3706 DEBUG(99, ("Found master browser %s\n", addr));
3708 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3709 user_info, pp_workgroup_out);
3710 if (cli)
3711 return(cli);
3714 return NULL;