s3:selftest: Add LARGE_READX test into our make test infrastructure.
[Samba/vl.git] / source3 / libsmb / cliconnect.c
blob872900c6f3a1eb257e6b3235963e28626927854d
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 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
297 const char *pass, size_t passlen,
298 const char *workgroup)
300 TALLOC_CTX *frame = talloc_stackframe();
301 struct tevent_context *ev;
302 struct tevent_req *req;
303 NTSTATUS status = NT_STATUS_NO_MEMORY;
305 if (smbXcli_conn_has_async_calls(cli->conn)) {
307 * Can't use sync call while an async call is in flight
309 status = NT_STATUS_INVALID_PARAMETER;
310 goto fail;
312 ev = samba_tevent_context_init(frame);
313 if (ev == NULL) {
314 goto fail;
316 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
317 workgroup);
318 if (req == NULL) {
319 goto fail;
321 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
322 goto fail;
324 status = cli_session_setup_lanman2_recv(req);
325 fail:
326 TALLOC_FREE(frame);
327 return status;
330 /****************************************************************************
331 Work out suitable capabilities to offer the server.
332 ****************************************************************************/
334 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
335 uint32_t sesssetup_capabilities)
337 uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
340 * We only send capabilities based on the mask for:
341 * - client only flags
342 * - flags used in both directions
344 * We do not echo the server only flags, except some legacy flags.
346 * SMB_CAP_LEGACY_CLIENT_MASK contains CAP_LARGE_READX and
347 * CAP_LARGE_WRITEX in order to allow us to do large reads
348 * against old Samba releases (<= 3.6.x).
350 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_LEGACY_CLIENT_MASK);
353 * Session Setup specific flags CAP_DYNAMIC_REAUTH
354 * and CAP_EXTENDED_SECURITY are passed by the caller.
355 * We need that in order to do guest logins even if
356 * CAP_EXTENDED_SECURITY is negotiated.
358 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
359 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
360 client_capabilities |= sesssetup_capabilities;
362 return client_capabilities;
365 /****************************************************************************
366 Do a NT1 guest session setup.
367 ****************************************************************************/
369 struct cli_session_setup_guest_state {
370 struct cli_state *cli;
371 uint16_t vwv[13];
372 struct iovec bytes;
375 static void cli_session_setup_guest_done(struct tevent_req *subreq);
377 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
378 struct tevent_context *ev,
379 struct cli_state *cli,
380 struct tevent_req **psmbreq)
382 struct tevent_req *req, *subreq;
383 struct cli_session_setup_guest_state *state;
384 uint16_t *vwv;
385 uint8_t *bytes;
387 req = tevent_req_create(mem_ctx, &state,
388 struct cli_session_setup_guest_state);
389 if (req == NULL) {
390 return NULL;
392 state->cli = cli;
393 vwv = state->vwv;
395 SCVAL(vwv+0, 0, 0xFF);
396 SCVAL(vwv+0, 1, 0);
397 SSVAL(vwv+1, 0, 0);
398 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
399 SSVAL(vwv+3, 0, 2);
400 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
401 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
402 SSVAL(vwv+7, 0, 0);
403 SSVAL(vwv+8, 0, 0);
404 SSVAL(vwv+9, 0, 0);
405 SSVAL(vwv+10, 0, 0);
406 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
408 bytes = talloc_array(state, uint8_t, 0);
410 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* username */
411 NULL);
412 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, /* workgroup */
413 NULL);
414 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
415 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
417 if (bytes == NULL) {
418 TALLOC_FREE(req);
419 return NULL;
422 state->bytes.iov_base = (void *)bytes;
423 state->bytes.iov_len = talloc_get_size(bytes);
425 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
426 1, &state->bytes);
427 if (subreq == NULL) {
428 TALLOC_FREE(req);
429 return NULL;
431 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
432 *psmbreq = subreq;
433 return req;
436 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
437 struct tevent_context *ev,
438 struct cli_state *cli)
440 struct tevent_req *req, *subreq;
441 NTSTATUS status;
443 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
444 if (req == NULL) {
445 return NULL;
448 status = smb1cli_req_chain_submit(&subreq, 1);
449 if (NT_STATUS_IS_OK(status)) {
450 tevent_req_nterror(req, status);
451 return tevent_req_post(req, ev);
453 return req;
456 static void cli_session_setup_guest_done(struct tevent_req *subreq)
458 struct tevent_req *req = tevent_req_callback_data(
459 subreq, struct tevent_req);
460 struct cli_session_setup_guest_state *state = tevent_req_data(
461 req, struct cli_session_setup_guest_state);
462 struct cli_state *cli = state->cli;
463 uint32_t num_bytes;
464 uint8_t *in;
465 uint8_t *inhdr;
466 uint8_t *bytes;
467 uint8_t *p;
468 NTSTATUS status;
469 ssize_t ret;
470 uint8_t wct;
471 uint16_t *vwv;
473 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
474 &num_bytes, &bytes);
475 TALLOC_FREE(subreq);
476 if (!NT_STATUS_IS_OK(status)) {
477 tevent_req_nterror(req, status);
478 return;
481 inhdr = in + NBT_HDR_SIZE;
482 p = bytes;
484 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
485 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
487 status = smb_bytes_talloc_string(cli,
488 inhdr,
489 &cli->server_os,
491 bytes+num_bytes-p,
492 &ret);
494 if (!NT_STATUS_IS_OK(status)) {
495 tevent_req_nterror(req, status);
496 return;
498 p += ret;
500 status = smb_bytes_talloc_string(cli,
501 inhdr,
502 &cli->server_type,
504 bytes+num_bytes-p,
505 &ret);
507 if (!NT_STATUS_IS_OK(status)) {
508 tevent_req_nterror(req, status);
509 return;
511 p += ret;
513 status = smb_bytes_talloc_string(cli,
514 inhdr,
515 &cli->server_domain,
517 bytes+num_bytes-p,
518 &ret);
520 if (!NT_STATUS_IS_OK(status)) {
521 tevent_req_nterror(req, status);
522 return;
524 p += ret;
526 status = cli_set_username(cli, "");
527 if (!NT_STATUS_IS_OK(status)) {
528 tevent_req_nterror(req, status);
529 return;
531 tevent_req_done(req);
534 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
536 return tevent_req_simple_recv_ntstatus(req);
539 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
541 TALLOC_CTX *frame = talloc_stackframe();
542 struct tevent_context *ev;
543 struct tevent_req *req;
544 NTSTATUS status = NT_STATUS_OK;
546 if (smbXcli_conn_has_async_calls(cli->conn)) {
548 * Can't use sync call while an async call is in flight
550 status = NT_STATUS_INVALID_PARAMETER;
551 goto fail;
554 ev = samba_tevent_context_init(frame);
555 if (ev == NULL) {
556 status = NT_STATUS_NO_MEMORY;
557 goto fail;
560 req = cli_session_setup_guest_send(frame, ev, cli);
561 if (req == NULL) {
562 status = NT_STATUS_NO_MEMORY;
563 goto fail;
566 if (!tevent_req_poll(req, ev)) {
567 status = map_nt_error_from_unix(errno);
568 goto fail;
571 status = cli_session_setup_guest_recv(req);
572 fail:
573 TALLOC_FREE(frame);
574 return status;
577 /****************************************************************************
578 Do a NT1 plaintext session setup.
579 ****************************************************************************/
581 struct cli_session_setup_plain_state {
582 struct cli_state *cli;
583 uint16_t vwv[13];
584 const char *user;
587 static void cli_session_setup_plain_done(struct tevent_req *subreq);
589 static struct tevent_req *cli_session_setup_plain_send(
590 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
591 struct cli_state *cli,
592 const char *user, const char *pass, const char *workgroup)
594 struct tevent_req *req, *subreq;
595 struct cli_session_setup_plain_state *state;
596 uint16_t *vwv;
597 uint8_t *bytes;
598 size_t passlen;
599 char *version;
601 req = tevent_req_create(mem_ctx, &state,
602 struct cli_session_setup_plain_state);
603 if (req == NULL) {
604 return NULL;
606 state->cli = cli;
607 state->user = user;
608 vwv = state->vwv;
610 SCVAL(vwv+0, 0, 0xff);
611 SCVAL(vwv+0, 1, 0);
612 SSVAL(vwv+1, 0, 0);
613 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
614 SSVAL(vwv+3, 0, 2);
615 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
616 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
617 SSVAL(vwv+7, 0, 0);
618 SSVAL(vwv+8, 0, 0);
619 SSVAL(vwv+9, 0, 0);
620 SSVAL(vwv+10, 0, 0);
621 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
623 bytes = talloc_array(state, uint8_t, 0);
624 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), pass, strlen(pass)+1,
625 &passlen);
626 if (tevent_req_nomem(bytes, req)) {
627 return tevent_req_post(req, ev);
629 SSVAL(vwv + (smbXcli_conn_use_unicode(cli->conn) ? 8 : 7), 0, passlen);
631 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
632 user, strlen(user)+1, NULL);
633 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
634 workgroup, strlen(workgroup)+1, NULL);
635 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
636 "Unix", 5, NULL);
638 version = talloc_asprintf(talloc_tos(), "Samba %s",
639 samba_version_string());
640 if (tevent_req_nomem(version, req)){
641 return tevent_req_post(req, ev);
643 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
644 version, strlen(version)+1, NULL);
645 TALLOC_FREE(version);
647 if (tevent_req_nomem(bytes, req)) {
648 return tevent_req_post(req, ev);
651 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
652 talloc_get_size(bytes), bytes);
653 if (tevent_req_nomem(subreq, req)) {
654 return tevent_req_post(req, ev);
656 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
657 return req;
660 static void cli_session_setup_plain_done(struct tevent_req *subreq)
662 struct tevent_req *req = tevent_req_callback_data(
663 subreq, struct tevent_req);
664 struct cli_session_setup_plain_state *state = tevent_req_data(
665 req, struct cli_session_setup_plain_state);
666 struct cli_state *cli = state->cli;
667 uint32_t num_bytes;
668 uint8_t *in;
669 uint8_t *inhdr;
670 uint8_t *bytes;
671 uint8_t *p;
672 NTSTATUS status;
673 ssize_t ret;
674 uint8_t wct;
675 uint16_t *vwv;
677 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
678 &num_bytes, &bytes);
679 TALLOC_FREE(subreq);
680 if (tevent_req_nterror(req, status)) {
681 return;
684 inhdr = in + NBT_HDR_SIZE;
685 p = bytes;
687 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
688 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
690 status = smb_bytes_talloc_string(cli,
691 inhdr,
692 &cli->server_os,
694 bytes+num_bytes-p,
695 &ret);
697 if (!NT_STATUS_IS_OK(status)) {
698 tevent_req_nterror(req, status);
699 return;
701 p += ret;
703 status = smb_bytes_talloc_string(cli,
704 inhdr,
705 &cli->server_type,
707 bytes+num_bytes-p,
708 &ret);
710 if (!NT_STATUS_IS_OK(status)) {
711 tevent_req_nterror(req, status);
712 return;
714 p += ret;
716 status = smb_bytes_talloc_string(cli,
717 inhdr,
718 &cli->server_domain,
720 bytes+num_bytes-p,
721 &ret);
723 if (!NT_STATUS_IS_OK(status)) {
724 tevent_req_nterror(req, status);
725 return;
727 p += ret;
729 status = cli_set_username(cli, state->user);
730 if (tevent_req_nterror(req, status)) {
731 return;
734 tevent_req_done(req);
737 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
739 return tevent_req_simple_recv_ntstatus(req);
742 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
743 const char *user, const char *pass,
744 const char *workgroup)
746 TALLOC_CTX *frame = talloc_stackframe();
747 struct tevent_context *ev;
748 struct tevent_req *req;
749 NTSTATUS status = NT_STATUS_NO_MEMORY;
751 if (smbXcli_conn_has_async_calls(cli->conn)) {
753 * Can't use sync call while an async call is in flight
755 status = NT_STATUS_INVALID_PARAMETER;
756 goto fail;
758 ev = samba_tevent_context_init(frame);
759 if (ev == NULL) {
760 goto fail;
762 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
763 workgroup);
764 if (req == NULL) {
765 goto fail;
767 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
768 goto fail;
770 status = cli_session_setup_plain_recv(req);
771 fail:
772 TALLOC_FREE(frame);
773 return status;
776 /****************************************************************************
777 do a NT1 NTLM/LM encrypted session setup - for when extended security
778 is not negotiated.
779 @param cli client state to create do session setup on
780 @param user username
781 @param pass *either* cleartext password (passlen !=24) or LM response.
782 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
783 @param workgroup The user's domain.
784 ****************************************************************************/
786 struct cli_session_setup_nt1_state {
787 struct cli_state *cli;
788 uint16_t vwv[13];
789 DATA_BLOB response;
790 DATA_BLOB session_key;
791 const char *user;
794 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
796 static struct tevent_req *cli_session_setup_nt1_send(
797 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
798 struct cli_state *cli, const char *user,
799 const char *pass, size_t passlen,
800 const char *ntpass, size_t ntpasslen,
801 const char *workgroup)
803 struct tevent_req *req, *subreq;
804 struct cli_session_setup_nt1_state *state;
805 DATA_BLOB lm_response = data_blob_null;
806 DATA_BLOB nt_response = data_blob_null;
807 DATA_BLOB session_key = data_blob_null;
808 uint16_t *vwv;
809 uint8_t *bytes;
810 char *workgroup_upper;
812 req = tevent_req_create(mem_ctx, &state,
813 struct cli_session_setup_nt1_state);
814 if (req == NULL) {
815 return NULL;
817 state->cli = cli;
818 state->user = user;
819 vwv = state->vwv;
821 if (passlen == 0) {
822 /* do nothing - guest login */
823 } else if (passlen != 24) {
824 if (lp_client_ntlmv2_auth()) {
825 DATA_BLOB server_chal;
826 DATA_BLOB names_blob;
828 server_chal =
829 data_blob_const(smb1cli_conn_server_challenge(cli->conn),
833 * note that the 'workgroup' here is a best
834 * guess - we don't know the server's domain
835 * at this point. Windows clients also don't
836 * use hostname...
838 names_blob = NTLMv2_generate_names_blob(
839 NULL, NULL, workgroup);
841 if (tevent_req_nomem(names_blob.data, req)) {
842 return tevent_req_post(req, ev);
845 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
846 &server_chal, &names_blob,
847 &lm_response, &nt_response,
848 NULL, &session_key)) {
849 data_blob_free(&names_blob);
850 tevent_req_nterror(
851 req, NT_STATUS_ACCESS_DENIED);
852 return tevent_req_post(req, ev);
854 data_blob_free(&names_blob);
856 } else {
857 uchar nt_hash[16];
858 E_md4hash(pass, nt_hash);
860 #ifdef LANMAN_ONLY
861 nt_response = data_blob_null;
862 #else
863 nt_response = data_blob(NULL, 24);
864 if (tevent_req_nomem(nt_response.data, req)) {
865 return tevent_req_post(req, ev);
868 SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
869 nt_response.data);
870 #endif
871 /* non encrypted password supplied. Ignore ntpass. */
872 if (lp_client_lanman_auth()) {
874 lm_response = data_blob(NULL, 24);
875 if (tevent_req_nomem(lm_response.data, req)) {
876 return tevent_req_post(req, ev);
879 if (!SMBencrypt(pass,
880 smb1cli_conn_server_challenge(cli->conn),
881 lm_response.data)) {
883 * Oops, the LM response is
884 * invalid, just put the NT
885 * response there instead
887 data_blob_free(&lm_response);
888 lm_response = data_blob(
889 nt_response.data,
890 nt_response.length);
892 } else {
894 * LM disabled, place NT# in LM field
895 * instead
897 lm_response = data_blob(
898 nt_response.data, nt_response.length);
901 if (tevent_req_nomem(lm_response.data, req)) {
902 return tevent_req_post(req, ev);
905 session_key = data_blob(NULL, 16);
906 if (tevent_req_nomem(session_key.data, req)) {
907 return tevent_req_post(req, ev);
909 #ifdef LANMAN_ONLY
910 E_deshash(pass, session_key.data);
911 memset(&session_key.data[8], '\0', 8);
912 #else
913 SMBsesskeygen_ntv1(nt_hash, session_key.data);
914 #endif
916 } else {
917 /* pre-encrypted password supplied. Only used for
918 security=server, can't do
919 signing because we don't have original key */
921 lm_response = data_blob(pass, passlen);
922 if (tevent_req_nomem(lm_response.data, req)) {
923 return tevent_req_post(req, ev);
926 nt_response = data_blob(ntpass, ntpasslen);
927 if (tevent_req_nomem(nt_response.data, req)) {
928 return tevent_req_post(req, ev);
932 #ifdef LANMAN_ONLY
933 state->response = data_blob_talloc(
934 state, lm_response.data, lm_response.length);
935 #else
936 state->response = data_blob_talloc(
937 state, nt_response.data, nt_response.length);
938 #endif
939 if (tevent_req_nomem(state->response.data, req)) {
940 return tevent_req_post(req, ev);
943 if (session_key.data) {
944 state->session_key = data_blob_talloc(
945 state, session_key.data, session_key.length);
946 if (tevent_req_nomem(state->session_key.data, req)) {
947 return tevent_req_post(req, ev);
950 data_blob_free(&session_key);
952 SCVAL(vwv+0, 0, 0xff);
953 SCVAL(vwv+0, 1, 0);
954 SSVAL(vwv+1, 0, 0);
955 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
956 SSVAL(vwv+3, 0, 2);
957 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
958 SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
959 SSVAL(vwv+7, 0, lm_response.length);
960 SSVAL(vwv+8, 0, nt_response.length);
961 SSVAL(vwv+9, 0, 0);
962 SSVAL(vwv+10, 0, 0);
963 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
965 bytes = talloc_array(state, uint8_t,
966 lm_response.length + nt_response.length);
967 if (tevent_req_nomem(bytes, req)) {
968 return tevent_req_post(req, ev);
970 if (lm_response.length != 0) {
971 memcpy(bytes, lm_response.data, lm_response.length);
973 if (nt_response.length != 0) {
974 memcpy(bytes + lm_response.length,
975 nt_response.data, nt_response.length);
977 data_blob_free(&lm_response);
978 data_blob_free(&nt_response);
980 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
981 user, strlen(user)+1, NULL);
984 * Upper case here might help some NTLMv2 implementations
986 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
987 if (tevent_req_nomem(workgroup_upper, req)) {
988 return tevent_req_post(req, ev);
990 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
991 workgroup_upper, strlen(workgroup_upper)+1,
992 NULL);
993 TALLOC_FREE(workgroup_upper);
995 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Unix", 5, NULL);
996 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "Samba", 6, NULL);
997 if (tevent_req_nomem(bytes, req)) {
998 return tevent_req_post(req, ev);
1001 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1002 talloc_get_size(bytes), bytes);
1003 if (tevent_req_nomem(subreq, req)) {
1004 return tevent_req_post(req, ev);
1006 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1007 return req;
1010 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1012 struct tevent_req *req = tevent_req_callback_data(
1013 subreq, struct tevent_req);
1014 struct cli_session_setup_nt1_state *state = tevent_req_data(
1015 req, struct cli_session_setup_nt1_state);
1016 struct cli_state *cli = state->cli;
1017 uint32_t num_bytes;
1018 uint8_t *in;
1019 uint8_t *inhdr;
1020 uint8_t *bytes;
1021 uint8_t *p;
1022 NTSTATUS status;
1023 ssize_t ret;
1024 uint8_t wct;
1025 uint16_t *vwv;
1027 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
1028 &num_bytes, &bytes);
1029 TALLOC_FREE(subreq);
1030 if (!NT_STATUS_IS_OK(status)) {
1031 tevent_req_nterror(req, status);
1032 return;
1035 inhdr = in + NBT_HDR_SIZE;
1036 p = bytes;
1038 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1039 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1041 status = smb_bytes_talloc_string(cli,
1042 inhdr,
1043 &cli->server_os,
1045 bytes+num_bytes-p,
1046 &ret);
1047 if (!NT_STATUS_IS_OK(status)) {
1048 tevent_req_nterror(req, status);
1049 return;
1051 p += ret;
1053 status = smb_bytes_talloc_string(cli,
1054 inhdr,
1055 &cli->server_type,
1057 bytes+num_bytes-p,
1058 &ret);
1059 if (!NT_STATUS_IS_OK(status)) {
1060 tevent_req_nterror(req, status);
1061 return;
1063 p += ret;
1065 status = smb_bytes_talloc_string(cli,
1066 inhdr,
1067 &cli->server_domain,
1069 bytes+num_bytes-p,
1070 &ret);
1071 if (!NT_STATUS_IS_OK(status)) {
1072 tevent_req_nterror(req, status);
1073 return;
1075 p += ret;
1077 status = cli_set_username(cli, state->user);
1078 if (tevent_req_nterror(req, status)) {
1079 return;
1081 if (smb1cli_conn_activate_signing(cli->conn, state->session_key, state->response)
1082 && !smb1cli_conn_check_signing(cli->conn, (uint8_t *)in, 1)) {
1083 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1084 return;
1086 if (state->session_key.data) {
1087 struct smbXcli_session *session = state->cli->smb1.session;
1089 status = smb1cli_session_set_session_key(session,
1090 state->session_key);
1091 if (tevent_req_nterror(req, status)) {
1092 return;
1095 tevent_req_done(req);
1098 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1100 return tevent_req_simple_recv_ntstatus(req);
1103 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1104 const char *pass, size_t passlen,
1105 const char *ntpass, size_t ntpasslen,
1106 const char *workgroup)
1108 TALLOC_CTX *frame = talloc_stackframe();
1109 struct tevent_context *ev;
1110 struct tevent_req *req;
1111 NTSTATUS status = NT_STATUS_NO_MEMORY;
1113 if (smbXcli_conn_has_async_calls(cli->conn)) {
1115 * Can't use sync call while an async call is in flight
1117 status = NT_STATUS_INVALID_PARAMETER;
1118 goto fail;
1120 ev = samba_tevent_context_init(frame);
1121 if (ev == NULL) {
1122 goto fail;
1124 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1125 ntpass, ntpasslen, workgroup);
1126 if (req == NULL) {
1127 goto fail;
1129 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1130 goto fail;
1132 status = cli_session_setup_nt1_recv(req);
1133 fail:
1134 TALLOC_FREE(frame);
1135 return status;
1138 /* The following is calculated from :
1139 * (smb_size-4) = 35
1140 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1141 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1142 * end of packet.
1145 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1147 struct cli_sesssetup_blob_state {
1148 struct tevent_context *ev;
1149 struct cli_state *cli;
1150 DATA_BLOB blob;
1151 uint16_t max_blob_size;
1152 uint16_t vwv[12];
1153 uint8_t *buf;
1155 DATA_BLOB smb2_blob;
1156 struct iovec *recv_iov;
1158 NTSTATUS status;
1159 uint8_t *inbuf;
1160 DATA_BLOB ret_blob;
1163 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1164 struct tevent_req **psubreq);
1165 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1167 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1168 struct tevent_context *ev,
1169 struct cli_state *cli,
1170 DATA_BLOB blob)
1172 struct tevent_req *req, *subreq;
1173 struct cli_sesssetup_blob_state *state;
1174 uint32_t usable_space;
1176 req = tevent_req_create(mem_ctx, &state,
1177 struct cli_sesssetup_blob_state);
1178 if (req == NULL) {
1179 return NULL;
1181 state->ev = ev;
1182 state->blob = blob;
1183 state->cli = cli;
1185 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1186 usable_space = UINT16_MAX;
1187 } else {
1188 usable_space = cli_state_available_size(cli,
1189 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1192 if (usable_space == 0) {
1193 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1194 "(not possible to send %u bytes)\n",
1195 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1196 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1197 return tevent_req_post(req, ev);
1199 state->max_blob_size = MIN(usable_space, 0xFFFF);
1201 if (!cli_sesssetup_blob_next(state, &subreq)) {
1202 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1203 return tevent_req_post(req, ev);
1205 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1206 return req;
1209 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1210 struct tevent_req **psubreq)
1212 struct tevent_req *subreq;
1213 uint16_t thistime;
1215 thistime = MIN(state->blob.length, state->max_blob_size);
1217 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1219 state->smb2_blob.data = state->blob.data;
1220 state->smb2_blob.length = thistime;
1222 state->blob.data += thistime;
1223 state->blob.length -= thistime;
1225 subreq = smb2cli_session_setup_send(state, state->ev,
1226 state->cli->conn,
1227 state->cli->timeout,
1228 state->cli->smb2.session,
1229 0, /* in_flags */
1230 SMB2_CAP_DFS, /* in_capabilities */
1231 0, /* in_channel */
1232 0, /* in_previous_session_id */
1233 &state->smb2_blob);
1234 if (subreq == NULL) {
1235 return false;
1237 *psubreq = subreq;
1238 return true;
1241 SCVAL(state->vwv+0, 0, 0xFF);
1242 SCVAL(state->vwv+0, 1, 0);
1243 SSVAL(state->vwv+1, 0, 0);
1244 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1245 SSVAL(state->vwv+3, 0, 2);
1246 SSVAL(state->vwv+4, 0, 1);
1247 SIVAL(state->vwv+5, 0, 0);
1249 SSVAL(state->vwv+7, 0, thistime);
1251 SSVAL(state->vwv+8, 0, 0);
1252 SSVAL(state->vwv+9, 0, 0);
1253 SIVAL(state->vwv+10, 0,
1254 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1256 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1257 thistime);
1258 if (state->buf == NULL) {
1259 return false;
1261 state->blob.data += thistime;
1262 state->blob.length -= thistime;
1264 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1265 "Unix", 5, NULL);
1266 state->buf = smb_bytes_push_str(state->buf, smbXcli_conn_use_unicode(state->cli->conn),
1267 "Samba", 6, NULL);
1268 if (state->buf == NULL) {
1269 return false;
1271 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1272 12, state->vwv,
1273 talloc_get_size(state->buf), state->buf);
1274 if (subreq == NULL) {
1275 return false;
1277 *psubreq = subreq;
1278 return true;
1281 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1283 struct tevent_req *req = tevent_req_callback_data(
1284 subreq, struct tevent_req);
1285 struct cli_sesssetup_blob_state *state = tevent_req_data(
1286 req, struct cli_sesssetup_blob_state);
1287 struct cli_state *cli = state->cli;
1288 uint8_t wct;
1289 uint16_t *vwv;
1290 uint32_t num_bytes;
1291 uint8_t *bytes;
1292 NTSTATUS status;
1293 uint8_t *p;
1294 uint16_t blob_length;
1295 uint8_t *in;
1296 uint8_t *inhdr;
1297 ssize_t ret;
1299 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1300 status = smb2cli_session_setup_recv(subreq, state,
1301 &state->recv_iov,
1302 &state->ret_blob);
1303 } else {
1304 status = cli_smb_recv(subreq, state, &in, 4, &wct, &vwv,
1305 &num_bytes, &bytes);
1306 TALLOC_FREE(state->buf);
1308 TALLOC_FREE(subreq);
1309 if (!NT_STATUS_IS_OK(status)
1310 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1311 tevent_req_nterror(req, status);
1312 return;
1315 state->status = status;
1317 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1318 goto next;
1321 state->inbuf = in;
1322 inhdr = in + NBT_HDR_SIZE;
1323 cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID));
1324 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1326 blob_length = SVAL(vwv+3, 0);
1327 if (blob_length > num_bytes) {
1328 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1329 return;
1331 state->ret_blob = data_blob_const(bytes, blob_length);
1333 p = bytes + blob_length;
1335 status = smb_bytes_talloc_string(cli,
1336 inhdr,
1337 &cli->server_os,
1339 bytes+num_bytes-p,
1340 &ret);
1342 if (!NT_STATUS_IS_OK(status)) {
1343 tevent_req_nterror(req, status);
1344 return;
1346 p += ret;
1348 status = smb_bytes_talloc_string(cli,
1349 inhdr,
1350 &cli->server_type,
1352 bytes+num_bytes-p,
1353 &ret);
1355 if (!NT_STATUS_IS_OK(status)) {
1356 tevent_req_nterror(req, status);
1357 return;
1359 p += ret;
1361 status = smb_bytes_talloc_string(cli,
1362 inhdr,
1363 &cli->server_domain,
1365 bytes+num_bytes-p,
1366 &ret);
1368 if (!NT_STATUS_IS_OK(status)) {
1369 tevent_req_nterror(req, status);
1370 return;
1372 p += ret;
1374 next:
1375 if (state->blob.length != 0) {
1377 * More to send
1379 if (!cli_sesssetup_blob_next(state, &subreq)) {
1380 tevent_req_oom(req);
1381 return;
1383 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1384 return;
1386 tevent_req_done(req);
1389 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1390 TALLOC_CTX *mem_ctx,
1391 DATA_BLOB *pblob,
1392 uint8_t **pinbuf,
1393 struct iovec **precv_iov)
1395 struct cli_sesssetup_blob_state *state = tevent_req_data(
1396 req, struct cli_sesssetup_blob_state);
1397 NTSTATUS status;
1398 uint8_t *inbuf;
1399 struct iovec *recv_iov;
1401 if (tevent_req_is_nterror(req, &status)) {
1402 TALLOC_FREE(state->cli->smb2.session);
1403 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1404 return status;
1407 inbuf = talloc_move(mem_ctx, &state->inbuf);
1408 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
1409 if (pblob != NULL) {
1410 *pblob = state->ret_blob;
1412 if (pinbuf != NULL) {
1413 *pinbuf = inbuf;
1415 if (precv_iov != NULL) {
1416 *precv_iov = recv_iov;
1418 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1419 return state->status;
1422 #ifdef HAVE_KRB5
1424 /****************************************************************************
1425 Use in-memory credentials cache
1426 ****************************************************************************/
1428 static void use_in_memory_ccache(void) {
1429 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1432 /****************************************************************************
1433 Do a spnego/kerberos encrypted session setup.
1434 ****************************************************************************/
1436 struct cli_session_setup_kerberos_state {
1437 struct cli_state *cli;
1438 DATA_BLOB negTokenTarg;
1439 DATA_BLOB session_key_krb5;
1440 ADS_STATUS ads_status;
1443 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1445 static struct tevent_req *cli_session_setup_kerberos_send(
1446 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1447 const char *principal)
1449 struct tevent_req *req, *subreq;
1450 struct cli_session_setup_kerberos_state *state;
1451 int rc;
1453 DEBUG(2,("Doing kerberos session setup\n"));
1455 req = tevent_req_create(mem_ctx, &state,
1456 struct cli_session_setup_kerberos_state);
1457 if (req == NULL) {
1458 return NULL;
1460 state->cli = cli;
1461 state->ads_status = ADS_SUCCESS;
1464 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1465 * we have to acquire a ticket. To be fixed later :-)
1467 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1468 &state->session_key_krb5, 0, NULL, NULL);
1469 if (rc) {
1470 DEBUG(1, ("cli_session_setup_kerberos: "
1471 "spnego_gen_krb5_negTokenInit failed: %s\n",
1472 error_message(rc)));
1473 state->ads_status = ADS_ERROR_KRB5(rc);
1474 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1475 return tevent_req_post(req, ev);
1478 #if 0
1479 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1480 state->negTokenTarg.length);
1481 #endif
1483 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1484 state->cli->smb2.session = smbXcli_session_create(cli,
1485 cli->conn);
1486 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1487 return tevent_req_post(req, ev);
1491 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1492 if (tevent_req_nomem(subreq, req)) {
1493 return tevent_req_post(req, ev);
1495 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1496 return req;
1499 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1501 struct tevent_req *req = tevent_req_callback_data(
1502 subreq, struct tevent_req);
1503 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1504 req, struct cli_session_setup_kerberos_state);
1505 uint8_t *inbuf = NULL;
1506 struct iovec *recv_iov = NULL;
1507 NTSTATUS status;
1509 status = cli_sesssetup_blob_recv(subreq, state,
1510 NULL, &inbuf, &recv_iov);
1511 TALLOC_FREE(subreq);
1512 if (!NT_STATUS_IS_OK(status)) {
1513 tevent_req_nterror(req, status);
1514 return;
1517 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1518 struct smbXcli_session *session = state->cli->smb2.session;
1519 status = smb2cli_session_set_session_key(session,
1520 state->session_key_krb5,
1521 recv_iov);
1522 if (tevent_req_nterror(req, status)) {
1523 return;
1525 } else {
1526 struct smbXcli_session *session = state->cli->smb1.session;
1528 status = smb1cli_session_set_session_key(session,
1529 state->session_key_krb5);
1530 if (tevent_req_nterror(req, status)) {
1531 return;
1534 if (smb1cli_conn_activate_signing(state->cli->conn, state->session_key_krb5,
1535 data_blob_null)
1536 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1537 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1538 return;
1542 tevent_req_done(req);
1545 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1547 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1548 req, struct cli_session_setup_kerberos_state);
1549 NTSTATUS status;
1551 if (tevent_req_is_nterror(req, &status)) {
1552 return ADS_ERROR_NT(status);
1554 return state->ads_status;
1557 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1558 const char *principal)
1560 struct tevent_context *ev;
1561 struct tevent_req *req;
1562 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1564 if (smbXcli_conn_has_async_calls(cli->conn)) {
1565 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1567 ev = samba_tevent_context_init(talloc_tos());
1568 if (ev == NULL) {
1569 goto fail;
1571 req = cli_session_setup_kerberos_send(ev, ev, cli, principal);
1572 if (req == NULL) {
1573 goto fail;
1575 if (!tevent_req_poll(req, ev)) {
1576 status = ADS_ERROR_SYSTEM(errno);
1577 goto fail;
1579 status = cli_session_setup_kerberos_recv(req);
1580 fail:
1581 TALLOC_FREE(ev);
1582 return status;
1584 #endif /* HAVE_KRB5 */
1586 /****************************************************************************
1587 Do a spnego/NTLMSSP encrypted session setup.
1588 ****************************************************************************/
1590 struct cli_session_setup_ntlmssp_state {
1591 struct tevent_context *ev;
1592 struct cli_state *cli;
1593 struct ntlmssp_state *ntlmssp_state;
1594 int turn;
1595 DATA_BLOB blob_out;
1598 static int cli_session_setup_ntlmssp_state_destructor(
1599 struct cli_session_setup_ntlmssp_state *state)
1601 if (state->ntlmssp_state != NULL) {
1602 TALLOC_FREE(state->ntlmssp_state);
1604 return 0;
1607 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1609 static struct tevent_req *cli_session_setup_ntlmssp_send(
1610 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1611 const char *user, const char *pass, const char *domain)
1613 struct tevent_req *req, *subreq;
1614 struct cli_session_setup_ntlmssp_state *state;
1615 NTSTATUS status;
1616 DATA_BLOB blob_out;
1617 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1619 req = tevent_req_create(mem_ctx, &state,
1620 struct cli_session_setup_ntlmssp_state);
1621 if (req == NULL) {
1622 return NULL;
1624 state->ev = ev;
1625 state->cli = cli;
1626 state->turn = 1;
1628 state->ntlmssp_state = NULL;
1629 talloc_set_destructor(
1630 state, cli_session_setup_ntlmssp_state_destructor);
1632 status = ntlmssp_client_start(state,
1633 lp_netbios_name(),
1634 lp_workgroup(),
1635 lp_client_ntlmv2_auth(),
1636 &state->ntlmssp_state);
1637 if (!NT_STATUS_IS_OK(status)) {
1638 goto fail;
1640 ntlmssp_want_feature(state->ntlmssp_state,
1641 NTLMSSP_FEATURE_SESSION_KEY);
1642 if (cli->use_ccache) {
1643 ntlmssp_want_feature(state->ntlmssp_state,
1644 NTLMSSP_FEATURE_CCACHE);
1646 status = ntlmssp_set_username(state->ntlmssp_state, user);
1647 if (!NT_STATUS_IS_OK(status)) {
1648 goto fail;
1650 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1651 if (!NT_STATUS_IS_OK(status)) {
1652 goto fail;
1654 if (cli->pw_nt_hash) {
1655 status = ntlmssp_set_password_hash(state->ntlmssp_state, pass);
1656 } else {
1657 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1659 if (!NT_STATUS_IS_OK(status)) {
1660 goto fail;
1662 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1663 &blob_out);
1664 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1665 goto fail;
1668 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1669 data_blob_free(&blob_out);
1671 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1672 state->cli->smb2.session = smbXcli_session_create(cli,
1673 cli->conn);
1674 if (tevent_req_nomem(state->cli->smb2.session, req)) {
1675 return tevent_req_post(req, ev);
1679 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1680 if (tevent_req_nomem(subreq, req)) {
1681 return tevent_req_post(req, ev);
1683 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1684 return req;
1685 fail:
1686 tevent_req_nterror(req, status);
1687 return tevent_req_post(req, ev);
1690 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1692 struct tevent_req *req = tevent_req_callback_data(
1693 subreq, struct tevent_req);
1694 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1695 req, struct cli_session_setup_ntlmssp_state);
1696 DATA_BLOB blob_in, msg_in, blob_out;
1697 uint8_t *inbuf = NULL;
1698 struct iovec *recv_iov = NULL;
1699 bool parse_ret;
1700 NTSTATUS status;
1702 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1703 &inbuf, &recv_iov);
1704 TALLOC_FREE(subreq);
1705 data_blob_free(&state->blob_out);
1707 if (NT_STATUS_IS_OK(status)) {
1708 if (state->cli->server_domain[0] == '\0') {
1709 TALLOC_FREE(state->cli->server_domain);
1710 state->cli->server_domain = talloc_strdup(state->cli,
1711 state->ntlmssp_state->server.netbios_domain);
1712 if (state->cli->server_domain == NULL) {
1713 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1714 return;
1718 if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
1719 struct smbXcli_session *session = state->cli->smb2.session;
1721 if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
1723 * Windows server does not set the
1724 * SMB2_SESSION_FLAG_IS_GUEST nor
1725 * SMB2_SESSION_FLAG_IS_NULL flag.
1727 * This fix makes sure we do not try
1728 * to verify a signature on the final
1729 * session setup response.
1731 TALLOC_FREE(state->ntlmssp_state);
1732 tevent_req_done(req);
1733 return;
1736 status = smb2cli_session_set_session_key(session,
1737 state->ntlmssp_state->session_key,
1738 recv_iov);
1739 if (tevent_req_nterror(req, status)) {
1740 return;
1742 } else {
1743 struct smbXcli_session *session = state->cli->smb1.session;
1745 status = smb1cli_session_set_session_key(session,
1746 state->ntlmssp_state->session_key);
1747 if (tevent_req_nterror(req, status)) {
1748 return;
1751 if (smb1cli_conn_activate_signing(
1752 state->cli->conn, state->ntlmssp_state->session_key,
1753 data_blob_null)
1754 && !smb1cli_conn_check_signing(state->cli->conn, inbuf, 1)) {
1755 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1756 return;
1759 TALLOC_FREE(state->ntlmssp_state);
1760 tevent_req_done(req);
1761 return;
1763 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1764 tevent_req_nterror(req, status);
1765 return;
1768 if (blob_in.length == 0) {
1769 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1770 return;
1773 if ((state->turn == 1)
1774 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1775 DATA_BLOB tmp_blob = data_blob_null;
1776 /* the server might give us back two challenges */
1777 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1778 &tmp_blob);
1779 data_blob_free(&tmp_blob);
1780 } else {
1781 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1782 OID_NTLMSSP, &msg_in);
1784 state->turn += 1;
1786 if (!parse_ret) {
1787 DEBUG(3,("Failed to parse auth response\n"));
1788 if (NT_STATUS_IS_OK(status)
1789 || NT_STATUS_EQUAL(status,
1790 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1791 tevent_req_nterror(
1792 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1793 return;
1797 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1799 if (!NT_STATUS_IS_OK(status)
1800 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1801 TALLOC_FREE(state->ntlmssp_state);
1802 tevent_req_nterror(req, status);
1803 return;
1806 state->blob_out = spnego_gen_auth(state, blob_out);
1807 if (tevent_req_nomem(state->blob_out.data, req)) {
1808 return;
1811 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1812 state->blob_out);
1813 if (tevent_req_nomem(subreq, req)) {
1814 return;
1816 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1819 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1821 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1822 req, struct cli_session_setup_ntlmssp_state);
1823 NTSTATUS status;
1825 if (tevent_req_is_nterror(req, &status)) {
1826 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1827 return status;
1829 return NT_STATUS_OK;
1832 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1833 const char *user,
1834 const char *pass,
1835 const char *domain)
1837 struct tevent_context *ev;
1838 struct tevent_req *req;
1839 NTSTATUS status = NT_STATUS_NO_MEMORY;
1841 if (smbXcli_conn_has_async_calls(cli->conn)) {
1842 return NT_STATUS_INVALID_PARAMETER;
1844 ev = samba_tevent_context_init(talloc_tos());
1845 if (ev == NULL) {
1846 goto fail;
1848 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1849 if (req == NULL) {
1850 goto fail;
1852 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1853 goto fail;
1855 status = cli_session_setup_ntlmssp_recv(req);
1856 fail:
1857 TALLOC_FREE(ev);
1858 return status;
1861 /****************************************************************************
1862 Do a spnego encrypted session setup.
1864 user_domain: The shortname of the domain the user/machine is a member of.
1865 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1866 ****************************************************************************/
1868 static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
1869 const char *user,
1870 const char *pass,
1871 const char *user_domain,
1872 const char * dest_realm)
1874 char *principal = NULL;
1875 char *OIDs[ASN1_MAX_OIDS];
1876 int i;
1877 const DATA_BLOB *server_blob;
1878 DATA_BLOB blob = data_blob_null;
1879 const char *p = NULL;
1880 char *account = NULL;
1881 NTSTATUS status;
1883 server_blob = smbXcli_conn_server_gss_blob(cli->conn);
1884 if (server_blob) {
1885 blob = data_blob(server_blob->data, server_blob->length);
1888 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)blob.length));
1890 /* the server might not even do spnego */
1891 if (blob.length == 0) {
1892 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1893 goto ntlmssp;
1896 #if 0
1897 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1898 #endif
1900 /* The server sent us the first part of the SPNEGO exchange in the
1901 * negprot reply. It is WRONG to depend on the principal sent in the
1902 * negprot reply, but right now we do it. If we don't receive one,
1903 * we try to best guess, then fall back to NTLM. */
1904 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1905 OIDs[0] == NULL) {
1906 data_blob_free(&blob);
1907 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1909 data_blob_free(&blob);
1911 /* make sure the server understands kerberos */
1912 for (i=0;OIDs[i];i++) {
1913 if (i == 0)
1914 DEBUG(3,("got OID=%s\n", OIDs[i]));
1915 else
1916 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1917 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1918 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1919 cli->got_kerberos_mechanism = True;
1921 talloc_free(OIDs[i]);
1924 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1926 status = cli_set_username(cli, user);
1927 if (!NT_STATUS_IS_OK(status)) {
1928 TALLOC_FREE(principal);
1929 return ADS_ERROR_NT(status);
1932 #ifdef HAVE_KRB5
1933 /* If password is set we reauthenticate to kerberos server
1934 * and do not store results */
1936 if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
1937 ADS_STATUS rc;
1938 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
1940 if (pass && *pass) {
1941 int ret;
1943 use_in_memory_ccache();
1944 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1946 if (ret){
1947 TALLOC_FREE(principal);
1948 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1949 if (cli->fallback_after_kerberos)
1950 goto ntlmssp;
1951 return ADS_ERROR_KRB5(ret);
1955 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1957 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1958 TALLOC_FREE(principal);
1961 if (principal == NULL &&
1962 !is_ipaddress(remote_name) &&
1963 !strequal(STAR_SMBSERVER,
1964 remote_name)) {
1965 DEBUG(3,("cli_session_setup_spnego: using target "
1966 "hostname not SPNEGO principal\n"));
1968 if (dest_realm) {
1969 char *realm = strupper_talloc(talloc_tos(), dest_realm);
1970 if (realm) {
1971 principal = talloc_asprintf(talloc_tos(),
1972 "cifs/%s@%s",
1973 remote_name,
1974 realm);
1975 TALLOC_FREE(realm);
1977 } else {
1978 principal = kerberos_get_principal_from_service_hostname(talloc_tos(),
1979 "cifs",
1980 remote_name,
1981 lp_realm());
1984 if (!principal) {
1985 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1987 DEBUG(3,("cli_session_setup_spnego: guessed "
1988 "server principal=%s\n",
1989 principal ? principal : "<null>"));
1992 if (principal) {
1993 rc = cli_session_setup_kerberos(cli, principal);
1994 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1995 TALLOC_FREE(principal);
1996 return rc;
2000 #endif
2002 TALLOC_FREE(principal);
2004 ntlmssp:
2006 account = talloc_strdup(talloc_tos(), user);
2007 if (!account) {
2008 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
2011 /* when falling back to ntlmssp while authenticating with a machine
2012 * account strip off the realm - gd */
2014 if ((p = strchr_m(user, '@')) != NULL) {
2015 account[PTR_DIFF(p,user)] = '\0';
2018 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
2021 /****************************************************************************
2022 Send a session setup. The username and workgroup is in UNIX character
2023 format and must be converted to DOS codepage format before sending. If the
2024 password is in plaintext, the same should be done.
2025 ****************************************************************************/
2027 NTSTATUS cli_session_setup(struct cli_state *cli,
2028 const char *user,
2029 const char *pass, int passlen,
2030 const char *ntpass, int ntpasslen,
2031 const char *workgroup)
2033 char *p;
2034 char *user2;
2035 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2037 if (user) {
2038 user2 = talloc_strdup(talloc_tos(), user);
2039 } else {
2040 user2 = talloc_strdup(talloc_tos(), "");
2042 if (user2 == NULL) {
2043 return NT_STATUS_NO_MEMORY;
2046 if (!workgroup) {
2047 workgroup = "";
2050 /* allow for workgroups as part of the username */
2051 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
2052 (p=strchr_m(user2,*lp_winbind_separator()))) {
2053 *p = 0;
2054 user = p+1;
2055 if (!strupper_m(user2)) {
2056 return NT_STATUS_INVALID_PARAMETER;
2058 workgroup = user2;
2061 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
2062 return NT_STATUS_OK;
2065 /* now work out what sort of session setup we are going to
2066 do. I have split this into separate functions to make the
2067 flow a bit easier to understand (tridge) */
2069 /* if its an older server then we have to use the older request format */
2071 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
2072 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2073 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2074 " or 'client ntlmv2 auth = yes'\n"));
2075 return NT_STATUS_ACCESS_DENIED;
2078 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2079 !lp_client_plaintext_auth() && (*pass)) {
2080 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2081 " or 'client ntlmv2 auth = yes'\n"));
2082 return NT_STATUS_ACCESS_DENIED;
2085 return cli_session_setup_lanman2(cli, user, pass, passlen,
2086 workgroup);
2089 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2090 const char *remote_realm = cli_state_remote_realm(cli);
2091 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2092 workgroup,
2093 remote_realm);
2094 if (!ADS_ERR_OK(status)) {
2095 DEBUG(3, ("SMB2-SPNEGO login failed: %s\n", ads_errstr(status)));
2096 return ads_ntstatus(status);
2098 return NT_STATUS_OK;
2101 /* if no user is supplied then we have to do an anonymous connection.
2102 passwords are ignored */
2104 if (!user || !*user)
2105 return cli_session_setup_guest(cli);
2107 /* if the server is share level then send a plaintext null
2108 password at this point. The password is sent in the tree
2109 connect */
2111 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2112 return cli_session_setup_plain(cli, user, "", workgroup);
2114 /* if the server doesn't support encryption then we have to use
2115 plaintext. The second password is ignored */
2117 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2118 if (!lp_client_plaintext_auth() && (*pass)) {
2119 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2120 " or 'client ntlmv2 auth = yes'\n"));
2121 return NT_STATUS_ACCESS_DENIED;
2123 return cli_session_setup_plain(cli, user, pass, workgroup);
2126 /* if the server supports extended security then use SPNEGO */
2128 if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
2129 const char *remote_realm = cli_state_remote_realm(cli);
2130 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2131 workgroup,
2132 remote_realm);
2133 if (!ADS_ERR_OK(status)) {
2134 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2135 return ads_ntstatus(status);
2137 } else {
2138 NTSTATUS status;
2140 /* otherwise do a NT1 style session setup */
2141 status = cli_session_setup_nt1(cli, user, pass, passlen,
2142 ntpass, ntpasslen, workgroup);
2143 if (!NT_STATUS_IS_OK(status)) {
2144 DEBUG(3,("cli_session_setup: NT1 session setup "
2145 "failed: %s\n", nt_errstr(status)));
2146 return status;
2150 return NT_STATUS_OK;
2153 /****************************************************************************
2154 Send a uloggoff.
2155 *****************************************************************************/
2157 struct cli_ulogoff_state {
2158 struct cli_state *cli;
2159 uint16_t vwv[3];
2162 static void cli_ulogoff_done(struct tevent_req *subreq);
2164 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2165 struct tevent_context *ev,
2166 struct cli_state *cli)
2168 struct tevent_req *req, *subreq;
2169 struct cli_ulogoff_state *state;
2171 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2172 if (req == NULL) {
2173 return NULL;
2175 state->cli = cli;
2177 SCVAL(state->vwv+0, 0, 0xFF);
2178 SCVAL(state->vwv+1, 0, 0);
2179 SSVAL(state->vwv+2, 0, 0);
2181 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2182 0, NULL);
2183 if (tevent_req_nomem(subreq, req)) {
2184 return tevent_req_post(req, ev);
2186 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2187 return req;
2190 static void cli_ulogoff_done(struct tevent_req *subreq)
2192 struct tevent_req *req = tevent_req_callback_data(
2193 subreq, struct tevent_req);
2194 struct cli_ulogoff_state *state = tevent_req_data(
2195 req, struct cli_ulogoff_state);
2196 NTSTATUS status;
2198 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2199 if (!NT_STATUS_IS_OK(status)) {
2200 tevent_req_nterror(req, status);
2201 return;
2203 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2204 tevent_req_done(req);
2207 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2209 return tevent_req_simple_recv_ntstatus(req);
2212 NTSTATUS cli_ulogoff(struct cli_state *cli)
2214 struct tevent_context *ev;
2215 struct tevent_req *req;
2216 NTSTATUS status = NT_STATUS_NO_MEMORY;
2218 if (smbXcli_conn_has_async_calls(cli->conn)) {
2219 return NT_STATUS_INVALID_PARAMETER;
2221 ev = samba_tevent_context_init(talloc_tos());
2222 if (ev == NULL) {
2223 goto fail;
2225 req = cli_ulogoff_send(ev, ev, cli);
2226 if (req == NULL) {
2227 goto fail;
2229 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2230 goto fail;
2232 status = cli_ulogoff_recv(req);
2233 fail:
2234 TALLOC_FREE(ev);
2235 return status;
2238 /****************************************************************************
2239 Send a tconX.
2240 ****************************************************************************/
2242 struct cli_tcon_andx_state {
2243 struct cli_state *cli;
2244 uint16_t vwv[4];
2245 struct iovec bytes;
2248 static void cli_tcon_andx_done(struct tevent_req *subreq);
2250 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2251 struct tevent_context *ev,
2252 struct cli_state *cli,
2253 const char *share, const char *dev,
2254 const char *pass, int passlen,
2255 struct tevent_req **psmbreq)
2257 struct tevent_req *req, *subreq;
2258 struct cli_tcon_andx_state *state;
2259 uint8_t p24[24];
2260 uint16_t *vwv;
2261 char *tmp = NULL;
2262 uint8_t *bytes;
2263 uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
2264 uint16_t tcon_flags = 0;
2266 *psmbreq = NULL;
2268 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2269 if (req == NULL) {
2270 return NULL;
2272 state->cli = cli;
2273 vwv = state->vwv;
2275 cli->share = talloc_strdup(cli, share);
2276 if (!cli->share) {
2277 return NULL;
2280 /* in user level security don't send a password now */
2281 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2282 passlen = 1;
2283 pass = "";
2284 } else if (pass == NULL) {
2285 DEBUG(1, ("Server not using user level security and no "
2286 "password supplied.\n"));
2287 goto access_denied;
2290 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2291 *pass && passlen != 24) {
2292 if (!lp_client_lanman_auth()) {
2293 DEBUG(1, ("Server requested LANMAN password "
2294 "(share-level security) but "
2295 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2296 goto access_denied;
2300 * Non-encrypted passwords - convert to DOS codepage before
2301 * encryption.
2303 SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
2304 passlen = 24;
2305 pass = (const char *)p24;
2306 } else {
2307 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2308 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2309 == 0) {
2310 uint8_t *tmp_pass;
2312 if (!lp_client_plaintext_auth() && (*pass)) {
2313 DEBUG(1, ("Server requested PLAINTEXT "
2314 "password but "
2315 "'client plaintext auth = no' or 'client ntlmv2 auth = yes'\n"));
2316 goto access_denied;
2320 * Non-encrypted passwords - convert to DOS codepage
2321 * before using.
2323 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2324 if (tevent_req_nomem(tmp_pass, req)) {
2325 return tevent_req_post(req, ev);
2327 tmp_pass = trans2_bytes_push_str(tmp_pass,
2328 false, /* always DOS */
2329 pass,
2330 passlen,
2331 NULL);
2332 if (tevent_req_nomem(tmp_pass, req)) {
2333 return tevent_req_post(req, ev);
2335 pass = (const char *)tmp_pass;
2336 passlen = talloc_get_size(tmp_pass);
2340 tcon_flags |= TCONX_FLAG_EXTENDED_RESPONSE;
2341 tcon_flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
2343 SCVAL(vwv+0, 0, 0xFF);
2344 SCVAL(vwv+0, 1, 0);
2345 SSVAL(vwv+1, 0, 0);
2346 SSVAL(vwv+2, 0, tcon_flags);
2347 SSVAL(vwv+3, 0, passlen);
2349 if (passlen && pass) {
2350 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2351 } else {
2352 bytes = talloc_array(state, uint8_t, 0);
2356 * Add the sharename
2358 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2359 smbXcli_conn_remote_name(cli->conn), share);
2360 if (tmp == NULL) {
2361 TALLOC_FREE(req);
2362 return NULL;
2364 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), tmp, strlen(tmp)+1,
2365 NULL);
2366 TALLOC_FREE(tmp);
2369 * Add the devicetype
2371 tmp = talloc_strdup_upper(talloc_tos(), dev);
2372 if (tmp == NULL) {
2373 TALLOC_FREE(req);
2374 return NULL;
2376 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2377 TALLOC_FREE(tmp);
2379 if (bytes == NULL) {
2380 TALLOC_FREE(req);
2381 return NULL;
2384 state->bytes.iov_base = (void *)bytes;
2385 state->bytes.iov_len = talloc_get_size(bytes);
2387 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2388 1, &state->bytes);
2389 if (subreq == NULL) {
2390 TALLOC_FREE(req);
2391 return NULL;
2393 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2394 *psmbreq = subreq;
2395 return req;
2397 access_denied:
2398 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2399 return tevent_req_post(req, ev);
2402 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2403 struct tevent_context *ev,
2404 struct cli_state *cli,
2405 const char *share, const char *dev,
2406 const char *pass, int passlen)
2408 struct tevent_req *req, *subreq;
2409 NTSTATUS status;
2411 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2412 &subreq);
2413 if (req == NULL) {
2414 return NULL;
2416 if (subreq == NULL) {
2417 return req;
2419 status = smb1cli_req_chain_submit(&subreq, 1);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 tevent_req_nterror(req, status);
2422 return tevent_req_post(req, ev);
2424 return req;
2427 static void cli_tcon_andx_done(struct tevent_req *subreq)
2429 struct tevent_req *req = tevent_req_callback_data(
2430 subreq, struct tevent_req);
2431 struct cli_tcon_andx_state *state = tevent_req_data(
2432 req, struct cli_tcon_andx_state);
2433 struct cli_state *cli = state->cli;
2434 uint8_t *in;
2435 uint8_t *inhdr;
2436 uint8_t wct;
2437 uint16_t *vwv;
2438 uint32_t num_bytes;
2439 uint8_t *bytes;
2440 NTSTATUS status;
2441 uint16_t optional_support = 0;
2443 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2444 &num_bytes, &bytes);
2445 TALLOC_FREE(subreq);
2446 if (!NT_STATUS_IS_OK(status)) {
2447 tevent_req_nterror(req, status);
2448 return;
2451 inhdr = in + NBT_HDR_SIZE;
2453 if (num_bytes) {
2454 if (clistr_pull_talloc(cli,
2455 (const char *)inhdr,
2456 SVAL(inhdr, HDR_FLG2),
2457 &cli->dev,
2458 bytes,
2459 num_bytes,
2460 STR_TERMINATE|STR_ASCII) == -1) {
2461 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2462 return;
2464 } else {
2465 cli->dev = talloc_strdup(cli, "");
2466 if (cli->dev == NULL) {
2467 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2468 return;
2472 if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2473 /* almost certainly win95 - enable bug fixes */
2474 cli->win95 = True;
2478 * Make sure that we have the optional support 16-bit field. WCT > 2.
2479 * Avoids issues when connecting to Win9x boxes sharing files
2482 cli->dfsroot = false;
2484 if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
2485 optional_support = SVAL(vwv+2, 0);
2488 if (optional_support & SMB_SHARE_IN_DFS) {
2489 cli->dfsroot = true;
2492 if (optional_support & SMB_EXTENDED_SIGNATURES) {
2493 smb1cli_session_protect_session_key(cli->smb1.session);
2496 cli_state_set_tid(cli, SVAL(inhdr, HDR_TID));
2497 tevent_req_done(req);
2500 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2502 return tevent_req_simple_recv_ntstatus(req);
2505 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2506 const char *dev, const char *pass, int passlen)
2508 TALLOC_CTX *frame = talloc_stackframe();
2509 struct tevent_context *ev;
2510 struct tevent_req *req;
2511 NTSTATUS status = NT_STATUS_OK;
2513 if (smbXcli_conn_has_async_calls(cli->conn)) {
2515 * Can't use sync call while an async call is in flight
2517 status = NT_STATUS_INVALID_PARAMETER;
2518 goto fail;
2521 ev = samba_tevent_context_init(frame);
2522 if (ev == NULL) {
2523 status = NT_STATUS_NO_MEMORY;
2524 goto fail;
2527 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2528 if (req == NULL) {
2529 status = NT_STATUS_NO_MEMORY;
2530 goto fail;
2533 if (!tevent_req_poll(req, ev)) {
2534 status = map_nt_error_from_unix(errno);
2535 goto fail;
2538 status = cli_tcon_andx_recv(req);
2539 fail:
2540 TALLOC_FREE(frame);
2541 return status;
2544 NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
2545 const char *dev, const char *pass, int passlen)
2547 NTSTATUS status;
2548 uint16_t max_xmit = 0;
2549 uint16_t tid = 0;
2551 cli->share = talloc_strdup(cli, share);
2552 if (!cli->share) {
2553 return NT_STATUS_NO_MEMORY;
2556 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2557 return smb2cli_tcon(cli, share);
2560 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) {
2561 return cli_tcon_andx(cli, share, dev, pass, passlen);
2564 status = cli_raw_tcon(cli, share, pass, dev, &max_xmit, &tid);
2565 if (!NT_STATUS_IS_OK(status)) {
2566 return status;
2569 cli_state_set_tid(cli, tid);
2571 return NT_STATUS_OK;
2574 /****************************************************************************
2575 Send a tree disconnect.
2576 ****************************************************************************/
2578 struct cli_tdis_state {
2579 struct cli_state *cli;
2582 static void cli_tdis_done(struct tevent_req *subreq);
2584 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2585 struct tevent_context *ev,
2586 struct cli_state *cli)
2588 struct tevent_req *req, *subreq;
2589 struct cli_tdis_state *state;
2591 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2592 if (req == NULL) {
2593 return NULL;
2595 state->cli = cli;
2597 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2598 if (tevent_req_nomem(subreq, req)) {
2599 return tevent_req_post(req, ev);
2601 tevent_req_set_callback(subreq, cli_tdis_done, req);
2602 return req;
2605 static void cli_tdis_done(struct tevent_req *subreq)
2607 struct tevent_req *req = tevent_req_callback_data(
2608 subreq, struct tevent_req);
2609 struct cli_tdis_state *state = tevent_req_data(
2610 req, struct cli_tdis_state);
2611 NTSTATUS status;
2613 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2614 TALLOC_FREE(subreq);
2615 if (!NT_STATUS_IS_OK(status)) {
2616 tevent_req_nterror(req, status);
2617 return;
2619 cli_state_set_tid(state->cli, UINT16_MAX);
2620 tevent_req_done(req);
2623 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2625 return tevent_req_simple_recv_ntstatus(req);
2628 NTSTATUS cli_tdis(struct cli_state *cli)
2630 struct tevent_context *ev;
2631 struct tevent_req *req;
2632 NTSTATUS status = NT_STATUS_NO_MEMORY;
2634 if (smbXcli_conn_has_async_calls(cli->conn)) {
2635 return NT_STATUS_INVALID_PARAMETER;
2637 ev = samba_tevent_context_init(talloc_tos());
2638 if (ev == NULL) {
2639 goto fail;
2641 req = cli_tdis_send(ev, ev, cli);
2642 if (req == NULL) {
2643 goto fail;
2645 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2646 goto fail;
2648 status = cli_tdis_recv(req);
2649 fail:
2650 TALLOC_FREE(ev);
2651 return status;
2654 static NTSTATUS cli_connect_sock(const char *host, int name_type,
2655 const struct sockaddr_storage *pss,
2656 const char *myname, uint16_t port,
2657 int sec_timeout, int *pfd, uint16_t *pport)
2659 TALLOC_CTX *frame = talloc_stackframe();
2660 const char *prog;
2661 unsigned int i, num_addrs;
2662 const char **called_names;
2663 const char **calling_names;
2664 int *called_types;
2665 NTSTATUS status;
2666 int fd;
2668 prog = getenv("LIBSMB_PROG");
2669 if (prog != NULL) {
2670 fd = sock_exec(prog);
2671 if (fd == -1) {
2672 return map_nt_error_from_unix(errno);
2674 port = 0;
2675 goto done;
2678 if ((pss == NULL) || is_zero_addr(pss)) {
2679 struct sockaddr_storage *addrs;
2680 status = resolve_name_list(talloc_tos(), host, name_type,
2681 &addrs, &num_addrs);
2682 if (!NT_STATUS_IS_OK(status)) {
2683 goto fail;
2685 pss = addrs;
2686 } else {
2687 num_addrs = 1;
2690 called_names = talloc_array(talloc_tos(), const char *, num_addrs);
2691 if (called_names == NULL) {
2692 status = NT_STATUS_NO_MEMORY;
2693 goto fail;
2695 called_types = talloc_array(talloc_tos(), int, num_addrs);
2696 if (called_types == NULL) {
2697 status = NT_STATUS_NO_MEMORY;
2698 goto fail;
2700 calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
2701 if (calling_names == NULL) {
2702 status = NT_STATUS_NO_MEMORY;
2703 goto fail;
2705 for (i=0; i<num_addrs; i++) {
2706 called_names[i] = host;
2707 called_types[i] = name_type;
2708 calling_names[i] = myname;
2710 status = smbsock_any_connect(pss, called_names, called_types,
2711 calling_names, NULL, num_addrs, port,
2712 sec_timeout, &fd, NULL, &port);
2713 if (!NT_STATUS_IS_OK(status)) {
2714 goto fail;
2716 set_socket_options(fd, lp_socket_options());
2717 done:
2718 *pfd = fd;
2719 *pport = port;
2720 status = NT_STATUS_OK;
2721 fail:
2722 TALLOC_FREE(frame);
2723 return status;
2726 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2727 uint16_t port, int name_type, const char *myname,
2728 int signing_state, int flags, struct cli_state **pcli)
2730 TALLOC_CTX *frame = talloc_stackframe();
2731 struct cli_state *cli;
2732 NTSTATUS status = NT_STATUS_NO_MEMORY;
2733 int fd = -1;
2734 char *desthost;
2735 char *p;
2737 desthost = talloc_strdup(talloc_tos(), host);
2738 if (desthost == NULL) {
2739 goto fail;
2742 p = strchr(host, '#');
2743 if (p != NULL) {
2744 name_type = strtol(p+1, NULL, 16);
2745 host = talloc_strndup(talloc_tos(), host, p - host);
2746 if (host == NULL) {
2747 goto fail;
2751 status = cli_connect_sock(host, name_type, dest_ss, myname, port,
2752 20, &fd, &port);
2753 if (!NT_STATUS_IS_OK(status)) {
2754 goto fail;
2757 cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
2758 if (cli == NULL) {
2759 close(fd);
2760 fd = -1;
2761 goto fail;
2764 *pcli = cli;
2765 status = NT_STATUS_OK;
2766 fail:
2767 TALLOC_FREE(frame);
2768 return status;
2772 establishes a connection to after the negprot.
2773 @param output_cli A fully initialised cli structure, non-null only on success
2774 @param dest_host The netbios name of the remote host
2775 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2776 @param port (optional) The destination port (0 for default)
2778 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2779 const char *my_name,
2780 const char *dest_host,
2781 const struct sockaddr_storage *dest_ss, int port,
2782 int signing_state, int flags)
2784 NTSTATUS nt_status;
2785 struct cli_state *cli;
2787 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
2788 signing_state, flags, &cli);
2789 if (!NT_STATUS_IS_OK(nt_status)) {
2790 DEBUG(10, ("cli_connect_nb failed: %s\n",
2791 nt_errstr(nt_status)));
2792 return nt_status;
2795 nt_status = smbXcli_negprot(cli->conn, cli->timeout, PROTOCOL_CORE,
2796 PROTOCOL_NT1);
2797 if (!NT_STATUS_IS_OK(nt_status)) {
2798 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2799 cli_shutdown(cli);
2800 return nt_status;
2803 *output_cli = cli;
2804 return NT_STATUS_OK;
2809 establishes a connection right up to doing tconX, password specified.
2810 @param output_cli A fully initialised cli structure, non-null only on success
2811 @param dest_host The netbios name of the remote host
2812 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2813 @param port (optional) The destination port (0 for default)
2814 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2815 @param service_type The 'type' of serivice.
2816 @param user Username, unix string
2817 @param domain User's domain
2818 @param password User's password, unencrypted unix string.
2821 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2822 const char *my_name,
2823 const char *dest_host,
2824 const struct sockaddr_storage *dest_ss, int port,
2825 const char *service, const char *service_type,
2826 const char *user, const char *domain,
2827 const char *password, int flags,
2828 int signing_state)
2830 NTSTATUS nt_status;
2831 struct cli_state *cli = NULL;
2832 int pw_len = password ? strlen(password)+1 : 0;
2834 *output_cli = NULL;
2836 if (password == NULL) {
2837 password = "";
2840 nt_status = cli_start_connection(&cli, my_name, dest_host,
2841 dest_ss, port, signing_state,
2842 flags);
2844 if (!NT_STATUS_IS_OK(nt_status)) {
2845 return nt_status;
2848 nt_status = cli_session_setup(cli, user, password, pw_len, password,
2849 pw_len, domain);
2850 if (!NT_STATUS_IS_OK(nt_status)) {
2852 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2853 DEBUG(1,("failed session setup with %s\n",
2854 nt_errstr(nt_status)));
2855 cli_shutdown(cli);
2856 return nt_status;
2859 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2860 if (!NT_STATUS_IS_OK(nt_status)) {
2861 DEBUG(1,("anonymous failed session setup with %s\n",
2862 nt_errstr(nt_status)));
2863 cli_shutdown(cli);
2864 return nt_status;
2868 if (service) {
2869 nt_status = cli_tree_connect(cli, service, service_type,
2870 password, pw_len);
2871 if (!NT_STATUS_IS_OK(nt_status)) {
2872 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2873 cli_shutdown(cli);
2874 if (NT_STATUS_IS_OK(nt_status)) {
2875 nt_status = NT_STATUS_UNSUCCESSFUL;
2877 return nt_status;
2881 nt_status = cli_init_creds(cli, user, domain, password);
2882 if (!NT_STATUS_IS_OK(nt_status)) {
2883 cli_shutdown(cli);
2884 return nt_status;
2887 *output_cli = cli;
2888 return NT_STATUS_OK;
2891 /****************************************************************************
2892 Send an old style tcon.
2893 ****************************************************************************/
2894 NTSTATUS cli_raw_tcon(struct cli_state *cli,
2895 const char *service, const char *pass, const char *dev,
2896 uint16 *max_xmit, uint16 *tid)
2898 struct tevent_req *req;
2899 uint16_t *ret_vwv;
2900 uint8_t *bytes;
2901 NTSTATUS status;
2903 if (!lp_client_plaintext_auth() && (*pass)) {
2904 DEBUG(1, ("Server requested PLAINTEXT password but 'client plaintext auth = no'"
2905 " or 'client ntlmv2 auth = yes'\n"));
2906 return NT_STATUS_ACCESS_DENIED;
2909 bytes = talloc_array(talloc_tos(), uint8_t, 0);
2910 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2911 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
2912 service, strlen(service)+1, NULL);
2913 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2914 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
2915 pass, strlen(pass)+1, NULL);
2916 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
2917 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
2918 dev, strlen(dev)+1, NULL);
2920 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
2921 talloc_get_size(bytes), bytes, &req,
2922 2, NULL, &ret_vwv, NULL, NULL);
2923 if (!NT_STATUS_IS_OK(status)) {
2924 return status;
2927 *max_xmit = SVAL(ret_vwv + 0, 0);
2928 *tid = SVAL(ret_vwv + 1, 0);
2930 return NT_STATUS_OK;
2933 /* Return a cli_state pointing at the IPC$ share for the given server */
2935 struct cli_state *get_ipc_connect(char *server,
2936 struct sockaddr_storage *server_ss,
2937 const struct user_auth_info *user_info)
2939 struct cli_state *cli;
2940 NTSTATUS nt_status;
2941 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2943 if (user_info->use_kerberos) {
2944 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2947 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
2948 user_info->username ? user_info->username : "",
2949 lp_workgroup(),
2950 user_info->password ? user_info->password : "",
2951 flags,
2952 SMB_SIGNING_DEFAULT);
2954 if (NT_STATUS_IS_OK(nt_status)) {
2955 return cli;
2956 } else if (is_ipaddress(server)) {
2957 /* windows 9* needs a correct NMB name for connections */
2958 fstring remote_name;
2960 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2961 cli = get_ipc_connect(remote_name, server_ss, user_info);
2962 if (cli)
2963 return cli;
2966 return NULL;
2970 * Given the IP address of a master browser on the network, return its
2971 * workgroup and connect to it.
2973 * This function is provided to allow additional processing beyond what
2974 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2975 * browsers and obtain each master browsers' list of domains (in case the
2976 * first master browser is recently on the network and has not yet
2977 * synchronized with other master browsers and therefore does not yet have the
2978 * entire network browse list)
2981 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2982 struct sockaddr_storage *mb_ip,
2983 const struct user_auth_info *user_info,
2984 char **pp_workgroup_out)
2986 char addr[INET6_ADDRSTRLEN];
2987 fstring name;
2988 struct cli_state *cli;
2989 struct sockaddr_storage server_ss;
2991 *pp_workgroup_out = NULL;
2993 print_sockaddr(addr, sizeof(addr), mb_ip);
2994 DEBUG(99, ("Looking up name of master browser %s\n",
2995 addr));
2998 * Do a name status query to find out the name of the master browser.
2999 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3000 * master browser will not respond to a wildcard query (or, at least,
3001 * an NT4 server acting as the domain master browser will not).
3003 * We might be able to use ONLY the query on MSBROWSE, but that's not
3004 * yet been tested with all Windows versions, so until it is, leave
3005 * the original wildcard query as the first choice and fall back to
3006 * MSBROWSE if the wildcard query fails.
3008 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3009 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3011 DEBUG(99, ("Could not retrieve name status for %s\n",
3012 addr));
3013 return NULL;
3016 if (!find_master_ip(name, &server_ss)) {
3017 DEBUG(99, ("Could not find master ip for %s\n", name));
3018 return NULL;
3021 *pp_workgroup_out = talloc_strdup(ctx, name);
3023 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3025 print_sockaddr(addr, sizeof(addr), &server_ss);
3026 cli = get_ipc_connect(addr, &server_ss, user_info);
3028 return cli;
3032 * Return the IP address and workgroup of a master browser on the network, and
3033 * connect to it.
3036 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3037 const struct user_auth_info *user_info,
3038 char **pp_workgroup_out)
3040 struct sockaddr_storage *ip_list;
3041 struct cli_state *cli;
3042 int i, count;
3043 NTSTATUS status;
3045 *pp_workgroup_out = NULL;
3047 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3049 /* Go looking for workgroups by broadcasting on the local network */
3051 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3052 &ip_list, &count);
3053 if (!NT_STATUS_IS_OK(status)) {
3054 DEBUG(99, ("No master browsers responded: %s\n",
3055 nt_errstr(status)));
3056 return NULL;
3059 for (i = 0; i < count; i++) {
3060 char addr[INET6_ADDRSTRLEN];
3061 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3062 DEBUG(99, ("Found master browser %s\n", addr));
3064 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3065 user_info, pp_workgroup_out);
3066 if (cli)
3067 return(cli);
3070 return NULL;