s3:smb2cli: ignore the NBT/Length header in smb2cli_inbuf_parse_compound()
[Samba/gebeck_regimport.git] / source3 / libsmb / cliconnect.c
blobaf6c51b7b5345d72a2fb48191e2009da1931d1c9
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 "popt_common.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"
37 static const struct {
38 int prot;
39 const char name[24];
40 } prots[10] = {
41 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
42 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
43 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
44 {PROTOCOL_LANMAN1, "LANMAN1.0"},
45 {PROTOCOL_LANMAN2, "LM1.2X002"},
46 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
47 {PROTOCOL_LANMAN2, "LANMAN2.1"},
48 {PROTOCOL_LANMAN2, "Samba"},
49 {PROTOCOL_NT1, "NT LANMAN 1.0"},
50 {PROTOCOL_NT1, "NT LM 0.12"},
53 #define STAR_SMBSERVER "*SMBSERVER"
55 /********************************************************
56 Utility function to ensure we always return at least
57 a valid char * pointer to an empty string for the
58 cli->server_os, cli->server_type and cli->server_domain
59 strings.
60 *******************************************************/
62 static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
63 char *inbuf,
64 char **dest,
65 uint8_t *src,
66 size_t srclen,
67 ssize_t *destlen)
69 *destlen = clistr_pull_talloc(mem_ctx,
70 inbuf,
71 SVAL(inbuf, smb_flg2),
72 dest,
73 (char *)src,
74 srclen,
75 STR_TERMINATE);
76 if (*destlen == -1) {
77 return NT_STATUS_NO_MEMORY;
80 if (*dest == NULL) {
81 *dest = talloc_strdup(mem_ctx, "");
82 if (*dest == NULL) {
83 return NT_STATUS_NO_MEMORY;
86 return NT_STATUS_OK;
89 /**
90 * Set the user session key for a connection
91 * @param cli The cli structure to add it too
92 * @param session_key The session key used. (A copy of this is taken for the cli struct)
96 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
98 cli->user_session_key = data_blob(session_key.data, session_key.length);
101 /****************************************************************************
102 Do an old lanman2 style session setup.
103 ****************************************************************************/
105 struct cli_session_setup_lanman2_state {
106 struct cli_state *cli;
107 uint16_t vwv[10];
108 const char *user;
111 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
113 static struct tevent_req *cli_session_setup_lanman2_send(
114 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
115 struct cli_state *cli, const char *user,
116 const char *pass, size_t passlen,
117 const char *workgroup)
119 struct tevent_req *req, *subreq;
120 struct cli_session_setup_lanman2_state *state;
121 DATA_BLOB lm_response = data_blob_null;
122 uint16_t *vwv;
123 uint8_t *bytes;
124 char *tmp;
125 uint16_t sec_mode = cli_state_security_mode(cli);
127 req = tevent_req_create(mem_ctx, &state,
128 struct cli_session_setup_lanman2_state);
129 if (req == NULL) {
130 return NULL;
132 state->cli = cli;
133 state->user = user;
134 vwv = state->vwv;
137 * if in share level security then don't send a password now
139 if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
140 passlen = 0;
143 if (passlen > 0
144 && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
145 && passlen != 24) {
147 * Encrypted mode needed, and non encrypted password
148 * supplied.
150 lm_response = data_blob(NULL, 24);
151 if (tevent_req_nomem(lm_response.data, req)) {
152 return tevent_req_post(req, ev);
155 if (!SMBencrypt(pass, cli_state_server_challenge(cli),
156 (uint8_t *)lm_response.data)) {
157 DEBUG(1, ("Password is > 14 chars in length, and is "
158 "therefore incompatible with Lanman "
159 "authentication\n"));
160 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
161 return tevent_req_post(req, ev);
163 } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
164 && passlen == 24) {
166 * Encrypted mode needed, and encrypted password
167 * supplied.
169 lm_response = data_blob(pass, passlen);
170 if (tevent_req_nomem(lm_response.data, req)) {
171 return tevent_req_post(req, ev);
173 } else if (passlen > 0) {
174 uint8_t *buf;
175 size_t converted_size;
177 * Plaintext mode needed, assume plaintext supplied.
179 buf = talloc_array(talloc_tos(), uint8_t, 0);
180 buf = smb_bytes_push_str(buf, cli_ucs2(cli), pass, passlen+1,
181 &converted_size);
182 if (tevent_req_nomem(buf, req)) {
183 return tevent_req_post(req, ev);
185 lm_response = data_blob(pass, passlen);
186 TALLOC_FREE(buf);
187 if (tevent_req_nomem(lm_response.data, req)) {
188 return tevent_req_post(req, ev);
192 SCVAL(vwv+0, 0, 0xff);
193 SCVAL(vwv+0, 1, 0);
194 SSVAL(vwv+1, 0, 0);
195 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
196 SSVAL(vwv+3, 0, 2);
197 SSVAL(vwv+4, 0, 1);
198 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
199 SSVAL(vwv+7, 0, lm_response.length);
201 bytes = talloc_array(state, uint8_t, lm_response.length);
202 if (tevent_req_nomem(bytes, req)) {
203 return tevent_req_post(req, ev);
205 if (lm_response.length != 0) {
206 memcpy(bytes, lm_response.data, lm_response.length);
208 data_blob_free(&lm_response);
210 tmp = talloc_strdup_upper(talloc_tos(), user);
211 if (tevent_req_nomem(tmp, req)) {
212 return tevent_req_post(req, ev);
214 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
215 NULL);
216 TALLOC_FREE(tmp);
218 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
219 if (tevent_req_nomem(tmp, req)) {
220 return tevent_req_post(req, ev);
222 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
223 NULL);
224 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
225 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
227 if (tevent_req_nomem(bytes, req)) {
228 return tevent_req_post(req, ev);
231 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
232 talloc_get_size(bytes), bytes);
233 if (tevent_req_nomem(subreq, req)) {
234 return tevent_req_post(req, ev);
236 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
237 return req;
240 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
242 struct tevent_req *req = tevent_req_callback_data(
243 subreq, struct tevent_req);
244 struct cli_session_setup_lanman2_state *state = tevent_req_data(
245 req, struct cli_session_setup_lanman2_state);
246 struct cli_state *cli = state->cli;
247 uint32_t num_bytes;
248 uint8_t *in;
249 char *inbuf;
250 uint8_t *bytes;
251 uint8_t *p;
252 NTSTATUS status;
253 ssize_t ret;
254 uint8_t wct;
255 uint16_t *vwv;
257 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
258 &num_bytes, &bytes);
259 TALLOC_FREE(subreq);
260 if (!NT_STATUS_IS_OK(status)) {
261 tevent_req_nterror(req, status);
262 return;
265 inbuf = (char *)in;
266 p = bytes;
268 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
269 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
271 status = smb_bytes_talloc_string(cli,
272 inbuf,
273 &cli->server_os,
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 = smb_bytes_talloc_string(cli,
285 inbuf,
286 &cli->server_type,
288 bytes+num_bytes-p,
289 &ret);
291 if (!NT_STATUS_IS_OK(status)) {
292 tevent_req_nterror(req, status);
293 return;
295 p += ret;
297 status = smb_bytes_talloc_string(cli,
298 inbuf,
299 &cli->server_domain,
301 bytes+num_bytes-p,
302 &ret);
304 if (!NT_STATUS_IS_OK(status)) {
305 tevent_req_nterror(req, status);
306 return;
308 p += ret;
310 status = cli_set_username(cli, state->user);
311 if (tevent_req_nterror(req, status)) {
312 return;
314 tevent_req_done(req);
317 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
319 return tevent_req_simple_recv_ntstatus(req);
322 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
323 const char *pass, size_t passlen,
324 const char *workgroup)
326 TALLOC_CTX *frame = talloc_stackframe();
327 struct event_context *ev;
328 struct tevent_req *req;
329 NTSTATUS status = NT_STATUS_NO_MEMORY;
331 if (cli_has_async_calls(cli)) {
333 * Can't use sync call while an async call is in flight
335 status = NT_STATUS_INVALID_PARAMETER;
336 goto fail;
338 ev = event_context_init(frame);
339 if (ev == NULL) {
340 goto fail;
342 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
343 workgroup);
344 if (req == NULL) {
345 goto fail;
347 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
348 goto fail;
350 status = cli_session_setup_lanman2_recv(req);
351 fail:
352 TALLOC_FREE(frame);
353 return status;
356 /****************************************************************************
357 Work out suitable capabilities to offer the server.
358 ****************************************************************************/
360 static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
361 uint32_t sesssetup_capabilities)
363 uint32_t client_capabilities = cli_state_capabilities(cli);
366 * We only send capabilities based on the mask for:
367 * - client only flags
368 * - flags used in both directions
370 * We do not echo the server only flags.
372 client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_CLIENT_MASK);
375 * Session Setup specific flags CAP_DYNAMIC_REAUTH
376 * and CAP_EXTENDED_SECURITY are passed by the caller.
377 * We need that in order to do guest logins even if
378 * CAP_EXTENDED_SECURITY is negotiated.
380 client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
381 sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
382 client_capabilities |= sesssetup_capabilities;
384 return client_capabilities;
387 /****************************************************************************
388 Do a NT1 guest session setup.
389 ****************************************************************************/
391 struct cli_session_setup_guest_state {
392 struct cli_state *cli;
393 uint16_t vwv[13];
394 struct iovec bytes;
397 static void cli_session_setup_guest_done(struct tevent_req *subreq);
399 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
400 struct event_context *ev,
401 struct cli_state *cli,
402 struct tevent_req **psmbreq)
404 struct tevent_req *req, *subreq;
405 struct cli_session_setup_guest_state *state;
406 uint16_t *vwv;
407 uint8_t *bytes;
409 req = tevent_req_create(mem_ctx, &state,
410 struct cli_session_setup_guest_state);
411 if (req == NULL) {
412 return NULL;
414 state->cli = cli;
415 vwv = state->vwv;
417 SCVAL(vwv+0, 0, 0xFF);
418 SCVAL(vwv+0, 1, 0);
419 SSVAL(vwv+1, 0, 0);
420 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
421 SSVAL(vwv+3, 0, 2);
422 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
423 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
424 SSVAL(vwv+7, 0, 0);
425 SSVAL(vwv+8, 0, 0);
426 SSVAL(vwv+9, 0, 0);
427 SSVAL(vwv+10, 0, 0);
428 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
430 bytes = talloc_array(state, uint8_t, 0);
432 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
433 NULL);
434 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
435 NULL);
436 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
437 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
439 if (bytes == NULL) {
440 TALLOC_FREE(req);
441 return NULL;
444 state->bytes.iov_base = (void *)bytes;
445 state->bytes.iov_len = talloc_get_size(bytes);
447 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
448 1, &state->bytes);
449 if (subreq == NULL) {
450 TALLOC_FREE(req);
451 return NULL;
453 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
454 *psmbreq = subreq;
455 return req;
458 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
459 struct event_context *ev,
460 struct cli_state *cli)
462 struct tevent_req *req, *subreq;
463 NTSTATUS status;
465 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
466 if (req == NULL) {
467 return NULL;
470 status = cli_smb_req_send(subreq);
471 if (NT_STATUS_IS_OK(status)) {
472 tevent_req_nterror(req, status);
473 return tevent_req_post(req, ev);
475 return req;
478 static void cli_session_setup_guest_done(struct tevent_req *subreq)
480 struct tevent_req *req = tevent_req_callback_data(
481 subreq, struct tevent_req);
482 struct cli_session_setup_guest_state *state = tevent_req_data(
483 req, struct cli_session_setup_guest_state);
484 struct cli_state *cli = state->cli;
485 uint32_t num_bytes;
486 uint8_t *in;
487 char *inbuf;
488 uint8_t *bytes;
489 uint8_t *p;
490 NTSTATUS status;
491 ssize_t ret;
492 uint8_t wct;
493 uint16_t *vwv;
495 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
496 &num_bytes, &bytes);
497 TALLOC_FREE(subreq);
498 if (!NT_STATUS_IS_OK(status)) {
499 tevent_req_nterror(req, status);
500 return;
503 inbuf = (char *)in;
504 p = bytes;
506 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
507 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
509 status = smb_bytes_talloc_string(cli,
510 inbuf,
511 &cli->server_os,
513 bytes+num_bytes-p,
514 &ret);
516 if (!NT_STATUS_IS_OK(status)) {
517 tevent_req_nterror(req, status);
518 return;
520 p += ret;
522 status = smb_bytes_talloc_string(cli,
523 inbuf,
524 &cli->server_type,
526 bytes+num_bytes-p,
527 &ret);
529 if (!NT_STATUS_IS_OK(status)) {
530 tevent_req_nterror(req, status);
531 return;
533 p += ret;
535 status = smb_bytes_talloc_string(cli,
536 inbuf,
537 &cli->server_domain,
539 bytes+num_bytes-p,
540 &ret);
542 if (!NT_STATUS_IS_OK(status)) {
543 tevent_req_nterror(req, status);
544 return;
546 p += ret;
548 status = cli_set_username(cli, "");
549 if (!NT_STATUS_IS_OK(status)) {
550 tevent_req_nterror(req, status);
551 return;
553 tevent_req_done(req);
556 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
558 return tevent_req_simple_recv_ntstatus(req);
561 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
563 TALLOC_CTX *frame = talloc_stackframe();
564 struct event_context *ev;
565 struct tevent_req *req;
566 NTSTATUS status = NT_STATUS_OK;
568 if (cli_has_async_calls(cli)) {
570 * Can't use sync call while an async call is in flight
572 status = NT_STATUS_INVALID_PARAMETER;
573 goto fail;
576 ev = event_context_init(frame);
577 if (ev == NULL) {
578 status = NT_STATUS_NO_MEMORY;
579 goto fail;
582 req = cli_session_setup_guest_send(frame, ev, cli);
583 if (req == NULL) {
584 status = NT_STATUS_NO_MEMORY;
585 goto fail;
588 if (!tevent_req_poll(req, ev)) {
589 status = map_nt_error_from_unix(errno);
590 goto fail;
593 status = cli_session_setup_guest_recv(req);
594 fail:
595 TALLOC_FREE(frame);
596 return status;
599 /****************************************************************************
600 Do a NT1 plaintext session setup.
601 ****************************************************************************/
603 struct cli_session_setup_plain_state {
604 struct cli_state *cli;
605 uint16_t vwv[13];
606 const char *user;
609 static void cli_session_setup_plain_done(struct tevent_req *subreq);
611 static struct tevent_req *cli_session_setup_plain_send(
612 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
613 struct cli_state *cli,
614 const char *user, const char *pass, const char *workgroup)
616 struct tevent_req *req, *subreq;
617 struct cli_session_setup_plain_state *state;
618 uint16_t *vwv;
619 uint8_t *bytes;
620 size_t passlen;
621 char *version;
623 req = tevent_req_create(mem_ctx, &state,
624 struct cli_session_setup_plain_state);
625 if (req == NULL) {
626 return NULL;
628 state->cli = cli;
629 state->user = user;
630 vwv = state->vwv;
632 SCVAL(vwv+0, 0, 0xff);
633 SCVAL(vwv+0, 1, 0);
634 SSVAL(vwv+1, 0, 0);
635 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
636 SSVAL(vwv+3, 0, 2);
637 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
638 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
639 SSVAL(vwv+7, 0, 0);
640 SSVAL(vwv+8, 0, 0);
641 SSVAL(vwv+9, 0, 0);
642 SSVAL(vwv+10, 0, 0);
643 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
645 bytes = talloc_array(state, uint8_t, 0);
646 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
647 &passlen);
648 if (tevent_req_nomem(bytes, req)) {
649 return tevent_req_post(req, ev);
651 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
653 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
654 user, strlen(user)+1, NULL);
655 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
656 workgroup, strlen(workgroup)+1, NULL);
657 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
658 "Unix", 5, NULL);
660 version = talloc_asprintf(talloc_tos(), "Samba %s",
661 samba_version_string());
662 if (tevent_req_nomem(version, req)){
663 return tevent_req_post(req, ev);
665 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
666 version, strlen(version)+1, NULL);
667 TALLOC_FREE(version);
669 if (tevent_req_nomem(bytes, req)) {
670 return tevent_req_post(req, ev);
673 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
674 talloc_get_size(bytes), bytes);
675 if (tevent_req_nomem(subreq, req)) {
676 return tevent_req_post(req, ev);
678 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
679 return req;
682 static void cli_session_setup_plain_done(struct tevent_req *subreq)
684 struct tevent_req *req = tevent_req_callback_data(
685 subreq, struct tevent_req);
686 struct cli_session_setup_plain_state *state = tevent_req_data(
687 req, struct cli_session_setup_plain_state);
688 struct cli_state *cli = state->cli;
689 uint32_t num_bytes;
690 uint8_t *in;
691 char *inbuf;
692 uint8_t *bytes;
693 uint8_t *p;
694 NTSTATUS status;
695 ssize_t ret;
696 uint8_t wct;
697 uint16_t *vwv;
699 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
700 &num_bytes, &bytes);
701 TALLOC_FREE(subreq);
702 if (tevent_req_nterror(req, status)) {
703 return;
706 inbuf = (char *)in;
707 p = bytes;
709 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
710 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
712 status = smb_bytes_talloc_string(cli,
713 inbuf,
714 &cli->server_os,
716 bytes+num_bytes-p,
717 &ret);
719 if (!NT_STATUS_IS_OK(status)) {
720 tevent_req_nterror(req, status);
721 return;
723 p += ret;
725 status = smb_bytes_talloc_string(cli,
726 inbuf,
727 &cli->server_type,
729 bytes+num_bytes-p,
730 &ret);
732 if (!NT_STATUS_IS_OK(status)) {
733 tevent_req_nterror(req, status);
734 return;
736 p += ret;
738 status = smb_bytes_talloc_string(cli,
739 inbuf,
740 &cli->server_domain,
742 bytes+num_bytes-p,
743 &ret);
745 if (!NT_STATUS_IS_OK(status)) {
746 tevent_req_nterror(req, status);
747 return;
749 p += ret;
751 status = cli_set_username(cli, state->user);
752 if (tevent_req_nterror(req, status)) {
753 return;
756 tevent_req_done(req);
759 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
761 return tevent_req_simple_recv_ntstatus(req);
764 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
765 const char *user, const char *pass,
766 const char *workgroup)
768 TALLOC_CTX *frame = talloc_stackframe();
769 struct event_context *ev;
770 struct tevent_req *req;
771 NTSTATUS status = NT_STATUS_NO_MEMORY;
773 if (cli_has_async_calls(cli)) {
775 * Can't use sync call while an async call is in flight
777 status = NT_STATUS_INVALID_PARAMETER;
778 goto fail;
780 ev = event_context_init(frame);
781 if (ev == NULL) {
782 goto fail;
784 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
785 workgroup);
786 if (req == NULL) {
787 goto fail;
789 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
790 goto fail;
792 status = cli_session_setup_plain_recv(req);
793 fail:
794 TALLOC_FREE(frame);
795 return status;
798 /****************************************************************************
799 do a NT1 NTLM/LM encrypted session setup - for when extended security
800 is not negotiated.
801 @param cli client state to create do session setup on
802 @param user username
803 @param pass *either* cleartext password (passlen !=24) or LM response.
804 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
805 @param workgroup The user's domain.
806 ****************************************************************************/
808 struct cli_session_setup_nt1_state {
809 struct cli_state *cli;
810 uint16_t vwv[13];
811 DATA_BLOB response;
812 DATA_BLOB session_key;
813 const char *user;
816 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
818 static struct tevent_req *cli_session_setup_nt1_send(
819 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
820 struct cli_state *cli, const char *user,
821 const char *pass, size_t passlen,
822 const char *ntpass, size_t ntpasslen,
823 const char *workgroup)
825 struct tevent_req *req, *subreq;
826 struct cli_session_setup_nt1_state *state;
827 DATA_BLOB lm_response = data_blob_null;
828 DATA_BLOB nt_response = data_blob_null;
829 DATA_BLOB session_key = data_blob_null;
830 uint16_t *vwv;
831 uint8_t *bytes;
832 char *workgroup_upper;
834 req = tevent_req_create(mem_ctx, &state,
835 struct cli_session_setup_nt1_state);
836 if (req == NULL) {
837 return NULL;
839 state->cli = cli;
840 state->user = user;
841 vwv = state->vwv;
843 if (passlen == 0) {
844 /* do nothing - guest login */
845 } else if (passlen != 24) {
846 if (lp_client_ntlmv2_auth()) {
847 DATA_BLOB server_chal;
848 DATA_BLOB names_blob;
850 server_chal =
851 data_blob_const(cli_state_server_challenge(cli),
855 * note that the 'workgroup' here is a best
856 * guess - we don't know the server's domain
857 * at this point. Windows clients also don't
858 * use hostname...
860 names_blob = NTLMv2_generate_names_blob(
861 NULL, NULL, workgroup);
863 if (tevent_req_nomem(names_blob.data, req)) {
864 return tevent_req_post(req, ev);
867 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
868 &server_chal, &names_blob,
869 &lm_response, &nt_response,
870 NULL, &session_key)) {
871 data_blob_free(&names_blob);
872 tevent_req_nterror(
873 req, NT_STATUS_ACCESS_DENIED);
874 return tevent_req_post(req, ev);
876 data_blob_free(&names_blob);
878 } else {
879 uchar nt_hash[16];
880 E_md4hash(pass, nt_hash);
882 #ifdef LANMAN_ONLY
883 nt_response = data_blob_null;
884 #else
885 nt_response = data_blob(NULL, 24);
886 if (tevent_req_nomem(nt_response.data, req)) {
887 return tevent_req_post(req, ev);
890 SMBNTencrypt(pass, cli_state_server_challenge(cli),
891 nt_response.data);
892 #endif
893 /* non encrypted password supplied. Ignore ntpass. */
894 if (lp_client_lanman_auth()) {
896 lm_response = data_blob(NULL, 24);
897 if (tevent_req_nomem(lm_response.data, req)) {
898 return tevent_req_post(req, ev);
901 if (!SMBencrypt(pass,
902 cli_state_server_challenge(cli),
903 lm_response.data)) {
905 * Oops, the LM response is
906 * invalid, just put the NT
907 * response there instead
909 data_blob_free(&lm_response);
910 lm_response = data_blob(
911 nt_response.data,
912 nt_response.length);
914 } else {
916 * LM disabled, place NT# in LM field
917 * instead
919 lm_response = data_blob(
920 nt_response.data, nt_response.length);
923 if (tevent_req_nomem(lm_response.data, req)) {
924 return tevent_req_post(req, ev);
927 session_key = data_blob(NULL, 16);
928 if (tevent_req_nomem(session_key.data, req)) {
929 return tevent_req_post(req, ev);
931 #ifdef LANMAN_ONLY
932 E_deshash(pass, session_key.data);
933 memset(&session_key.data[8], '\0', 8);
934 #else
935 SMBsesskeygen_ntv1(nt_hash, session_key.data);
936 #endif
938 } else {
939 /* pre-encrypted password supplied. Only used for
940 security=server, can't do
941 signing because we don't have original key */
943 lm_response = data_blob(pass, passlen);
944 if (tevent_req_nomem(lm_response.data, req)) {
945 return tevent_req_post(req, ev);
948 nt_response = data_blob(ntpass, ntpasslen);
949 if (tevent_req_nomem(nt_response.data, req)) {
950 return tevent_req_post(req, ev);
954 #ifdef LANMAN_ONLY
955 state->response = data_blob_talloc(
956 state, lm_response.data, lm_response.length);
957 #else
958 state->response = data_blob_talloc(
959 state, nt_response.data, nt_response.length);
960 #endif
961 if (tevent_req_nomem(state->response.data, req)) {
962 return tevent_req_post(req, ev);
965 if (session_key.data) {
966 state->session_key = data_blob_talloc(
967 state, session_key.data, session_key.length);
968 if (tevent_req_nomem(state->session_key.data, req)) {
969 return tevent_req_post(req, ev);
972 data_blob_free(&session_key);
974 SCVAL(vwv+0, 0, 0xff);
975 SCVAL(vwv+0, 1, 0);
976 SSVAL(vwv+1, 0, 0);
977 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
978 SSVAL(vwv+3, 0, 2);
979 SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
980 SIVAL(vwv+5, 0, cli_state_server_session_key(cli));
981 SSVAL(vwv+7, 0, lm_response.length);
982 SSVAL(vwv+8, 0, nt_response.length);
983 SSVAL(vwv+9, 0, 0);
984 SSVAL(vwv+10, 0, 0);
985 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
987 bytes = talloc_array(state, uint8_t,
988 lm_response.length + nt_response.length);
989 if (tevent_req_nomem(bytes, req)) {
990 return tevent_req_post(req, ev);
992 if (lm_response.length != 0) {
993 memcpy(bytes, lm_response.data, lm_response.length);
995 if (nt_response.length != 0) {
996 memcpy(bytes + lm_response.length,
997 nt_response.data, nt_response.length);
999 data_blob_free(&lm_response);
1000 data_blob_free(&nt_response);
1002 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1003 user, strlen(user)+1, NULL);
1006 * Upper case here might help some NTLMv2 implementations
1008 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
1009 if (tevent_req_nomem(workgroup_upper, req)) {
1010 return tevent_req_post(req, ev);
1012 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1013 workgroup_upper, strlen(workgroup_upper)+1,
1014 NULL);
1015 TALLOC_FREE(workgroup_upper);
1017 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
1018 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
1019 if (tevent_req_nomem(bytes, req)) {
1020 return tevent_req_post(req, ev);
1023 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1024 talloc_get_size(bytes), bytes);
1025 if (tevent_req_nomem(subreq, req)) {
1026 return tevent_req_post(req, ev);
1028 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1029 return req;
1032 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1034 struct tevent_req *req = tevent_req_callback_data(
1035 subreq, struct tevent_req);
1036 struct cli_session_setup_nt1_state *state = tevent_req_data(
1037 req, struct cli_session_setup_nt1_state);
1038 struct cli_state *cli = state->cli;
1039 uint32_t num_bytes;
1040 uint8_t *in;
1041 char *inbuf;
1042 uint8_t *bytes;
1043 uint8_t *p;
1044 NTSTATUS status;
1045 ssize_t ret;
1046 uint8_t wct;
1047 uint16_t *vwv;
1049 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
1050 &num_bytes, &bytes);
1051 TALLOC_FREE(subreq);
1052 if (!NT_STATUS_IS_OK(status)) {
1053 tevent_req_nterror(req, status);
1054 return;
1057 inbuf = (char *)in;
1058 p = bytes;
1060 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
1061 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1063 status = smb_bytes_talloc_string(cli,
1064 inbuf,
1065 &cli->server_os,
1067 bytes+num_bytes-p,
1068 &ret);
1069 if (!NT_STATUS_IS_OK(status)) {
1070 tevent_req_nterror(req, status);
1071 return;
1073 p += ret;
1075 status = smb_bytes_talloc_string(cli,
1076 inbuf,
1077 &cli->server_type,
1079 bytes+num_bytes-p,
1080 &ret);
1081 if (!NT_STATUS_IS_OK(status)) {
1082 tevent_req_nterror(req, status);
1083 return;
1085 p += ret;
1087 status = smb_bytes_talloc_string(cli,
1088 inbuf,
1089 &cli->server_domain,
1091 bytes+num_bytes-p,
1092 &ret);
1093 if (!NT_STATUS_IS_OK(status)) {
1094 tevent_req_nterror(req, status);
1095 return;
1097 p += ret;
1099 status = cli_set_username(cli, state->user);
1100 if (tevent_req_nterror(req, status)) {
1101 return;
1103 if (cli_simple_set_signing(cli, state->session_key, state->response)
1104 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1105 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1106 return;
1108 if (state->session_key.data) {
1109 /* Have plaintext orginal */
1110 cli_set_session_key(cli, state->session_key);
1112 tevent_req_done(req);
1115 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1117 return tevent_req_simple_recv_ntstatus(req);
1120 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1121 const char *pass, size_t passlen,
1122 const char *ntpass, size_t ntpasslen,
1123 const char *workgroup)
1125 TALLOC_CTX *frame = talloc_stackframe();
1126 struct event_context *ev;
1127 struct tevent_req *req;
1128 NTSTATUS status = NT_STATUS_NO_MEMORY;
1130 if (cli_has_async_calls(cli)) {
1132 * Can't use sync call while an async call is in flight
1134 status = NT_STATUS_INVALID_PARAMETER;
1135 goto fail;
1137 ev = event_context_init(frame);
1138 if (ev == NULL) {
1139 goto fail;
1141 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1142 ntpass, ntpasslen, workgroup);
1143 if (req == NULL) {
1144 goto fail;
1146 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1147 goto fail;
1149 status = cli_session_setup_nt1_recv(req);
1150 fail:
1151 TALLOC_FREE(frame);
1152 return status;
1155 /* The following is calculated from :
1156 * (smb_size-4) = 35
1157 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1158 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1159 * end of packet.
1162 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1164 struct cli_sesssetup_blob_state {
1165 struct tevent_context *ev;
1166 struct cli_state *cli;
1167 DATA_BLOB blob;
1168 uint16_t max_blob_size;
1169 uint16_t vwv[12];
1170 uint8_t *buf;
1172 NTSTATUS status;
1173 char *inbuf;
1174 DATA_BLOB ret_blob;
1177 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1178 struct tevent_req **psubreq);
1179 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1181 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1182 struct tevent_context *ev,
1183 struct cli_state *cli,
1184 DATA_BLOB blob)
1186 struct tevent_req *req, *subreq;
1187 struct cli_sesssetup_blob_state *state;
1188 uint32_t usable_space;
1190 req = tevent_req_create(mem_ctx, &state,
1191 struct cli_sesssetup_blob_state);
1192 if (req == NULL) {
1193 return NULL;
1195 state->ev = ev;
1196 state->blob = blob;
1197 state->cli = cli;
1199 usable_space = cli_state_available_size(cli,
1200 BASE_SESSSETUP_BLOB_PACKET_SIZE);
1202 if (usable_space == 0) {
1203 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1204 "(not possible to send %u bytes)\n",
1205 BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
1206 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1207 return tevent_req_post(req, ev);
1209 state->max_blob_size = MIN(usable_space, 0xFFFF);
1211 if (!cli_sesssetup_blob_next(state, &subreq)) {
1212 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1213 return tevent_req_post(req, ev);
1215 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1216 return req;
1219 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1220 struct tevent_req **psubreq)
1222 struct tevent_req *subreq;
1223 uint16_t thistime;
1225 SCVAL(state->vwv+0, 0, 0xFF);
1226 SCVAL(state->vwv+0, 1, 0);
1227 SSVAL(state->vwv+1, 0, 0);
1228 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1229 SSVAL(state->vwv+3, 0, 2);
1230 SSVAL(state->vwv+4, 0, 1);
1231 SIVAL(state->vwv+5, 0, 0);
1233 thistime = MIN(state->blob.length, state->max_blob_size);
1234 SSVAL(state->vwv+7, 0, thistime);
1236 SSVAL(state->vwv+8, 0, 0);
1237 SSVAL(state->vwv+9, 0, 0);
1238 SIVAL(state->vwv+10, 0,
1239 cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
1241 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1242 thistime);
1243 if (state->buf == NULL) {
1244 return false;
1246 state->blob.data += thistime;
1247 state->blob.length -= thistime;
1249 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1250 "Unix", 5, NULL);
1251 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1252 "Samba", 6, NULL);
1253 if (state->buf == NULL) {
1254 return false;
1256 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1257 12, state->vwv,
1258 talloc_get_size(state->buf), state->buf);
1259 if (subreq == NULL) {
1260 return false;
1262 *psubreq = subreq;
1263 return true;
1266 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1268 struct tevent_req *req = tevent_req_callback_data(
1269 subreq, struct tevent_req);
1270 struct cli_sesssetup_blob_state *state = tevent_req_data(
1271 req, struct cli_sesssetup_blob_state);
1272 struct cli_state *cli = state->cli;
1273 uint8_t wct;
1274 uint16_t *vwv;
1275 uint32_t num_bytes;
1276 uint8_t *bytes;
1277 NTSTATUS status;
1278 uint8_t *p;
1279 uint16_t blob_length;
1280 uint8_t *inbuf;
1281 ssize_t ret;
1283 status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
1284 &num_bytes, &bytes);
1285 TALLOC_FREE(subreq);
1286 if (!NT_STATUS_IS_OK(status)
1287 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1288 tevent_req_nterror(req, status);
1289 return;
1292 state->status = status;
1293 TALLOC_FREE(state->buf);
1295 state->inbuf = (char *)inbuf;
1296 cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
1297 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1299 blob_length = SVAL(vwv+3, 0);
1300 if (blob_length > num_bytes) {
1301 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1302 return;
1304 state->ret_blob = data_blob_const(bytes, blob_length);
1306 p = bytes + blob_length;
1308 status = smb_bytes_talloc_string(cli,
1309 (char *)inbuf,
1310 &cli->server_os,
1312 bytes+num_bytes-p,
1313 &ret);
1315 if (!NT_STATUS_IS_OK(status)) {
1316 tevent_req_nterror(req, status);
1317 return;
1319 p += ret;
1321 status = smb_bytes_talloc_string(cli,
1322 (char *)inbuf,
1323 &cli->server_type,
1325 bytes+num_bytes-p,
1326 &ret);
1328 if (!NT_STATUS_IS_OK(status)) {
1329 tevent_req_nterror(req, status);
1330 return;
1332 p += ret;
1334 status = smb_bytes_talloc_string(cli,
1335 (char *)inbuf,
1336 &cli->server_domain,
1338 bytes+num_bytes-p,
1339 &ret);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 tevent_req_nterror(req, status);
1343 return;
1345 p += ret;
1347 if (state->blob.length != 0) {
1349 * More to send
1351 if (!cli_sesssetup_blob_next(state, &subreq)) {
1352 tevent_req_oom(req);
1353 return;
1355 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1356 return;
1358 tevent_req_done(req);
1361 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1362 TALLOC_CTX *mem_ctx,
1363 DATA_BLOB *pblob,
1364 char **pinbuf)
1366 struct cli_sesssetup_blob_state *state = tevent_req_data(
1367 req, struct cli_sesssetup_blob_state);
1368 NTSTATUS status;
1369 char *inbuf;
1371 if (tevent_req_is_nterror(req, &status)) {
1372 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1373 return status;
1376 inbuf = talloc_move(mem_ctx, &state->inbuf);
1377 if (pblob != NULL) {
1378 *pblob = state->ret_blob;
1380 if (pinbuf != NULL) {
1381 *pinbuf = inbuf;
1383 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1384 return state->status;
1387 #ifdef HAVE_KRB5
1389 /****************************************************************************
1390 Use in-memory credentials cache
1391 ****************************************************************************/
1393 static void use_in_memory_ccache(void) {
1394 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1397 /****************************************************************************
1398 Do a spnego/kerberos encrypted session setup.
1399 ****************************************************************************/
1401 struct cli_session_setup_kerberos_state {
1402 struct cli_state *cli;
1403 DATA_BLOB negTokenTarg;
1404 DATA_BLOB session_key_krb5;
1405 ADS_STATUS ads_status;
1408 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1410 static struct tevent_req *cli_session_setup_kerberos_send(
1411 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1412 const char *principal)
1414 struct tevent_req *req, *subreq;
1415 struct cli_session_setup_kerberos_state *state;
1416 int rc;
1418 DEBUG(2,("Doing kerberos session setup\n"));
1420 req = tevent_req_create(mem_ctx, &state,
1421 struct cli_session_setup_kerberos_state);
1422 if (req == NULL) {
1423 return NULL;
1425 state->cli = cli;
1426 state->ads_status = ADS_SUCCESS;
1429 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1430 * we have to acquire a ticket. To be fixed later :-)
1432 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1433 &state->session_key_krb5, 0, NULL);
1434 if (rc) {
1435 DEBUG(1, ("cli_session_setup_kerberos: "
1436 "spnego_gen_krb5_negTokenInit failed: %s\n",
1437 error_message(rc)));
1438 state->ads_status = ADS_ERROR_KRB5(rc);
1439 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1440 return tevent_req_post(req, ev);
1443 #if 0
1444 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1445 state->negTokenTarg.length);
1446 #endif
1448 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1449 if (tevent_req_nomem(subreq, req)) {
1450 return tevent_req_post(req, ev);
1452 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1453 return req;
1456 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1458 struct tevent_req *req = tevent_req_callback_data(
1459 subreq, struct tevent_req);
1460 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1461 req, struct cli_session_setup_kerberos_state);
1462 char *inbuf = NULL;
1463 NTSTATUS status;
1465 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
1466 TALLOC_FREE(subreq);
1467 if (!NT_STATUS_IS_OK(status)) {
1468 tevent_req_nterror(req, status);
1469 return;
1472 cli_set_session_key(state->cli, state->session_key_krb5);
1474 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
1475 data_blob_null)
1476 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1477 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1478 return;
1481 tevent_req_done(req);
1484 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1486 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1487 req, struct cli_session_setup_kerberos_state);
1488 NTSTATUS status;
1490 if (tevent_req_is_nterror(req, &status)) {
1491 return ADS_ERROR_NT(status);
1493 return state->ads_status;
1496 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1497 const char *principal)
1499 struct tevent_context *ev;
1500 struct tevent_req *req;
1501 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1503 if (cli_has_async_calls(cli)) {
1504 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1506 ev = tevent_context_init(talloc_tos());
1507 if (ev == NULL) {
1508 goto fail;
1510 req = cli_session_setup_kerberos_send(ev, ev, cli, principal);
1511 if (req == NULL) {
1512 goto fail;
1514 if (!tevent_req_poll(req, ev)) {
1515 status = ADS_ERROR_SYSTEM(errno);
1516 goto fail;
1518 status = cli_session_setup_kerberos_recv(req);
1519 fail:
1520 TALLOC_FREE(ev);
1521 return status;
1523 #endif /* HAVE_KRB5 */
1525 /****************************************************************************
1526 Do a spnego/NTLMSSP encrypted session setup.
1527 ****************************************************************************/
1529 struct cli_session_setup_ntlmssp_state {
1530 struct tevent_context *ev;
1531 struct cli_state *cli;
1532 struct ntlmssp_state *ntlmssp_state;
1533 int turn;
1534 DATA_BLOB blob_out;
1537 static int cli_session_setup_ntlmssp_state_destructor(
1538 struct cli_session_setup_ntlmssp_state *state)
1540 if (state->ntlmssp_state != NULL) {
1541 TALLOC_FREE(state->ntlmssp_state);
1543 return 0;
1546 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1548 static struct tevent_req *cli_session_setup_ntlmssp_send(
1549 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1550 const char *user, const char *pass, const char *domain)
1552 struct tevent_req *req, *subreq;
1553 struct cli_session_setup_ntlmssp_state *state;
1554 NTSTATUS status;
1555 DATA_BLOB blob_out;
1556 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1558 req = tevent_req_create(mem_ctx, &state,
1559 struct cli_session_setup_ntlmssp_state);
1560 if (req == NULL) {
1561 return NULL;
1563 state->ev = ev;
1564 state->cli = cli;
1565 state->turn = 1;
1567 state->ntlmssp_state = NULL;
1568 talloc_set_destructor(
1569 state, cli_session_setup_ntlmssp_state_destructor);
1571 status = ntlmssp_client_start(state,
1572 lp_netbios_name(),
1573 lp_workgroup(),
1574 lp_client_ntlmv2_auth(),
1575 &state->ntlmssp_state);
1576 if (!NT_STATUS_IS_OK(status)) {
1577 goto fail;
1579 ntlmssp_want_feature(state->ntlmssp_state,
1580 NTLMSSP_FEATURE_SESSION_KEY);
1581 if (cli->use_ccache) {
1582 ntlmssp_want_feature(state->ntlmssp_state,
1583 NTLMSSP_FEATURE_CCACHE);
1585 status = ntlmssp_set_username(state->ntlmssp_state, user);
1586 if (!NT_STATUS_IS_OK(status)) {
1587 goto fail;
1589 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1590 if (!NT_STATUS_IS_OK(status)) {
1591 goto fail;
1593 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1594 if (!NT_STATUS_IS_OK(status)) {
1595 goto fail;
1597 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1598 &blob_out);
1599 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1600 goto fail;
1603 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1604 data_blob_free(&blob_out);
1606 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1607 if (tevent_req_nomem(subreq, req)) {
1608 return tevent_req_post(req, ev);
1610 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1611 return req;
1612 fail:
1613 tevent_req_nterror(req, status);
1614 return tevent_req_post(req, ev);
1617 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1619 struct tevent_req *req = tevent_req_callback_data(
1620 subreq, struct tevent_req);
1621 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1622 req, struct cli_session_setup_ntlmssp_state);
1623 DATA_BLOB blob_in, msg_in, blob_out;
1624 char *inbuf = NULL;
1625 bool parse_ret;
1626 NTSTATUS status;
1628 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1629 &inbuf);
1630 TALLOC_FREE(subreq);
1631 data_blob_free(&state->blob_out);
1633 if (NT_STATUS_IS_OK(status)) {
1634 if (state->cli->server_domain[0] == '\0') {
1635 TALLOC_FREE(state->cli->server_domain);
1636 state->cli->server_domain = talloc_strdup(state->cli,
1637 state->ntlmssp_state->server.netbios_domain);
1638 if (state->cli->server_domain == NULL) {
1639 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1640 return;
1643 cli_set_session_key(
1644 state->cli, state->ntlmssp_state->session_key);
1646 if (cli_simple_set_signing(
1647 state->cli, state->ntlmssp_state->session_key,
1648 data_blob_null)
1649 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1650 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1651 return;
1653 TALLOC_FREE(state->ntlmssp_state);
1654 tevent_req_done(req);
1655 return;
1657 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1658 tevent_req_nterror(req, status);
1659 return;
1662 if (blob_in.length == 0) {
1663 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1664 return;
1667 if ((state->turn == 1)
1668 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1669 DATA_BLOB tmp_blob = data_blob_null;
1670 /* the server might give us back two challenges */
1671 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1672 &tmp_blob);
1673 data_blob_free(&tmp_blob);
1674 } else {
1675 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1676 OID_NTLMSSP, &msg_in);
1678 state->turn += 1;
1680 if (!parse_ret) {
1681 DEBUG(3,("Failed to parse auth response\n"));
1682 if (NT_STATUS_IS_OK(status)
1683 || NT_STATUS_EQUAL(status,
1684 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1685 tevent_req_nterror(
1686 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1687 return;
1691 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1693 if (!NT_STATUS_IS_OK(status)
1694 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1695 TALLOC_FREE(state->ntlmssp_state);
1696 tevent_req_nterror(req, status);
1697 return;
1700 state->blob_out = spnego_gen_auth(state, blob_out);
1701 if (tevent_req_nomem(state->blob_out.data, req)) {
1702 return;
1705 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1706 state->blob_out);
1707 if (tevent_req_nomem(subreq, req)) {
1708 return;
1710 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1713 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1715 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1716 req, struct cli_session_setup_ntlmssp_state);
1717 NTSTATUS status;
1719 if (tevent_req_is_nterror(req, &status)) {
1720 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1721 return status;
1723 return NT_STATUS_OK;
1726 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1727 const char *user,
1728 const char *pass,
1729 const char *domain)
1731 struct tevent_context *ev;
1732 struct tevent_req *req;
1733 NTSTATUS status = NT_STATUS_NO_MEMORY;
1735 if (cli_has_async_calls(cli)) {
1736 return NT_STATUS_INVALID_PARAMETER;
1738 ev = tevent_context_init(talloc_tos());
1739 if (ev == NULL) {
1740 goto fail;
1742 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1743 if (req == NULL) {
1744 goto fail;
1746 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1747 goto fail;
1749 status = cli_session_setup_ntlmssp_recv(req);
1750 fail:
1751 TALLOC_FREE(ev);
1752 return status;
1755 /****************************************************************************
1756 Do a spnego encrypted session setup.
1758 user_domain: The shortname of the domain the user/machine is a member of.
1759 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1760 ****************************************************************************/
1762 static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
1763 const char *user,
1764 const char *pass,
1765 const char *user_domain,
1766 const char * dest_realm)
1768 char *principal = NULL;
1769 char *OIDs[ASN1_MAX_OIDS];
1770 int i;
1771 const DATA_BLOB *server_blob;
1772 DATA_BLOB blob = data_blob_null;
1773 const char *p = NULL;
1774 char *account = NULL;
1775 NTSTATUS status;
1777 server_blob = cli_state_server_gss_blob(cli);
1778 if (server_blob) {
1779 blob = data_blob(server_blob->data, server_blob->length);
1782 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)blob.length));
1784 /* the server might not even do spnego */
1785 if (blob.length == 0) {
1786 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1787 goto ntlmssp;
1790 #if 0
1791 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1792 #endif
1794 /* The server sent us the first part of the SPNEGO exchange in the
1795 * negprot reply. It is WRONG to depend on the principal sent in the
1796 * negprot reply, but right now we do it. If we don't receive one,
1797 * we try to best guess, then fall back to NTLM. */
1798 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1799 OIDs[0] == NULL) {
1800 data_blob_free(&blob);
1801 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1803 data_blob_free(&blob);
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 TALLOC_FREE(principal);
1823 return ADS_ERROR_NT(status);
1826 #ifdef HAVE_KRB5
1827 /* If password is set we reauthenticate to kerberos server
1828 * and do not store results */
1830 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1831 ADS_STATUS rc;
1832 const char *remote_name = cli_state_remote_name(cli);
1834 if (pass && *pass) {
1835 int ret;
1837 use_in_memory_ccache();
1838 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1840 if (ret){
1841 TALLOC_FREE(principal);
1842 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1843 if (cli->fallback_after_kerberos)
1844 goto ntlmssp;
1845 return ADS_ERROR_KRB5(ret);
1849 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1851 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1852 TALLOC_FREE(principal);
1855 if (principal == NULL &&
1856 !is_ipaddress(remote_name) &&
1857 !strequal(STAR_SMBSERVER,
1858 remote_name)) {
1859 char *realm = NULL;
1860 char *host = NULL;
1861 DEBUG(3,("cli_session_setup_spnego: using target "
1862 "hostname not SPNEGO principal\n"));
1864 host = strchr_m(remote_name, '.');
1865 if (dest_realm) {
1866 realm = SMB_STRDUP(dest_realm);
1867 if (!realm) {
1868 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1870 strupper_m(realm);
1871 } else {
1872 if (host) {
1873 /* DNS name. */
1874 realm = kerberos_get_realm_from_hostname(remote_name);
1875 } else {
1876 /* NetBIOS name - use our realm. */
1877 realm = kerberos_get_default_realm_from_ccache();
1881 if (realm == NULL || *realm == '\0') {
1882 realm = SMB_STRDUP(lp_realm());
1883 if (!realm) {
1884 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1886 strupper_m(realm);
1887 DEBUG(3,("cli_session_setup_spnego: cannot "
1888 "get realm from dest_realm %s, "
1889 "desthost %s. Using default "
1890 "smb.conf realm %s\n",
1891 dest_realm ? dest_realm : "<null>",
1892 remote_name,
1893 realm));
1896 principal = talloc_asprintf(talloc_tos(),
1897 "cifs/%s@%s",
1898 remote_name,
1899 realm);
1900 if (!principal) {
1901 SAFE_FREE(realm);
1902 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1904 DEBUG(3,("cli_session_setup_spnego: guessed "
1905 "server principal=%s\n",
1906 principal ? principal : "<null>"));
1908 SAFE_FREE(realm);
1911 if (principal) {
1912 rc = cli_session_setup_kerberos(cli, principal);
1913 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1914 TALLOC_FREE(principal);
1915 return rc;
1919 #endif
1921 TALLOC_FREE(principal);
1923 ntlmssp:
1925 account = talloc_strdup(talloc_tos(), user);
1926 if (!account) {
1927 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1930 /* when falling back to ntlmssp while authenticating with a machine
1931 * account strip off the realm - gd */
1933 if ((p = strchr_m(user, '@')) != NULL) {
1934 account[PTR_DIFF(p,user)] = '\0';
1937 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1940 /****************************************************************************
1941 Send a session setup. The username and workgroup is in UNIX character
1942 format and must be converted to DOS codepage format before sending. If the
1943 password is in plaintext, the same should be done.
1944 ****************************************************************************/
1946 NTSTATUS cli_session_setup(struct cli_state *cli,
1947 const char *user,
1948 const char *pass, int passlen,
1949 const char *ntpass, int ntpasslen,
1950 const char *workgroup)
1952 char *p;
1953 char *user2;
1954 uint16_t sec_mode = cli_state_security_mode(cli);
1956 if (user) {
1957 user2 = talloc_strdup(talloc_tos(), user);
1958 } else {
1959 user2 = talloc_strdup(talloc_tos(), "");
1961 if (user2 == NULL) {
1962 return NT_STATUS_NO_MEMORY;
1965 if (!workgroup) {
1966 workgroup = "";
1969 /* allow for workgroups as part of the username */
1970 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1971 (p=strchr_m(user2,*lp_winbind_separator()))) {
1972 *p = 0;
1973 user = p+1;
1974 strupper_m(user2);
1975 workgroup = user2;
1978 if (cli_state_protocol(cli) < PROTOCOL_LANMAN1) {
1980 * Ensure cli->server_domain,
1981 * cli->server_os and cli->server_type
1982 * are valid pointers.
1984 cli->server_domain = talloc_strdup(cli, "");
1985 cli->server_os = talloc_strdup(cli, "");
1986 cli->server_type = talloc_strdup(cli, "");
1987 if (cli->server_domain == NULL ||
1988 cli->server_os == NULL ||
1989 cli->server_type == NULL) {
1990 return NT_STATUS_NO_MEMORY;
1992 return NT_STATUS_OK;
1995 /* now work out what sort of session setup we are going to
1996 do. I have split this into separate functions to make the
1997 flow a bit easier to understand (tridge) */
1999 /* if its an older server then we have to use the older request format */
2001 if (cli_state_protocol(cli) < PROTOCOL_NT1) {
2002 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2003 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2004 " or 'client ntlmv2 auth = yes'\n"));
2005 return NT_STATUS_ACCESS_DENIED;
2008 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2009 !lp_client_plaintext_auth() && (*pass)) {
2010 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2011 " or 'client ntlmv2 auth = yes'\n"));
2012 return NT_STATUS_ACCESS_DENIED;
2015 return cli_session_setup_lanman2(cli, user, pass, passlen,
2016 workgroup);
2019 /* if no user is supplied then we have to do an anonymous connection.
2020 passwords are ignored */
2022 if (!user || !*user)
2023 return cli_session_setup_guest(cli);
2025 /* if the server is share level then send a plaintext null
2026 password at this point. The password is sent in the tree
2027 connect */
2029 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2030 return cli_session_setup_plain(cli, user, "", workgroup);
2032 /* if the server doesn't support encryption then we have to use
2033 plaintext. The second password is ignored */
2035 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2036 if (!lp_client_plaintext_auth() && (*pass)) {
2037 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2038 " or 'client ntlmv2 auth = yes'\n"));
2039 return NT_STATUS_ACCESS_DENIED;
2041 return cli_session_setup_plain(cli, user, pass, workgroup);
2044 /* if the server supports extended security then use SPNEGO */
2046 if (cli_state_capabilities(cli) & CAP_EXTENDED_SECURITY) {
2047 const char *remote_realm = cli_state_remote_realm(cli);
2048 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2049 workgroup,
2050 remote_realm);
2051 if (!ADS_ERR_OK(status)) {
2052 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2053 return ads_ntstatus(status);
2055 } else {
2056 NTSTATUS status;
2058 /* otherwise do a NT1 style session setup */
2059 status = cli_session_setup_nt1(cli, user, pass, passlen,
2060 ntpass, ntpasslen, workgroup);
2061 if (!NT_STATUS_IS_OK(status)) {
2062 DEBUG(3,("cli_session_setup: NT1 session setup "
2063 "failed: %s\n", nt_errstr(status)));
2064 return status;
2068 return NT_STATUS_OK;
2071 /****************************************************************************
2072 Send a uloggoff.
2073 *****************************************************************************/
2075 struct cli_ulogoff_state {
2076 struct cli_state *cli;
2077 uint16_t vwv[3];
2080 static void cli_ulogoff_done(struct tevent_req *subreq);
2082 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2083 struct tevent_context *ev,
2084 struct cli_state *cli)
2086 struct tevent_req *req, *subreq;
2087 struct cli_ulogoff_state *state;
2089 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2090 if (req == NULL) {
2091 return NULL;
2093 state->cli = cli;
2095 SCVAL(state->vwv+0, 0, 0xFF);
2096 SCVAL(state->vwv+1, 0, 0);
2097 SSVAL(state->vwv+2, 0, 0);
2099 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2100 0, NULL);
2101 if (tevent_req_nomem(subreq, req)) {
2102 return tevent_req_post(req, ev);
2104 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2105 return req;
2108 static void cli_ulogoff_done(struct tevent_req *subreq)
2110 struct tevent_req *req = tevent_req_callback_data(
2111 subreq, struct tevent_req);
2112 struct cli_ulogoff_state *state = tevent_req_data(
2113 req, struct cli_ulogoff_state);
2114 NTSTATUS status;
2116 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2117 if (!NT_STATUS_IS_OK(status)) {
2118 tevent_req_nterror(req, status);
2119 return;
2121 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2122 tevent_req_done(req);
2125 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2127 return tevent_req_simple_recv_ntstatus(req);
2130 NTSTATUS cli_ulogoff(struct cli_state *cli)
2132 struct tevent_context *ev;
2133 struct tevent_req *req;
2134 NTSTATUS status = NT_STATUS_NO_MEMORY;
2136 if (cli_has_async_calls(cli)) {
2137 return NT_STATUS_INVALID_PARAMETER;
2139 ev = tevent_context_init(talloc_tos());
2140 if (ev == NULL) {
2141 goto fail;
2143 req = cli_ulogoff_send(ev, ev, cli);
2144 if (req == NULL) {
2145 goto fail;
2147 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2148 goto fail;
2150 status = cli_ulogoff_recv(req);
2151 fail:
2152 TALLOC_FREE(ev);
2153 return status;
2156 /****************************************************************************
2157 Send a tconX.
2158 ****************************************************************************/
2160 struct cli_tcon_andx_state {
2161 struct cli_state *cli;
2162 uint16_t vwv[4];
2163 struct iovec bytes;
2166 static void cli_tcon_andx_done(struct tevent_req *subreq);
2168 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2169 struct event_context *ev,
2170 struct cli_state *cli,
2171 const char *share, const char *dev,
2172 const char *pass, int passlen,
2173 struct tevent_req **psmbreq)
2175 struct tevent_req *req, *subreq;
2176 struct cli_tcon_andx_state *state;
2177 uint8_t p24[24];
2178 uint16_t *vwv;
2179 char *tmp = NULL;
2180 uint8_t *bytes;
2181 uint16_t sec_mode = cli_state_security_mode(cli);
2183 *psmbreq = NULL;
2185 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2186 if (req == NULL) {
2187 return NULL;
2189 state->cli = cli;
2190 vwv = state->vwv;
2192 cli->share = talloc_strdup(cli, share);
2193 if (!cli->share) {
2194 return NULL;
2197 /* in user level security don't send a password now */
2198 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2199 passlen = 1;
2200 pass = "";
2201 } else if (pass == NULL) {
2202 DEBUG(1, ("Server not using user level security and no "
2203 "password supplied.\n"));
2204 goto access_denied;
2207 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2208 *pass && passlen != 24) {
2209 if (!lp_client_lanman_auth()) {
2210 DEBUG(1, ("Server requested LANMAN password "
2211 "(share-level security) but "
2212 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2213 goto access_denied;
2217 * Non-encrypted passwords - convert to DOS codepage before
2218 * encryption.
2220 SMBencrypt(pass, cli_state_server_challenge(cli), p24);
2221 passlen = 24;
2222 pass = (const char *)p24;
2223 } else {
2224 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2225 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2226 == 0) {
2227 uint8_t *tmp_pass;
2229 if (!lp_client_plaintext_auth() && (*pass)) {
2230 DEBUG(1, ("Server requested plaintext "
2231 "password but "
2232 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2233 goto access_denied;
2237 * Non-encrypted passwords - convert to DOS codepage
2238 * before using.
2240 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2241 if (tevent_req_nomem(tmp_pass, req)) {
2242 return tevent_req_post(req, ev);
2244 tmp_pass = trans2_bytes_push_str(tmp_pass,
2245 false, /* always DOS */
2246 pass,
2247 passlen,
2248 NULL);
2249 if (tevent_req_nomem(tmp_pass, req)) {
2250 return tevent_req_post(req, ev);
2252 pass = (const char *)tmp_pass;
2253 passlen = talloc_get_size(tmp_pass);
2257 SCVAL(vwv+0, 0, 0xFF);
2258 SCVAL(vwv+0, 1, 0);
2259 SSVAL(vwv+1, 0, 0);
2260 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2261 SSVAL(vwv+3, 0, passlen);
2263 if (passlen && pass) {
2264 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2265 } else {
2266 bytes = talloc_array(state, uint8_t, 0);
2270 * Add the sharename
2272 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2273 cli_state_remote_name(cli), share);
2274 if (tmp == NULL) {
2275 TALLOC_FREE(req);
2276 return NULL;
2278 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2279 NULL);
2280 TALLOC_FREE(tmp);
2283 * Add the devicetype
2285 tmp = talloc_strdup_upper(talloc_tos(), dev);
2286 if (tmp == NULL) {
2287 TALLOC_FREE(req);
2288 return NULL;
2290 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2291 TALLOC_FREE(tmp);
2293 if (bytes == NULL) {
2294 TALLOC_FREE(req);
2295 return NULL;
2298 state->bytes.iov_base = (void *)bytes;
2299 state->bytes.iov_len = talloc_get_size(bytes);
2301 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2302 1, &state->bytes);
2303 if (subreq == NULL) {
2304 TALLOC_FREE(req);
2305 return NULL;
2307 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2308 *psmbreq = subreq;
2309 return req;
2311 access_denied:
2312 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2313 return tevent_req_post(req, ev);
2316 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2317 struct event_context *ev,
2318 struct cli_state *cli,
2319 const char *share, const char *dev,
2320 const char *pass, int passlen)
2322 struct tevent_req *req, *subreq;
2323 NTSTATUS status;
2325 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2326 &subreq);
2327 if (req == NULL) {
2328 return NULL;
2330 if (subreq == NULL) {
2331 return req;
2333 status = cli_smb_req_send(subreq);
2334 if (!NT_STATUS_IS_OK(status)) {
2335 tevent_req_nterror(req, status);
2336 return tevent_req_post(req, ev);
2338 return req;
2341 static void cli_tcon_andx_done(struct tevent_req *subreq)
2343 struct tevent_req *req = tevent_req_callback_data(
2344 subreq, struct tevent_req);
2345 struct cli_tcon_andx_state *state = tevent_req_data(
2346 req, struct cli_tcon_andx_state);
2347 struct cli_state *cli = state->cli;
2348 uint8_t *in;
2349 char *inbuf;
2350 uint8_t wct;
2351 uint16_t *vwv;
2352 uint32_t num_bytes;
2353 uint8_t *bytes;
2354 NTSTATUS status;
2356 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2357 &num_bytes, &bytes);
2358 TALLOC_FREE(subreq);
2359 if (!NT_STATUS_IS_OK(status)) {
2360 tevent_req_nterror(req, status);
2361 return;
2364 inbuf = (char *)in;
2366 if (num_bytes) {
2367 if (clistr_pull_talloc(cli,
2368 inbuf,
2369 SVAL(inbuf, smb_flg2),
2370 &cli->dev,
2371 bytes,
2372 num_bytes,
2373 STR_TERMINATE|STR_ASCII) == -1) {
2374 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2375 return;
2377 } else {
2378 cli->dev = talloc_strdup(cli, "");
2379 if (cli->dev == NULL) {
2380 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2381 return;
2385 if ((cli_state_protocol(cli) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2386 /* almost certainly win95 - enable bug fixes */
2387 cli->win95 = True;
2391 * Make sure that we have the optional support 16-bit field. WCT > 2.
2392 * Avoids issues when connecting to Win9x boxes sharing files
2395 cli->dfsroot = false;
2397 if ((wct > 2) && (cli_state_protocol(cli) >= PROTOCOL_LANMAN2)) {
2398 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2401 cli->smb1.tid = SVAL(inbuf,smb_tid);
2402 tevent_req_done(req);
2405 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2407 return tevent_req_simple_recv_ntstatus(req);
2410 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2411 const char *dev, const char *pass, int passlen)
2413 TALLOC_CTX *frame = talloc_stackframe();
2414 struct event_context *ev;
2415 struct tevent_req *req;
2416 NTSTATUS status = NT_STATUS_OK;
2418 if (cli_has_async_calls(cli)) {
2420 * Can't use sync call while an async call is in flight
2422 status = NT_STATUS_INVALID_PARAMETER;
2423 goto fail;
2426 ev = event_context_init(frame);
2427 if (ev == NULL) {
2428 status = NT_STATUS_NO_MEMORY;
2429 goto fail;
2432 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2433 if (req == NULL) {
2434 status = NT_STATUS_NO_MEMORY;
2435 goto fail;
2438 if (!tevent_req_poll(req, ev)) {
2439 status = map_nt_error_from_unix(errno);
2440 goto fail;
2443 status = cli_tcon_andx_recv(req);
2444 fail:
2445 TALLOC_FREE(frame);
2446 return status;
2449 /****************************************************************************
2450 Send a tree disconnect.
2451 ****************************************************************************/
2453 struct cli_tdis_state {
2454 struct cli_state *cli;
2457 static void cli_tdis_done(struct tevent_req *subreq);
2459 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2460 struct tevent_context *ev,
2461 struct cli_state *cli)
2463 struct tevent_req *req, *subreq;
2464 struct cli_tdis_state *state;
2466 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2467 if (req == NULL) {
2468 return NULL;
2470 state->cli = cli;
2472 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2473 if (tevent_req_nomem(subreq, req)) {
2474 return tevent_req_post(req, ev);
2476 tevent_req_set_callback(subreq, cli_tdis_done, req);
2477 return req;
2480 static void cli_tdis_done(struct tevent_req *subreq)
2482 struct tevent_req *req = tevent_req_callback_data(
2483 subreq, struct tevent_req);
2484 struct cli_tdis_state *state = tevent_req_data(
2485 req, struct cli_tdis_state);
2486 NTSTATUS status;
2488 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2489 TALLOC_FREE(subreq);
2490 if (!NT_STATUS_IS_OK(status)) {
2491 tevent_req_nterror(req, status);
2492 return;
2494 state->cli->smb1.tid = UINT16_MAX;
2495 tevent_req_done(req);
2498 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2500 return tevent_req_simple_recv_ntstatus(req);
2503 NTSTATUS cli_tdis(struct cli_state *cli)
2505 struct tevent_context *ev;
2506 struct tevent_req *req;
2507 NTSTATUS status = NT_STATUS_NO_MEMORY;
2509 if (cli_has_async_calls(cli)) {
2510 return NT_STATUS_INVALID_PARAMETER;
2512 ev = tevent_context_init(talloc_tos());
2513 if (ev == NULL) {
2514 goto fail;
2516 req = cli_tdis_send(ev, ev, cli);
2517 if (req == NULL) {
2518 goto fail;
2520 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2521 goto fail;
2523 status = cli_tdis_recv(req);
2524 fail:
2525 TALLOC_FREE(ev);
2526 return status;
2529 /****************************************************************************
2530 Send a negprot command.
2531 ****************************************************************************/
2533 struct cli_negprot_state {
2534 struct cli_state *cli;
2535 enum protocol_types max_protocol;
2538 static void cli_negprot_done(struct tevent_req *subreq);
2540 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2541 struct event_context *ev,
2542 struct cli_state *cli,
2543 enum protocol_types max_protocol)
2545 struct tevent_req *req, *subreq;
2546 struct cli_negprot_state *state;
2547 uint8_t *bytes = NULL;
2548 int numprots;
2549 enum protocol_types tmp_protocol;
2551 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2552 if (req == NULL) {
2553 return NULL;
2555 state->cli = cli;
2556 state->max_protocol = max_protocol;
2558 /* setup the protocol strings */
2559 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2560 uint8_t c = 2;
2561 if (prots[numprots].prot > state->max_protocol) {
2562 break;
2564 bytes = (uint8_t *)talloc_append_blob(
2565 state, bytes, data_blob_const(&c, sizeof(c)));
2566 if (tevent_req_nomem(bytes, req)) {
2567 return tevent_req_post(req, ev);
2569 bytes = smb_bytes_push_str(bytes, false,
2570 prots[numprots].name,
2571 strlen(prots[numprots].name)+1,
2572 NULL);
2573 if (tevent_req_nomem(bytes, req)) {
2574 return tevent_req_post(req, ev);
2578 tmp_protocol = cli->conn.protocol;
2579 cli->conn.protocol = state->max_protocol;
2580 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2581 talloc_get_size(bytes), bytes);
2582 cli->conn.protocol = tmp_protocol;
2583 if (tevent_req_nomem(subreq, req)) {
2584 return tevent_req_post(req, ev);
2586 tevent_req_set_callback(subreq, cli_negprot_done, req);
2587 return req;
2590 static void cli_negprot_done(struct tevent_req *subreq)
2592 struct tevent_req *req = tevent_req_callback_data(
2593 subreq, struct tevent_req);
2594 struct cli_negprot_state *state = tevent_req_data(
2595 req, struct cli_negprot_state);
2596 struct cli_state *cli = state->cli;
2597 uint8_t flags;
2598 uint8_t wct;
2599 uint16_t *vwv;
2600 uint32_t num_bytes;
2601 uint8_t *bytes;
2602 NTSTATUS status;
2603 uint16_t protnum;
2604 uint8_t *inbuf;
2605 uint32_t client_capabilities = cli->conn.smb1.client.capabilities;
2606 uint32_t both_capabilities;
2607 uint32_t server_capabilities = 0;
2608 uint32_t capabilities;
2609 uint32_t client_max_xmit = cli->conn.smb1.client.max_xmit;
2610 uint32_t server_max_xmit = 0;
2611 uint32_t max_xmit;
2612 uint32_t server_max_mux = 0;
2613 uint16_t server_security_mode = 0;
2614 uint32_t server_session_key = 0;
2615 bool server_readbraw = false;
2616 bool server_writebraw = false;
2617 bool server_lockread = false;
2618 bool server_writeunlock = false;
2619 struct GUID server_guid = GUID_zero();
2620 DATA_BLOB server_gss_blob = data_blob_null;
2621 uint8_t server_challenge[8];
2622 char *server_workgroup = NULL;
2623 char *server_name = NULL;
2624 int server_time_zone = 0;
2625 time_t server_system_time = 0;
2626 enum protocol_types protocol;
2628 ZERO_STRUCT(server_challenge);
2630 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2631 &num_bytes, &bytes);
2632 TALLOC_FREE(subreq);
2633 if (!NT_STATUS_IS_OK(status)) {
2634 tevent_req_nterror(req, status);
2635 return;
2638 flags = CVAL(inbuf, smb_flg);
2640 protnum = SVAL(vwv, 0);
2642 if ((protnum >= ARRAY_SIZE(prots))
2643 || (prots[protnum].prot > state->max_protocol)) {
2644 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2645 return;
2648 protocol = prots[protnum].prot;
2650 if ((protocol < PROTOCOL_NT1) &&
2651 client_is_signing_mandatory(cli)) {
2652 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2653 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2654 return;
2657 if (flags & FLAG_SUPPORT_LOCKREAD) {
2658 server_lockread = true;
2659 server_writeunlock = true;
2662 if (protocol >= PROTOCOL_NT1) {
2663 struct timespec ts;
2664 const char *client_signing = NULL;
2665 bool server_mandatory;
2666 bool server_allowed;
2667 const char *server_signing = NULL;
2668 bool ok;
2669 uint16_t key_len;
2671 if (wct != 0x11) {
2672 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2673 return;
2676 /* NT protocol */
2677 server_security_mode = CVAL(vwv + 1, 0);
2678 server_max_mux = SVAL(vwv + 1, 1);
2679 server_max_xmit = IVAL(vwv + 3, 1);
2680 server_session_key = IVAL(vwv + 7, 1);
2681 server_time_zone = SVALS(vwv + 15, 1);
2682 server_time_zone *= 60;
2683 /* this time arrives in real GMT */
2684 ts = interpret_long_date(((char *)(vwv+11))+1);
2685 server_system_time = ts.tv_sec;
2686 server_capabilities = IVAL(vwv + 9, 1);
2688 key_len = CVAL(vwv + 16, 1);
2690 if (server_capabilities & CAP_RAW_MODE) {
2691 server_readbraw = true;
2692 server_writebraw = true;
2694 if (server_capabilities & CAP_LOCK_AND_READ) {
2695 server_lockread = true;
2698 if (server_capabilities & CAP_EXTENDED_SECURITY) {
2699 DATA_BLOB blob1, blob2;
2701 if (num_bytes < 16) {
2702 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2703 return;
2706 blob1 = data_blob_const(bytes, 16);
2707 GUID_from_data_blob(&blob1, &server_guid);
2709 blob1 = data_blob_const(bytes+16, num_bytes-16);
2710 blob2 = data_blob_dup_talloc(state, blob1);
2711 if (blob1.length > 0 &&
2712 tevent_req_nomem(blob2.data, req)) {
2713 return;
2715 server_gss_blob = blob2;
2716 } else {
2717 DATA_BLOB blob1, blob2;
2718 ssize_t ret = 0;
2720 if (num_bytes < key_len) {
2721 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2722 return;
2725 if (key_len != 0 && key_len != 8) {
2726 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2727 return;
2730 if (key_len == 8) {
2731 memcpy(server_challenge, bytes, 8);
2734 blob1 = data_blob_const(bytes+key_len, num_bytes-key_len);
2735 blob2 = data_blob_const(bytes+key_len, num_bytes-key_len);
2736 if (blob1.length > 0) {
2737 ret = pull_string_talloc(state,
2738 (char *)inbuf,
2739 SVAL(inbuf, smb_flg2),
2740 &server_workgroup,
2741 blob1.data,
2742 blob1.length,
2743 STR_TERMINATE|
2744 STR_UNICODE|
2745 STR_NOALIGN);
2746 if (ret == -1) {
2747 tevent_req_oom(req);
2748 return;
2752 blob2.data += ret;
2753 blob2.length -= ret;
2754 if (blob2.length > 0) {
2755 ret = pull_string_talloc(state,
2756 (char *)inbuf,
2757 SVAL(inbuf, smb_flg2),
2758 &server_name,
2759 blob2.data,
2760 blob2.length,
2761 STR_TERMINATE|
2762 STR_UNICODE|
2763 STR_NOALIGN);
2764 if (ret == -1) {
2765 tevent_req_oom(req);
2766 return;
2771 client_signing = "disabled";
2772 if (client_is_signing_allowed(cli)) {
2773 client_signing = "allowed";
2775 if (client_is_signing_mandatory(cli)) {
2776 client_signing = "required";
2779 server_signing = "not supported";
2781 server_allowed = false;
2782 if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2783 server_signing = "supported";
2784 server_allowed = true;
2787 server_mandatory = false;
2788 if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2789 server_signing = "required";
2790 server_mandatory = true;
2793 ok = cli_set_signing_negotiated(cli,
2794 server_allowed,
2795 server_mandatory);
2796 if (!ok) {
2797 DEBUG(1,("cli_negprot: SMB signing is required, "
2798 "but client[%s] and server[%s] mismatch\n",
2799 client_signing, server_signing));
2800 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2801 return;
2804 } else if (protocol >= PROTOCOL_LANMAN1) {
2805 if (wct != 0x0D) {
2806 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2807 return;
2810 server_security_mode = SVAL(vwv + 1, 0);
2811 server_max_xmit = SVAL(vwv + 2, 0);
2812 server_max_mux = SVAL(vwv + 3, 0);
2813 server_session_key = IVAL(vwv + 6, 0);
2814 server_time_zone = SVALS(vwv + 10, 0);
2815 server_time_zone *= 60;
2816 /* this time is converted to GMT by make_unix_date */
2817 server_system_time = make_unix_date(
2818 (char *)(vwv + 8), server_time_zone);
2819 server_readbraw = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2820 server_writebraw = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2822 if (num_bytes != 0 && num_bytes != 8) {
2823 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2824 return;
2827 if (num_bytes == 8) {
2828 memcpy(server_challenge, bytes, 8);
2830 } else {
2831 /* the old core protocol */
2832 server_time_zone = get_time_zone(time(NULL));
2833 server_system_time = 0;
2834 server_max_xmit = 1024;
2835 server_max_mux = 1;
2836 server_security_mode = 0;
2839 if (server_max_xmit < 1024) {
2840 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2841 return;
2844 if (server_max_mux < 1) {
2845 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2846 return;
2850 * Now calculate the negotiated capabilities
2851 * based on the mask for:
2852 * - client only flags
2853 * - flags used in both directions
2854 * - server only flags
2856 both_capabilities = client_capabilities & server_capabilities;
2857 capabilities = client_capabilities & SMB_CAP_CLIENT_MASK;
2858 capabilities |= both_capabilities & SMB_CAP_BOTH_MASK;
2859 capabilities |= server_capabilities & SMB_CAP_SERVER_MASK;
2861 max_xmit = MIN(client_max_xmit, server_max_xmit);
2863 if (server_workgroup) {
2864 cli->server_domain = talloc_strdup(cli, server_workgroup);
2865 if (tevent_req_nomem(cli->server_domain, req)) {
2866 return;
2870 cli->conn.protocol = protocol;
2872 cli->conn.smb1.server.capabilities = server_capabilities;
2873 cli->conn.smb1.capabilities = capabilities;
2875 cli->conn.smb1.server.max_xmit = server_max_xmit;
2876 cli->conn.smb1.max_xmit = max_xmit;
2878 cli->conn.smb1.server.max_mux = server_max_mux;
2880 cli->conn.smb1.server.security_mode = server_security_mode;
2882 cli->conn.smb1.server.readbraw = server_readbraw;
2883 cli->conn.smb1.server.writebraw = server_writebraw;
2884 cli->conn.smb1.server.lockread = server_lockread;
2885 cli->conn.smb1.server.writeunlock = server_writeunlock;
2887 cli->conn.smb1.server.session_key = server_session_key;
2889 talloc_steal(cli, server_gss_blob.data);
2890 cli->conn.smb1.server.gss_blob = server_gss_blob;
2891 cli->conn.smb1.server.guid = server_guid;
2892 memcpy(cli->conn.smb1.server.challenge, server_challenge, 8);
2893 cli->conn.smb1.server.workgroup = talloc_move(cli, &server_workgroup);
2894 cli->conn.smb1.server.name = talloc_move(cli, &server_name);
2896 cli->conn.smb1.server.time_zone = server_time_zone;
2897 cli->conn.smb1.server.system_time = server_system_time;
2899 tevent_req_done(req);
2902 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2904 return tevent_req_simple_recv_ntstatus(req);
2907 NTSTATUS cli_negprot(struct cli_state *cli, enum protocol_types max_protocol)
2909 TALLOC_CTX *frame = talloc_stackframe();
2910 struct event_context *ev;
2911 struct tevent_req *req;
2912 NTSTATUS status = NT_STATUS_OK;
2914 if (cli_has_async_calls(cli)) {
2916 * Can't use sync call while an async call is in flight
2918 status = NT_STATUS_INVALID_PARAMETER;
2919 goto fail;
2922 ev = event_context_init(frame);
2923 if (ev == NULL) {
2924 status = NT_STATUS_NO_MEMORY;
2925 goto fail;
2928 req = cli_negprot_send(frame, ev, cli, max_protocol);
2929 if (req == NULL) {
2930 status = NT_STATUS_NO_MEMORY;
2931 goto fail;
2934 if (!tevent_req_poll(req, ev)) {
2935 status = map_nt_error_from_unix(errno);
2936 goto fail;
2939 status = cli_negprot_recv(req);
2940 fail:
2941 TALLOC_FREE(frame);
2942 return status;
2945 static NTSTATUS cli_connect_sock(const char *host, int name_type,
2946 const struct sockaddr_storage *pss,
2947 const char *myname, uint16_t port,
2948 int sec_timeout, int *pfd, uint16_t *pport)
2950 TALLOC_CTX *frame = talloc_stackframe();
2951 const char *prog;
2952 unsigned int i, num_addrs;
2953 const char **called_names;
2954 const char **calling_names;
2955 int *called_types;
2956 NTSTATUS status;
2957 int fd;
2959 prog = getenv("LIBSMB_PROG");
2960 if (prog != NULL) {
2961 fd = sock_exec(prog);
2962 if (fd == -1) {
2963 return map_nt_error_from_unix(errno);
2965 port = 0;
2966 goto done;
2969 if ((pss == NULL) || is_zero_addr(pss)) {
2970 struct sockaddr_storage *addrs;
2971 status = resolve_name_list(talloc_tos(), host, name_type,
2972 &addrs, &num_addrs);
2973 if (!NT_STATUS_IS_OK(status)) {
2974 goto fail;
2976 pss = addrs;
2977 } else {
2978 num_addrs = 1;
2981 called_names = talloc_array(talloc_tos(), const char *, num_addrs);
2982 if (called_names == NULL) {
2983 status = NT_STATUS_NO_MEMORY;
2984 goto fail;
2986 called_types = talloc_array(talloc_tos(), int, num_addrs);
2987 if (called_types == NULL) {
2988 status = NT_STATUS_NO_MEMORY;
2989 goto fail;
2991 calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
2992 if (calling_names == NULL) {
2993 status = NT_STATUS_NO_MEMORY;
2994 goto fail;
2996 for (i=0; i<num_addrs; i++) {
2997 called_names[i] = host;
2998 called_types[i] = name_type;
2999 calling_names[i] = myname;
3001 status = smbsock_any_connect(pss, called_names, called_types,
3002 calling_names, NULL, num_addrs, port,
3003 sec_timeout, &fd, NULL, &port);
3004 if (!NT_STATUS_IS_OK(status)) {
3005 goto fail;
3007 set_socket_options(fd, lp_socket_options());
3008 done:
3009 *pfd = fd;
3010 *pport = port;
3011 status = NT_STATUS_OK;
3012 fail:
3013 TALLOC_FREE(frame);
3014 return status;
3017 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
3018 uint16_t port, int name_type, const char *myname,
3019 int signing_state, int flags, struct cli_state **pcli)
3021 TALLOC_CTX *frame = talloc_stackframe();
3022 struct cli_state *cli;
3023 NTSTATUS status = NT_STATUS_NO_MEMORY;
3024 int fd = -1;
3025 char *desthost;
3026 char *p;
3028 desthost = talloc_strdup(talloc_tos(), host);
3029 if (desthost == NULL) {
3030 goto fail;
3033 p = strchr(host, '#');
3034 if (p != NULL) {
3035 name_type = strtol(p+1, NULL, 16);
3036 host = talloc_strndup(talloc_tos(), host, p - host);
3037 if (host == NULL) {
3038 goto fail;
3042 status = cli_connect_sock(host, name_type, dest_ss, myname, port,
3043 20, &fd, &port);
3044 if (!NT_STATUS_IS_OK(status)) {
3045 goto fail;
3048 cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
3049 if (cli == NULL) {
3050 goto fail;
3053 *pcli = cli;
3054 status = NT_STATUS_OK;
3055 fail:
3056 TALLOC_FREE(frame);
3057 return status;
3061 establishes a connection to after the negprot.
3062 @param output_cli A fully initialised cli structure, non-null only on success
3063 @param dest_host The netbios name of the remote host
3064 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3065 @param port (optional) The destination port (0 for default)
3067 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3068 const char *my_name,
3069 const char *dest_host,
3070 const struct sockaddr_storage *dest_ss, int port,
3071 int signing_state, int flags)
3073 NTSTATUS nt_status;
3074 struct cli_state *cli;
3076 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
3077 signing_state, flags, &cli);
3078 if (!NT_STATUS_IS_OK(nt_status)) {
3079 DEBUG(10, ("cli_connect_nb failed: %s\n",
3080 nt_errstr(nt_status)));
3081 return nt_status;
3084 nt_status = cli_negprot(cli, PROTOCOL_NT1);
3085 if (!NT_STATUS_IS_OK(nt_status)) {
3086 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
3087 cli_shutdown(cli);
3088 return nt_status;
3091 *output_cli = cli;
3092 return NT_STATUS_OK;
3097 establishes a connection right up to doing tconX, password specified.
3098 @param output_cli A fully initialised cli structure, non-null only on success
3099 @param dest_host The netbios name of the remote host
3100 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3101 @param port (optional) The destination port (0 for default)
3102 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3103 @param service_type The 'type' of serivice.
3104 @param user Username, unix string
3105 @param domain User's domain
3106 @param password User's password, unencrypted unix string.
3109 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3110 const char *my_name,
3111 const char *dest_host,
3112 const struct sockaddr_storage *dest_ss, int port,
3113 const char *service, const char *service_type,
3114 const char *user, const char *domain,
3115 const char *password, int flags,
3116 int signing_state)
3118 NTSTATUS nt_status;
3119 struct cli_state *cli = NULL;
3120 int pw_len = password ? strlen(password)+1 : 0;
3122 *output_cli = NULL;
3124 if (password == NULL) {
3125 password = "";
3128 nt_status = cli_start_connection(&cli, my_name, dest_host,
3129 dest_ss, port, signing_state,
3130 flags);
3132 if (!NT_STATUS_IS_OK(nt_status)) {
3133 return nt_status;
3136 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3137 pw_len, domain);
3138 if (!NT_STATUS_IS_OK(nt_status)) {
3140 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3141 DEBUG(1,("failed session setup with %s\n",
3142 nt_errstr(nt_status)));
3143 cli_shutdown(cli);
3144 return nt_status;
3147 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3148 if (!NT_STATUS_IS_OK(nt_status)) {
3149 DEBUG(1,("anonymous failed session setup with %s\n",
3150 nt_errstr(nt_status)));
3151 cli_shutdown(cli);
3152 return nt_status;
3156 if (service) {
3157 nt_status = cli_tcon_andx(cli, service, service_type, password,
3158 pw_len);
3159 if (!NT_STATUS_IS_OK(nt_status)) {
3160 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3161 cli_shutdown(cli);
3162 if (NT_STATUS_IS_OK(nt_status)) {
3163 nt_status = NT_STATUS_UNSUCCESSFUL;
3165 return nt_status;
3169 nt_status = cli_init_creds(cli, user, domain, password);
3170 if (!NT_STATUS_IS_OK(nt_status)) {
3171 cli_shutdown(cli);
3172 return nt_status;
3175 *output_cli = cli;
3176 return NT_STATUS_OK;
3179 /****************************************************************************
3180 Send an old style tcon.
3181 ****************************************************************************/
3182 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3183 const char *service, const char *pass, const char *dev,
3184 uint16 *max_xmit, uint16 *tid)
3186 struct tevent_req *req;
3187 uint16_t *ret_vwv;
3188 uint8_t *bytes;
3189 NTSTATUS status;
3191 if (!lp_client_plaintext_auth() && (*pass)) {
3192 DEBUG(1, ("Server requested plaintext password but 'client "
3193 "plaintext auth' is disabled\n"));
3194 return NT_STATUS_ACCESS_DENIED;
3197 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3198 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3199 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3200 service, strlen(service)+1, NULL);
3201 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3202 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3203 pass, strlen(pass)+1, NULL);
3204 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3205 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3206 dev, strlen(dev)+1, NULL);
3208 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3209 talloc_get_size(bytes), bytes, &req,
3210 2, NULL, &ret_vwv, NULL, NULL);
3211 if (!NT_STATUS_IS_OK(status)) {
3212 return status;
3215 *max_xmit = SVAL(ret_vwv + 0, 0);
3216 *tid = SVAL(ret_vwv + 1, 0);
3218 return NT_STATUS_OK;
3221 /* Return a cli_state pointing at the IPC$ share for the given server */
3223 struct cli_state *get_ipc_connect(char *server,
3224 struct sockaddr_storage *server_ss,
3225 const struct user_auth_info *user_info)
3227 struct cli_state *cli;
3228 NTSTATUS nt_status;
3229 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3231 if (user_info->use_kerberos) {
3232 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3235 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3236 user_info->username ? user_info->username : "",
3237 lp_workgroup(),
3238 user_info->password ? user_info->password : "",
3239 flags,
3240 SMB_SIGNING_DEFAULT);
3242 if (NT_STATUS_IS_OK(nt_status)) {
3243 return cli;
3244 } else if (is_ipaddress(server)) {
3245 /* windows 9* needs a correct NMB name for connections */
3246 fstring remote_name;
3248 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3249 cli = get_ipc_connect(remote_name, server_ss, user_info);
3250 if (cli)
3251 return cli;
3254 return NULL;
3258 * Given the IP address of a master browser on the network, return its
3259 * workgroup and connect to it.
3261 * This function is provided to allow additional processing beyond what
3262 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3263 * browsers and obtain each master browsers' list of domains (in case the
3264 * first master browser is recently on the network and has not yet
3265 * synchronized with other master browsers and therefore does not yet have the
3266 * entire network browse list)
3269 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3270 struct sockaddr_storage *mb_ip,
3271 const struct user_auth_info *user_info,
3272 char **pp_workgroup_out)
3274 char addr[INET6_ADDRSTRLEN];
3275 fstring name;
3276 struct cli_state *cli;
3277 struct sockaddr_storage server_ss;
3279 *pp_workgroup_out = NULL;
3281 print_sockaddr(addr, sizeof(addr), mb_ip);
3282 DEBUG(99, ("Looking up name of master browser %s\n",
3283 addr));
3286 * Do a name status query to find out the name of the master browser.
3287 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3288 * master browser will not respond to a wildcard query (or, at least,
3289 * an NT4 server acting as the domain master browser will not).
3291 * We might be able to use ONLY the query on MSBROWSE, but that's not
3292 * yet been tested with all Windows versions, so until it is, leave
3293 * the original wildcard query as the first choice and fall back to
3294 * MSBROWSE if the wildcard query fails.
3296 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3297 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3299 DEBUG(99, ("Could not retrieve name status for %s\n",
3300 addr));
3301 return NULL;
3304 if (!find_master_ip(name, &server_ss)) {
3305 DEBUG(99, ("Could not find master ip for %s\n", name));
3306 return NULL;
3309 *pp_workgroup_out = talloc_strdup(ctx, name);
3311 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3313 print_sockaddr(addr, sizeof(addr), &server_ss);
3314 cli = get_ipc_connect(addr, &server_ss, user_info);
3316 return cli;
3320 * Return the IP address and workgroup of a master browser on the network, and
3321 * connect to it.
3324 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3325 const struct user_auth_info *user_info,
3326 char **pp_workgroup_out)
3328 struct sockaddr_storage *ip_list;
3329 struct cli_state *cli;
3330 int i, count;
3331 NTSTATUS status;
3333 *pp_workgroup_out = NULL;
3335 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3337 /* Go looking for workgroups by broadcasting on the local network */
3339 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3340 &ip_list, &count);
3341 if (!NT_STATUS_IS_OK(status)) {
3342 DEBUG(99, ("No master browsers responded: %s\n",
3343 nt_errstr(status)));
3344 return False;
3347 for (i = 0; i < count; i++) {
3348 char addr[INET6_ADDRSTRLEN];
3349 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3350 DEBUG(99, ("Found master browser %s\n", addr));
3352 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3353 user_info, pp_workgroup_out);
3354 if (cli)
3355 return(cli);
3358 return NULL;