s3:libsmb: make use of cli_state_server_challenge()
[Samba/vl.git] / source3 / libsmb / cliconnect.c
blob865e03bde7d2c765f0886a7f2e80224d6db56362
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 "../libcli/auth/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 "read_smb.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 if (!NT_STATUS_IS_OK(status)) {
1467 TALLOC_FREE(subreq);
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 TALLOC_FREE(subreq);
1478 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1479 return;
1481 TALLOC_FREE(subreq);
1482 tevent_req_done(req);
1485 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1487 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1488 req, struct cli_session_setup_kerberos_state);
1489 NTSTATUS status;
1491 if (tevent_req_is_nterror(req, &status)) {
1492 return ADS_ERROR_NT(status);
1494 return state->ads_status;
1497 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1498 const char *principal)
1500 struct tevent_context *ev;
1501 struct tevent_req *req;
1502 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1504 if (cli_has_async_calls(cli)) {
1505 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1507 ev = tevent_context_init(talloc_tos());
1508 if (ev == NULL) {
1509 goto fail;
1511 req = cli_session_setup_kerberos_send(ev, ev, cli, principal);
1512 if (req == NULL) {
1513 goto fail;
1515 if (!tevent_req_poll(req, ev)) {
1516 status = ADS_ERROR_SYSTEM(errno);
1517 goto fail;
1519 status = cli_session_setup_kerberos_recv(req);
1520 fail:
1521 TALLOC_FREE(ev);
1522 return status;
1524 #endif /* HAVE_KRB5 */
1526 /****************************************************************************
1527 Do a spnego/NTLMSSP encrypted session setup.
1528 ****************************************************************************/
1530 struct cli_session_setup_ntlmssp_state {
1531 struct tevent_context *ev;
1532 struct cli_state *cli;
1533 struct ntlmssp_state *ntlmssp_state;
1534 int turn;
1535 DATA_BLOB blob_out;
1538 static int cli_session_setup_ntlmssp_state_destructor(
1539 struct cli_session_setup_ntlmssp_state *state)
1541 if (state->ntlmssp_state != NULL) {
1542 TALLOC_FREE(state->ntlmssp_state);
1544 return 0;
1547 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1549 static struct tevent_req *cli_session_setup_ntlmssp_send(
1550 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1551 const char *user, const char *pass, const char *domain)
1553 struct tevent_req *req, *subreq;
1554 struct cli_session_setup_ntlmssp_state *state;
1555 NTSTATUS status;
1556 DATA_BLOB blob_out;
1557 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1559 req = tevent_req_create(mem_ctx, &state,
1560 struct cli_session_setup_ntlmssp_state);
1561 if (req == NULL) {
1562 return NULL;
1564 state->ev = ev;
1565 state->cli = cli;
1566 state->turn = 1;
1568 state->ntlmssp_state = NULL;
1569 talloc_set_destructor(
1570 state, cli_session_setup_ntlmssp_state_destructor);
1572 status = ntlmssp_client_start(state,
1573 lp_netbios_name(),
1574 lp_workgroup(),
1575 lp_client_ntlmv2_auth(),
1576 &state->ntlmssp_state);
1577 if (!NT_STATUS_IS_OK(status)) {
1578 goto fail;
1580 ntlmssp_want_feature(state->ntlmssp_state,
1581 NTLMSSP_FEATURE_SESSION_KEY);
1582 if (cli->use_ccache) {
1583 ntlmssp_want_feature(state->ntlmssp_state,
1584 NTLMSSP_FEATURE_CCACHE);
1586 status = ntlmssp_set_username(state->ntlmssp_state, user);
1587 if (!NT_STATUS_IS_OK(status)) {
1588 goto fail;
1590 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1591 if (!NT_STATUS_IS_OK(status)) {
1592 goto fail;
1594 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1595 if (!NT_STATUS_IS_OK(status)) {
1596 goto fail;
1598 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1599 &blob_out);
1600 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1601 goto fail;
1604 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1605 data_blob_free(&blob_out);
1607 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1608 if (tevent_req_nomem(subreq, req)) {
1609 return tevent_req_post(req, ev);
1611 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1612 return req;
1613 fail:
1614 tevent_req_nterror(req, status);
1615 return tevent_req_post(req, ev);
1618 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1620 struct tevent_req *req = tevent_req_callback_data(
1621 subreq, struct tevent_req);
1622 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1623 req, struct cli_session_setup_ntlmssp_state);
1624 DATA_BLOB blob_in, msg_in, blob_out;
1625 char *inbuf = NULL;
1626 bool parse_ret;
1627 NTSTATUS status;
1629 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1630 &inbuf);
1631 TALLOC_FREE(subreq);
1632 data_blob_free(&state->blob_out);
1634 if (NT_STATUS_IS_OK(status)) {
1635 if (state->cli->server_domain[0] == '\0') {
1636 TALLOC_FREE(state->cli->server_domain);
1637 state->cli->server_domain = talloc_strdup(state->cli,
1638 state->ntlmssp_state->server.netbios_domain);
1639 if (state->cli->server_domain == NULL) {
1640 TALLOC_FREE(subreq);
1641 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1642 return;
1645 cli_set_session_key(
1646 state->cli, state->ntlmssp_state->session_key);
1648 if (cli_simple_set_signing(
1649 state->cli, state->ntlmssp_state->session_key,
1650 data_blob_null)
1651 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1652 TALLOC_FREE(subreq);
1653 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1654 return;
1656 TALLOC_FREE(subreq);
1657 TALLOC_FREE(state->ntlmssp_state);
1658 tevent_req_done(req);
1659 return;
1661 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1662 tevent_req_nterror(req, status);
1663 return;
1666 if (blob_in.length == 0) {
1667 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1668 return;
1671 if ((state->turn == 1)
1672 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1673 DATA_BLOB tmp_blob = data_blob_null;
1674 /* the server might give us back two challenges */
1675 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1676 &tmp_blob);
1677 data_blob_free(&tmp_blob);
1678 } else {
1679 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1680 OID_NTLMSSP, &msg_in);
1682 state->turn += 1;
1684 if (!parse_ret) {
1685 DEBUG(3,("Failed to parse auth response\n"));
1686 if (NT_STATUS_IS_OK(status)
1687 || NT_STATUS_EQUAL(status,
1688 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1689 tevent_req_nterror(
1690 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1691 return;
1695 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1697 if (!NT_STATUS_IS_OK(status)
1698 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1699 TALLOC_FREE(subreq);
1700 TALLOC_FREE(state->ntlmssp_state);
1701 tevent_req_nterror(req, status);
1702 return;
1705 state->blob_out = spnego_gen_auth(state, blob_out);
1706 TALLOC_FREE(subreq);
1707 if (tevent_req_nomem(state->blob_out.data, req)) {
1708 return;
1711 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1712 state->blob_out);
1713 if (tevent_req_nomem(subreq, req)) {
1714 return;
1716 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1719 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1721 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1722 req, struct cli_session_setup_ntlmssp_state);
1723 NTSTATUS status;
1725 if (tevent_req_is_nterror(req, &status)) {
1726 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
1727 return status;
1729 return NT_STATUS_OK;
1732 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1733 const char *user,
1734 const char *pass,
1735 const char *domain)
1737 struct tevent_context *ev;
1738 struct tevent_req *req;
1739 NTSTATUS status = NT_STATUS_NO_MEMORY;
1741 if (cli_has_async_calls(cli)) {
1742 return NT_STATUS_INVALID_PARAMETER;
1744 ev = tevent_context_init(talloc_tos());
1745 if (ev == NULL) {
1746 goto fail;
1748 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1749 if (req == NULL) {
1750 goto fail;
1752 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1753 goto fail;
1755 status = cli_session_setup_ntlmssp_recv(req);
1756 fail:
1757 TALLOC_FREE(ev);
1758 return status;
1761 /****************************************************************************
1762 Do a spnego encrypted session setup.
1764 user_domain: The shortname of the domain the user/machine is a member of.
1765 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1766 ****************************************************************************/
1768 static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
1769 const char *user,
1770 const char *pass,
1771 const char *user_domain,
1772 const char * dest_realm)
1774 char *principal = NULL;
1775 char *OIDs[ASN1_MAX_OIDS];
1776 int i;
1777 DATA_BLOB blob;
1778 const char *p = NULL;
1779 char *account = NULL;
1780 NTSTATUS status;
1782 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1784 /* the server might not even do spnego */
1785 if (cli->secblob.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 blob = data_blob(cli->secblob.data, cli->secblob.length);
1796 /* The server sent us the first part of the SPNEGO exchange in the
1797 * negprot reply. It is WRONG to depend on the principal sent in the
1798 * negprot reply, but right now we do it. If we don't receive one,
1799 * we try to best guess, then fall back to NTLM. */
1800 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1801 OIDs[0] == NULL) {
1802 data_blob_free(&blob);
1803 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1805 data_blob_free(&blob);
1807 /* make sure the server understands kerberos */
1808 for (i=0;OIDs[i];i++) {
1809 if (i == 0)
1810 DEBUG(3,("got OID=%s\n", OIDs[i]));
1811 else
1812 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1813 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1814 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1815 cli->got_kerberos_mechanism = True;
1817 talloc_free(OIDs[i]);
1820 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1822 status = cli_set_username(cli, user);
1823 if (!NT_STATUS_IS_OK(status)) {
1824 TALLOC_FREE(principal);
1825 return ADS_ERROR_NT(status);
1828 #ifdef HAVE_KRB5
1829 /* If password is set we reauthenticate to kerberos server
1830 * and do not store results */
1832 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1833 ADS_STATUS rc;
1834 const char *remote_name = cli_state_remote_name(cli);
1836 if (pass && *pass) {
1837 int ret;
1839 use_in_memory_ccache();
1840 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1842 if (ret){
1843 TALLOC_FREE(principal);
1844 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1845 if (cli->fallback_after_kerberos)
1846 goto ntlmssp;
1847 return ADS_ERROR_KRB5(ret);
1851 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1853 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1854 TALLOC_FREE(principal);
1857 if (principal == NULL &&
1858 !is_ipaddress(remote_name) &&
1859 !strequal(STAR_SMBSERVER,
1860 remote_name)) {
1861 char *realm = NULL;
1862 char *host = NULL;
1863 DEBUG(3,("cli_session_setup_spnego: using target "
1864 "hostname not SPNEGO principal\n"));
1866 host = strchr_m(remote_name, '.');
1867 if (dest_realm) {
1868 realm = SMB_STRDUP(dest_realm);
1869 if (!realm) {
1870 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1872 strupper_m(realm);
1873 } else {
1874 if (host) {
1875 /* DNS name. */
1876 realm = kerberos_get_realm_from_hostname(remote_name);
1877 } else {
1878 /* NetBIOS name - use our realm. */
1879 realm = kerberos_get_default_realm_from_ccache();
1883 if (realm == NULL || *realm == '\0') {
1884 realm = SMB_STRDUP(lp_realm());
1885 if (!realm) {
1886 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1888 strupper_m(realm);
1889 DEBUG(3,("cli_session_setup_spnego: cannot "
1890 "get realm from dest_realm %s, "
1891 "desthost %s. Using default "
1892 "smb.conf realm %s\n",
1893 dest_realm ? dest_realm : "<null>",
1894 remote_name,
1895 realm));
1898 principal = talloc_asprintf(talloc_tos(),
1899 "cifs/%s@%s",
1900 remote_name,
1901 realm);
1902 if (!principal) {
1903 SAFE_FREE(realm);
1904 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1906 DEBUG(3,("cli_session_setup_spnego: guessed "
1907 "server principal=%s\n",
1908 principal ? principal : "<null>"));
1910 SAFE_FREE(realm);
1913 if (principal) {
1914 rc = cli_session_setup_kerberos(cli, principal);
1915 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1916 TALLOC_FREE(principal);
1917 return rc;
1921 #endif
1923 TALLOC_FREE(principal);
1925 ntlmssp:
1927 account = talloc_strdup(talloc_tos(), user);
1928 if (!account) {
1929 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1932 /* when falling back to ntlmssp while authenticating with a machine
1933 * account strip off the realm - gd */
1935 if ((p = strchr_m(user, '@')) != NULL) {
1936 account[PTR_DIFF(p,user)] = '\0';
1939 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1942 /****************************************************************************
1943 Send a session setup. The username and workgroup is in UNIX character
1944 format and must be converted to DOS codepage format before sending. If the
1945 password is in plaintext, the same should be done.
1946 ****************************************************************************/
1948 NTSTATUS cli_session_setup(struct cli_state *cli,
1949 const char *user,
1950 const char *pass, int passlen,
1951 const char *ntpass, int ntpasslen,
1952 const char *workgroup)
1954 char *p;
1955 char *user2;
1956 uint16_t sec_mode = cli_state_security_mode(cli);
1958 if (user) {
1959 user2 = talloc_strdup(talloc_tos(), user);
1960 } else {
1961 user2 = talloc_strdup(talloc_tos(), "");
1963 if (user2 == NULL) {
1964 return NT_STATUS_NO_MEMORY;
1967 if (!workgroup) {
1968 workgroup = "";
1971 /* allow for workgroups as part of the username */
1972 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1973 (p=strchr_m(user2,*lp_winbind_separator()))) {
1974 *p = 0;
1975 user = p+1;
1976 strupper_m(user2);
1977 workgroup = user2;
1980 if (cli_state_protocol(cli) < PROTOCOL_LANMAN1) {
1982 * Ensure cli->server_domain,
1983 * cli->server_os and cli->server_type
1984 * are valid pointers.
1986 cli->server_domain = talloc_strdup(cli, "");
1987 cli->server_os = talloc_strdup(cli, "");
1988 cli->server_type = talloc_strdup(cli, "");
1989 if (cli->server_domain == NULL ||
1990 cli->server_os == NULL ||
1991 cli->server_type == NULL) {
1992 return NT_STATUS_NO_MEMORY;
1994 return NT_STATUS_OK;
1997 /* now work out what sort of session setup we are going to
1998 do. I have split this into separate functions to make the
1999 flow a bit easier to understand (tridge) */
2001 /* if its an older server then we have to use the older request format */
2003 if (cli_state_protocol(cli) < PROTOCOL_NT1) {
2004 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2005 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2006 " or 'client ntlmv2 auth = yes'\n"));
2007 return NT_STATUS_ACCESS_DENIED;
2010 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2011 !lp_client_plaintext_auth() && (*pass)) {
2012 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2013 " or 'client ntlmv2 auth = yes'\n"));
2014 return NT_STATUS_ACCESS_DENIED;
2017 return cli_session_setup_lanman2(cli, user, pass, passlen,
2018 workgroup);
2021 /* if no user is supplied then we have to do an anonymous connection.
2022 passwords are ignored */
2024 if (!user || !*user)
2025 return cli_session_setup_guest(cli);
2027 /* if the server is share level then send a plaintext null
2028 password at this point. The password is sent in the tree
2029 connect */
2031 if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2032 return cli_session_setup_plain(cli, user, "", workgroup);
2034 /* if the server doesn't support encryption then we have to use
2035 plaintext. The second password is ignored */
2037 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2038 if (!lp_client_plaintext_auth() && (*pass)) {
2039 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2040 " or 'client ntlmv2 auth = yes'\n"));
2041 return NT_STATUS_ACCESS_DENIED;
2043 return cli_session_setup_plain(cli, user, pass, workgroup);
2046 /* if the server supports extended security then use SPNEGO */
2048 if (cli_state_capabilities(cli) & CAP_EXTENDED_SECURITY) {
2049 const char *remote_realm = cli_state_remote_realm(cli);
2050 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2051 workgroup,
2052 remote_realm);
2053 if (!ADS_ERR_OK(status)) {
2054 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2055 return ads_ntstatus(status);
2057 } else {
2058 NTSTATUS status;
2060 /* otherwise do a NT1 style session setup */
2061 status = cli_session_setup_nt1(cli, user, pass, passlen,
2062 ntpass, ntpasslen, workgroup);
2063 if (!NT_STATUS_IS_OK(status)) {
2064 DEBUG(3,("cli_session_setup: NT1 session setup "
2065 "failed: %s\n", nt_errstr(status)));
2066 return status;
2070 return NT_STATUS_OK;
2073 /****************************************************************************
2074 Send a uloggoff.
2075 *****************************************************************************/
2077 struct cli_ulogoff_state {
2078 struct cli_state *cli;
2079 uint16_t vwv[3];
2082 static void cli_ulogoff_done(struct tevent_req *subreq);
2084 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2085 struct tevent_context *ev,
2086 struct cli_state *cli)
2088 struct tevent_req *req, *subreq;
2089 struct cli_ulogoff_state *state;
2091 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2092 if (req == NULL) {
2093 return NULL;
2095 state->cli = cli;
2097 SCVAL(state->vwv+0, 0, 0xFF);
2098 SCVAL(state->vwv+1, 0, 0);
2099 SSVAL(state->vwv+2, 0, 0);
2101 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2102 0, NULL);
2103 if (tevent_req_nomem(subreq, req)) {
2104 return tevent_req_post(req, ev);
2106 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2107 return req;
2110 static void cli_ulogoff_done(struct tevent_req *subreq)
2112 struct tevent_req *req = tevent_req_callback_data(
2113 subreq, struct tevent_req);
2114 struct cli_ulogoff_state *state = tevent_req_data(
2115 req, struct cli_ulogoff_state);
2116 NTSTATUS status;
2118 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2119 if (!NT_STATUS_IS_OK(status)) {
2120 tevent_req_nterror(req, status);
2121 return;
2123 cli_state_set_uid(state->cli, UID_FIELD_INVALID);
2124 tevent_req_done(req);
2127 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2129 return tevent_req_simple_recv_ntstatus(req);
2132 NTSTATUS cli_ulogoff(struct cli_state *cli)
2134 struct tevent_context *ev;
2135 struct tevent_req *req;
2136 NTSTATUS status = NT_STATUS_NO_MEMORY;
2138 if (cli_has_async_calls(cli)) {
2139 return NT_STATUS_INVALID_PARAMETER;
2141 ev = tevent_context_init(talloc_tos());
2142 if (ev == NULL) {
2143 goto fail;
2145 req = cli_ulogoff_send(ev, ev, cli);
2146 if (req == NULL) {
2147 goto fail;
2149 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2150 goto fail;
2152 status = cli_ulogoff_recv(req);
2153 fail:
2154 TALLOC_FREE(ev);
2155 return status;
2158 /****************************************************************************
2159 Send a tconX.
2160 ****************************************************************************/
2162 struct cli_tcon_andx_state {
2163 struct cli_state *cli;
2164 uint16_t vwv[4];
2165 struct iovec bytes;
2168 static void cli_tcon_andx_done(struct tevent_req *subreq);
2170 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2171 struct event_context *ev,
2172 struct cli_state *cli,
2173 const char *share, const char *dev,
2174 const char *pass, int passlen,
2175 struct tevent_req **psmbreq)
2177 struct tevent_req *req, *subreq;
2178 struct cli_tcon_andx_state *state;
2179 uint8_t p24[24];
2180 uint16_t *vwv;
2181 char *tmp = NULL;
2182 uint8_t *bytes;
2183 uint16_t sec_mode = cli_state_security_mode(cli);
2185 *psmbreq = NULL;
2187 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2188 if (req == NULL) {
2189 return NULL;
2191 state->cli = cli;
2192 vwv = state->vwv;
2194 cli->share = talloc_strdup(cli, share);
2195 if (!cli->share) {
2196 return NULL;
2199 /* in user level security don't send a password now */
2200 if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2201 passlen = 1;
2202 pass = "";
2203 } else if (pass == NULL) {
2204 DEBUG(1, ("Server not using user level security and no "
2205 "password supplied.\n"));
2206 goto access_denied;
2209 if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2210 *pass && passlen != 24) {
2211 if (!lp_client_lanman_auth()) {
2212 DEBUG(1, ("Server requested LANMAN password "
2213 "(share-level security) but "
2214 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2215 goto access_denied;
2219 * Non-encrypted passwords - convert to DOS codepage before
2220 * encryption.
2222 SMBencrypt(pass, cli_state_server_challenge(cli), p24);
2223 passlen = 24;
2224 pass = (const char *)p24;
2225 } else {
2226 if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2227 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2228 == 0) {
2229 uint8_t *tmp_pass;
2231 if (!lp_client_plaintext_auth() && (*pass)) {
2232 DEBUG(1, ("Server requested plaintext "
2233 "password but "
2234 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2235 goto access_denied;
2239 * Non-encrypted passwords - convert to DOS codepage
2240 * before using.
2242 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2243 if (tevent_req_nomem(tmp_pass, req)) {
2244 return tevent_req_post(req, ev);
2246 tmp_pass = trans2_bytes_push_str(tmp_pass,
2247 false, /* always DOS */
2248 pass,
2249 passlen,
2250 NULL);
2251 if (tevent_req_nomem(tmp_pass, req)) {
2252 return tevent_req_post(req, ev);
2254 pass = (const char *)tmp_pass;
2255 passlen = talloc_get_size(tmp_pass);
2259 SCVAL(vwv+0, 0, 0xFF);
2260 SCVAL(vwv+0, 1, 0);
2261 SSVAL(vwv+1, 0, 0);
2262 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2263 SSVAL(vwv+3, 0, passlen);
2265 if (passlen && pass) {
2266 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2267 } else {
2268 bytes = talloc_array(state, uint8_t, 0);
2272 * Add the sharename
2274 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2275 cli_state_remote_name(cli), share);
2276 if (tmp == NULL) {
2277 TALLOC_FREE(req);
2278 return NULL;
2280 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2281 NULL);
2282 TALLOC_FREE(tmp);
2285 * Add the devicetype
2287 tmp = talloc_strdup_upper(talloc_tos(), dev);
2288 if (tmp == NULL) {
2289 TALLOC_FREE(req);
2290 return NULL;
2292 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2293 TALLOC_FREE(tmp);
2295 if (bytes == NULL) {
2296 TALLOC_FREE(req);
2297 return NULL;
2300 state->bytes.iov_base = (void *)bytes;
2301 state->bytes.iov_len = talloc_get_size(bytes);
2303 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2304 1, &state->bytes);
2305 if (subreq == NULL) {
2306 TALLOC_FREE(req);
2307 return NULL;
2309 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2310 *psmbreq = subreq;
2311 return req;
2313 access_denied:
2314 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2315 return tevent_req_post(req, ev);
2318 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2319 struct event_context *ev,
2320 struct cli_state *cli,
2321 const char *share, const char *dev,
2322 const char *pass, int passlen)
2324 struct tevent_req *req, *subreq;
2325 NTSTATUS status;
2327 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2328 &subreq);
2329 if (req == NULL) {
2330 return NULL;
2332 if (subreq == NULL) {
2333 return req;
2335 status = cli_smb_req_send(subreq);
2336 if (!NT_STATUS_IS_OK(status)) {
2337 tevent_req_nterror(req, status);
2338 return tevent_req_post(req, ev);
2340 return req;
2343 static void cli_tcon_andx_done(struct tevent_req *subreq)
2345 struct tevent_req *req = tevent_req_callback_data(
2346 subreq, struct tevent_req);
2347 struct cli_tcon_andx_state *state = tevent_req_data(
2348 req, struct cli_tcon_andx_state);
2349 struct cli_state *cli = state->cli;
2350 uint8_t *in;
2351 char *inbuf;
2352 uint8_t wct;
2353 uint16_t *vwv;
2354 uint32_t num_bytes;
2355 uint8_t *bytes;
2356 NTSTATUS status;
2358 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2359 &num_bytes, &bytes);
2360 TALLOC_FREE(subreq);
2361 if (!NT_STATUS_IS_OK(status)) {
2362 tevent_req_nterror(req, status);
2363 return;
2366 inbuf = (char *)in;
2368 if (num_bytes) {
2369 if (clistr_pull_talloc(cli,
2370 inbuf,
2371 SVAL(inbuf, smb_flg2),
2372 &cli->dev,
2373 bytes,
2374 num_bytes,
2375 STR_TERMINATE|STR_ASCII) == -1) {
2376 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2377 return;
2379 } else {
2380 cli->dev = talloc_strdup(cli, "");
2381 if (cli->dev == NULL) {
2382 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2383 return;
2387 if ((cli_state_protocol(cli) >= PROTOCOL_NT1) && (num_bytes == 3)) {
2388 /* almost certainly win95 - enable bug fixes */
2389 cli->win95 = True;
2393 * Make sure that we have the optional support 16-bit field. WCT > 2.
2394 * Avoids issues when connecting to Win9x boxes sharing files
2397 cli->dfsroot = false;
2399 if ((wct > 2) && (cli_state_protocol(cli) >= PROTOCOL_LANMAN2)) {
2400 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2403 cli->smb1.tid = SVAL(inbuf,smb_tid);
2404 tevent_req_done(req);
2407 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2409 return tevent_req_simple_recv_ntstatus(req);
2412 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2413 const char *dev, const char *pass, int passlen)
2415 TALLOC_CTX *frame = talloc_stackframe();
2416 struct event_context *ev;
2417 struct tevent_req *req;
2418 NTSTATUS status = NT_STATUS_OK;
2420 if (cli_has_async_calls(cli)) {
2422 * Can't use sync call while an async call is in flight
2424 status = NT_STATUS_INVALID_PARAMETER;
2425 goto fail;
2428 ev = event_context_init(frame);
2429 if (ev == NULL) {
2430 status = NT_STATUS_NO_MEMORY;
2431 goto fail;
2434 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2435 if (req == NULL) {
2436 status = NT_STATUS_NO_MEMORY;
2437 goto fail;
2440 if (!tevent_req_poll(req, ev)) {
2441 status = map_nt_error_from_unix(errno);
2442 goto fail;
2445 status = cli_tcon_andx_recv(req);
2446 fail:
2447 TALLOC_FREE(frame);
2448 return status;
2451 /****************************************************************************
2452 Send a tree disconnect.
2453 ****************************************************************************/
2455 struct cli_tdis_state {
2456 struct cli_state *cli;
2459 static void cli_tdis_done(struct tevent_req *subreq);
2461 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2462 struct tevent_context *ev,
2463 struct cli_state *cli)
2465 struct tevent_req *req, *subreq;
2466 struct cli_tdis_state *state;
2468 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2469 if (req == NULL) {
2470 return NULL;
2472 state->cli = cli;
2474 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2475 if (tevent_req_nomem(subreq, req)) {
2476 return tevent_req_post(req, ev);
2478 tevent_req_set_callback(subreq, cli_tdis_done, req);
2479 return req;
2482 static void cli_tdis_done(struct tevent_req *subreq)
2484 struct tevent_req *req = tevent_req_callback_data(
2485 subreq, struct tevent_req);
2486 struct cli_tdis_state *state = tevent_req_data(
2487 req, struct cli_tdis_state);
2488 NTSTATUS status;
2490 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2491 TALLOC_FREE(subreq);
2492 if (!NT_STATUS_IS_OK(status)) {
2493 tevent_req_nterror(req, status);
2494 return;
2496 state->cli->smb1.tid = UINT16_MAX;
2497 tevent_req_done(req);
2500 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2502 return tevent_req_simple_recv_ntstatus(req);
2505 NTSTATUS cli_tdis(struct cli_state *cli)
2507 struct tevent_context *ev;
2508 struct tevent_req *req;
2509 NTSTATUS status = NT_STATUS_NO_MEMORY;
2511 if (cli_has_async_calls(cli)) {
2512 return NT_STATUS_INVALID_PARAMETER;
2514 ev = tevent_context_init(talloc_tos());
2515 if (ev == NULL) {
2516 goto fail;
2518 req = cli_tdis_send(ev, ev, cli);
2519 if (req == NULL) {
2520 goto fail;
2522 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2523 goto fail;
2525 status = cli_tdis_recv(req);
2526 fail:
2527 TALLOC_FREE(ev);
2528 return status;
2531 /****************************************************************************
2532 Send a negprot command.
2533 ****************************************************************************/
2535 struct cli_negprot_state {
2536 struct cli_state *cli;
2537 enum protocol_types max_protocol;
2540 static void cli_negprot_done(struct tevent_req *subreq);
2542 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2543 struct event_context *ev,
2544 struct cli_state *cli,
2545 enum protocol_types max_protocol)
2547 struct tevent_req *req, *subreq;
2548 struct cli_negprot_state *state;
2549 uint8_t *bytes = NULL;
2550 int numprots;
2551 enum protocol_types tmp_protocol;
2553 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2554 if (req == NULL) {
2555 return NULL;
2557 state->cli = cli;
2558 state->max_protocol = max_protocol;
2560 /* setup the protocol strings */
2561 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2562 uint8_t c = 2;
2563 if (prots[numprots].prot > state->max_protocol) {
2564 break;
2566 bytes = (uint8_t *)talloc_append_blob(
2567 state, bytes, data_blob_const(&c, sizeof(c)));
2568 if (tevent_req_nomem(bytes, req)) {
2569 return tevent_req_post(req, ev);
2571 bytes = smb_bytes_push_str(bytes, false,
2572 prots[numprots].name,
2573 strlen(prots[numprots].name)+1,
2574 NULL);
2575 if (tevent_req_nomem(bytes, req)) {
2576 return tevent_req_post(req, ev);
2580 tmp_protocol = cli->conn.protocol;
2581 cli->conn.protocol = state->max_protocol;
2582 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2583 talloc_get_size(bytes), bytes);
2584 cli->conn.protocol = tmp_protocol;
2585 if (tevent_req_nomem(subreq, req)) {
2586 return tevent_req_post(req, ev);
2588 tevent_req_set_callback(subreq, cli_negprot_done, req);
2589 return req;
2592 static void cli_negprot_done(struct tevent_req *subreq)
2594 struct tevent_req *req = tevent_req_callback_data(
2595 subreq, struct tevent_req);
2596 struct cli_negprot_state *state = tevent_req_data(
2597 req, struct cli_negprot_state);
2598 struct cli_state *cli = state->cli;
2599 uint8_t flags;
2600 uint8_t wct;
2601 uint16_t *vwv;
2602 uint32_t num_bytes;
2603 uint8_t *bytes;
2604 NTSTATUS status;
2605 uint16_t protnum;
2606 uint8_t *inbuf;
2607 uint32_t client_capabilities = cli->conn.smb1.client.capabilities;
2608 uint32_t both_capabilities;
2609 uint32_t server_capabilities = 0;
2610 uint32_t capabilities;
2611 uint32_t client_max_xmit = cli->conn.smb1.client.max_xmit;
2612 uint32_t server_max_xmit = 0;
2613 uint32_t max_xmit;
2614 uint32_t server_max_mux = 0;
2615 uint16_t server_security_mode = 0;
2616 uint32_t server_session_key = 0;
2617 bool server_readbraw = false;
2618 bool server_writebraw = false;
2619 bool server_lockread = false;
2620 bool server_writeunlock = false;
2621 enum protocol_types protocol;
2623 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2624 &num_bytes, &bytes);
2625 TALLOC_FREE(subreq);
2626 if (!NT_STATUS_IS_OK(status)) {
2627 tevent_req_nterror(req, status);
2628 return;
2631 flags = CVAL(inbuf, smb_flg);
2633 protnum = SVAL(vwv, 0);
2635 if ((protnum >= ARRAY_SIZE(prots))
2636 || (prots[protnum].prot > state->max_protocol)) {
2637 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2638 return;
2641 protocol = prots[protnum].prot;
2643 if ((protocol < PROTOCOL_NT1) &&
2644 client_is_signing_mandatory(cli)) {
2645 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2646 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2647 return;
2650 if (flags & FLAG_SUPPORT_LOCKREAD) {
2651 server_lockread = true;
2652 server_writeunlock = true;
2655 if (protocol >= PROTOCOL_NT1) {
2656 struct timespec ts;
2657 const char *client_signing = NULL;
2658 bool server_mandatory;
2659 bool server_allowed;
2660 const char *server_signing = NULL;
2661 bool ok;
2663 if (wct != 0x11) {
2664 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2665 return;
2668 /* NT protocol */
2669 server_security_mode = CVAL(vwv + 1, 0);
2670 server_max_mux = SVAL(vwv + 1, 1);
2671 server_max_xmit = IVAL(vwv + 3, 1);
2672 server_session_key = IVAL(vwv + 7, 1);
2673 cli->serverzone = SVALS(vwv + 15, 1);
2674 cli->serverzone *= 60;
2675 /* this time arrives in real GMT */
2676 ts = interpret_long_date(((char *)(vwv+11))+1);
2677 cli->servertime = ts.tv_sec;
2678 server_capabilities = IVAL(vwv + 9, 1);
2679 if (server_capabilities & CAP_RAW_MODE) {
2680 server_readbraw = true;
2681 server_writebraw = true;
2683 if (server_capabilities & CAP_LOCK_AND_READ) {
2684 server_lockread = true;
2686 if (server_capabilities & CAP_EXTENDED_SECURITY) {
2687 if (num_bytes < 16) {
2688 tevent_req_nterror(req,
2689 NT_STATUS_INVALID_NETWORK_RESPONSE);
2690 return;
2692 cli->secblob = data_blob(bytes+16, num_bytes-16);
2693 } else {
2694 cli->secblob = data_blob(bytes, MIN(num_bytes, 8));
2695 /* work out if they sent us a workgroup */
2696 if (num_bytes > 8) {
2697 ssize_t ret;
2698 status = smb_bytes_talloc_string(
2699 cli, (char *)inbuf, &cli->server_domain,
2700 bytes + 8, num_bytes - 8, &ret);
2701 if (tevent_req_nterror(req, status)) {
2702 return;
2707 client_signing = "disabled";
2708 if (client_is_signing_allowed(cli)) {
2709 client_signing = "allowed";
2711 if (client_is_signing_mandatory(cli)) {
2712 client_signing = "required";
2715 server_signing = "not supported";
2716 if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2717 server_signing = "supported";
2718 server_allowed = true;
2720 if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2721 server_signing = "required";
2722 server_mandatory = true;
2725 ok = cli_set_signing_negotiated(cli,
2726 server_allowed,
2727 server_mandatory);
2728 if (!ok) {
2729 DEBUG(1,("cli_negprot: SMB signing is required, "
2730 "but client[%s] and server[%s] mismatch\n",
2731 client_signing, server_signing));
2732 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2733 return;
2736 } else if (protocol >= PROTOCOL_LANMAN1) {
2737 if (wct != 0x0D) {
2738 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2739 return;
2742 server_security_mode = SVAL(vwv + 1, 0);
2743 server_max_xmit = SVAL(vwv + 2, 0);
2744 server_max_mux = SVAL(vwv + 3, 0);
2745 server_session_key = IVAL(vwv + 6, 0);
2746 cli->serverzone = SVALS(vwv + 10, 0);
2747 cli->serverzone *= 60;
2748 /* this time is converted to GMT by make_unix_date */
2749 cli->servertime = make_unix_date(
2750 (char *)(vwv + 8), cli->serverzone);
2751 server_readbraw = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2752 server_writebraw = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2753 cli->secblob = data_blob(bytes, MIN(num_bytes, 8));
2754 } else {
2755 /* the old core protocol */
2756 cli->serverzone = get_time_zone(time(NULL));
2757 server_max_xmit = 1024;
2758 server_max_mux = 1;
2759 server_security_mode = 0;
2762 if (server_max_xmit < 1024) {
2763 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2764 return;
2767 if (server_max_mux < 1) {
2768 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2769 return;
2773 * Now calculate the negotiated capabilities
2774 * based on the mask for:
2775 * - client only flags
2776 * - flags used in both directions
2777 * - server only flags
2779 both_capabilities = client_capabilities & server_capabilities;
2780 capabilities = client_capabilities & SMB_CAP_CLIENT_MASK;
2781 capabilities |= both_capabilities & SMB_CAP_BOTH_MASK;
2782 capabilities |= server_capabilities & SMB_CAP_SERVER_MASK;
2784 max_xmit = MIN(client_max_xmit, server_max_xmit);
2786 cli->conn.protocol = protocol;
2788 cli->conn.smb1.server.capabilities = server_capabilities;
2789 cli->conn.smb1.capabilities = capabilities;
2791 cli->conn.smb1.server.max_xmit = server_max_xmit;
2792 cli->conn.smb1.max_xmit = max_xmit;
2794 cli->conn.smb1.server.max_mux = server_max_mux;
2796 cli->conn.smb1.server.security_mode = server_security_mode;
2798 cli->conn.smb1.server.readbraw = server_readbraw;
2799 cli->conn.smb1.server.writebraw = server_writebraw;
2800 cli->conn.smb1.server.lockread = server_lockread;
2801 cli->conn.smb1.server.writeunlock = server_writeunlock;
2803 cli->conn.smb1.server.session_key = server_session_key;
2805 tevent_req_done(req);
2808 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2810 return tevent_req_simple_recv_ntstatus(req);
2813 NTSTATUS cli_negprot(struct cli_state *cli, enum protocol_types max_protocol)
2815 TALLOC_CTX *frame = talloc_stackframe();
2816 struct event_context *ev;
2817 struct tevent_req *req;
2818 NTSTATUS status = NT_STATUS_OK;
2820 if (cli_has_async_calls(cli)) {
2822 * Can't use sync call while an async call is in flight
2824 status = NT_STATUS_INVALID_PARAMETER;
2825 goto fail;
2828 ev = event_context_init(frame);
2829 if (ev == NULL) {
2830 status = NT_STATUS_NO_MEMORY;
2831 goto fail;
2834 req = cli_negprot_send(frame, ev, cli, max_protocol);
2835 if (req == NULL) {
2836 status = NT_STATUS_NO_MEMORY;
2837 goto fail;
2840 if (!tevent_req_poll(req, ev)) {
2841 status = map_nt_error_from_unix(errno);
2842 goto fail;
2845 status = cli_negprot_recv(req);
2846 fail:
2847 TALLOC_FREE(frame);
2848 return status;
2851 static NTSTATUS cli_connect_sock(const char *host, int name_type,
2852 const struct sockaddr_storage *pss,
2853 const char *myname, uint16_t port,
2854 int sec_timeout, int *pfd, uint16_t *pport)
2856 TALLOC_CTX *frame = talloc_stackframe();
2857 const char *prog;
2858 unsigned int i, num_addrs;
2859 const char **called_names;
2860 const char **calling_names;
2861 int *called_types;
2862 NTSTATUS status;
2863 int fd;
2865 prog = getenv("LIBSMB_PROG");
2866 if (prog != NULL) {
2867 fd = sock_exec(prog);
2868 if (fd == -1) {
2869 return map_nt_error_from_unix(errno);
2871 port = 0;
2872 goto done;
2875 if ((pss == NULL) || is_zero_addr(pss)) {
2876 struct sockaddr_storage *addrs;
2877 status = resolve_name_list(talloc_tos(), host, name_type,
2878 &addrs, &num_addrs);
2879 if (!NT_STATUS_IS_OK(status)) {
2880 goto fail;
2882 pss = addrs;
2883 } else {
2884 num_addrs = 1;
2887 called_names = talloc_array(talloc_tos(), const char *, num_addrs);
2888 if (called_names == NULL) {
2889 status = NT_STATUS_NO_MEMORY;
2890 goto fail;
2892 called_types = talloc_array(talloc_tos(), int, num_addrs);
2893 if (called_types == NULL) {
2894 status = NT_STATUS_NO_MEMORY;
2895 goto fail;
2897 calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
2898 if (calling_names == NULL) {
2899 status = NT_STATUS_NO_MEMORY;
2900 goto fail;
2902 for (i=0; i<num_addrs; i++) {
2903 called_names[i] = host;
2904 called_types[i] = name_type;
2905 calling_names[i] = myname;
2907 status = smbsock_any_connect(pss, called_names, called_types,
2908 calling_names, NULL, num_addrs, port,
2909 sec_timeout, &fd, NULL, &port);
2910 if (!NT_STATUS_IS_OK(status)) {
2911 goto fail;
2913 set_socket_options(fd, lp_socket_options());
2914 done:
2915 *pfd = fd;
2916 *pport = port;
2917 status = NT_STATUS_OK;
2918 fail:
2919 TALLOC_FREE(frame);
2920 return status;
2923 NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
2924 uint16_t port, int name_type, const char *myname,
2925 int signing_state, int flags, struct cli_state **pcli)
2927 TALLOC_CTX *frame = talloc_stackframe();
2928 struct cli_state *cli;
2929 NTSTATUS status = NT_STATUS_NO_MEMORY;
2930 int fd = -1;
2931 char *desthost;
2932 char *p;
2934 desthost = talloc_strdup(talloc_tos(), host);
2935 if (desthost == NULL) {
2936 goto fail;
2939 p = strchr(host, '#');
2940 if (p != NULL) {
2941 name_type = strtol(p+1, NULL, 16);
2942 host = talloc_strndup(talloc_tos(), host, p - host);
2943 if (host == NULL) {
2944 goto fail;
2948 status = cli_connect_sock(host, name_type, dest_ss, myname, port,
2949 20, &fd, &port);
2950 if (!NT_STATUS_IS_OK(status)) {
2951 goto fail;
2954 cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
2955 if (cli == NULL) {
2956 goto fail;
2959 *pcli = cli;
2960 status = NT_STATUS_OK;
2961 fail:
2962 TALLOC_FREE(frame);
2963 return status;
2967 establishes a connection to after the negprot.
2968 @param output_cli A fully initialised cli structure, non-null only on success
2969 @param dest_host The netbios name of the remote host
2970 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2971 @param port (optional) The destination port (0 for default)
2973 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2974 const char *my_name,
2975 const char *dest_host,
2976 const struct sockaddr_storage *dest_ss, int port,
2977 int signing_state, int flags)
2979 NTSTATUS nt_status;
2980 struct cli_state *cli;
2982 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
2983 signing_state, flags, &cli);
2984 if (!NT_STATUS_IS_OK(nt_status)) {
2985 DEBUG(10, ("cli_connect_nb failed: %s\n",
2986 nt_errstr(nt_status)));
2987 return nt_status;
2990 nt_status = cli_negprot(cli, PROTOCOL_NT1);
2991 if (!NT_STATUS_IS_OK(nt_status)) {
2992 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2993 cli_shutdown(cli);
2994 return nt_status;
2997 *output_cli = cli;
2998 return NT_STATUS_OK;
3003 establishes a connection right up to doing tconX, password specified.
3004 @param output_cli A fully initialised cli structure, non-null only on success
3005 @param dest_host The netbios name of the remote host
3006 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3007 @param port (optional) The destination port (0 for default)
3008 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3009 @param service_type The 'type' of serivice.
3010 @param user Username, unix string
3011 @param domain User's domain
3012 @param password User's password, unencrypted unix string.
3015 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3016 const char *my_name,
3017 const char *dest_host,
3018 const struct sockaddr_storage *dest_ss, int port,
3019 const char *service, const char *service_type,
3020 const char *user, const char *domain,
3021 const char *password, int flags,
3022 int signing_state)
3024 NTSTATUS nt_status;
3025 struct cli_state *cli = NULL;
3026 int pw_len = password ? strlen(password)+1 : 0;
3028 *output_cli = NULL;
3030 if (password == NULL) {
3031 password = "";
3034 nt_status = cli_start_connection(&cli, my_name, dest_host,
3035 dest_ss, port, signing_state,
3036 flags);
3038 if (!NT_STATUS_IS_OK(nt_status)) {
3039 return nt_status;
3042 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3043 pw_len, domain);
3044 if (!NT_STATUS_IS_OK(nt_status)) {
3046 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3047 DEBUG(1,("failed session setup with %s\n",
3048 nt_errstr(nt_status)));
3049 cli_shutdown(cli);
3050 return nt_status;
3053 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3054 if (!NT_STATUS_IS_OK(nt_status)) {
3055 DEBUG(1,("anonymous failed session setup with %s\n",
3056 nt_errstr(nt_status)));
3057 cli_shutdown(cli);
3058 return nt_status;
3062 if (service) {
3063 nt_status = cli_tcon_andx(cli, service, service_type, password,
3064 pw_len);
3065 if (!NT_STATUS_IS_OK(nt_status)) {
3066 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3067 cli_shutdown(cli);
3068 if (NT_STATUS_IS_OK(nt_status)) {
3069 nt_status = NT_STATUS_UNSUCCESSFUL;
3071 return nt_status;
3075 nt_status = cli_init_creds(cli, user, domain, password);
3076 if (!NT_STATUS_IS_OK(nt_status)) {
3077 cli_shutdown(cli);
3078 return nt_status;
3081 *output_cli = cli;
3082 return NT_STATUS_OK;
3085 /****************************************************************************
3086 Send an old style tcon.
3087 ****************************************************************************/
3088 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3089 const char *service, const char *pass, const char *dev,
3090 uint16 *max_xmit, uint16 *tid)
3092 struct tevent_req *req;
3093 uint16_t *ret_vwv;
3094 uint8_t *bytes;
3095 NTSTATUS status;
3097 if (!lp_client_plaintext_auth() && (*pass)) {
3098 DEBUG(1, ("Server requested plaintext password but 'client "
3099 "plaintext auth' is disabled\n"));
3100 return NT_STATUS_ACCESS_DENIED;
3103 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3104 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3105 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3106 service, strlen(service)+1, NULL);
3107 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3108 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3109 pass, strlen(pass)+1, NULL);
3110 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3111 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3112 dev, strlen(dev)+1, NULL);
3114 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3115 talloc_get_size(bytes), bytes, &req,
3116 2, NULL, &ret_vwv, NULL, NULL);
3117 if (!NT_STATUS_IS_OK(status)) {
3118 return status;
3121 *max_xmit = SVAL(ret_vwv + 0, 0);
3122 *tid = SVAL(ret_vwv + 1, 0);
3124 return NT_STATUS_OK;
3127 /* Return a cli_state pointing at the IPC$ share for the given server */
3129 struct cli_state *get_ipc_connect(char *server,
3130 struct sockaddr_storage *server_ss,
3131 const struct user_auth_info *user_info)
3133 struct cli_state *cli;
3134 NTSTATUS nt_status;
3135 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3137 if (user_info->use_kerberos) {
3138 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3141 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3142 user_info->username ? user_info->username : "",
3143 lp_workgroup(),
3144 user_info->password ? user_info->password : "",
3145 flags,
3146 Undefined);
3148 if (NT_STATUS_IS_OK(nt_status)) {
3149 return cli;
3150 } else if (is_ipaddress(server)) {
3151 /* windows 9* needs a correct NMB name for connections */
3152 fstring remote_name;
3154 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3155 cli = get_ipc_connect(remote_name, server_ss, user_info);
3156 if (cli)
3157 return cli;
3160 return NULL;
3164 * Given the IP address of a master browser on the network, return its
3165 * workgroup and connect to it.
3167 * This function is provided to allow additional processing beyond what
3168 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3169 * browsers and obtain each master browsers' list of domains (in case the
3170 * first master browser is recently on the network and has not yet
3171 * synchronized with other master browsers and therefore does not yet have the
3172 * entire network browse list)
3175 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3176 struct sockaddr_storage *mb_ip,
3177 const struct user_auth_info *user_info,
3178 char **pp_workgroup_out)
3180 char addr[INET6_ADDRSTRLEN];
3181 fstring name;
3182 struct cli_state *cli;
3183 struct sockaddr_storage server_ss;
3185 *pp_workgroup_out = NULL;
3187 print_sockaddr(addr, sizeof(addr), mb_ip);
3188 DEBUG(99, ("Looking up name of master browser %s\n",
3189 addr));
3192 * Do a name status query to find out the name of the master browser.
3193 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3194 * master browser will not respond to a wildcard query (or, at least,
3195 * an NT4 server acting as the domain master browser will not).
3197 * We might be able to use ONLY the query on MSBROWSE, but that's not
3198 * yet been tested with all Windows versions, so until it is, leave
3199 * the original wildcard query as the first choice and fall back to
3200 * MSBROWSE if the wildcard query fails.
3202 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3203 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3205 DEBUG(99, ("Could not retrieve name status for %s\n",
3206 addr));
3207 return NULL;
3210 if (!find_master_ip(name, &server_ss)) {
3211 DEBUG(99, ("Could not find master ip for %s\n", name));
3212 return NULL;
3215 *pp_workgroup_out = talloc_strdup(ctx, name);
3217 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3219 print_sockaddr(addr, sizeof(addr), &server_ss);
3220 cli = get_ipc_connect(addr, &server_ss, user_info);
3222 return cli;
3226 * Return the IP address and workgroup of a master browser on the network, and
3227 * connect to it.
3230 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3231 const struct user_auth_info *user_info,
3232 char **pp_workgroup_out)
3234 struct sockaddr_storage *ip_list;
3235 struct cli_state *cli;
3236 int i, count;
3237 NTSTATUS status;
3239 *pp_workgroup_out = NULL;
3241 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3243 /* Go looking for workgroups by broadcasting on the local network */
3245 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3246 &ip_list, &count);
3247 if (!NT_STATUS_IS_OK(status)) {
3248 DEBUG(99, ("No master browsers responded: %s\n",
3249 nt_errstr(status)));
3250 return False;
3253 for (i = 0; i < count; i++) {
3254 char addr[INET6_ADDRSTRLEN];
3255 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3256 DEBUG(99, ("Found master browser %s\n", addr));
3258 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3259 user_info, pp_workgroup_out);
3260 if (cli)
3261 return(cli);
3264 return NULL;