librpc: Shorten dcerpc_binding_handle_call a bit
[Samba/gebeck_regimport.git] / source3 / libsmb / cliconnect.c
blob7179c4f209dbc442d9a86f6bb54841e11520e557
1 /*
2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
6 Copyright (C) Volker Lendecke 2011
7 Copyright (C) Jeremy Allison 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "libsmb/libsmb.h"
25 #include "auth_info.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
28 #include "smb_krb5.h"
29 #include "../auth/ntlmssp/ntlmssp.h"
30 #include "libads/kerberos_proto.h"
31 #include "krb5_env.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "async_smb.h"
34 #include "libsmb/nmblib.h"
35 #include "librpc/ndr/libndr.h"
36 #include "../libcli/smb/smbXcli_base.h"
37 #include "smb2cli.h"
39 #define STAR_SMBSERVER "*SMBSERVER"
41 /********************************************************
42 Utility function to ensure we always return at least
43 a valid char * pointer to an empty string for the
44 cli->server_os, cli->server_type and cli->server_domain
45 strings.
46 *******************************************************/
48 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
49 const uint8_t *hdr,
50 char **dest,
51 uint8_t *src,
52 size_t srclen,
53 ssize_t *destlen)
55 *destlen = clistr_pull_talloc(mem_ctx,
56 (const char *)hdr,
57 SVAL(hdr, HDR_FLG2),
58 dest,
59 (char *)src,
60 srclen,
61 STR_TERMINATE);
62 if (*destlen == -1) {
63 return NT_STATUS_NO_MEMORY;
66 if (*dest == NULL) {
67 *dest = talloc_strdup(mem_ctx, "");
68 if (*dest == NULL) {
69 return NT_STATUS_NO_MEMORY;
72 return NT_STATUS_OK;
75 /****************************************************************************
76 Do an old lanman2 style session setup.
77 ****************************************************************************/
79 struct cli_session_setup_lanman2_state {
80 struct cli_state *cli;
81 uint16_t vwv[10];
82 const char *user;
85 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
87 static struct tevent_req *cli_session_setup_lanman2_send(
88 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
89 struct cli_state *cli, const char *user,
90 const char *pass, size_t passlen,
91 const char *workgroup)
93 struct tevent_req *req, *subreq;
94 struct cli_session_setup_lanman2_state *state;
95 DATA_BLOB lm_response = data_blob_null;
96 uint16_t *vwv;
97 uint8_t *bytes;
98 char *tmp;
99 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
101 req = tevent_req_create(mem_ctx, &state,
102 struct cli_session_setup_lanman2_state);
103 if (req == NULL) {
104 return NULL;
106 state->cli = cli;
107 state->user = user;
108 vwv = state->vwv;
111 * if in share level security then don't send a password now
113 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
114 passlen = 0;
117 if (passlen > 0
118 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
119 && passlen != 24) {
121 * Encrypted mode needed, and non encrypted password
122 * supplied.
124 lm_response = data_blob(NULL, 24);
125 if (tevent_req_nomem(lm_response.data, req)) {
126 return tevent_req_post(req, ev);
129 if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
130 (uint8_t *)lm_response.data)) {
131 DEBUG(1, ("Password is > 14 chars in length, and is "
132 "therefore incompatible with Lanman "
133 "authentication\n"));
134 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
135 return tevent_req_post(req, ev);
137 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
138 && passlen == 24) {
140 * Encrypted mode needed, and encrypted password
141 * supplied.
143 lm_response = data_blob(pass, passlen);
144 if (tevent_req_nomem(lm_response.data, req)) {
145 return tevent_req_post(req, ev);
147 } else if (passlen > 0) {
148 uint8_t *buf;
149 size_t converted_size;
151 * Plaintext mode needed, assume plaintext supplied.
153 buf = talloc_array(talloc_tos(), uint8_t, 0);
154 buf = smb_bytes_push_str(buf, smbXcli_conn_use_unicode(cli->conn), pass, passlen+1,
155 &converted_size);
156 if (tevent_req_nomem(buf, req)) {
157 return tevent_req_post(req, ev);
159 lm_response = data_blob(pass, passlen);
160 TALLOC_FREE(buf);
161 if (tevent_req_nomem(lm_response.data, req)) {
162 return tevent_req_post(req, ev);
166 SCVAL(vwv+0, 0, 0xff);
167 SCVAL(vwv+0, 1, 0);
168 SSVAL(vwv+1, 0, 0);
169 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
170 SSVAL(vwv+3, 0, 2);
171 SSVAL(vwv+4, 0, 1);
172 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
173 SSVAL(vwv+7, 0, lm_response.length);
175 bytes = talloc_array(state, uint8_t, lm_response.length);
176 if (tevent_req_nomem(bytes, req)) {
177 return tevent_req_post(req, ev);
179 if (lm_response.length != 0) {
180 memcpy(bytes, lm_response.data, lm_response.length);
182 data_blob_free(&lm_response);
184 tmp = talloc_strdup_upper(talloc_tos(), user);
185 if (tevent_req_nomem(tmp, req)) {
186 return tevent_req_post(req, ev);
188 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
189 NULL);
190 TALLOC_FREE(tmp);
192 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
193 if (tevent_req_nomem(tmp, req)) {
194 return tevent_req_post(req, ev);
196 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
197 NULL);
198 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
199 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
201 if (tevent_req_nomem(bytes, req)) {
202 return tevent_req_post(req, ev);
205 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
206 talloc_get_size(bytes), bytes);
207 if (tevent_req_nomem(subreq, req)) {
208 return tevent_req_post(req, ev);
210 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
211 return req;
214 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
216 struct tevent_req *req = tevent_req_callback_data(
217 subreq, struct tevent_req);
218 struct cli_session_setup_lanman2_state *state = tevent_req_data(
219 req, struct cli_session_setup_lanman2_state);
220 struct cli_state *cli = state->cli;
221 uint32_t num_bytes;
222 uint8_t *in;
223 uint8_t *inhdr;
224 uint8_t *bytes;
225 uint8_t *p;
226 NTSTATUS status;
227 ssize_t ret;
228 uint8_t wct;
229 uint16_t *vwv;
231 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
232 &num_bytes, &bytes);
233 TALLOC_FREE(subreq);
234 if (!NT_STATUS_IS_OK(status)) {
235 tevent_req_nterror(req, status);
236 return;
239 inhdr = in + NBT_HDR_SIZE;
240 p = bytes;
242 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
243 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
245 status = smb_bytes_talloc_string(cli,
246 inhdr,
247 &cli->server_os,
249 bytes+num_bytes-p,
250 &ret);
252 if (!NT_STATUS_IS_OK(status)) {
253 tevent_req_nterror(req, status);
254 return;
256 p += ret;
258 status = smb_bytes_talloc_string(cli,
259 inhdr,
260 &cli->server_type,
262 bytes+num_bytes-p,
263 &ret);
265 if (!NT_STATUS_IS_OK(status)) {
266 tevent_req_nterror(req, status);
267 return;
269 p += ret;
271 status = smb_bytes_talloc_string(cli,
272 inhdr,
273 &cli->server_domain,
275 bytes+num_bytes-p,
276 &ret);
278 if (!NT_STATUS_IS_OK(status)) {
279 tevent_req_nterror(req, status);
280 return;
282 p += ret;
284 status = cli_set_username(cli, state->user);
285 if (tevent_req_nterror(req, status)) {
286 return;
288 tevent_req_done(req);
291 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
293 return tevent_req_simple_recv_ntstatus(req);
296 /****************************************************************************
297 Work out suitable capabilities to offer the server.
298 ****************************************************************************/
300 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
301 uint32_t sesssetup_capabilities)
303 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
306 * We only send capabilities based on the mask for:
307 * - client only flags
308 * - flags used in both directions
310 * We do not echo the server only flags, except some legacy flags.
312 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
313 * CAP_LARGE_WRITEX in order to allow us to do large reads
314 * against old Samba releases (<= 3.6.x).
316 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
319 * Session Setup specific flags CAP_DYNAMIC_REAUTH
320 * and CAP_EXTENDED_SECURITY are passed by the caller.
321 * We need that in order to do guest logins even if
322 * CAP_EXTENDED_SECURITY is negotiated.
324 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
325 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
326 client_capabilities |= sesssetup_capabilities;
328 return client_capabilities;
331 /****************************************************************************
332 Do a NT1 guest session setup.
333 ****************************************************************************/
335 struct cli_session_setup_guest_state {
336 struct cli_state *cli;
337 uint16_t vwv[13];
338 struct iovec bytes;
341 static void cli_session_setup_guest_done(struct tevent_req *subreq);
343 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
344 struct tevent_context *ev,
345 struct cli_state *cli,
346 struct tevent_req **psmbreq)
348 struct tevent_req *req, *subreq;
349 struct cli_session_setup_guest_state *state;
350 uint16_t *vwv;
351 uint8_t *bytes;
353 req = tevent_req_create(mem_ctx, &state,
354 struct cli_session_setup_guest_state);
355 if (req == NULL) {
356 return NULL;
358 state->cli = cli;
359 vwv = state->vwv;
361 SCVAL(vwv+0, 0, 0xFF);
362 SCVAL(vwv+0, 1, 0);
363 SSVAL(vwv+1, 0, 0);
364 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
365 SSVAL(vwv+3, 0, 2);
366 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
367 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
368 SSVAL(vwv+7, 0, 0);
369 SSVAL(vwv+8, 0, 0);
370 SSVAL(vwv+9, 0, 0);
371 SSVAL(vwv+10, 0, 0);
372 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
374 bytes = talloc_array(state, uint8_t, 0);
376 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
377 NULL);
378 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
379 NULL);
380 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
381 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
383 if (bytes == NULL) {
384 TALLOC_FREE(req);
385 return NULL;
388 state->bytes.iov_base = (void *)bytes;
389 state->bytes.iov_len = talloc_get_size(bytes);
391 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
392 1, &state->bytes);
393 if (subreq == NULL) {
394 TALLOC_FREE(req);
395 return NULL;
397 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
398 *psmbreq = subreq;
399 return req;
402 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
403 struct tevent_context *ev,
404 struct cli_state *cli)
406 struct tevent_req *req, *subreq;
407 NTSTATUS status;
409 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
410 if (req == NULL) {
411 return NULL;
414 status = smb1cli_req_chain_submit(&subreq, 1);
415 if (!NT_STATUS_IS_OK(status)) {
416 tevent_req_nterror(req, status);
417 return tevent_req_post(req, ev);
419 return req;
422 static void cli_session_setup_guest_done(struct tevent_req *subreq)
424 struct tevent_req *req = tevent_req_callback_data(
425 subreq, struct tevent_req);
426 struct cli_session_setup_guest_state *state = tevent_req_data(
427 req, struct cli_session_setup_guest_state);
428 struct cli_state *cli = state->cli;
429 uint32_t num_bytes;
430 uint8_t *in;
431 uint8_t *inhdr;
432 uint8_t *bytes;
433 uint8_t *p;
434 NTSTATUS status;
435 ssize_t ret;
436 uint8_t wct;
437 uint16_t *vwv;
439 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
440 &num_bytes, &bytes);
441 TALLOC_FREE(subreq);
442 if (!NT_STATUS_IS_OK(status)) {
443 tevent_req_nterror(req, status);
444 return;
447 inhdr = in + NBT_HDR_SIZE;
448 p = bytes;
450 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
451 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
453 status = smb_bytes_talloc_string(cli,
454 inhdr,
455 &cli->server_os,
457 bytes+num_bytes-p,
458 &ret);
460 if (!NT_STATUS_IS_OK(status)) {
461 tevent_req_nterror(req, status);
462 return;
464 p += ret;
466 status = smb_bytes_talloc_string(cli,
467 inhdr,
468 &cli->server_type,
470 bytes+num_bytes-p,
471 &ret);
473 if (!NT_STATUS_IS_OK(status)) {
474 tevent_req_nterror(req, status);
475 return;
477 p += ret;
479 status = smb_bytes_talloc_string(cli,
480 inhdr,
481 &cli->server_domain,
483 bytes+num_bytes-p,
484 &ret);
486 if (!NT_STATUS_IS_OK(status)) {
487 tevent_req_nterror(req, status);
488 return;
490 p += ret;
492 status = cli_set_username(cli, "");
493 if (!NT_STATUS_IS_OK(status)) {
494 tevent_req_nterror(req, status);
495 return;
497 tevent_req_done(req);
500 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
502 return tevent_req_simple_recv_ntstatus(req);
505 /****************************************************************************
506 Do a NT1 plaintext session setup.
507 ****************************************************************************/
509 struct cli_session_setup_plain_state {
510 struct cli_state *cli;
511 uint16_t vwv[13];
512 const char *user;
515 static void cli_session_setup_plain_done(struct tevent_req *subreq);
517 static struct tevent_req *cli_session_setup_plain_send(
518 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
519 struct cli_state *cli,
520 const char *user, const char *pass, const char *workgroup)
522 struct tevent_req *req, *subreq;
523 struct cli_session_setup_plain_state *state;
524 uint16_t *vwv;
525 uint8_t *bytes;
526 size_t passlen;
527 char *version;
529 req = tevent_req_create(mem_ctx, &state,
530 struct cli_session_setup_plain_state);
531 if (req == NULL) {
532 return NULL;
534 state->cli = cli;
535 state->user = user;
536 vwv = state->vwv;
538 SCVAL(vwv+0, 0, 0xff);
539 SCVAL(vwv+0, 1, 0);
540 SSVAL(vwv+1, 0, 0);
541 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
542 SSVAL(vwv+3, 0, 2);
543 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
544 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
545 SSVAL(vwv+7, 0, 0);
546 SSVAL(vwv+8, 0, 0);
547 SSVAL(vwv+9, 0, 0);
548 SSVAL(vwv+10, 0, 0);
549 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
551 bytes = talloc_array(state, uint8_t, 0);
552 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
553 &passlen);
554 if (tevent_req_nomem(bytes, req)) {
555 return tevent_req_post(req, ev);
557 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
559 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
560 user, strlen(user)+1, NULL);
561 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
562 workgroup, strlen(workgroup)+1, NULL);
563 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
564 "Unix", 5, NULL);
566 version = talloc_asprintf(talloc_tos(), "Samba %s",
567 samba_version_string());
568 if (tevent_req_nomem(version, req)){
569 return tevent_req_post(req, ev);
571 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
572 version, strlen(version)+1, NULL);
573 TALLOC_FREE(version);
575 if (tevent_req_nomem(bytes, req)) {
576 return tevent_req_post(req, ev);
579 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
580 talloc_get_size(bytes), bytes);
581 if (tevent_req_nomem(subreq, req)) {
582 return tevent_req_post(req, ev);
584 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
585 return req;
588 static void cli_session_setup_plain_done(struct tevent_req *subreq)
590 struct tevent_req *req = tevent_req_callback_data(
591 subreq, struct tevent_req);
592 struct cli_session_setup_plain_state *state = tevent_req_data(
593 req, struct cli_session_setup_plain_state);
594 struct cli_state *cli = state->cli;
595 uint32_t num_bytes;
596 uint8_t *in;
597 uint8_t *inhdr;
598 uint8_t *bytes;
599 uint8_t *p;
600 NTSTATUS status;
601 ssize_t ret;
602 uint8_t wct;
603 uint16_t *vwv;
605 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
606 &num_bytes, &bytes);
607 TALLOC_FREE(subreq);
608 if (tevent_req_nterror(req, status)) {
609 return;
612 inhdr = in + NBT_HDR_SIZE;
613 p = bytes;
615 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
616 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
618 status = smb_bytes_talloc_string(cli,
619 inhdr,
620 &cli->server_os,
622 bytes+num_bytes-p,
623 &ret);
625 if (!NT_STATUS_IS_OK(status)) {
626 tevent_req_nterror(req, status);
627 return;
629 p += ret;
631 status = smb_bytes_talloc_string(cli,
632 inhdr,
633 &cli->server_type,
635 bytes+num_bytes-p,
636 &ret);
638 if (!NT_STATUS_IS_OK(status)) {
639 tevent_req_nterror(req, status);
640 return;
642 p += ret;
644 status = smb_bytes_talloc_string(cli,
645 inhdr,
646 &cli->server_domain,
648 bytes+num_bytes-p,
649 &ret);
651 if (!NT_STATUS_IS_OK(status)) {
652 tevent_req_nterror(req, status);
653 return;
655 p += ret;
657 status = cli_set_username(cli, state->user);
658 if (tevent_req_nterror(req, status)) {
659 return;
662 tevent_req_done(req);
665 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
667 return tevent_req_simple_recv_ntstatus(req);
670 /****************************************************************************
671 do a NT1 NTLM/LM encrypted session setup - for when extended security
672 is not negotiated.
673 @param cli client state to create do session setup on
674 @param user username
675 @param pass *either* cleartext password (passlen !=24) or LM response.
676 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
677 @param workgroup The user's domain.
678 ****************************************************************************/
680 struct cli_session_setup_nt1_state {
681 struct cli_state *cli;
682 uint16_t vwv[13];
683 DATA_BLOB response;
684 DATA_BLOB session_key;
685 const char *user;
688 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
690 static struct tevent_req *cli_session_setup_nt1_send(
691 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
692 struct cli_state *cli, const char *user,
693 const char *pass, size_t passlen,
694 const char *ntpass, size_t ntpasslen,
695 const char *workgroup)
697 struct tevent_req *req, *subreq;
698 struct cli_session_setup_nt1_state *state;
699 DATA_BLOB lm_response = data_blob_null;
700 DATA_BLOB nt_response = data_blob_null;
701 DATA_BLOB session_key = data_blob_null;
702 uint16_t *vwv;
703 uint8_t *bytes;
704 char *workgroup_upper;
706 req = tevent_req_create(mem_ctx, &state,
707 struct cli_session_setup_nt1_state);
708 if (req == NULL) {
709 return NULL;
711 state->cli = cli;
712 state->user = user;
713 vwv = state->vwv;
715 if (passlen == 0) {
716 /* do nothing - guest login */
717 } else if (passlen != 24) {
718 if (lp_client_ntlmv2_auth()) {
719 DATA_BLOB server_chal;
720 DATA_BLOB names_blob;
722 server_chal =
723 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
727 * note that the 'workgroup' here is a best
728 * guess - we don't know the server's domain
729 * at this point. Windows clients also don't
730 * use hostname...
732 names_blob = NTLMv2_generate_names_blob(
733 NULL, NULL, workgroup);
735 if (tevent_req_nomem(names_blob.data, req)) {
736 return tevent_req_post(req, ev);
739 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
740 &server_chal, &names_blob,
741 &lm_response, &nt_response,
742 NULL, &session_key)) {
743 data_blob_free(&names_blob);
744 tevent_req_nterror(
745 req, NT_STATUS_ACCESS_DENIED);
746 return tevent_req_post(req, ev);
748 data_blob_free(&names_blob);
750 } else {
751 uchar nt_hash[16];
752 E_md4hash(pass, nt_hash);
754 #ifdef LANMAN_ONLY
755 nt_response = data_blob_null;
756 #else
757 nt_response = data_blob(NULL, 24);
758 if (tevent_req_nomem(nt_response.data, req)) {
759 return tevent_req_post(req, ev);
762 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
763 nt_response.data);
764 #endif
765 /* non encrypted password supplied. Ignore ntpass. */
766 if (lp_client_lanman_auth()) {
768 lm_response = data_blob(NULL, 24);
769 if (tevent_req_nomem(lm_response.data, req)) {
770 return tevent_req_post(req, ev);
773 if (!SMBencrypt(pass,
774 smb1cli_conn_server_challenge(cli->conn),
775 lm_response.data)) {
777 * Oops, the LM response is
778 * invalid, just put the NT
779 * response there instead
781 data_blob_free(&lm_response);
782 lm_response = data_blob(
783 nt_response.data,
784 nt_response.length);
786 } else {
788 * LM disabled, place NT# in LM field
789 * instead
791 lm_response = data_blob(
792 nt_response.data, nt_response.length);
795 if (tevent_req_nomem(lm_response.data, req)) {
796 return tevent_req_post(req, ev);
799 session_key = data_blob(NULL, 16);
800 if (tevent_req_nomem(session_key.data, req)) {
801 return tevent_req_post(req, ev);
803 #ifdef LANMAN_ONLY
804 E_deshash(pass, session_key.data);
805 memset(&session_key.data[8], '\0', 8);
806 #else
807 SMBsesskeygen_ntv1(nt_hash, session_key.data);
808 #endif
810 } else {
811 /* pre-encrypted password supplied. Only used for
812 security=server, can't do
813 signing because we don't have original key */
815 lm_response = data_blob(pass, passlen);
816 if (tevent_req_nomem(lm_response.data, req)) {
817 return tevent_req_post(req, ev);
820 nt_response = data_blob(ntpass, ntpasslen);
821 if (tevent_req_nomem(nt_response.data, req)) {
822 return tevent_req_post(req, ev);
826 #ifdef LANMAN_ONLY
827 state->response = data_blob_talloc(
828 state, lm_response.data, lm_response.length);
829 #else
830 state->response = data_blob_talloc(
831 state, nt_response.data, nt_response.length);
832 #endif
833 if (tevent_req_nomem(state->response.data, req)) {
834 return tevent_req_post(req, ev);
837 if (session_key.data) {
838 state->session_key = data_blob_talloc(
839 state, session_key.data, session_key.length);
840 if (tevent_req_nomem(state->session_key.data, req)) {
841 return tevent_req_post(req, ev);
844 data_blob_free(&session_key);
846 SCVAL(vwv+0, 0, 0xff);
847 SCVAL(vwv+0, 1, 0);
848 SSVAL(vwv+1, 0, 0);
849 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
850 SSVAL(vwv+3, 0, 2);
851 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
852 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
853 SSVAL(vwv+7, 0, lm_response.length);
854 SSVAL(vwv+8, 0, nt_response.length);
855 SSVAL(vwv+9, 0, 0);
856 SSVAL(vwv+10, 0, 0);
857 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
859 bytes = talloc_array(state, uint8_t,
860 lm_response.length + nt_response.length);
861 if (tevent_req_nomem(bytes, req)) {
862 return tevent_req_post(req, ev);
864 if (lm_response.length != 0) {
865 memcpy(bytes, lm_response.data, lm_response.length);
867 if (nt_response.length != 0) {
868 memcpy(bytes + lm_response.length,
869 nt_response.data, nt_response.length);
871 data_blob_free(&lm_response);
872 data_blob_free(&nt_response);
874 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
875 user, strlen(user)+1, NULL);
878 * Upper case here might help some NTLMv2 implementations
880 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
881 if (tevent_req_nomem(workgroup_upper, req)) {
882 return tevent_req_post(req, ev);
884 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
885 workgroup_upper, strlen(workgroup_upper)+1,
886 NULL);
887 TALLOC_FREE(workgroup_upper);
889 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
890 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
891 if (tevent_req_nomem(bytes, req)) {
892 return tevent_req_post(req, ev);
895 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
896 talloc_get_size(bytes), bytes);
897 if (tevent_req_nomem(subreq, req)) {
898 return tevent_req_post(req, ev);
900 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
901 return req;
904 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
906 struct tevent_req *req = tevent_req_callback_data(
907 subreq, struct tevent_req);
908 struct cli_session_setup_nt1_state *state = tevent_req_data(
909 req, struct cli_session_setup_nt1_state);
910 struct cli_state *cli = state->cli;
911 uint32_t num_bytes;
912 uint8_t *in;
913 uint8_t *inhdr;
914 uint8_t *bytes;
915 uint8_t *p;
916 NTSTATUS status;
917 ssize_t ret;
918 uint8_t wct;
919 uint16_t *vwv;
921 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
922 &num_bytes, &bytes);
923 TALLOC_FREE(subreq);
924 if (!NT_STATUS_IS_OK(status)) {
925 tevent_req_nterror(req, status);
926 return;
929 inhdr = in + NBT_HDR_SIZE;
930 p = bytes;
932 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
933 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
935 status = smb_bytes_talloc_string(cli,
936 inhdr,
937 &cli->server_os,
939 bytes+num_bytes-p,
940 &ret);
941 if (!NT_STATUS_IS_OK(status)) {
942 tevent_req_nterror(req, status);
943 return;
945 p += ret;
947 status = smb_bytes_talloc_string(cli,
948 inhdr,
949 &cli->server_type,
951 bytes+num_bytes-p,
952 &ret);
953 if (!NT_STATUS_IS_OK(status)) {
954 tevent_req_nterror(req, status);
955 return;
957 p += ret;
959 status = smb_bytes_talloc_string(cli,
960 inhdr,
961 &cli->server_domain,
963 bytes+num_bytes-p,
964 &ret);
965 if (!NT_STATUS_IS_OK(status)) {
966 tevent_req_nterror(req, status);
967 return;
969 p += ret;
971 status = cli_set_username(cli, state->user);
972 if (tevent_req_nterror(req, status)) {
973 return;
975 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
976 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
977 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
978 return;
980 if (state->session_key.data) {
981 struct smbXcli_session *session = state->cli->smb1.session;
983 status = smb1cli_session_set_session_key(session,
984 state->session_key);
985 if (tevent_req_nterror(req, status)) {
986 return;
989 tevent_req_done(req);
992 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
994 return tevent_req_simple_recv_ntstatus(req);
997 /* The following is calculated from :
998 * (smb_size-4) = 35
999 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1000 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1001 * end of packet.
1004 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1006 struct cli_sesssetup_blob_state {
1007 struct tevent_context *ev;
1008 struct cli_state *cli;
1009 DATA_BLOB blob;
1010 uint16_t max_blob_size;
1011 uint16_t vwv[12];
1012 uint8_t *buf;
1014 DATA_BLOB smb2_blob;
1015 struct iovec *recv_iov;
1017 NTSTATUS status;
1018 uint8_t *inbuf;
1019 DATA_BLOB ret_blob;
1022 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1023 struct tevent_req **psubreq);
1024 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1026 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1027 struct tevent_context *ev,
1028 struct cli_state *cli,
1029 DATA_BLOB blob)
1031 struct tevent_req *req, *subreq;
1032 struct cli_sesssetup_blob_state *state;
1033 uint32_t usable_space;
1035 req = tevent_req_create(mem_ctx, &state,
1036 struct cli_sesssetup_blob_state);
1037 if (req == NULL) {
1038 return NULL;
1040 state->ev = ev;
1041 state->blob = blob;
1042 state->cli = cli;
1044 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1045 usable_space = UINT16_MAX;
1046 } else {
1047 usable_space = cli_state_available_size(cli,
1048 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1051 if (usable_space == 0) {
1052 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1053 "(not possible to send %u bytes)\n",
1054 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1055 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1056 return tevent_req_post(req, ev);
1058 state->max_blob_size = MIN(usable_space, 0xFFFF);
1060 if (!cli_sesssetup_blob_next(state, &subreq)) {
1061 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1062 return tevent_req_post(req, ev);
1064 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1065 return req;
1068 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1069 struct tevent_req **psubreq)
1071 struct tevent_req *subreq;
1072 uint16_t thistime;
1074 thistime = MIN(state->blob.length, state->max_blob_size);
1076 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1078 state->smb2_blob.data = state->blob.data;
1079 state->smb2_blob.length = thistime;
1081 state->blob.data += thistime;
1082 state->blob.length -= thistime;
1084 subreq = smb2cli_session_setup_send(state, state->ev,
1085 state->cli->conn,
1086 state->cli->timeout,
1087 state->cli->smb2.session,
1088 0, /* in_flags */
1089 SMB2_CAP_DFS, /* in_capabilities */
1090 0, /* in_channel */
1091 0, /* in_previous_session_id */
1092 &state->smb2_blob);
1093 if (subreq == NULL) {
1094 return false;
1096 *psubreq = subreq;
1097 return true;
1100 SCVAL(state->vwv+0, 0, 0xFF);
1101 SCVAL(state->vwv+0, 1, 0);
1102 SSVAL(state->vwv+1, 0, 0);
1103 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1104 SSVAL(state->vwv+3, 0, 2);
1105 SSVAL(state->vwv+4, 0, 1);
1106 SIVAL(state->vwv+5, 0, 0);
1108 SSVAL(state->vwv+7, 0, thistime);
1110 SSVAL(state->vwv+8, 0, 0);
1111 SSVAL(state->vwv+9, 0, 0);
1112 SIVAL(state->vwv+10, 0,
1113 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1115 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1116 thistime);
1117 if (state->buf == NULL) {
1118 return false;
1120 state->blob.data += thistime;
1121 state->blob.length -= thistime;
1123 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1124 "Unix", 5, NULL);
1125 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1126 "Samba", 6, NULL);
1127 if (state->buf == NULL) {
1128 return false;
1130 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1131 12, state->vwv,
1132 talloc_get_size(state->buf), state->buf);
1133 if (subreq == NULL) {
1134 return false;
1136 *psubreq = subreq;
1137 return true;
1140 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1142 struct tevent_req *req = tevent_req_callback_data(
1143 subreq, struct tevent_req);
1144 struct cli_sesssetup_blob_state *state = tevent_req_data(
1145 req, struct cli_sesssetup_blob_state);
1146 struct cli_state *cli = state->cli;
1147 uint8_t wct;
1148 uint16_t *vwv;
1149 uint32_t num_bytes;
1150 uint8_t *bytes;
1151 NTSTATUS status;
1152 uint8_t *p;
1153 uint16_t blob_length;
1154 uint8_t *in;
1155 uint8_t *inhdr;
1156 ssize_t ret;
1158 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1159 status = smb2cli_session_setup_recv(subreq, state,
1160 &state->recv_iov,
1161 &state->ret_blob);
1162 } else {
1163 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1164 &num_bytes, &bytes);
1165 TALLOC_FREE(state->buf);
1167 TALLOC_FREE(subreq);
1168 if (!NT_STATUS_IS_OK(status)
1169 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1170 tevent_req_nterror(req, status);
1171 return;
1174 state->status = status;
1176 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1177 goto next;
1180 state->inbuf = in;
1181 inhdr = in + NBT_HDR_SIZE;
1182 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1183 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1185 blob_length = SVAL(vwv+3, 0);
1186 if (blob_length > num_bytes) {
1187 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1188 return;
1190 state->ret_blob = data_blob_const(bytes, blob_length);
1192 p = bytes + blob_length;
1194 status = smb_bytes_talloc_string(cli,
1195 inhdr,
1196 &cli->server_os,
1198 bytes+num_bytes-p,
1199 &ret);
1201 if (!NT_STATUS_IS_OK(status)) {
1202 tevent_req_nterror(req, status);
1203 return;
1205 p += ret;
1207 status = smb_bytes_talloc_string(cli,
1208 inhdr,
1209 &cli->server_type,
1211 bytes+num_bytes-p,
1212 &ret);
1214 if (!NT_STATUS_IS_OK(status)) {
1215 tevent_req_nterror(req, status);
1216 return;
1218 p += ret;
1220 status = smb_bytes_talloc_string(cli,
1221 inhdr,
1222 &cli->server_domain,
1224 bytes+num_bytes-p,
1225 &ret);
1227 if (!NT_STATUS_IS_OK(status)) {
1228 tevent_req_nterror(req, status);
1229 return;
1231 p += ret;
1233 next:
1234 if (state->blob.length != 0) {
1236 * More to send
1238 if (!cli_sesssetup_blob_next(state, &subreq)) {
1239 tevent_req_oom(req);
1240 return;
1242 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1243 return;
1245 tevent_req_done(req);
1248 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1249 TALLOC_CTX *mem_ctx,
1250 DATA_BLOB *pblob,
1251 uint8_t **pinbuf,
1252 struct iovec **precv_iov)
1254 struct cli_sesssetup_blob_state *state = tevent_req_data(
1255 req, struct cli_sesssetup_blob_state);
1256 NTSTATUS status;
1257 uint8_t *inbuf;
1258 struct iovec *recv_iov;
1260 if (tevent_req_is_nterror(req, &status)) {
1261 TALLOC_FREE(state->cli->smb2.session);
1262 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1263 return status;
1266 inbuf = talloc_move(mem_ctx, &state->inbuf);
1267 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1268 if (pblob != NULL) {
1269 *pblob = state->ret_blob;
1271 if (pinbuf != NULL) {
1272 *pinbuf = inbuf;
1274 if (precv_iov != NULL) {
1275 *precv_iov = recv_iov;
1277 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1278 return state->status;
1281 #ifdef HAVE_KRB5
1283 /****************************************************************************
1284 Use in-memory credentials cache
1285 ****************************************************************************/
1287 static void use_in_memory_ccache(void) {
1288 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1291 /****************************************************************************
1292 Do a spnego/kerberos encrypted session setup.
1293 ****************************************************************************/
1295 struct cli_session_setup_kerberos_state {
1296 struct cli_state *cli;
1297 DATA_BLOB negTokenTarg;
1298 DATA_BLOB session_key_krb5;
1299 ADS_STATUS ads_status;
1302 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1304 static struct tevent_req *cli_session_setup_kerberos_send(
1305 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1306 const char *principal)
1308 struct tevent_req *req, *subreq;
1309 struct cli_session_setup_kerberos_state *state;
1310 int rc;
1312 DEBUG(2,("Doing kerberos session setup\n"));
1314 req = tevent_req_create(mem_ctx, &state,
1315 struct cli_session_setup_kerberos_state);
1316 if (req == NULL) {
1317 return NULL;
1319 state->cli = cli;
1320 state->ads_status = ADS_SUCCESS;
1323 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1324 * we have to acquire a ticket. To be fixed later :-)
1326 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1327 &state->session_key_krb5, 0, NULL, NULL);
1328 if (rc) {
1329 DEBUG(1, ("cli_session_setup_kerberos: "
1330 "spnego_gen_krb5_negTokenInit failed: %s\n",
1331 error_message(rc)));
1332 state->ads_status = ADS_ERROR_KRB5(rc);
1333 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1334 return tevent_req_post(req, ev);
1337 #if 0
1338 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1339 state->negTokenTarg.length);
1340 #endif
1342 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1343 state->cli->smb2.session = smbXcli_session_create(cli,
1344 cli->conn);
1345 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1346 return tevent_req_post(req, ev);
1350 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1351 if (tevent_req_nomem(subreq, req)) {
1352 return tevent_req_post(req, ev);
1354 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1355 return req;
1358 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1360 struct tevent_req *req = tevent_req_callback_data(
1361 subreq, struct tevent_req);
1362 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1363 req, struct cli_session_setup_kerberos_state);
1364 uint8_t *inbuf = NULL;
1365 struct iovec *recv_iov = NULL;
1366 NTSTATUS status;
1368 status = cli_sesssetup_blob_recv(subreq, state,
1369 NULL, &inbuf, &recv_iov);
1370 TALLOC_FREE(subreq);
1371 if (!NT_STATUS_IS_OK(status)) {
1372 tevent_req_nterror(req, status);
1373 return;
1376 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1377 struct smbXcli_session *session = state->cli->smb2.session;
1378 status = smb2cli_session_set_session_key(session,
1379 state->session_key_krb5,
1380 recv_iov);
1381 if (tevent_req_nterror(req, status)) {
1382 return;
1384 } else {
1385 struct smbXcli_session *session = state->cli->smb1.session;
1387 status = smb1cli_session_set_session_key(session,
1388 state->session_key_krb5);
1389 if (tevent_req_nterror(req, status)) {
1390 return;
1393 if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5,
1394 data_blob_null)
1395 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1396 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1397 return;
1401 tevent_req_done(req);
1404 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1406 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1407 req, struct cli_session_setup_kerberos_state);
1408 NTSTATUS status;
1410 if (tevent_req_is_nterror(req, &status)) {
1411 return ADS_ERROR_NT(status);
1413 return state->ads_status;
1416 #endif /* HAVE_KRB5 */
1418 /****************************************************************************
1419 Do a spnego/NTLMSSP encrypted session setup.
1420 ****************************************************************************/
1422 struct cli_session_setup_ntlmssp_state {
1423 struct tevent_context *ev;
1424 struct cli_state *cli;
1425 struct ntlmssp_state *ntlmssp_state;
1426 int turn;
1427 DATA_BLOB blob_out;
1430 static int cli_session_setup_ntlmssp_state_destructor(
1431 struct cli_session_setup_ntlmssp_state *state)
1433 if (state->ntlmssp_state != NULL) {
1434 TALLOC_FREE(state->ntlmssp_state);
1436 return 0;
1439 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1441 static struct tevent_req *cli_session_setup_ntlmssp_send(
1442 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1443 const char *user, const char *pass, const char *domain)
1445 struct tevent_req *req, *subreq;
1446 struct cli_session_setup_ntlmssp_state *state;
1447 NTSTATUS status;
1448 DATA_BLOB blob_out;
1449 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1451 req = tevent_req_create(mem_ctx, &state,
1452 struct cli_session_setup_ntlmssp_state);
1453 if (req == NULL) {
1454 return NULL;
1456 state->ev = ev;
1457 state->cli = cli;
1458 state->turn = 1;
1460 state->ntlmssp_state = NULL;
1461 talloc_set_destructor(
1462 state, cli_session_setup_ntlmssp_state_destructor);
1464 status = ntlmssp_client_start(state,
1465 lp_netbios_name(),
1466 lp_workgroup(),
1467 lp_client_ntlmv2_auth(),
1468 &state->ntlmssp_state);
1469 if (!NT_STATUS_IS_OK(status)) {
1470 goto fail;
1472 ntlmssp_want_feature(state->ntlmssp_state,
1473 NTLMSSP_FEATURE_SESSION_KEY);
1474 if (cli->use_ccache) {
1475 ntlmssp_want_feature(state->ntlmssp_state,
1476 NTLMSSP_FEATURE_CCACHE);
1478 status = ntlmssp_set_username(state->ntlmssp_state, user);
1479 if (!NT_STATUS_IS_OK(status)) {
1480 goto fail;
1482 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1483 if (!NT_STATUS_IS_OK(status)) {
1484 goto fail;
1486 if (cli->pw_nt_hash) {
1487 status = ntlmssp_set_password_hash(state->ntlmssp_state, pass);
1488 } else {
1489 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1491 if (!NT_STATUS_IS_OK(status)) {
1492 goto fail;
1494 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1495 &blob_out);
1496 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1497 goto fail;
1500 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1501 data_blob_free(&blob_out);
1503 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1504 state->cli->smb2.session = smbXcli_session_create(cli,
1505 cli->conn);
1506 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1507 return tevent_req_post(req, ev);
1511 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1512 if (tevent_req_nomem(subreq, req)) {
1513 return tevent_req_post(req, ev);
1515 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1516 return req;
1517 fail:
1518 tevent_req_nterror(req, status);
1519 return tevent_req_post(req, ev);
1522 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1524 struct tevent_req *req = tevent_req_callback_data(
1525 subreq, struct tevent_req);
1526 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1527 req, struct cli_session_setup_ntlmssp_state);
1528 DATA_BLOB blob_in, msg_in, blob_out;
1529 uint8_t *inbuf = NULL;
1530 struct iovec *recv_iov = NULL;
1531 bool parse_ret;
1532 NTSTATUS status;
1534 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1535 &inbuf, &recv_iov);
1536 TALLOC_FREE(subreq);
1537 data_blob_free(&state->blob_out);
1539 if (NT_STATUS_IS_OK(status)) {
1540 if (state->cli->server_domain[0] == '\0') {
1541 TALLOC_FREE(state->cli->server_domain);
1542 state->cli->server_domain = talloc_strdup(state->cli,
1543 state->ntlmssp_state->server.netbios_domain);
1544 if (state->cli->server_domain == NULL) {
1545 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1546 return;
1550 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1551 struct smbXcli_session *session = state->cli->smb2.session;
1553 if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
1555 * Windows server does not set the
1556 * SMB2_SESSION_FLAG_IS_GUEST nor
1557 * SMB2_SESSION_FLAG_IS_NULL flag.
1559 * This fix makes sure we do not try
1560 * to verify a signature on the final
1561 * session setup response.
1563 TALLOC_FREE(state->ntlmssp_state);
1564 tevent_req_done(req);
1565 return;
1568 status = smb2cli_session_set_session_key(session,
1569 state->ntlmssp_state->session_key,
1570 recv_iov);
1571 if (tevent_req_nterror(req, status)) {
1572 return;
1574 } else {
1575 struct smbXcli_session *session = state->cli->smb1.session;
1577 status = smb1cli_session_set_session_key(session,
1578 state->ntlmssp_state->session_key);
1579 if (tevent_req_nterror(req, status)) {
1580 return;
1583 if (smb1cli_conn_activate_signing(
1584 state->cli->conn, state->ntlmssp_state->session_key,
1585 data_blob_null)
1586 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1587 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1588 return;
1591 TALLOC_FREE(state->ntlmssp_state);
1592 tevent_req_done(req);
1593 return;
1595 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1596 tevent_req_nterror(req, status);
1597 return;
1600 if (blob_in.length == 0) {
1601 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1602 return;
1605 if ((state->turn == 1)
1606 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1607 DATA_BLOB tmp_blob = data_blob_null;
1608 /* the server might give us back two challenges */
1609 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1610 &tmp_blob);
1611 data_blob_free(&tmp_blob);
1612 } else {
1613 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1614 OID_NTLMSSP, &msg_in);
1616 state->turn += 1;
1618 if (!parse_ret) {
1619 DEBUG(3,("Failed to parse auth response\n"));
1620 if (NT_STATUS_IS_OK(status)
1621 || NT_STATUS_EQUAL(status,
1622 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1623 tevent_req_nterror(
1624 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1625 return;
1629 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1631 if (!NT_STATUS_IS_OK(status)
1632 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1633 TALLOC_FREE(state->ntlmssp_state);
1634 tevent_req_nterror(req, status);
1635 return;
1638 state->blob_out = spnego_gen_auth(state, blob_out);
1639 if (tevent_req_nomem(state->blob_out.data, req)) {
1640 return;
1643 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1644 state->blob_out);
1645 if (tevent_req_nomem(subreq, req)) {
1646 return;
1648 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1651 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1653 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1654 req, struct cli_session_setup_ntlmssp_state);
1655 NTSTATUS status;
1657 if (tevent_req_is_nterror(req, &status)) {
1658 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1659 return status;
1661 return NT_STATUS_OK;
1664 #ifdef HAVE_KRB5
1666 static char *cli_session_setup_get_principal(
1667 TALLOC_CTX *mem_ctx, const char *spnego_principal,
1668 const char *remote_name, const char *dest_realm)
1670 char *principal = NULL;
1672 if (!lp_client_use_spnego_principal() ||
1673 strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1674 spnego_principal = NULL;
1676 if (spnego_principal != NULL) {
1677 DEBUG(3, ("cli_session_setup_spnego: using spnego provided "
1678 "principal %s\n", spnego_principal));
1679 return talloc_strdup(mem_ctx, spnego_principal);
1681 if (is_ipaddress(remote_name) ||
1682 strequal(remote_name, STAR_SMBSERVER)) {
1683 return NULL;
1686 DEBUG(3, ("cli_session_setup_spnego: using target "
1687 "hostname not SPNEGO principal\n"));
1689 if (dest_realm) {
1690 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1691 if (realm == NULL) {
1692 return NULL;
1694 principal = talloc_asprintf(talloc_tos(), "cifs/%s@%s",
1695 remote_name, realm);
1696 TALLOC_FREE(realm);
1697 } else {
1698 principal = kerberos_get_principal_from_service_hostname(
1699 talloc_tos(), "cifs", remote_name, lp_realm());
1701 DEBUG(3, ("cli_session_setup_spnego: guessed server principal=%s\n",
1702 principal ? principal : "<null>"));
1704 return principal;
1706 #endif
1708 static char *cli_session_setup_get_account(TALLOC_CTX *mem_ctx,
1709 const char *principal)
1711 char *account, *p;
1713 account = talloc_strdup(mem_ctx, principal);
1714 if (account == NULL) {
1715 return NULL;
1717 p = strchr_m(account, '@');
1718 if (p != NULL) {
1719 *p = '\0';
1721 return account;
1724 /****************************************************************************
1725 Do a spnego encrypted session setup.
1727 user_domain: The shortname of the domain the user/machine is a member of.
1728 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1729 ****************************************************************************/
1731 struct cli_session_setup_spnego_state {
1732 struct tevent_context *ev;
1733 struct cli_state *cli;
1734 const char *user;
1735 const char *account;
1736 const char *pass;
1737 const char *user_domain;
1738 const char *dest_realm;
1739 ADS_STATUS result;
1742 #ifdef HAVE_KRB5
1743 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq);
1744 #endif
1746 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq);
1748 static struct tevent_req *cli_session_setup_spnego_send(
1749 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1750 const char *user, const char *pass, const char *user_domain,
1751 const char *dest_realm)
1753 struct tevent_req *req, *subreq;
1754 struct cli_session_setup_spnego_state *state;
1755 char *principal = NULL;
1756 char *OIDs[ASN1_MAX_OIDS];
1757 int i;
1758 const DATA_BLOB *server_blob;
1759 NTSTATUS status;
1761 req = tevent_req_create(mem_ctx, &state,
1762 struct cli_session_setup_spnego_state);
1763 if (req == NULL) {
1764 return NULL;
1766 state->ev = ev;
1767 state->cli = cli;
1768 state->user = user;
1769 state->pass = pass;
1770 state->user_domain = user_domain;
1771 state->dest_realm = dest_realm;
1773 state->account = cli_session_setup_get_account(state, user);
1774 if (tevent_req_nomem(state->account, req)) {
1775 return tevent_req_post(req, ev);
1778 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1780 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n",
1781 (unsigned long)server_blob->length));
1783 /* the server might not even do spnego */
1784 if (server_blob->length == 0) {
1785 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1786 goto ntlmssp;
1789 #if 0
1790 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1791 #endif
1793 /* The server sent us the first part of the SPNEGO exchange in the
1794 * negprot reply. It is WRONG to depend on the principal sent in the
1795 * negprot reply, but right now we do it. If we don't receive one,
1796 * we try to best guess, then fall back to NTLM. */
1797 if (!spnego_parse_negTokenInit(state, *server_blob, OIDs,
1798 &principal, NULL) ||
1799 OIDs[0] == NULL) {
1800 state->result = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1801 tevent_req_done(req);
1802 return tevent_req_post(req, ev);
1805 /* make sure the server understands kerberos */
1806 for (i=0;OIDs[i];i++) {
1807 if (i == 0)
1808 DEBUG(3,("got OID=%s\n", OIDs[i]));
1809 else
1810 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1811 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1812 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1813 cli->got_kerberos_mechanism = True;
1815 talloc_free(OIDs[i]);
1818 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1820 status = cli_set_username(cli, user);
1821 if (!NT_STATUS_IS_OK(status)) {
1822 state->result = ADS_ERROR_NT(status);
1823 tevent_req_done(req);
1824 return tevent_req_post(req, ev);
1827 #ifdef HAVE_KRB5
1828 /* If password is set we reauthenticate to kerberos server
1829 * and do not store results */
1831 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1832 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
1833 char *tmp;
1835 if (pass && *pass) {
1836 int ret;
1838 use_in_memory_ccache();
1839 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1841 if (ret){
1842 TALLOC_FREE(principal);
1843 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1844 if (cli->fallback_after_kerberos)
1845 goto ntlmssp;
1846 state->result = ADS_ERROR_KRB5(ret);
1847 tevent_req_done(req);
1848 return tevent_req_post(req, ev);
1852 tmp = cli_session_setup_get_principal(
1853 talloc_tos(), principal, remote_name, dest_realm);
1854 TALLOC_FREE(principal);
1855 principal = tmp;
1857 if (principal) {
1858 subreq = cli_session_setup_kerberos_send(
1859 state, ev, cli, principal);
1860 if (tevent_req_nomem(subreq, req)) {
1861 return tevent_req_post(req, ev);
1863 tevent_req_set_callback(
1864 subreq, cli_session_setup_spnego_done_krb,
1865 req);
1866 return req;
1869 #endif
1871 ntlmssp:
1872 subreq = cli_session_setup_ntlmssp_send(
1873 state, ev, cli, state->account, pass, user_domain);
1874 if (tevent_req_nomem(subreq, req)) {
1875 return tevent_req_post(req, ev);
1877 tevent_req_set_callback(
1878 subreq, cli_session_setup_spnego_done_ntlmssp, req);
1879 return req;
1882 #ifdef HAVE_KRB5
1883 static void cli_session_setup_spnego_done_krb(struct tevent_req *subreq)
1885 struct tevent_req *req = tevent_req_callback_data(
1886 subreq, struct tevent_req);
1887 struct cli_session_setup_spnego_state *state = tevent_req_data(
1888 req, struct cli_session_setup_spnego_state);
1890 state->result = cli_session_setup_kerberos_recv(subreq);
1891 TALLOC_FREE(subreq);
1893 if (ADS_ERR_OK(state->result) ||
1894 !state->cli->fallback_after_kerberos) {
1895 tevent_req_done(req);
1896 return;
1899 subreq = cli_session_setup_ntlmssp_send(
1900 state, state->ev, state->cli, state->account, state->pass,
1901 state->user_domain);
1902 if (tevent_req_nomem(subreq, req)) {
1903 return;
1905 tevent_req_set_callback(subreq, cli_session_setup_spnego_done_ntlmssp,
1906 req);
1908 #endif
1910 static void cli_session_setup_spnego_done_ntlmssp(struct tevent_req *subreq)
1912 struct tevent_req *req = tevent_req_callback_data(
1913 subreq, struct tevent_req);
1914 struct cli_session_setup_spnego_state *state = tevent_req_data(
1915 req, struct cli_session_setup_spnego_state);
1916 NTSTATUS status;
1918 status = cli_session_setup_ntlmssp_recv(subreq);
1919 TALLOC_FREE(subreq);
1920 state->result = ADS_ERROR_NT(status);
1921 tevent_req_done(req);
1924 static ADS_STATUS cli_session_setup_spnego_recv(struct tevent_req *req)
1926 struct cli_session_setup_spnego_state *state = tevent_req_data(
1927 req, struct cli_session_setup_spnego_state);
1929 return state->result;
1932 struct cli_session_setup_state {
1933 uint8_t dummy;
1936 static void cli_session_setup_done_lanman2(struct tevent_req *subreq);
1937 static void cli_session_setup_done_spnego(struct tevent_req *subreq);
1938 static void cli_session_setup_done_guest(struct tevent_req *subreq);
1939 static void cli_session_setup_done_plain(struct tevent_req *subreq);
1940 static void cli_session_setup_done_nt1(struct tevent_req *subreq);
1942 /****************************************************************************
1943 Send a session setup. The username and workgroup is in UNIX character
1944 format and must be converted to DOS codepage format before sending. If the
1945 password is in plaintext, the same should be done.
1946 ****************************************************************************/
1948 struct tevent_req *cli_session_setup_send(TALLOC_CTX *mem_ctx,
1949 struct tevent_context *ev,
1950 struct cli_state *cli,
1951 const char *user,
1952 const char *pass, int passlen,
1953 const char *ntpass, int ntpasslen,
1954 const char *workgroup)
1956 struct tevent_req *req, *subreq;
1957 struct cli_session_setup_state *state;
1958 char *p;
1959 char *user2;
1960 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
1962 req = tevent_req_create(mem_ctx, &state,
1963 struct cli_session_setup_state);
1964 if (req == NULL) {
1965 return NULL;
1968 if (user) {
1969 user2 = talloc_strdup(state, user);
1970 } else {
1971 user2 = talloc_strdup(state, "");
1973 if (user2 == NULL) {
1974 tevent_req_oom(req);
1975 return tevent_req_post(req, ev);
1978 if (!workgroup) {
1979 workgroup = "";
1982 /* allow for workgroups as part of the username */
1983 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1984 (p=strchr_m(user2,*lp_winbind_separator()))) {
1985 *p = 0;
1986 user = p+1;
1987 if (!strupper_m(user2)) {
1988 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1989 return tevent_req_post(req, ev);
1991 workgroup = user2;
1994 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
1995 tevent_req_done(req);
1996 return tevent_req_post(req, ev);
1999 /* now work out what sort of session setup we are going to
2000 do. I have split this into separate functions to make the
2001 flow a bit easier to understand (tridge) */
2003 /* if its an older server then we have to use the older request format */
2005 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2006 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2007 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2008 " or 'client ntlmv2 auth = yes'\n"));
2009 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2010 return tevent_req_post(req, ev);
2013 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2014 !lp_client_plaintext_auth() && (*pass)) {
2015 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2016 " or 'client ntlmv2 auth = yes'\n"));
2017 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2018 return tevent_req_post(req, ev);
2021 subreq = cli_session_setup_lanman2_send(
2022 state, ev, cli, user, pass, passlen, workgroup);
2023 if (tevent_req_nomem(subreq, req)) {
2024 return tevent_req_post(req, ev);
2026 tevent_req_set_callback(subreq, cli_session_setup_done_lanman2,
2027 req);
2028 return req;
2031 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2032 const char *remote_realm = cli_state_remote_realm(cli);
2034 subreq = cli_session_setup_spnego_send(
2035 state, ev, cli, user, pass, workgroup, remote_realm);
2036 if (tevent_req_nomem(subreq, req)) {
2037 return tevent_req_post(req, ev);
2039 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2040 req);
2041 return req;
2044 /* if no user is supplied then we have to do an anonymous connection.
2045 passwords are ignored */
2047 if (!user || !*user) {
2048 subreq = cli_session_setup_guest_send(state, ev, cli);
2049 if (tevent_req_nomem(subreq, req)) {
2050 return tevent_req_post(req, ev);
2052 tevent_req_set_callback(subreq, cli_session_setup_done_guest,
2053 req);
2054 return req;
2057 /* if the server is share level then send a plaintext null
2058 password at this point. The password is sent in the tree
2059 connect */
2061 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
2062 subreq = cli_session_setup_plain_send(
2063 state, ev, cli, user, "", workgroup);
2064 if (tevent_req_nomem(subreq, req)) {
2065 return tevent_req_post(req, ev);
2067 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2068 req);
2069 return req;
2072 /* if the server doesn't support encryption then we have to use
2073 plaintext. The second password is ignored */
2075 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2076 if (!lp_client_plaintext_auth() && (*pass)) {
2077 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2078 " or 'client ntlmv2 auth = yes'\n"));
2079 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2080 return tevent_req_post(req, ev);
2082 subreq = cli_session_setup_plain_send(
2083 state, ev, cli, user, pass, workgroup);
2084 if (tevent_req_nomem(subreq, req)) {
2085 return tevent_req_post(req, ev);
2087 tevent_req_set_callback(subreq, cli_session_setup_done_plain,
2088 req);
2089 return req;
2092 /* if the server supports extended security then use SPNEGO */
2094 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2095 const char *remote_realm = cli_state_remote_realm(cli);
2097 subreq = cli_session_setup_spnego_send(
2098 state, ev, cli, user, pass, workgroup, remote_realm);
2099 if (tevent_req_nomem(subreq, req)) {
2100 return tevent_req_post(req, ev);
2102 tevent_req_set_callback(subreq, cli_session_setup_done_spnego,
2103 req);
2104 return req;
2105 } else {
2106 /* otherwise do a NT1 style session setup */
2108 subreq = cli_session_setup_nt1_send(
2109 state, ev, cli, user, pass, passlen, ntpass, ntpasslen,
2110 workgroup);
2111 if (tevent_req_nomem(subreq, req)) {
2112 return tevent_req_post(req, ev);
2114 tevent_req_set_callback(subreq, cli_session_setup_done_nt1,
2115 req);
2116 return req;
2119 tevent_req_done(req);
2120 return tevent_req_post(req, ev);
2123 static void cli_session_setup_done_lanman2(struct tevent_req *subreq)
2125 struct tevent_req *req = tevent_req_callback_data(
2126 subreq, struct tevent_req);
2127 NTSTATUS status;
2129 status = cli_session_setup_lanman2_recv(subreq);
2130 TALLOC_FREE(subreq);
2131 if (!NT_STATUS_IS_OK(status)) {
2132 tevent_req_nterror(req, status);
2133 return;
2135 tevent_req_done(req);
2138 static void cli_session_setup_done_spnego(struct tevent_req *subreq)
2140 struct tevent_req *req = tevent_req_callback_data(
2141 subreq, struct tevent_req);
2142 ADS_STATUS status;
2144 status = cli_session_setup_spnego_recv(subreq);
2145 TALLOC_FREE(subreq);
2146 if (!ADS_ERR_OK(status)) {
2147 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2148 tevent_req_nterror(req, ads_ntstatus(status));
2149 return;
2151 tevent_req_done(req);
2154 static void cli_session_setup_done_guest(struct tevent_req *subreq)
2156 struct tevent_req *req = tevent_req_callback_data(
2157 subreq, struct tevent_req);
2158 NTSTATUS status;
2160 status = cli_session_setup_guest_recv(subreq);
2161 TALLOC_FREE(subreq);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 tevent_req_nterror(req, status);
2164 return;
2166 tevent_req_done(req);
2169 static void cli_session_setup_done_plain(struct tevent_req *subreq)
2171 struct tevent_req *req = tevent_req_callback_data(
2172 subreq, struct tevent_req);
2173 NTSTATUS status;
2175 status = cli_session_setup_plain_recv(subreq);
2176 TALLOC_FREE(subreq);
2177 if (!NT_STATUS_IS_OK(status)) {
2178 tevent_req_nterror(req, status);
2179 return;
2181 tevent_req_done(req);
2184 static void cli_session_setup_done_nt1(struct tevent_req *subreq)
2186 struct tevent_req *req = tevent_req_callback_data(
2187 subreq, struct tevent_req);
2188 NTSTATUS status;
2190 status = cli_session_setup_nt1_recv(subreq);
2191 TALLOC_FREE(subreq);
2192 if (!NT_STATUS_IS_OK(status)) {
2193 DEBUG(3, ("cli_session_setup: NT1 session setup "
2194 "failed: %s\n", nt_errstr(status)));
2195 tevent_req_nterror(req, status);
2196 return;
2198 tevent_req_done(req);
2201 NTSTATUS cli_session_setup_recv(struct tevent_req *req)
2203 return tevent_req_simple_recv_ntstatus(req);
2206 NTSTATUS cli_session_setup(struct cli_state *cli,
2207 const char *user,
2208 const char *pass, int passlen,
2209 const char *ntpass, int ntpasslen,
2210 const char *workgroup)
2212 struct tevent_context *ev;
2213 struct tevent_req *req;
2214 NTSTATUS status = NT_STATUS_NO_MEMORY;
2216 if (smbXcli_conn_has_async_calls(cli->conn)) {
2217 return NT_STATUS_INVALID_PARAMETER;
2219 ev = samba_tevent_context_init(talloc_tos());
2220 if (ev == NULL) {
2221 goto fail;
2223 req = cli_session_setup_send(ev, ev, cli, user, pass, passlen,
2224 ntpass, ntpasslen, workgroup);
2225 if (req == NULL) {
2226 goto fail;
2228 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2229 goto fail;
2231 status = cli_session_setup_recv(req);
2232 fail:
2233 TALLOC_FREE(ev);
2234 return status;
2237 /****************************************************************************
2238 Send a uloggoff.
2239 *****************************************************************************/
2241 struct cli_ulogoff_state {
2242 struct cli_state *cli;
2243 uint16_t vwv[3];
2246 static void cli_ulogoff_done(struct tevent_req *subreq);
2248 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2249 struct tevent_context *ev,
2250 struct cli_state *cli)
2252 struct tevent_req *req, *subreq;
2253 struct cli_ulogoff_state *state;
2255 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2256 if (req == NULL) {
2257 return NULL;
2259 state->cli = cli;
2261 SCVAL(state->vwv+0, 0, 0xFF);
2262 SCVAL(state->vwv+1, 0, 0);
2263 SSVAL(state->vwv+2, 0, 0);
2265 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2266 0, NULL);
2267 if (tevent_req_nomem(subreq, req)) {
2268 return tevent_req_post(req, ev);
2270 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2271 return req;
2274 static void cli_ulogoff_done(struct tevent_req *subreq)
2276 struct tevent_req *req = tevent_req_callback_data(
2277 subreq, struct tevent_req);
2278 struct cli_ulogoff_state *state = tevent_req_data(
2279 req, struct cli_ulogoff_state);
2280 NTSTATUS status;
2282 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2283 if (!NT_STATUS_IS_OK(status)) {
2284 tevent_req_nterror(req, status);
2285 return;
2287 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2288 tevent_req_done(req);
2291 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2293 return tevent_req_simple_recv_ntstatus(req);
2296 NTSTATUS cli_ulogoff(struct cli_state *cli)
2298 struct tevent_context *ev;
2299 struct tevent_req *req;
2300 NTSTATUS status = NT_STATUS_NO_MEMORY;
2302 if (smbXcli_conn_has_async_calls(cli->conn)) {
2303 return NT_STATUS_INVALID_PARAMETER;
2305 ev = samba_tevent_context_init(talloc_tos());
2306 if (ev == NULL) {
2307 goto fail;
2309 req = cli_ulogoff_send(ev, ev, cli);
2310 if (req == NULL) {
2311 goto fail;
2313 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2314 goto fail;
2316 status = cli_ulogoff_recv(req);
2317 fail:
2318 TALLOC_FREE(ev);
2319 return status;
2322 /****************************************************************************
2323 Send a tconX.
2324 ****************************************************************************/
2326 struct cli_tcon_andx_state {
2327 struct cli_state *cli;
2328 uint16_t vwv[4];
2329 struct iovec bytes;
2332 static void cli_tcon_andx_done(struct tevent_req *subreq);
2334 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2335 struct tevent_context *ev,
2336 struct cli_state *cli,
2337 const char *share, const char *dev,
2338 const char *pass, int passlen,
2339 struct tevent_req **psmbreq)
2341 struct tevent_req *req, *subreq;
2342 struct cli_tcon_andx_state *state;
2343 uint8_t p24[24];
2344 uint16_t *vwv;
2345 char *tmp = NULL;
2346 uint8_t *bytes;
2347 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2348 uint16_t tcon_flags = 0;
2350 *psmbreq = NULL;
2352 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2353 if (req == NULL) {
2354 return NULL;
2356 state->cli = cli;
2357 vwv = state->vwv;
2359 cli->share = talloc_strdup(cli, share);
2360 if (!cli->share) {
2361 return NULL;
2364 /* in user level security don't send a password now */
2365 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2366 passlen = 1;
2367 pass = "";
2368 } else if (pass == NULL) {
2369 DEBUG(1, ("Server not using user level security and no "
2370 "password supplied.\n"));
2371 goto access_denied;
2374 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2375 *pass && passlen != 24) {
2376 if (!lp_client_lanman_auth()) {
2377 DEBUG(1, ("Server requested LANMAN password "
2378 "(share-level security) but "
2379 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2380 goto access_denied;
2384 * Non-encrypted passwords - convert to DOS codepage before
2385 * encryption.
2387 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2388 passlen = 24;
2389 pass = (const char *)p24;
2390 } else {
2391 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2392 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2393 == 0) {
2394 uint8_t *tmp_pass;
2396 if (!lp_client_plaintext_auth() && (*pass)) {
2397 DEBUG(1, ("Server requested PLAINTEXT "
2398 "password but "
2399 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2400 goto access_denied;
2404 * Non-encrypted passwords - convert to DOS codepage
2405 * before using.
2407 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2408 if (tevent_req_nomem(tmp_pass, req)) {
2409 return tevent_req_post(req, ev);
2411 tmp_pass = trans2_bytes_push_str(tmp_pass,
2412 false, /* always DOS */
2413 pass,
2414 passlen,
2415 NULL);
2416 if (tevent_req_nomem(tmp_pass, req)) {
2417 return tevent_req_post(req, ev);
2419 pass = (const char *)tmp_pass;
2420 passlen = talloc_get_size(tmp_pass);
2424 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2425 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2427 SCVAL(vwv+0, 0, 0xFF);
2428 SCVAL(vwv+0, 1, 0);
2429 SSVAL(vwv+1, 0, 0);
2430 SSVAL(vwv+2, 0, tcon_flags);
2431 SSVAL(vwv+3, 0, passlen);
2433 if (passlen && pass) {
2434 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2435 } else {
2436 bytes = talloc_array(state, uint8_t, 0);
2440 * Add the sharename
2442 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2443 smbXcli_conn_remote_name(cli->conn), share);
2444 if (tmp == NULL) {
2445 TALLOC_FREE(req);
2446 return NULL;
2448 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2449 NULL);
2450 TALLOC_FREE(tmp);
2453 * Add the devicetype
2455 tmp = talloc_strdup_upper(talloc_tos(), dev);
2456 if (tmp == NULL) {
2457 TALLOC_FREE(req);
2458 return NULL;
2460 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2461 TALLOC_FREE(tmp);
2463 if (bytes == NULL) {
2464 TALLOC_FREE(req);
2465 return NULL;
2468 state->bytes.iov_base = (void *)bytes;
2469 state->bytes.iov_len = talloc_get_size(bytes);
2471 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2472 1, &state->bytes);
2473 if (subreq == NULL) {
2474 TALLOC_FREE(req);
2475 return NULL;
2477 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2478 *psmbreq = subreq;
2479 return req;
2481 access_denied:
2482 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2483 return tevent_req_post(req, ev);
2486 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2487 struct tevent_context *ev,
2488 struct cli_state *cli,
2489 const char *share, const char *dev,
2490 const char *pass, int passlen)
2492 struct tevent_req *req, *subreq;
2493 NTSTATUS status;
2495 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2496 &subreq);
2497 if (req == NULL) {
2498 return NULL;
2500 if (subreq == NULL) {
2501 return req;
2503 status = smb1cli_req_chain_submit(&subreq, 1);
2504 if (!NT_STATUS_IS_OK(status)) {
2505 tevent_req_nterror(req, status);
2506 return tevent_req_post(req, ev);
2508 return req;
2511 static void cli_tcon_andx_done(struct tevent_req *subreq)
2513 struct tevent_req *req = tevent_req_callback_data(
2514 subreq, struct tevent_req);
2515 struct cli_tcon_andx_state *state = tevent_req_data(
2516 req, struct cli_tcon_andx_state);
2517 struct cli_state *cli = state->cli;
2518 uint8_t *in;
2519 uint8_t *inhdr;
2520 uint8_t wct;
2521 uint16_t *vwv;
2522 uint32_t num_bytes;
2523 uint8_t *bytes;
2524 NTSTATUS status;
2525 uint16_t optional_support = 0;
2527 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2528 &num_bytes, &bytes);
2529 TALLOC_FREE(subreq);
2530 if (!NT_STATUS_IS_OK(status)) {
2531 tevent_req_nterror(req, status);
2532 return;
2535 inhdr = in + NBT_HDR_SIZE;
2537 if (num_bytes) {
2538 if (clistr_pull_talloc(cli,
2539 (const char *)inhdr,
2540 SVAL(inhdr, HDR_FLG2),
2541 &cli->dev,
2542 bytes,
2543 num_bytes,
2544 STR_TERMINATE|STR_ASCII) == -1) {
2545 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2546 return;
2548 } else {
2549 cli->dev = talloc_strdup(cli, "");
2550 if (cli->dev == NULL) {
2551 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2552 return;
2556 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2557 /* almost certainly win95 - enable bug fixes */
2558 cli->win95 = True;
2562 * Make sure that we have the optional support 16-bit field. WCT > 2.
2563 * Avoids issues when connecting to Win9x boxes sharing files
2566 cli->dfsroot = false;
2568 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2569 optional_support = SVAL(vwv+2, 0);
2572 if (optional_support & SMB_SHARE_IN_DFS) {
2573 cli->dfsroot = true;
2576 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2577 smb1cli_session_protect_session_key(cli->smb1.session);
2580 cli_state_set_tid(cli, SVAL(inhdr, HDR_TID));
2581 tevent_req_done(req);
2584 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2586 return tevent_req_simple_recv_ntstatus(req);
2589 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2590 const char *dev, const char *pass, int passlen)
2592 TALLOC_CTX *frame = talloc_stackframe();
2593 struct tevent_context *ev;
2594 struct tevent_req *req;
2595 NTSTATUS status = NT_STATUS_NO_MEMORY;
2597 if (smbXcli_conn_has_async_calls(cli->conn)) {
2599 * Can't use sync call while an async call is in flight
2601 status = NT_STATUS_INVALID_PARAMETER;
2602 goto fail;
2605 ev = samba_tevent_context_init(frame);
2606 if (ev == NULL) {
2607 goto fail;
2610 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2611 if (req == NULL) {
2612 goto fail;
2615 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2616 goto fail;
2619 status = cli_tcon_andx_recv(req);
2620 fail:
2621 TALLOC_FREE(frame);
2622 return status;
2625 struct cli_tree_connect_state {
2626 struct cli_state *cli;
2629 static struct tevent_req *cli_raw_tcon_send(
2630 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2631 const char *service, const char *pass, const char *dev);
2632 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
2633 uint16 *max_xmit, uint16 *tid);
2635 static void cli_tree_connect_smb2_done(struct tevent_req *subreq);
2636 static void cli_tree_connect_andx_done(struct tevent_req *subreq);
2637 static void cli_tree_connect_raw_done(struct tevent_req *subreq);
2639 static struct tevent_req *cli_tree_connect_send(
2640 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
2641 const char *share, const char *dev, const char *pass, int passlen)
2643 struct tevent_req *req, *subreq;
2644 struct cli_tree_connect_state *state;
2646 req = tevent_req_create(mem_ctx, &state,
2647 struct cli_tree_connect_state);
2648 if (req == NULL) {
2649 return NULL;
2651 state->cli = cli;
2653 cli->share = talloc_strdup(cli, share);
2654 if (tevent_req_nomem(cli->share, req)) {
2655 return tevent_req_post(req, ev);
2658 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2659 subreq = smb2cli_tcon_send(state, ev, cli, share);
2660 if (tevent_req_nomem(subreq, req)) {
2661 return tevent_req_post(req, ev);
2663 tevent_req_set_callback(subreq, cli_tree_connect_smb2_done,
2664 req);
2665 return req;
2668 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2669 subreq = cli_tcon_andx_send(state, ev, cli, share, dev,
2670 pass, passlen);
2671 if (tevent_req_nomem(subreq, req)) {
2672 return tevent_req_post(req, ev);
2674 tevent_req_set_callback(subreq, cli_tree_connect_andx_done,
2675 req);
2676 return req;
2679 subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev);
2680 if (tevent_req_nomem(subreq, req)) {
2681 return tevent_req_post(req, ev);
2683 tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req);
2685 return req;
2688 static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
2690 tevent_req_simple_finish_ntstatus(
2691 subreq, smb2cli_tcon_recv(subreq));
2694 static void cli_tree_connect_andx_done(struct tevent_req *subreq)
2696 tevent_req_simple_finish_ntstatus(
2697 subreq, cli_tcon_andx_recv(subreq));
2700 static void cli_tree_connect_raw_done(struct tevent_req *subreq)
2702 struct tevent_req *req = tevent_req_callback_data(
2703 subreq, struct tevent_req);
2704 struct cli_tree_connect_state *state = tevent_req_data(
2705 req, struct cli_tree_connect_state);
2706 NTSTATUS status;
2707 uint16_t max_xmit = 0;
2708 uint16_t tid = 0;
2710 status = cli_raw_tcon_recv(subreq, &max_xmit, &tid);
2711 if (tevent_req_nterror(req, status)) {
2712 return;
2714 cli_state_set_tid(state->cli, tid);
2715 tevent_req_done(req);
2718 static NTSTATUS cli_tree_connect_recv(struct tevent_req *req)
2720 return tevent_req_simple_recv_ntstatus(req);
2723 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2724 const char *dev, const char *pass, int passlen)
2726 struct tevent_context *ev;
2727 struct tevent_req *req;
2728 NTSTATUS status = NT_STATUS_NO_MEMORY;
2730 if (smbXcli_conn_has_async_calls(cli->conn)) {
2731 return NT_STATUS_INVALID_PARAMETER;
2733 ev = samba_tevent_context_init(talloc_tos());
2734 if (ev == NULL) {
2735 goto fail;
2737 req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen);
2738 if (req == NULL) {
2739 goto fail;
2741 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2742 goto fail;
2744 status = cli_tree_connect_recv(req);
2745 fail:
2746 TALLOC_FREE(ev);
2747 return status;
2750 /****************************************************************************
2751 Send a tree disconnect.
2752 ****************************************************************************/
2754 struct cli_tdis_state {
2755 struct cli_state *cli;
2758 static void cli_tdis_done(struct tevent_req *subreq);
2760 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2761 struct tevent_context *ev,
2762 struct cli_state *cli)
2764 struct tevent_req *req, *subreq;
2765 struct cli_tdis_state *state;
2767 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2768 if (req == NULL) {
2769 return NULL;
2771 state->cli = cli;
2773 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2774 if (tevent_req_nomem(subreq, req)) {
2775 return tevent_req_post(req, ev);
2777 tevent_req_set_callback(subreq, cli_tdis_done, req);
2778 return req;
2781 static void cli_tdis_done(struct tevent_req *subreq)
2783 struct tevent_req *req = tevent_req_callback_data(
2784 subreq, struct tevent_req);
2785 struct cli_tdis_state *state = tevent_req_data(
2786 req, struct cli_tdis_state);
2787 NTSTATUS status;
2789 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2790 TALLOC_FREE(subreq);
2791 if (!NT_STATUS_IS_OK(status)) {
2792 tevent_req_nterror(req, status);
2793 return;
2795 cli_state_set_tid(state->cli, UINT16_MAX);
2796 tevent_req_done(req);
2799 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2801 return tevent_req_simple_recv_ntstatus(req);
2804 NTSTATUS cli_tdis(struct cli_state *cli)
2806 struct tevent_context *ev;
2807 struct tevent_req *req;
2808 NTSTATUS status = NT_STATUS_NO_MEMORY;
2810 if (smbXcli_conn_has_async_calls(cli->conn)) {
2811 return NT_STATUS_INVALID_PARAMETER;
2813 ev = samba_tevent_context_init(talloc_tos());
2814 if (ev == NULL) {
2815 goto fail;
2817 req = cli_tdis_send(ev, ev, cli);
2818 if (req == NULL) {
2819 goto fail;
2821 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2822 goto fail;
2824 status = cli_tdis_recv(req);
2825 fail:
2826 TALLOC_FREE(ev);
2827 return status;
2830 struct cli_connect_sock_state {
2831 const char **called_names;
2832 const char **calling_names;
2833 int *called_types;
2834 int fd;
2835 uint16_t port;
2838 static void cli_connect_sock_done(struct tevent_req *subreq);
2841 * Async only if we don't have to look up the name, i.e. "pss" is set with a
2842 * nonzero address.
2845 static struct tevent_req *cli_connect_sock_send(
2846 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2847 const char *host, int name_type, const struct sockaddr_storage *pss,
2848 const char *myname, uint16_t port)
2850 struct tevent_req *req, *subreq;
2851 struct cli_connect_sock_state *state;
2852 const char *prog;
2853 unsigned i, num_addrs;
2854 NTSTATUS status;
2856 req = tevent_req_create(mem_ctx, &state,
2857 struct cli_connect_sock_state);
2858 if (req == NULL) {
2859 return NULL;
2862 prog = getenv("LIBSMB_PROG");
2863 if (prog != NULL) {
2864 state->fd = sock_exec(prog);
2865 if (state->fd == -1) {
2866 status = map_nt_error_from_unix(errno);
2867 tevent_req_nterror(req, status);
2868 } else {
2869 state->port = 0;
2870 tevent_req_done(req);
2872 return tevent_req_post(req, ev);
2875 if ((pss == NULL) || is_zero_addr(pss)) {
2876 struct sockaddr_storage *addrs;
2879 * Here we cheat. resolve_name_list is not async at all. So
2880 * this call will only be really async if the name lookup has
2881 * been done externally.
2884 status = resolve_name_list(state, host, name_type,
2885 &addrs, &num_addrs);
2886 if (!NT_STATUS_IS_OK(status)) {
2887 tevent_req_nterror(req, status);
2888 return tevent_req_post(req, ev);
2890 pss = addrs;
2891 } else {
2892 num_addrs = 1;
2895 state->called_names = talloc_array(state, const char *, num_addrs);
2896 if (tevent_req_nomem(state->called_names, req)) {
2897 return tevent_req_post(req, ev);
2899 state->called_types = talloc_array(state, int, num_addrs);
2900 if (tevent_req_nomem(state->called_types, req)) {
2901 return tevent_req_post(req, ev);
2903 state->calling_names = talloc_array(state, const char *, num_addrs);
2904 if (tevent_req_nomem(state->calling_names, req)) {
2905 return tevent_req_post(req, ev);
2907 for (i=0; i<num_addrs; i++) {
2908 state->called_names[i] = host;
2909 state->called_types[i] = name_type;
2910 state->calling_names[i] = myname;
2913 subreq = smbsock_any_connect_send(
2914 state, ev, pss, state->called_names, state->called_types,
2915 state->calling_names, NULL, num_addrs, port);
2916 if (tevent_req_nomem(subreq, req)) {
2917 return tevent_req_post(req, ev);
2919 tevent_req_set_callback(subreq, cli_connect_sock_done, req);
2920 return req;
2923 static void cli_connect_sock_done(struct tevent_req *subreq)
2925 struct tevent_req *req = tevent_req_callback_data(
2926 subreq, struct tevent_req);
2927 struct cli_connect_sock_state *state = tevent_req_data(
2928 req, struct cli_connect_sock_state);
2929 NTSTATUS status;
2931 status = smbsock_any_connect_recv(subreq, &state->fd, NULL,
2932 &state->port);
2933 TALLOC_FREE(subreq);
2934 if (tevent_req_nterror(req, status)) {
2935 return;
2937 set_socket_options(state->fd, lp_socket_options());
2938 tevent_req_done(req);
2941 static NTSTATUS cli_connect_sock_recv(struct tevent_req *req,
2942 int *pfd, uint16_t *pport)
2944 struct cli_connect_sock_state *state = tevent_req_data(
2945 req, struct cli_connect_sock_state);
2946 NTSTATUS status;
2948 if (tevent_req_is_nterror(req, &status)) {
2949 return status;
2951 *pfd = state->fd;
2952 *pport = state->port;
2953 return NT_STATUS_OK;
2956 struct cli_connect_nb_state {
2957 const char *desthost;
2958 int signing_state;
2959 int flags;
2960 struct cli_state *cli;
2963 static void cli_connect_nb_done(struct tevent_req *subreq);
2965 static struct tevent_req *cli_connect_nb_send(
2966 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2967 const char *host, const struct sockaddr_storage *dest_ss,
2968 uint16_t port, int name_type, const char *myname,
2969 int signing_state, int flags)
2971 struct tevent_req *req, *subreq;
2972 struct cli_connect_nb_state *state;
2973 char *p;
2975 req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state);
2976 if (req == NULL) {
2977 return NULL;
2979 state->desthost = host;
2980 state->signing_state = signing_state;
2981 state->flags = flags;
2983 p = strchr(host, '#');
2984 if (p != NULL) {
2985 name_type = strtol(p+1, NULL, 16);
2986 host = talloc_strndup(state, host, p - host);
2987 if (tevent_req_nomem(host, req)) {
2988 return tevent_req_post(req, ev);
2992 subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss,
2993 myname, port);
2994 if (tevent_req_nomem(subreq, req)) {
2995 return tevent_req_post(req, ev);
2997 tevent_req_set_callback(subreq, cli_connect_nb_done, req);
2998 return req;
3001 static void cli_connect_nb_done(struct tevent_req *subreq)
3003 struct tevent_req *req = tevent_req_callback_data(
3004 subreq, struct tevent_req);
3005 struct cli_connect_nb_state *state = tevent_req_data(
3006 req, struct cli_connect_nb_state);
3007 NTSTATUS status;
3008 int fd;
3009 uint16_t port;
3011 status = cli_connect_sock_recv(subreq, &fd, &port);
3012 TALLOC_FREE(subreq);
3013 if (tevent_req_nterror(req, status)) {
3014 return;
3017 state->cli = cli_state_create(state, fd, state->desthost, NULL,
3018 state->signing_state, state->flags);
3019 if (tevent_req_nomem(state->cli, req)) {
3020 close(fd);
3021 return;
3023 tevent_req_done(req);
3026 static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
3027 struct cli_state **pcli)
3029 struct cli_connect_nb_state *state = tevent_req_data(
3030 req, struct cli_connect_nb_state);
3031 NTSTATUS status;
3033 if (tevent_req_is_nterror(req, &status)) {
3034 return status;
3036 *pcli = talloc_move(NULL, &state->cli);
3037 return NT_STATUS_OK;
3040 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3041 uint16_t port, int name_type, const char *myname,
3042 int signing_state, int flags, struct cli_state **pcli)
3044 struct tevent_context *ev;
3045 struct tevent_req *req;
3046 NTSTATUS status = NT_STATUS_NO_MEMORY;
3048 ev = samba_tevent_context_init(talloc_tos());
3049 if (ev == NULL) {
3050 goto fail;
3052 req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type,
3053 myname, signing_state, flags);
3054 if (req == NULL) {
3055 goto fail;
3057 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) {
3058 goto fail;
3060 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3061 goto fail;
3063 status = cli_connect_nb_recv(req, pcli);
3064 fail:
3065 TALLOC_FREE(ev);
3066 return status;
3069 struct cli_start_connection_state {
3070 struct tevent_context *ev;
3071 struct cli_state *cli;
3074 static void cli_start_connection_connected(struct tevent_req *subreq);
3075 static void cli_start_connection_done(struct tevent_req *subreq);
3078 establishes a connection to after the negprot.
3079 @param output_cli A fully initialised cli structure, non-null only on success
3080 @param dest_host The netbios name of the remote host
3081 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3082 @param port (optional) The destination port (0 for default)
3085 static struct tevent_req *cli_start_connection_send(
3086 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3087 const char *my_name, const char *dest_host,
3088 const struct sockaddr_storage *dest_ss, int port,
3089 int signing_state, int flags)
3091 struct tevent_req *req, *subreq;
3092 struct cli_start_connection_state *state;
3094 req = tevent_req_create(mem_ctx, &state,
3095 struct cli_start_connection_state);
3096 if (req == NULL) {
3097 return NULL;
3099 state->ev = ev;
3101 subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
3102 0x20, my_name, signing_state, flags);
3103 if (tevent_req_nomem(subreq, req)) {
3104 return tevent_req_post(req, ev);
3106 tevent_req_set_callback(subreq, cli_start_connection_connected, req);
3107 return req;
3110 static void cli_start_connection_connected(struct tevent_req *subreq)
3112 struct tevent_req *req = tevent_req_callback_data(
3113 subreq, struct tevent_req);
3114 struct cli_start_connection_state *state = tevent_req_data(
3115 req, struct cli_start_connection_state);
3116 NTSTATUS status;
3118 status = cli_connect_nb_recv(subreq, &state->cli);
3119 TALLOC_FREE(subreq);
3120 if (tevent_req_nterror(req, status)) {
3121 return;
3124 subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
3125 state->cli->timeout,
3126 PROTOCOL_CORE, PROTOCOL_NT1);
3127 if (tevent_req_nomem(subreq, req)) {
3128 return;
3130 tevent_req_set_callback(subreq, cli_start_connection_done, req);
3133 static void cli_start_connection_done(struct tevent_req *subreq)
3135 struct tevent_req *req = tevent_req_callback_data(
3136 subreq, struct tevent_req);
3137 NTSTATUS status;
3139 status = smbXcli_negprot_recv(subreq);
3140 TALLOC_FREE(subreq);
3141 if (tevent_req_nterror(req, status)) {
3142 return;
3144 tevent_req_done(req);
3147 static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
3148 struct cli_state **output_cli)
3150 struct cli_start_connection_state *state = tevent_req_data(
3151 req, struct cli_start_connection_state);
3152 NTSTATUS status;
3154 if (tevent_req_is_nterror(req, &status)) {
3155 return status;
3157 *output_cli = state->cli;
3158 return NT_STATUS_OK;
3161 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3162 const char *my_name,
3163 const char *dest_host,
3164 const struct sockaddr_storage *dest_ss, int port,
3165 int signing_state, int flags)
3167 struct tevent_context *ev;
3168 struct tevent_req *req;
3169 NTSTATUS status = NT_STATUS_NO_MEMORY;
3171 ev = samba_tevent_context_init(talloc_tos());
3172 if (ev == NULL) {
3173 goto fail;
3175 req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
3176 port, signing_state, flags);
3177 if (req == NULL) {
3178 goto fail;
3180 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3181 goto fail;
3183 status = cli_start_connection_recv(req, output_cli);
3184 fail:
3185 TALLOC_FREE(ev);
3186 return status;
3190 establishes a connection right up to doing tconX, password specified.
3191 @param output_cli A fully initialised cli structure, non-null only on success
3192 @param dest_host The netbios name of the remote host
3193 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3194 @param port (optional) The destination port (0 for default)
3195 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3196 @param service_type The 'type' of serivice.
3197 @param user Username, unix string
3198 @param domain User's domain
3199 @param password User's password, unencrypted unix string.
3202 struct cli_full_connection_state {
3203 struct tevent_context *ev;
3204 const char *service;
3205 const char *service_type;
3206 const char *user;
3207 const char *domain;
3208 const char *password;
3209 int pw_len;
3210 int flags;
3211 struct cli_state *cli;
3214 static int cli_full_connection_state_destructor(
3215 struct cli_full_connection_state *s);
3216 static void cli_full_connection_started(struct tevent_req *subreq);
3217 static void cli_full_connection_sess_set_up(struct tevent_req *subreq);
3218 static void cli_full_connection_done(struct tevent_req *subreq);
3220 struct tevent_req *cli_full_connection_send(
3221 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
3222 const char *my_name, const char *dest_host,
3223 const struct sockaddr_storage *dest_ss, int port,
3224 const char *service, const char *service_type,
3225 const char *user, const char *domain,
3226 const char *password, int flags, int signing_state)
3228 struct tevent_req *req, *subreq;
3229 struct cli_full_connection_state *state;
3231 req = tevent_req_create(mem_ctx, &state,
3232 struct cli_full_connection_state);
3233 if (req == NULL) {
3234 return NULL;
3236 talloc_set_destructor(state, cli_full_connection_state_destructor);
3238 state->ev = ev;
3239 state->service = service;
3240 state->service_type = service_type;
3241 state->user = user;
3242 state->domain = domain;
3243 state->password = password;
3244 state->flags = flags;
3246 state->pw_len = state->password ? strlen(state->password)+1 : 0;
3247 if (state->password == NULL) {
3248 state->password = "";
3251 subreq = cli_start_connection_send(
3252 state, ev, my_name, dest_host, dest_ss, port,
3253 signing_state, flags);
3254 if (tevent_req_nomem(subreq, req)) {
3255 return tevent_req_post(req, ev);
3257 tevent_req_set_callback(subreq, cli_full_connection_started, req);
3258 return req;
3261 static int cli_full_connection_state_destructor(
3262 struct cli_full_connection_state *s)
3264 if (s->cli != NULL) {
3265 cli_shutdown(s->cli);
3266 s->cli = NULL;
3268 return 0;
3271 static void cli_full_connection_started(struct tevent_req *subreq)
3273 struct tevent_req *req = tevent_req_callback_data(
3274 subreq, struct tevent_req);
3275 struct cli_full_connection_state *state = tevent_req_data(
3276 req, struct cli_full_connection_state);
3277 NTSTATUS status;
3279 status = cli_start_connection_recv(subreq, &state->cli);
3280 TALLOC_FREE(subreq);
3281 if (tevent_req_nterror(req, status)) {
3282 return;
3284 subreq = cli_session_setup_send(
3285 state, state->ev, state->cli, state->user,
3286 state->password, state->pw_len, state->password, state->pw_len,
3287 state->domain);
3288 if (tevent_req_nomem(subreq, req)) {
3289 return;
3291 tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req);
3294 static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
3296 struct tevent_req *req = tevent_req_callback_data(
3297 subreq, struct tevent_req);
3298 struct cli_full_connection_state *state = tevent_req_data(
3299 req, struct cli_full_connection_state);
3300 NTSTATUS status;
3302 status = cli_session_setup_recv(subreq);
3303 TALLOC_FREE(subreq);
3305 if (!NT_STATUS_IS_OK(status) &&
3306 (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3308 state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3310 subreq = cli_session_setup_send(
3311 state, state->ev, state->cli, "", "", 0, "", 0,
3312 state->domain);
3313 if (tevent_req_nomem(subreq, req)) {
3314 return;
3316 tevent_req_set_callback(
3317 subreq, cli_full_connection_sess_set_up, req);
3318 return;
3321 if (tevent_req_nterror(req, status)) {
3322 return;
3325 if (state->service != NULL) {
3326 subreq = cli_tree_connect_send(
3327 state, state->ev, state->cli,
3328 state->service, state->service_type,
3329 state->password, state->pw_len);
3330 if (tevent_req_nomem(subreq, req)) {
3331 return;
3333 tevent_req_set_callback(subreq, cli_full_connection_done, req);
3334 return;
3337 status = cli_init_creds(state->cli, state->user, state->domain,
3338 state->password);
3339 if (tevent_req_nterror(req, status)) {
3340 return;
3342 tevent_req_done(req);
3345 static void cli_full_connection_done(struct tevent_req *subreq)
3347 struct tevent_req *req = tevent_req_callback_data(
3348 subreq, struct tevent_req);
3349 struct cli_full_connection_state *state = tevent_req_data(
3350 req, struct cli_full_connection_state);
3351 NTSTATUS status;
3353 status = cli_tree_connect_recv(subreq);
3354 TALLOC_FREE(subreq);
3355 if (tevent_req_nterror(req, status)) {
3356 return;
3358 status = cli_init_creds(state->cli, state->user, state->domain,
3359 state->password);
3360 if (tevent_req_nterror(req, status)) {
3361 return;
3363 tevent_req_done(req);
3366 NTSTATUS cli_full_connection_recv(struct tevent_req *req,
3367 struct cli_state **output_cli)
3369 struct cli_full_connection_state *state = tevent_req_data(
3370 req, struct cli_full_connection_state);
3371 NTSTATUS status;
3373 if (tevent_req_is_nterror(req, &status)) {
3374 return status;
3376 *output_cli = state->cli;
3377 talloc_set_destructor(state, NULL);
3378 return NT_STATUS_OK;
3381 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3382 const char *my_name,
3383 const char *dest_host,
3384 const struct sockaddr_storage *dest_ss, int port,
3385 const char *service, const char *service_type,
3386 const char *user, const char *domain,
3387 const char *password, int flags,
3388 int signing_state)
3390 struct tevent_context *ev;
3391 struct tevent_req *req;
3392 NTSTATUS status = NT_STATUS_NO_MEMORY;
3394 ev = samba_tevent_context_init(talloc_tos());
3395 if (ev == NULL) {
3396 goto fail;
3398 req = cli_full_connection_send(
3399 ev, ev, my_name, dest_host, dest_ss, port, service,
3400 service_type, user, domain, password, flags, signing_state);
3401 if (req == NULL) {
3402 goto fail;
3404 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3405 goto fail;
3407 status = cli_full_connection_recv(req, output_cli);
3408 fail:
3409 TALLOC_FREE(ev);
3410 return status;
3413 /****************************************************************************
3414 Send an old style tcon.
3415 ****************************************************************************/
3416 struct cli_raw_tcon_state {
3417 uint16_t *ret_vwv;
3420 static void cli_raw_tcon_done(struct tevent_req *subreq);
3422 static struct tevent_req *cli_raw_tcon_send(
3423 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
3424 const char *service, const char *pass, const char *dev)
3426 struct tevent_req *req, *subreq;
3427 struct cli_raw_tcon_state *state;
3428 uint8_t *bytes;
3430 req = tevent_req_create(mem_ctx, &state, struct cli_raw_tcon_state);
3431 if (req == NULL) {
3432 return NULL;
3435 if (!lp_client_plaintext_auth() && (*pass)) {
3436 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
3437 " or 'client ntlmv2 auth = yes'\n"));
3438 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
3439 return tevent_req_post(req, ev);
3442 bytes = talloc_array(state, uint8_t, 0);
3443 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3444 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3445 service, strlen(service)+1, NULL);
3446 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3447 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3448 pass, strlen(pass)+1, NULL);
3449 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3450 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
3451 dev, strlen(dev)+1, NULL);
3453 if (tevent_req_nomem(bytes, req)) {
3454 return tevent_req_post(req, ev);
3457 subreq = cli_smb_send(state, ev, cli, SMBtcon, 0, 0, NULL,
3458 talloc_get_size(bytes), bytes);
3459 if (tevent_req_nomem(subreq, req)) {
3460 return tevent_req_post(req, ev);
3462 tevent_req_set_callback(subreq, cli_raw_tcon_done, req);
3463 return req;
3466 static void cli_raw_tcon_done(struct tevent_req *subreq)
3468 struct tevent_req *req = tevent_req_callback_data(
3469 subreq, struct tevent_req);
3470 struct cli_raw_tcon_state *state = tevent_req_data(
3471 req, struct cli_raw_tcon_state);
3472 NTSTATUS status;
3474 status = cli_smb_recv(subreq, state, NULL, 2, NULL, &state->ret_vwv,
3475 NULL, NULL);
3476 TALLOC_FREE(subreq);
3477 if (tevent_req_nterror(req, status)) {
3478 return;
3480 tevent_req_done(req);
3483 static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req,
3484 uint16 *max_xmit, uint16 *tid)
3486 struct cli_raw_tcon_state *state = tevent_req_data(
3487 req, struct cli_raw_tcon_state);
3488 NTSTATUS status;
3490 if (tevent_req_is_nterror(req, &status)) {
3491 return status;
3493 *max_xmit = SVAL(state->ret_vwv + 0, 0);
3494 *tid = SVAL(state->ret_vwv + 1, 0);
3495 return NT_STATUS_OK;
3498 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3499 const char *service, const char *pass, const char *dev,
3500 uint16 *max_xmit, uint16 *tid)
3502 struct tevent_context *ev;
3503 struct tevent_req *req;
3504 NTSTATUS status = NT_STATUS_NO_MEMORY;
3506 ev = samba_tevent_context_init(talloc_tos());
3507 if (ev == NULL) {
3508 goto fail;
3510 req = cli_raw_tcon_send(ev, ev, cli, service, pass, dev);
3511 if (req == NULL) {
3512 goto fail;
3514 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3515 goto fail;
3517 status = cli_raw_tcon_recv(req, max_xmit, tid);
3518 fail:
3519 TALLOC_FREE(ev);
3520 return status;
3523 /* Return a cli_state pointing at the IPC$ share for the given server */
3525 struct cli_state *get_ipc_connect(char *server,
3526 struct sockaddr_storage *server_ss,
3527 const struct user_auth_info *user_info)
3529 struct cli_state *cli;
3530 NTSTATUS nt_status;
3531 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3533 if (user_info->use_kerberos) {
3534 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3537 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3538 user_info->username ? user_info->username : "",
3539 lp_workgroup(),
3540 user_info->password ? user_info->password : "",
3541 flags,
3542 SMB_SIGNING_DEFAULT);
3544 if (NT_STATUS_IS_OK(nt_status)) {
3545 return cli;
3546 } else if (is_ipaddress(server)) {
3547 /* windows 9* needs a correct NMB name for connections */
3548 fstring remote_name;
3550 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3551 cli = get_ipc_connect(remote_name, server_ss, user_info);
3552 if (cli)
3553 return cli;
3556 return NULL;
3560 * Given the IP address of a master browser on the network, return its
3561 * workgroup and connect to it.
3563 * This function is provided to allow additional processing beyond what
3564 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3565 * browsers and obtain each master browsers' list of domains (in case the
3566 * first master browser is recently on the network and has not yet
3567 * synchronized with other master browsers and therefore does not yet have the
3568 * entire network browse list)
3571 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3572 struct sockaddr_storage *mb_ip,
3573 const struct user_auth_info *user_info,
3574 char **pp_workgroup_out)
3576 char addr[INET6_ADDRSTRLEN];
3577 fstring name;
3578 struct cli_state *cli;
3579 struct sockaddr_storage server_ss;
3581 *pp_workgroup_out = NULL;
3583 print_sockaddr(addr, sizeof(addr), mb_ip);
3584 DEBUG(99, ("Looking up name of master browser %s\n",
3585 addr));
3588 * Do a name status query to find out the name of the master browser.
3589 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3590 * master browser will not respond to a wildcard query (or, at least,
3591 * an NT4 server acting as the domain master browser will not).
3593 * We might be able to use ONLY the query on MSBROWSE, but that's not
3594 * yet been tested with all Windows versions, so until it is, leave
3595 * the original wildcard query as the first choice and fall back to
3596 * MSBROWSE if the wildcard query fails.
3598 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3599 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3601 DEBUG(99, ("Could not retrieve name status for %s\n",
3602 addr));
3603 return NULL;
3606 if (!find_master_ip(name, &server_ss)) {
3607 DEBUG(99, ("Could not find master ip for %s\n", name));
3608 return NULL;
3611 *pp_workgroup_out = talloc_strdup(ctx, name);
3613 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3615 print_sockaddr(addr, sizeof(addr), &server_ss);
3616 cli = get_ipc_connect(addr, &server_ss, user_info);
3618 return cli;
3622 * Return the IP address and workgroup of a master browser on the network, and
3623 * connect to it.
3626 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3627 const struct user_auth_info *user_info,
3628 char **pp_workgroup_out)
3630 struct sockaddr_storage *ip_list;
3631 struct cli_state *cli;
3632 int i, count;
3633 NTSTATUS status;
3635 *pp_workgroup_out = NULL;
3637 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3639 /* Go looking for workgroups by broadcasting on the local network */
3641 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3642 &ip_list, &count);
3643 if (!NT_STATUS_IS_OK(status)) {
3644 DEBUG(99, ("No master browsers responded: %s\n",
3645 nt_errstr(status)));
3646 return NULL;
3649 for (i = 0; i < count; i++) {
3650 char addr[INET6_ADDRSTRLEN];
3651 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3652 DEBUG(99, ("Found master browser %s\n", addr));
3654 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3655 user_info, pp_workgroup_out);
3656 if (cli)
3657 return(cli);
3660 return NULL;