s3: Remove unused cli_setup_packet()
[Samba.git] / source3 / libsmb / cliconnect.c
blob374dd97ff46515579872f55121183daad0134615
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(struct cli_state *cli,
63 char *inbuf,
64 char **dest,
65 uint8_t *src,
66 size_t srclen,
67 ssize_t *destlen)
69 *destlen = clistr_pull_talloc(cli,
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(cli, "");
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;
126 req = tevent_req_create(mem_ctx, &state,
127 struct cli_session_setup_lanman2_state);
128 if (req == NULL) {
129 return NULL;
131 state->cli = cli;
132 state->user = user;
133 vwv = state->vwv;
136 * LANMAN servers predate NT status codes and Unicode and
137 * ignore those smb flags so we must disable the corresponding
138 * default capabilities that would otherwise cause the Unicode
139 * and NT Status flags to be set (and even returned by the
140 * server)
143 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
146 * if in share level security then don't send a password now
148 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
149 passlen = 0;
152 if (passlen > 0
153 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
154 && passlen != 24) {
156 * Encrypted mode needed, and non encrypted password
157 * supplied.
159 lm_response = data_blob(NULL, 24);
160 if (tevent_req_nomem(lm_response.data, req)) {
161 return tevent_req_post(req, ev);
164 if (!SMBencrypt(pass, cli->secblob.data,
165 (uint8_t *)lm_response.data)) {
166 DEBUG(1, ("Password is > 14 chars in length, and is "
167 "therefore incompatible with Lanman "
168 "authentication\n"));
169 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
170 return tevent_req_post(req, ev);
172 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
173 && passlen == 24) {
175 * Encrypted mode needed, and encrypted password
176 * supplied.
178 lm_response = data_blob(pass, passlen);
179 if (tevent_req_nomem(lm_response.data, req)) {
180 return tevent_req_post(req, ev);
182 } else if (passlen > 0) {
183 uint8_t *buf;
184 size_t converted_size;
186 * Plaintext mode needed, assume plaintext supplied.
188 buf = talloc_array(talloc_tos(), uint8_t, 0);
189 buf = smb_bytes_push_str(buf, cli_ucs2(cli), pass, passlen+1,
190 &converted_size);
191 if (tevent_req_nomem(buf, req)) {
192 return tevent_req_post(req, ev);
194 lm_response = data_blob(pass, passlen);
195 TALLOC_FREE(buf);
196 if (tevent_req_nomem(lm_response.data, req)) {
197 return tevent_req_post(req, ev);
201 SCVAL(vwv+0, 0, 0xff);
202 SCVAL(vwv+0, 1, 0);
203 SSVAL(vwv+1, 0, 0);
204 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
205 SSVAL(vwv+3, 0, 2);
206 SSVAL(vwv+4, 0, 1);
207 SIVAL(vwv+5, 0, cli->sesskey);
208 SSVAL(vwv+7, 0, lm_response.length);
210 bytes = talloc_array(state, uint8_t, lm_response.length);
211 if (tevent_req_nomem(bytes, req)) {
212 return tevent_req_post(req, ev);
214 if (lm_response.length != 0) {
215 memcpy(bytes, lm_response.data, lm_response.length);
217 data_blob_free(&lm_response);
219 tmp = talloc_strdup_upper(talloc_tos(), user);
220 if (tevent_req_nomem(tmp, req)) {
221 return tevent_req_post(req, ev);
223 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
224 NULL);
225 TALLOC_FREE(tmp);
227 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
228 if (tevent_req_nomem(tmp, req)) {
229 return tevent_req_post(req, ev);
231 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
232 NULL);
233 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
234 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
236 if (tevent_req_nomem(bytes, req)) {
237 return tevent_req_post(req, ev);
240 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
241 talloc_get_size(bytes), bytes);
242 if (tevent_req_nomem(subreq, req)) {
243 return tevent_req_post(req, ev);
245 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
246 return req;
249 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
251 struct tevent_req *req = tevent_req_callback_data(
252 subreq, struct tevent_req);
253 struct cli_session_setup_lanman2_state *state = tevent_req_data(
254 req, struct cli_session_setup_lanman2_state);
255 struct cli_state *cli = state->cli;
256 uint32_t num_bytes;
257 uint8_t *in;
258 char *inbuf;
259 uint8_t *bytes;
260 uint8_t *p;
261 NTSTATUS status;
262 ssize_t ret;
264 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
265 &num_bytes, &bytes);
266 TALLOC_FREE(subreq);
267 if (!NT_STATUS_IS_OK(status)) {
268 tevent_req_nterror(req, status);
269 return;
272 inbuf = (char *)in;
273 p = bytes;
275 cli->vuid = SVAL(inbuf, smb_uid);
277 status = smb_bytes_talloc_string(cli,
278 inbuf,
279 &cli->server_os,
281 bytes+num_bytes-p,
282 &ret);
284 if (!NT_STATUS_IS_OK(status)) {
285 tevent_req_nterror(req, status);
286 return;
288 p += ret;
290 status = smb_bytes_talloc_string(cli,
291 inbuf,
292 &cli->server_type,
294 bytes+num_bytes-p,
295 &ret);
297 if (!NT_STATUS_IS_OK(status)) {
298 tevent_req_nterror(req, status);
299 return;
301 p += ret;
303 status = smb_bytes_talloc_string(cli,
304 inbuf,
305 &cli->server_domain,
307 bytes+num_bytes-p,
308 &ret);
310 if (!NT_STATUS_IS_OK(status)) {
311 tevent_req_nterror(req, status);
312 return;
314 p += ret;
316 if (strstr(cli->server_type, "Samba")) {
317 cli->is_samba = True;
319 status = cli_set_username(cli, state->user);
320 if (tevent_req_nterror(req, status)) {
321 return;
323 tevent_req_done(req);
326 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
328 return tevent_req_simple_recv_ntstatus(req);
331 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
332 const char *pass, size_t passlen,
333 const char *workgroup)
335 TALLOC_CTX *frame = talloc_stackframe();
336 struct event_context *ev;
337 struct tevent_req *req;
338 NTSTATUS status = NT_STATUS_NO_MEMORY;
340 if (cli_has_async_calls(cli)) {
342 * Can't use sync call while an async call is in flight
344 status = NT_STATUS_INVALID_PARAMETER;
345 goto fail;
347 ev = event_context_init(frame);
348 if (ev == NULL) {
349 goto fail;
351 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
352 workgroup);
353 if (req == NULL) {
354 goto fail;
356 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
357 goto fail;
359 status = cli_session_setup_lanman2_recv(req);
360 fail:
361 TALLOC_FREE(frame);
362 return status;
365 /****************************************************************************
366 Work out suitable capabilities to offer the server.
367 ****************************************************************************/
369 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
371 uint32 capabilities = CAP_NT_SMBS;
373 if (!cli->force_dos_errors)
374 capabilities |= CAP_STATUS32;
376 if (cli->use_level_II_oplocks)
377 capabilities |= CAP_LEVEL_II_OPLOCKS;
379 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
380 return capabilities;
383 /****************************************************************************
384 Do a NT1 guest session setup.
385 ****************************************************************************/
387 struct cli_session_setup_guest_state {
388 struct cli_state *cli;
389 uint16_t vwv[13];
390 struct iovec bytes;
393 static void cli_session_setup_guest_done(struct tevent_req *subreq);
395 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
396 struct event_context *ev,
397 struct cli_state *cli,
398 struct tevent_req **psmbreq)
400 struct tevent_req *req, *subreq;
401 struct cli_session_setup_guest_state *state;
402 uint16_t *vwv;
403 uint8_t *bytes;
405 req = tevent_req_create(mem_ctx, &state,
406 struct cli_session_setup_guest_state);
407 if (req == NULL) {
408 return NULL;
410 state->cli = cli;
411 vwv = state->vwv;
413 SCVAL(vwv+0, 0, 0xFF);
414 SCVAL(vwv+0, 1, 0);
415 SSVAL(vwv+1, 0, 0);
416 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
417 SSVAL(vwv+3, 0, 2);
418 SSVAL(vwv+4, 0, cli->pid);
419 SIVAL(vwv+5, 0, cli->sesskey);
420 SSVAL(vwv+7, 0, 0);
421 SSVAL(vwv+8, 0, 0);
422 SSVAL(vwv+9, 0, 0);
423 SSVAL(vwv+10, 0, 0);
424 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
426 bytes = talloc_array(state, uint8_t, 0);
428 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
429 NULL);
430 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
431 NULL);
432 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
433 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
435 if (bytes == NULL) {
436 TALLOC_FREE(req);
437 return NULL;
440 state->bytes.iov_base = (void *)bytes;
441 state->bytes.iov_len = talloc_get_size(bytes);
443 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
444 1, &state->bytes);
445 if (subreq == NULL) {
446 TALLOC_FREE(req);
447 return NULL;
449 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
450 *psmbreq = subreq;
451 return req;
454 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
455 struct event_context *ev,
456 struct cli_state *cli)
458 struct tevent_req *req, *subreq;
459 NTSTATUS status;
461 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
462 if (req == NULL) {
463 return NULL;
466 status = cli_smb_req_send(subreq);
467 if (NT_STATUS_IS_OK(status)) {
468 tevent_req_nterror(req, status);
469 return tevent_req_post(req, ev);
471 return req;
474 static void cli_session_setup_guest_done(struct tevent_req *subreq)
476 struct tevent_req *req = tevent_req_callback_data(
477 subreq, struct tevent_req);
478 struct cli_session_setup_guest_state *state = tevent_req_data(
479 req, struct cli_session_setup_guest_state);
480 struct cli_state *cli = state->cli;
481 uint32_t num_bytes;
482 uint8_t *in;
483 char *inbuf;
484 uint8_t *bytes;
485 uint8_t *p;
486 NTSTATUS status;
487 ssize_t ret;
489 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
490 &num_bytes, &bytes);
491 TALLOC_FREE(subreq);
492 if (!NT_STATUS_IS_OK(status)) {
493 tevent_req_nterror(req, status);
494 return;
497 inbuf = (char *)in;
498 p = bytes;
500 cli->vuid = SVAL(inbuf, smb_uid);
502 status = smb_bytes_talloc_string(cli,
503 inbuf,
504 &cli->server_os,
506 bytes+num_bytes-p,
507 &ret);
509 if (!NT_STATUS_IS_OK(status)) {
510 tevent_req_nterror(req, status);
511 return;
513 p += ret;
515 status = smb_bytes_talloc_string(cli,
516 inbuf,
517 &cli->server_type,
519 bytes+num_bytes-p,
520 &ret);
522 if (!NT_STATUS_IS_OK(status)) {
523 tevent_req_nterror(req, status);
524 return;
526 p += ret;
528 status = smb_bytes_talloc_string(cli,
529 inbuf,
530 &cli->server_domain,
532 bytes+num_bytes-p,
533 &ret);
535 if (!NT_STATUS_IS_OK(status)) {
536 tevent_req_nterror(req, status);
537 return;
539 p += ret;
541 if (strstr(cli->server_type, "Samba")) {
542 cli->is_samba = True;
545 status = cli_set_username(cli, "");
546 if (!NT_STATUS_IS_OK(status)) {
547 tevent_req_nterror(req, status);
548 return;
550 tevent_req_done(req);
553 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
555 return tevent_req_simple_recv_ntstatus(req);
558 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
560 TALLOC_CTX *frame = talloc_stackframe();
561 struct event_context *ev;
562 struct tevent_req *req;
563 NTSTATUS status = NT_STATUS_OK;
565 if (cli_has_async_calls(cli)) {
567 * Can't use sync call while an async call is in flight
569 status = NT_STATUS_INVALID_PARAMETER;
570 goto fail;
573 ev = event_context_init(frame);
574 if (ev == NULL) {
575 status = NT_STATUS_NO_MEMORY;
576 goto fail;
579 req = cli_session_setup_guest_send(frame, ev, cli);
580 if (req == NULL) {
581 status = NT_STATUS_NO_MEMORY;
582 goto fail;
585 if (!tevent_req_poll(req, ev)) {
586 status = map_nt_error_from_unix(errno);
587 goto fail;
590 status = cli_session_setup_guest_recv(req);
591 fail:
592 TALLOC_FREE(frame);
593 return status;
596 /****************************************************************************
597 Do a NT1 plaintext session setup.
598 ****************************************************************************/
600 struct cli_session_setup_plain_state {
601 struct cli_state *cli;
602 uint16_t vwv[13];
603 const char *user;
606 static void cli_session_setup_plain_done(struct tevent_req *subreq);
608 static struct tevent_req *cli_session_setup_plain_send(
609 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
610 struct cli_state *cli,
611 const char *user, const char *pass, const char *workgroup)
613 struct tevent_req *req, *subreq;
614 struct cli_session_setup_plain_state *state;
615 uint16_t *vwv;
616 uint8_t *bytes;
617 size_t passlen;
618 char *version;
620 req = tevent_req_create(mem_ctx, &state,
621 struct cli_session_setup_plain_state);
622 if (req == NULL) {
623 return NULL;
625 state->cli = cli;
626 state->user = user;
627 vwv = state->vwv;
629 SCVAL(vwv+0, 0, 0xff);
630 SCVAL(vwv+0, 1, 0);
631 SSVAL(vwv+1, 0, 0);
632 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
633 SSVAL(vwv+3, 0, 2);
634 SSVAL(vwv+4, 0, cli->pid);
635 SIVAL(vwv+5, 0, cli->sesskey);
636 SSVAL(vwv+7, 0, 0);
637 SSVAL(vwv+8, 0, 0);
638 SSVAL(vwv+9, 0, 0);
639 SSVAL(vwv+10, 0, 0);
640 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
642 bytes = talloc_array(state, uint8_t, 0);
643 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
644 &passlen);
645 if (tevent_req_nomem(bytes, req)) {
646 return tevent_req_post(req, ev);
648 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
650 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
651 user, strlen(user)+1, NULL);
652 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
653 workgroup, strlen(workgroup)+1, NULL);
654 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
655 "Unix", 5, NULL);
657 version = talloc_asprintf(talloc_tos(), "Samba %s",
658 samba_version_string());
659 if (tevent_req_nomem(version, req)){
660 return tevent_req_post(req, ev);
662 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
663 version, strlen(version)+1, NULL);
664 TALLOC_FREE(version);
666 if (tevent_req_nomem(bytes, req)) {
667 return tevent_req_post(req, ev);
670 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
671 talloc_get_size(bytes), bytes);
672 if (tevent_req_nomem(subreq, req)) {
673 return tevent_req_post(req, ev);
675 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
676 return req;
679 static void cli_session_setup_plain_done(struct tevent_req *subreq)
681 struct tevent_req *req = tevent_req_callback_data(
682 subreq, struct tevent_req);
683 struct cli_session_setup_plain_state *state = tevent_req_data(
684 req, struct cli_session_setup_plain_state);
685 struct cli_state *cli = state->cli;
686 uint32_t num_bytes;
687 uint8_t *in;
688 char *inbuf;
689 uint8_t *bytes;
690 uint8_t *p;
691 NTSTATUS status;
692 ssize_t ret;
694 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
695 &num_bytes, &bytes);
696 TALLOC_FREE(subreq);
697 if (tevent_req_nterror(req, status)) {
698 return;
701 inbuf = (char *)in;
702 p = bytes;
704 cli->vuid = SVAL(inbuf, smb_uid);
706 status = smb_bytes_talloc_string(cli,
707 inbuf,
708 &cli->server_os,
710 bytes+num_bytes-p,
711 &ret);
713 if (!NT_STATUS_IS_OK(status)) {
714 tevent_req_nterror(req, status);
715 return;
717 p += ret;
719 status = smb_bytes_talloc_string(cli,
720 inbuf,
721 &cli->server_type,
723 bytes+num_bytes-p,
724 &ret);
726 if (!NT_STATUS_IS_OK(status)) {
727 tevent_req_nterror(req, status);
728 return;
730 p += ret;
732 status = smb_bytes_talloc_string(cli,
733 inbuf,
734 &cli->server_domain,
736 bytes+num_bytes-p,
737 &ret);
739 if (!NT_STATUS_IS_OK(status)) {
740 tevent_req_nterror(req, status);
741 return;
743 p += ret;
745 status = cli_set_username(cli, state->user);
746 if (tevent_req_nterror(req, status)) {
747 return;
749 if (strstr(cli->server_type, "Samba")) {
750 cli->is_samba = True;
752 tevent_req_done(req);
755 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
757 return tevent_req_simple_recv_ntstatus(req);
760 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
761 const char *user, const char *pass,
762 const char *workgroup)
764 TALLOC_CTX *frame = talloc_stackframe();
765 struct event_context *ev;
766 struct tevent_req *req;
767 NTSTATUS status = NT_STATUS_NO_MEMORY;
769 if (cli_has_async_calls(cli)) {
771 * Can't use sync call while an async call is in flight
773 status = NT_STATUS_INVALID_PARAMETER;
774 goto fail;
776 ev = event_context_init(frame);
777 if (ev == NULL) {
778 goto fail;
780 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
781 workgroup);
782 if (req == NULL) {
783 goto fail;
785 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
786 goto fail;
788 status = cli_session_setup_plain_recv(req);
789 fail:
790 TALLOC_FREE(frame);
791 return status;
794 /****************************************************************************
795 do a NT1 NTLM/LM encrypted session setup - for when extended security
796 is not negotiated.
797 @param cli client state to create do session setup on
798 @param user username
799 @param pass *either* cleartext password (passlen !=24) or LM response.
800 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
801 @param workgroup The user's domain.
802 ****************************************************************************/
804 struct cli_session_setup_nt1_state {
805 struct cli_state *cli;
806 uint16_t vwv[13];
807 DATA_BLOB response;
808 DATA_BLOB session_key;
809 const char *user;
812 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
814 static struct tevent_req *cli_session_setup_nt1_send(
815 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
816 struct cli_state *cli, const char *user,
817 const char *pass, size_t passlen,
818 const char *ntpass, size_t ntpasslen,
819 const char *workgroup)
821 struct tevent_req *req, *subreq;
822 struct cli_session_setup_nt1_state *state;
823 DATA_BLOB lm_response = data_blob_null;
824 DATA_BLOB nt_response = data_blob_null;
825 DATA_BLOB session_key = data_blob_null;
826 uint16_t *vwv;
827 uint8_t *bytes;
828 char *workgroup_upper;
830 req = tevent_req_create(mem_ctx, &state,
831 struct cli_session_setup_nt1_state);
832 if (req == NULL) {
833 return NULL;
835 state->cli = cli;
836 state->user = user;
837 vwv = state->vwv;
839 if (passlen == 0) {
840 /* do nothing - guest login */
841 } else if (passlen != 24) {
842 if (lp_client_ntlmv2_auth()) {
843 DATA_BLOB server_chal;
844 DATA_BLOB names_blob;
846 server_chal = data_blob(cli->secblob.data,
847 MIN(cli->secblob.length, 8));
848 if (tevent_req_nomem(server_chal.data, req)) {
849 return tevent_req_post(req, ev);
853 * note that the 'workgroup' here is a best
854 * guess - we don't know the server's domain
855 * at this point. The 'server name' is also
856 * dodgy...
858 names_blob = NTLMv2_generate_names_blob(
859 NULL, cli->called.name, workgroup);
861 if (tevent_req_nomem(names_blob.data, req)) {
862 return tevent_req_post(req, ev);
865 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
866 &server_chal, &names_blob,
867 &lm_response, &nt_response,
868 NULL, &session_key)) {
869 data_blob_free(&names_blob);
870 data_blob_free(&server_chal);
871 tevent_req_nterror(
872 req, NT_STATUS_ACCESS_DENIED);
873 return tevent_req_post(req, ev);
875 data_blob_free(&names_blob);
876 data_blob_free(&server_chal);
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->secblob.data,
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,cli->secblob.data,
902 lm_response.data)) {
904 * Oops, the LM response is
905 * invalid, just put the NT
906 * response there instead
908 data_blob_free(&lm_response);
909 lm_response = data_blob(
910 nt_response.data,
911 nt_response.length);
913 } else {
915 * LM disabled, place NT# in LM field
916 * instead
918 lm_response = data_blob(
919 nt_response.data, nt_response.length);
922 if (tevent_req_nomem(lm_response.data, req)) {
923 return tevent_req_post(req, ev);
926 session_key = data_blob(NULL, 16);
927 if (tevent_req_nomem(session_key.data, req)) {
928 return tevent_req_post(req, ev);
930 #ifdef LANMAN_ONLY
931 E_deshash(pass, session_key.data);
932 memset(&session_key.data[8], '\0', 8);
933 #else
934 SMBsesskeygen_ntv1(nt_hash, session_key.data);
935 #endif
937 cli_temp_set_signing(cli);
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->pid);
980 SIVAL(vwv+5, 0, cli->sesskey);
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));
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;
1047 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
1048 &num_bytes, &bytes);
1049 TALLOC_FREE(subreq);
1050 if (!NT_STATUS_IS_OK(status)) {
1051 tevent_req_nterror(req, status);
1052 return;
1055 inbuf = (char *)in;
1056 p = bytes;
1058 cli->vuid = SVAL(inbuf, smb_uid);
1060 status = smb_bytes_talloc_string(cli,
1061 inbuf,
1062 &cli->server_os,
1064 bytes+num_bytes-p,
1065 &ret);
1066 if (!NT_STATUS_IS_OK(status)) {
1067 tevent_req_nterror(req, status);
1068 return;
1070 p += ret;
1072 status = smb_bytes_talloc_string(cli,
1073 inbuf,
1074 &cli->server_type,
1076 bytes+num_bytes-p,
1077 &ret);
1078 if (!NT_STATUS_IS_OK(status)) {
1079 tevent_req_nterror(req, status);
1080 return;
1082 p += ret;
1084 status = smb_bytes_talloc_string(cli,
1085 inbuf,
1086 &cli->server_domain,
1088 bytes+num_bytes-p,
1089 &ret);
1090 if (!NT_STATUS_IS_OK(status)) {
1091 tevent_req_nterror(req, status);
1092 return;
1094 p += ret;
1096 if (strstr(cli->server_type, "Samba")) {
1097 cli->is_samba = True;
1100 status = cli_set_username(cli, state->user);
1101 if (tevent_req_nterror(req, status)) {
1102 return;
1104 if (cli_simple_set_signing(cli, state->session_key, state->response)
1105 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1106 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1107 return;
1109 if (state->session_key.data) {
1110 /* Have plaintext orginal */
1111 cli_set_session_key(cli, state->session_key);
1113 tevent_req_done(req);
1116 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1118 return tevent_req_simple_recv_ntstatus(req);
1121 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1122 const char *pass, size_t passlen,
1123 const char *ntpass, size_t ntpasslen,
1124 const char *workgroup)
1126 TALLOC_CTX *frame = talloc_stackframe();
1127 struct event_context *ev;
1128 struct tevent_req *req;
1129 NTSTATUS status = NT_STATUS_NO_MEMORY;
1131 if (cli_has_async_calls(cli)) {
1133 * Can't use sync call while an async call is in flight
1135 status = NT_STATUS_INVALID_PARAMETER;
1136 goto fail;
1138 ev = event_context_init(frame);
1139 if (ev == NULL) {
1140 goto fail;
1142 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1143 ntpass, ntpasslen, workgroup);
1144 if (req == NULL) {
1145 goto fail;
1147 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1148 goto fail;
1150 status = cli_session_setup_nt1_recv(req);
1151 fail:
1152 TALLOC_FREE(frame);
1153 return status;
1156 /* The following is calculated from :
1157 * (smb_size-4) = 35
1158 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1159 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1160 * end of packet.
1163 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1165 struct cli_sesssetup_blob_state {
1166 struct tevent_context *ev;
1167 struct cli_state *cli;
1168 DATA_BLOB blob;
1169 uint16_t max_blob_size;
1170 uint16_t vwv[12];
1171 uint8_t *buf;
1173 NTSTATUS status;
1174 char *inbuf;
1175 DATA_BLOB ret_blob;
1178 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1179 struct tevent_req **psubreq);
1180 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1182 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1183 struct tevent_context *ev,
1184 struct cli_state *cli,
1185 DATA_BLOB blob)
1187 struct tevent_req *req, *subreq;
1188 struct cli_sesssetup_blob_state *state;
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 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
1200 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1201 "(was %u, need minimum %u)\n",
1202 (unsigned int)cli->max_xmit,
1203 BASE_SESSSETUP_BLOB_PACKET_SIZE));
1204 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1205 return tevent_req_post(req, ev);
1207 state->max_blob_size =
1208 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
1210 if (!cli_sesssetup_blob_next(state, &subreq)) {
1211 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1212 return tevent_req_post(req, ev);
1214 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1215 return req;
1218 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1219 struct tevent_req **psubreq)
1221 struct tevent_req *subreq;
1222 uint16_t thistime;
1224 SCVAL(state->vwv+0, 0, 0xFF);
1225 SCVAL(state->vwv+0, 1, 0);
1226 SSVAL(state->vwv+1, 0, 0);
1227 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1228 SSVAL(state->vwv+3, 0, 2);
1229 SSVAL(state->vwv+4, 0, 1);
1230 SIVAL(state->vwv+5, 0, 0);
1232 thistime = MIN(state->blob.length, state->max_blob_size);
1233 SSVAL(state->vwv+7, 0, thistime);
1235 SSVAL(state->vwv+8, 0, 0);
1236 SSVAL(state->vwv+9, 0, 0);
1237 SIVAL(state->vwv+10, 0,
1238 cli_session_setup_capabilities(state->cli)
1239 | 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, 1, &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->vuid = SVAL(state->inbuf, smb_uid);
1298 blob_length = SVAL(vwv+3, 0);
1299 if (blob_length > num_bytes) {
1300 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1301 return;
1303 state->ret_blob = data_blob_const(bytes, blob_length);
1305 p = bytes + blob_length;
1307 status = smb_bytes_talloc_string(cli,
1308 (char *)inbuf,
1309 &cli->server_os,
1311 bytes+num_bytes-p,
1312 &ret);
1314 if (!NT_STATUS_IS_OK(status)) {
1315 tevent_req_nterror(req, status);
1316 return;
1318 p += ret;
1320 status = smb_bytes_talloc_string(cli,
1321 (char *)inbuf,
1322 &cli->server_type,
1324 bytes+num_bytes-p,
1325 &ret);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 tevent_req_nterror(req, status);
1329 return;
1331 p += ret;
1333 status = smb_bytes_talloc_string(cli,
1334 (char *)inbuf,
1335 &cli->server_domain,
1337 bytes+num_bytes-p,
1338 &ret);
1340 if (!NT_STATUS_IS_OK(status)) {
1341 tevent_req_nterror(req, status);
1342 return;
1344 p += ret;
1346 if (strstr(cli->server_type, "Samba")) {
1347 cli->is_samba = True;
1350 if (state->blob.length != 0) {
1352 * More to send
1354 if (!cli_sesssetup_blob_next(state, &subreq)) {
1355 tevent_req_nomem(NULL, req);
1356 return;
1358 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1359 return;
1361 tevent_req_done(req);
1364 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1365 TALLOC_CTX *mem_ctx,
1366 DATA_BLOB *pblob,
1367 char **pinbuf)
1369 struct cli_sesssetup_blob_state *state = tevent_req_data(
1370 req, struct cli_sesssetup_blob_state);
1371 NTSTATUS status;
1372 char *inbuf;
1374 if (tevent_req_is_nterror(req, &status)) {
1375 state->cli->vuid = 0;
1376 return status;
1379 inbuf = talloc_move(mem_ctx, &state->inbuf);
1380 if (pblob != NULL) {
1381 *pblob = state->ret_blob;
1383 if (pinbuf != NULL) {
1384 *pinbuf = inbuf;
1386 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1387 return state->status;
1390 #ifdef HAVE_KRB5
1392 /****************************************************************************
1393 Use in-memory credentials cache
1394 ****************************************************************************/
1396 static void use_in_memory_ccache(void) {
1397 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1400 /****************************************************************************
1401 Do a spnego/kerberos encrypted session setup.
1402 ****************************************************************************/
1404 struct cli_session_setup_kerberos_state {
1405 struct cli_state *cli;
1406 DATA_BLOB negTokenTarg;
1407 DATA_BLOB session_key_krb5;
1408 ADS_STATUS ads_status;
1411 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1413 static struct tevent_req *cli_session_setup_kerberos_send(
1414 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1415 const char *principal, const char *workgroup)
1417 struct tevent_req *req, *subreq;
1418 struct cli_session_setup_kerberos_state *state;
1419 int rc;
1421 DEBUG(2,("Doing kerberos session setup\n"));
1423 req = tevent_req_create(mem_ctx, &state,
1424 struct cli_session_setup_kerberos_state);
1425 if (req == NULL) {
1426 return NULL;
1428 state->cli = cli;
1429 state->ads_status = ADS_SUCCESS;
1431 cli_temp_set_signing(cli);
1434 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1435 * we have to acquire a ticket. To be fixed later :-)
1437 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1438 &state->session_key_krb5, 0, NULL);
1439 if (rc) {
1440 DEBUG(1, ("cli_session_setup_kerberos: "
1441 "spnego_gen_krb5_negTokenInit failed: %s\n",
1442 error_message(rc)));
1443 state->ads_status = ADS_ERROR_KRB5(rc);
1444 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1445 return tevent_req_post(req, ev);
1448 #if 0
1449 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1450 state->negTokenTarg.length);
1451 #endif
1453 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1454 if (tevent_req_nomem(subreq, req)) {
1455 return tevent_req_post(req, ev);
1457 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1458 return req;
1461 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1463 struct tevent_req *req = tevent_req_callback_data(
1464 subreq, struct tevent_req);
1465 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1466 req, struct cli_session_setup_kerberos_state);
1467 char *inbuf = NULL;
1468 NTSTATUS status;
1470 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
1471 if (!NT_STATUS_IS_OK(status)) {
1472 TALLOC_FREE(subreq);
1473 tevent_req_nterror(req, status);
1474 return;
1477 cli_set_session_key(state->cli, state->session_key_krb5);
1479 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
1480 data_blob_null)
1481 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1482 TALLOC_FREE(subreq);
1483 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1484 return;
1486 TALLOC_FREE(subreq);
1487 tevent_req_done(req);
1490 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1492 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1493 req, struct cli_session_setup_kerberos_state);
1494 NTSTATUS status;
1496 if (tevent_req_is_nterror(req, &status)) {
1497 return ADS_ERROR_NT(status);
1499 return state->ads_status;
1502 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1503 const char *principal,
1504 const char *workgroup)
1506 struct tevent_context *ev;
1507 struct tevent_req *req;
1508 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1510 if (cli_has_async_calls(cli)) {
1511 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1513 ev = tevent_context_init(talloc_tos());
1514 if (ev == NULL) {
1515 goto fail;
1517 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
1518 workgroup);
1519 if (req == NULL) {
1520 goto fail;
1522 if (!tevent_req_poll(req, ev)) {
1523 status = ADS_ERROR_SYSTEM(errno);
1524 goto fail;
1526 status = cli_session_setup_kerberos_recv(req);
1527 fail:
1528 TALLOC_FREE(ev);
1529 return status;
1531 #endif /* HAVE_KRB5 */
1533 /****************************************************************************
1534 Do a spnego/NTLMSSP encrypted session setup.
1535 ****************************************************************************/
1537 struct cli_session_setup_ntlmssp_state {
1538 struct tevent_context *ev;
1539 struct cli_state *cli;
1540 struct ntlmssp_state *ntlmssp_state;
1541 int turn;
1542 DATA_BLOB blob_out;
1545 static int cli_session_setup_ntlmssp_state_destructor(
1546 struct cli_session_setup_ntlmssp_state *state)
1548 if (state->ntlmssp_state != NULL) {
1549 TALLOC_FREE(state->ntlmssp_state);
1551 return 0;
1554 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1556 static struct tevent_req *cli_session_setup_ntlmssp_send(
1557 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1558 const char *user, const char *pass, const char *domain)
1560 struct tevent_req *req, *subreq;
1561 struct cli_session_setup_ntlmssp_state *state;
1562 NTSTATUS status;
1563 DATA_BLOB blob_out;
1564 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1566 req = tevent_req_create(mem_ctx, &state,
1567 struct cli_session_setup_ntlmssp_state);
1568 if (req == NULL) {
1569 return NULL;
1571 state->ev = ev;
1572 state->cli = cli;
1573 state->turn = 1;
1575 state->ntlmssp_state = NULL;
1576 talloc_set_destructor(
1577 state, cli_session_setup_ntlmssp_state_destructor);
1579 cli_temp_set_signing(cli);
1581 status = ntlmssp_client_start(state,
1582 global_myname(),
1583 lp_workgroup(),
1584 lp_client_ntlmv2_auth(),
1585 &state->ntlmssp_state);
1586 if (!NT_STATUS_IS_OK(status)) {
1587 goto fail;
1589 ntlmssp_want_feature(state->ntlmssp_state,
1590 NTLMSSP_FEATURE_SESSION_KEY);
1591 if (cli->use_ccache) {
1592 ntlmssp_want_feature(state->ntlmssp_state,
1593 NTLMSSP_FEATURE_CCACHE);
1595 status = ntlmssp_set_username(state->ntlmssp_state, user);
1596 if (!NT_STATUS_IS_OK(status)) {
1597 goto fail;
1599 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1600 if (!NT_STATUS_IS_OK(status)) {
1601 goto fail;
1603 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1604 if (!NT_STATUS_IS_OK(status)) {
1605 goto fail;
1607 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1608 &blob_out);
1609 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1610 goto fail;
1613 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1614 data_blob_free(&blob_out);
1616 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1617 if (tevent_req_nomem(subreq, req)) {
1618 return tevent_req_post(req, ev);
1620 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1621 return req;
1622 fail:
1623 tevent_req_nterror(req, status);
1624 return tevent_req_post(req, ev);
1627 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1629 struct tevent_req *req = tevent_req_callback_data(
1630 subreq, struct tevent_req);
1631 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1632 req, struct cli_session_setup_ntlmssp_state);
1633 DATA_BLOB blob_in, msg_in, blob_out;
1634 char *inbuf = NULL;
1635 bool parse_ret;
1636 NTSTATUS status;
1638 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1639 &inbuf);
1640 TALLOC_FREE(subreq);
1641 data_blob_free(&state->blob_out);
1643 if (NT_STATUS_IS_OK(status)) {
1644 if (state->cli->server_domain[0] == '\0') {
1645 TALLOC_FREE(state->cli->server_domain);
1646 state->cli->server_domain = talloc_strdup(state->cli,
1647 state->ntlmssp_state->server.netbios_domain);
1648 if (state->cli->server_domain == NULL) {
1649 TALLOC_FREE(subreq);
1650 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1651 return;
1654 cli_set_session_key(
1655 state->cli, state->ntlmssp_state->session_key);
1657 if (cli_simple_set_signing(
1658 state->cli, state->ntlmssp_state->session_key,
1659 data_blob_null)
1660 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1661 TALLOC_FREE(subreq);
1662 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1663 return;
1665 TALLOC_FREE(subreq);
1666 TALLOC_FREE(state->ntlmssp_state);
1667 tevent_req_done(req);
1668 return;
1670 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1671 tevent_req_nterror(req, status);
1672 return;
1675 if (blob_in.length == 0) {
1676 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1677 return;
1680 if ((state->turn == 1)
1681 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1682 DATA_BLOB tmp_blob = data_blob_null;
1683 /* the server might give us back two challenges */
1684 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1685 &tmp_blob);
1686 data_blob_free(&tmp_blob);
1687 } else {
1688 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1689 OID_NTLMSSP, &msg_in);
1691 state->turn += 1;
1693 if (!parse_ret) {
1694 DEBUG(3,("Failed to parse auth response\n"));
1695 if (NT_STATUS_IS_OK(status)
1696 || NT_STATUS_EQUAL(status,
1697 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1698 tevent_req_nterror(
1699 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1700 return;
1704 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1706 if (!NT_STATUS_IS_OK(status)
1707 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1708 TALLOC_FREE(subreq);
1709 TALLOC_FREE(state->ntlmssp_state);
1710 tevent_req_nterror(req, status);
1711 return;
1714 state->blob_out = spnego_gen_auth(state, blob_out);
1715 TALLOC_FREE(subreq);
1716 if (tevent_req_nomem(state->blob_out.data, req)) {
1717 return;
1720 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1721 state->blob_out);
1722 if (tevent_req_nomem(subreq, req)) {
1723 return;
1725 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1728 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1730 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1731 req, struct cli_session_setup_ntlmssp_state);
1732 NTSTATUS status;
1734 if (tevent_req_is_nterror(req, &status)) {
1735 state->cli->vuid = 0;
1736 return status;
1738 return NT_STATUS_OK;
1741 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1742 const char *user,
1743 const char *pass,
1744 const char *domain)
1746 struct tevent_context *ev;
1747 struct tevent_req *req;
1748 NTSTATUS status = NT_STATUS_NO_MEMORY;
1750 if (cli_has_async_calls(cli)) {
1751 return NT_STATUS_INVALID_PARAMETER;
1753 ev = tevent_context_init(talloc_tos());
1754 if (ev == NULL) {
1755 goto fail;
1757 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1758 if (req == NULL) {
1759 goto fail;
1761 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1762 goto fail;
1764 status = cli_session_setup_ntlmssp_recv(req);
1765 fail:
1766 TALLOC_FREE(ev);
1767 return status;
1770 /****************************************************************************
1771 Do a spnego encrypted session setup.
1773 user_domain: The shortname of the domain the user/machine is a member of.
1774 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1775 ****************************************************************************/
1777 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1778 const char *pass, const char *user_domain,
1779 const char * dest_realm)
1781 char *principal = NULL;
1782 char *OIDs[ASN1_MAX_OIDS];
1783 int i;
1784 DATA_BLOB blob;
1785 const char *p = NULL;
1786 char *account = NULL;
1787 NTSTATUS status;
1789 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1791 /* the server might not even do spnego */
1792 if (cli->secblob.length <= 16) {
1793 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1794 goto ntlmssp;
1797 #if 0
1798 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1799 #endif
1801 /* there is 16 bytes of GUID before the real spnego packet starts */
1802 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1804 /* The server sent us the first part of the SPNEGO exchange in the
1805 * negprot reply. It is WRONG to depend on the principal sent in the
1806 * negprot reply, but right now we do it. If we don't receive one,
1807 * we try to best guess, then fall back to NTLM. */
1808 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1809 OIDs[0] == NULL) {
1810 data_blob_free(&blob);
1811 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1813 data_blob_free(&blob);
1815 /* make sure the server understands kerberos */
1816 for (i=0;OIDs[i];i++) {
1817 if (i == 0)
1818 DEBUG(3,("got OID=%s\n", OIDs[i]));
1819 else
1820 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1821 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1822 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1823 cli->got_kerberos_mechanism = True;
1825 talloc_free(OIDs[i]);
1828 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1830 status = cli_set_username(cli, user);
1831 if (!NT_STATUS_IS_OK(status)) {
1832 TALLOC_FREE(principal);
1833 return ADS_ERROR_NT(status);
1836 #ifdef HAVE_KRB5
1837 /* If password is set we reauthenticate to kerberos server
1838 * and do not store results */
1840 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1841 ADS_STATUS rc;
1843 if (pass && *pass) {
1844 int ret;
1846 use_in_memory_ccache();
1847 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1849 if (ret){
1850 TALLOC_FREE(principal);
1851 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1852 if (cli->fallback_after_kerberos)
1853 goto ntlmssp;
1854 return ADS_ERROR_KRB5(ret);
1858 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1860 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1861 TALLOC_FREE(principal);
1864 if (principal == NULL &&
1865 !is_ipaddress(cli->desthost) &&
1866 !strequal(STAR_SMBSERVER,
1867 cli->desthost)) {
1868 char *realm = NULL;
1869 char *host = NULL;
1870 DEBUG(3,("cli_session_setup_spnego: using target "
1871 "hostname not SPNEGO principal\n"));
1873 host = strchr_m(cli->desthost, '.');
1874 if (dest_realm) {
1875 realm = SMB_STRDUP(dest_realm);
1876 strupper_m(realm);
1877 } else {
1878 if (host) {
1879 /* DNS name. */
1880 realm = kerberos_get_realm_from_hostname(cli->desthost);
1881 } else {
1882 /* NetBIOS name - use our realm. */
1883 realm = kerberos_get_default_realm_from_ccache();
1887 if (realm && *realm) {
1888 principal = talloc_asprintf(talloc_tos(),
1889 "cifs/%s@%s",
1890 cli->desthost,
1891 realm);
1892 if (!principal) {
1893 SAFE_FREE(realm);
1894 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1896 DEBUG(3,("cli_session_setup_spnego: guessed "
1897 "server principal=%s\n",
1898 principal ? principal : "<null>"));
1900 SAFE_FREE(realm);
1903 if (principal) {
1904 rc = cli_session_setup_kerberos(cli, principal,
1905 dest_realm);
1906 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1907 TALLOC_FREE(principal);
1908 return rc;
1912 #endif
1914 TALLOC_FREE(principal);
1916 ntlmssp:
1918 account = talloc_strdup(talloc_tos(), user);
1919 if (!account) {
1920 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1923 /* when falling back to ntlmssp while authenticating with a machine
1924 * account strip off the realm - gd */
1926 if ((p = strchr_m(user, '@')) != NULL) {
1927 account[PTR_DIFF(p,user)] = '\0';
1930 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1933 /****************************************************************************
1934 Send a session setup. The username and workgroup is in UNIX character
1935 format and must be converted to DOS codepage format before sending. If the
1936 password is in plaintext, the same should be done.
1937 ****************************************************************************/
1939 NTSTATUS cli_session_setup(struct cli_state *cli,
1940 const char *user,
1941 const char *pass, int passlen,
1942 const char *ntpass, int ntpasslen,
1943 const char *workgroup)
1945 char *p;
1946 char *user2;
1948 if (user) {
1949 user2 = talloc_strdup(talloc_tos(), user);
1950 } else {
1951 user2 = talloc_strdup(talloc_tos(), "");
1953 if (user2 == NULL) {
1954 return NT_STATUS_NO_MEMORY;
1957 if (!workgroup) {
1958 workgroup = "";
1961 /* allow for workgroups as part of the username */
1962 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1963 (p=strchr_m(user2,*lp_winbind_separator()))) {
1964 *p = 0;
1965 user = p+1;
1966 strupper_m(user2);
1967 workgroup = user2;
1970 if (cli->protocol < PROTOCOL_LANMAN1) {
1971 return NT_STATUS_OK;
1974 /* now work out what sort of session setup we are going to
1975 do. I have split this into separate functions to make the
1976 flow a bit easier to understand (tridge) */
1978 /* if its an older server then we have to use the older request format */
1980 if (cli->protocol < PROTOCOL_NT1) {
1981 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1982 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
1983 " or 'client ntlmv2 auth = yes'\n"));
1984 return NT_STATUS_ACCESS_DENIED;
1987 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1988 !lp_client_plaintext_auth() && (*pass)) {
1989 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
1990 " or 'client ntlmv2 auth = yes'\n"));
1991 return NT_STATUS_ACCESS_DENIED;
1994 return cli_session_setup_lanman2(cli, user, pass, passlen,
1995 workgroup);
1998 /* if no user is supplied then we have to do an anonymous connection.
1999 passwords are ignored */
2001 if (!user || !*user)
2002 return cli_session_setup_guest(cli);
2004 /* if the server is share level then send a plaintext null
2005 password at this point. The password is sent in the tree
2006 connect */
2008 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2009 return cli_session_setup_plain(cli, user, "", workgroup);
2011 /* if the server doesn't support encryption then we have to use
2012 plaintext. The second password is ignored */
2014 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2015 if (!lp_client_plaintext_auth() && (*pass)) {
2016 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2017 " or 'client ntlmv2 auth = yes'\n"));
2018 return NT_STATUS_ACCESS_DENIED;
2020 return cli_session_setup_plain(cli, user, pass, workgroup);
2023 /* if the server supports extended security then use SPNEGO */
2025 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
2026 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2027 workgroup, NULL);
2028 if (!ADS_ERR_OK(status)) {
2029 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2030 return ads_ntstatus(status);
2032 } else {
2033 NTSTATUS status;
2035 /* otherwise do a NT1 style session setup */
2036 status = cli_session_setup_nt1(cli, user, pass, passlen,
2037 ntpass, ntpasslen, workgroup);
2038 if (!NT_STATUS_IS_OK(status)) {
2039 DEBUG(3,("cli_session_setup: NT1 session setup "
2040 "failed: %s\n", nt_errstr(status)));
2041 return status;
2045 if (strstr(cli->server_type, "Samba")) {
2046 cli->is_samba = True;
2049 return NT_STATUS_OK;
2052 /****************************************************************************
2053 Send a uloggoff.
2054 *****************************************************************************/
2056 struct cli_ulogoff_state {
2057 struct cli_state *cli;
2058 uint16_t vwv[3];
2061 static void cli_ulogoff_done(struct tevent_req *subreq);
2063 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2064 struct tevent_context *ev,
2065 struct cli_state *cli)
2067 struct tevent_req *req, *subreq;
2068 struct cli_ulogoff_state *state;
2070 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2071 if (req == NULL) {
2072 return NULL;
2074 state->cli = cli;
2076 SCVAL(state->vwv+0, 0, 0xFF);
2077 SCVAL(state->vwv+1, 0, 0);
2078 SSVAL(state->vwv+2, 0, 0);
2080 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2081 0, NULL);
2082 if (tevent_req_nomem(subreq, req)) {
2083 return tevent_req_post(req, ev);
2085 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2086 return req;
2089 static void cli_ulogoff_done(struct tevent_req *subreq)
2091 struct tevent_req *req = tevent_req_callback_data(
2092 subreq, struct tevent_req);
2093 struct cli_ulogoff_state *state = tevent_req_data(
2094 req, struct cli_ulogoff_state);
2095 NTSTATUS status;
2097 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2098 if (!NT_STATUS_IS_OK(status)) {
2099 tevent_req_nterror(req, status);
2100 return;
2102 state->cli->vuid = -1;
2103 tevent_req_done(req);
2106 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2108 return tevent_req_simple_recv_ntstatus(req);
2111 NTSTATUS cli_ulogoff(struct cli_state *cli)
2113 struct tevent_context *ev;
2114 struct tevent_req *req;
2115 NTSTATUS status = NT_STATUS_NO_MEMORY;
2117 if (cli_has_async_calls(cli)) {
2118 return NT_STATUS_INVALID_PARAMETER;
2120 ev = tevent_context_init(talloc_tos());
2121 if (ev == NULL) {
2122 goto fail;
2124 req = cli_ulogoff_send(ev, ev, cli);
2125 if (req == NULL) {
2126 goto fail;
2128 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2129 goto fail;
2131 status = cli_ulogoff_recv(req);
2132 fail:
2133 TALLOC_FREE(ev);
2134 return status;
2137 /****************************************************************************
2138 Send a tconX.
2139 ****************************************************************************/
2141 struct cli_tcon_andx_state {
2142 struct cli_state *cli;
2143 uint16_t vwv[4];
2144 struct iovec bytes;
2147 static void cli_tcon_andx_done(struct tevent_req *subreq);
2149 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2150 struct event_context *ev,
2151 struct cli_state *cli,
2152 const char *share, const char *dev,
2153 const char *pass, int passlen,
2154 struct tevent_req **psmbreq)
2156 struct tevent_req *req, *subreq;
2157 struct cli_tcon_andx_state *state;
2158 uint8_t p24[24];
2159 uint16_t *vwv;
2160 char *tmp = NULL;
2161 uint8_t *bytes;
2163 *psmbreq = NULL;
2165 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2166 if (req == NULL) {
2167 return NULL;
2169 state->cli = cli;
2170 vwv = state->vwv;
2172 cli->share = talloc_strdup(cli, share);
2173 if (!cli->share) {
2174 return NULL;
2177 /* in user level security don't send a password now */
2178 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2179 passlen = 1;
2180 pass = "";
2181 } else if (pass == NULL) {
2182 DEBUG(1, ("Server not using user level security and no "
2183 "password supplied.\n"));
2184 goto access_denied;
2187 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2188 *pass && passlen != 24) {
2189 if (!lp_client_lanman_auth()) {
2190 DEBUG(1, ("Server requested LANMAN password "
2191 "(share-level security) but "
2192 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2193 goto access_denied;
2197 * Non-encrypted passwords - convert to DOS codepage before
2198 * encryption.
2200 SMBencrypt(pass, cli->secblob.data, p24);
2201 passlen = 24;
2202 pass = (const char *)p24;
2203 } else {
2204 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2205 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2206 == 0) {
2207 char *tmp_pass;
2209 if (!lp_client_plaintext_auth() && (*pass)) {
2210 DEBUG(1, ("Server requested plaintext "
2211 "password but "
2212 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2213 goto access_denied;
2217 * Non-encrypted passwords - convert to DOS codepage
2218 * before using.
2220 tmp_pass = talloc_array(talloc_tos(), char, 128);
2221 if (tmp_pass == NULL) {
2222 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2223 return tevent_req_post(req, ev);
2225 passlen = clistr_push(cli,
2226 tmp_pass,
2227 pass,
2228 talloc_get_size(tmp_pass),
2229 STR_TERMINATE);
2230 if (passlen == -1) {
2231 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2232 return tevent_req_post(req, ev);
2234 pass = tmp_pass;
2238 SCVAL(vwv+0, 0, 0xFF);
2239 SCVAL(vwv+0, 1, 0);
2240 SSVAL(vwv+1, 0, 0);
2241 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2242 SSVAL(vwv+3, 0, passlen);
2244 if (passlen && pass) {
2245 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2246 } else {
2247 bytes = talloc_array(state, uint8_t, 0);
2251 * Add the sharename
2253 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2254 cli->desthost, share);
2255 if (tmp == NULL) {
2256 TALLOC_FREE(req);
2257 return NULL;
2259 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2260 NULL);
2261 TALLOC_FREE(tmp);
2264 * Add the devicetype
2266 tmp = talloc_strdup_upper(talloc_tos(), dev);
2267 if (tmp == NULL) {
2268 TALLOC_FREE(req);
2269 return NULL;
2271 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2272 TALLOC_FREE(tmp);
2274 if (bytes == NULL) {
2275 TALLOC_FREE(req);
2276 return NULL;
2279 state->bytes.iov_base = (void *)bytes;
2280 state->bytes.iov_len = talloc_get_size(bytes);
2282 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2283 1, &state->bytes);
2284 if (subreq == NULL) {
2285 TALLOC_FREE(req);
2286 return NULL;
2288 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2289 *psmbreq = subreq;
2290 return req;
2292 access_denied:
2293 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2294 return tevent_req_post(req, ev);
2297 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2298 struct event_context *ev,
2299 struct cli_state *cli,
2300 const char *share, const char *dev,
2301 const char *pass, int passlen)
2303 struct tevent_req *req, *subreq;
2304 NTSTATUS status;
2306 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2307 &subreq);
2308 if (req == NULL) {
2309 return NULL;
2311 if (subreq == NULL) {
2312 return req;
2314 status = cli_smb_req_send(subreq);
2315 if (!NT_STATUS_IS_OK(status)) {
2316 tevent_req_nterror(req, status);
2317 return tevent_req_post(req, ev);
2319 return req;
2322 static void cli_tcon_andx_done(struct tevent_req *subreq)
2324 struct tevent_req *req = tevent_req_callback_data(
2325 subreq, struct tevent_req);
2326 struct cli_tcon_andx_state *state = tevent_req_data(
2327 req, struct cli_tcon_andx_state);
2328 struct cli_state *cli = state->cli;
2329 uint8_t *in;
2330 char *inbuf;
2331 uint8_t wct;
2332 uint16_t *vwv;
2333 uint32_t num_bytes;
2334 uint8_t *bytes;
2335 NTSTATUS status;
2337 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2338 &num_bytes, &bytes);
2339 TALLOC_FREE(subreq);
2340 if (!NT_STATUS_IS_OK(status)) {
2341 tevent_req_nterror(req, status);
2342 return;
2345 inbuf = (char *)in;
2347 if (num_bytes) {
2348 if (clistr_pull_talloc(cli,
2349 inbuf,
2350 SVAL(inbuf, smb_flg2),
2351 &cli->dev,
2352 bytes,
2353 num_bytes,
2354 STR_TERMINATE|STR_ASCII) == -1) {
2355 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2356 return;
2358 } else {
2359 cli->dev = talloc_strdup(cli, "");
2360 if (cli->dev == NULL) {
2361 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2362 return;
2366 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
2367 /* almost certainly win95 - enable bug fixes */
2368 cli->win95 = True;
2372 * Make sure that we have the optional support 16-bit field. WCT > 2.
2373 * Avoids issues when connecting to Win9x boxes sharing files
2376 cli->dfsroot = false;
2378 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
2379 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2382 cli->cnum = SVAL(inbuf,smb_tid);
2383 tevent_req_done(req);
2386 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2388 return tevent_req_simple_recv_ntstatus(req);
2391 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2392 const char *dev, const char *pass, int passlen)
2394 TALLOC_CTX *frame = talloc_stackframe();
2395 struct event_context *ev;
2396 struct tevent_req *req;
2397 NTSTATUS status = NT_STATUS_OK;
2399 if (cli_has_async_calls(cli)) {
2401 * Can't use sync call while an async call is in flight
2403 status = NT_STATUS_INVALID_PARAMETER;
2404 goto fail;
2407 ev = event_context_init(frame);
2408 if (ev == NULL) {
2409 status = NT_STATUS_NO_MEMORY;
2410 goto fail;
2413 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2414 if (req == NULL) {
2415 status = NT_STATUS_NO_MEMORY;
2416 goto fail;
2419 if (!tevent_req_poll(req, ev)) {
2420 status = map_nt_error_from_unix(errno);
2421 goto fail;
2424 status = cli_tcon_andx_recv(req);
2425 fail:
2426 TALLOC_FREE(frame);
2427 return status;
2430 /****************************************************************************
2431 Send a tree disconnect.
2432 ****************************************************************************/
2434 struct cli_tdis_state {
2435 struct cli_state *cli;
2438 static void cli_tdis_done(struct tevent_req *subreq);
2440 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2441 struct tevent_context *ev,
2442 struct cli_state *cli)
2444 struct tevent_req *req, *subreq;
2445 struct cli_tdis_state *state;
2447 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2448 if (req == NULL) {
2449 return NULL;
2451 state->cli = cli;
2453 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2454 if (tevent_req_nomem(subreq, req)) {
2455 return tevent_req_post(req, ev);
2457 tevent_req_set_callback(subreq, cli_tdis_done, req);
2458 return req;
2461 static void cli_tdis_done(struct tevent_req *subreq)
2463 struct tevent_req *req = tevent_req_callback_data(
2464 subreq, struct tevent_req);
2465 struct cli_tdis_state *state = tevent_req_data(
2466 req, struct cli_tdis_state);
2467 NTSTATUS status;
2469 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2470 TALLOC_FREE(subreq);
2471 if (!NT_STATUS_IS_OK(status)) {
2472 tevent_req_nterror(req, status);
2473 return;
2475 state->cli->cnum = -1;
2476 tevent_req_done(req);
2479 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2481 return tevent_req_simple_recv_ntstatus(req);
2484 NTSTATUS cli_tdis(struct cli_state *cli)
2486 struct tevent_context *ev;
2487 struct tevent_req *req;
2488 NTSTATUS status = NT_STATUS_NO_MEMORY;
2490 if (cli_has_async_calls(cli)) {
2491 return NT_STATUS_INVALID_PARAMETER;
2493 ev = tevent_context_init(talloc_tos());
2494 if (ev == NULL) {
2495 goto fail;
2497 req = cli_tdis_send(ev, ev, cli);
2498 if (req == NULL) {
2499 goto fail;
2501 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2502 goto fail;
2504 status = cli_tdis_recv(req);
2505 fail:
2506 TALLOC_FREE(ev);
2507 return status;
2510 /****************************************************************************
2511 Send a negprot command.
2512 ****************************************************************************/
2514 struct cli_negprot_state {
2515 struct cli_state *cli;
2518 static void cli_negprot_done(struct tevent_req *subreq);
2520 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2521 struct event_context *ev,
2522 struct cli_state *cli)
2524 struct tevent_req *req, *subreq;
2525 struct cli_negprot_state *state;
2526 uint8_t *bytes = NULL;
2527 int numprots;
2528 uint16_t cnum;
2530 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2531 if (req == NULL) {
2532 return NULL;
2534 state->cli = cli;
2536 if (cli->protocol < PROTOCOL_NT1)
2537 cli->use_spnego = False;
2539 /* setup the protocol strings */
2540 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2541 uint8_t c = 2;
2542 if (prots[numprots].prot > cli->protocol) {
2543 break;
2545 bytes = (uint8_t *)talloc_append_blob(
2546 state, bytes, data_blob_const(&c, sizeof(c)));
2547 if (tevent_req_nomem(bytes, req)) {
2548 return tevent_req_post(req, ev);
2550 bytes = smb_bytes_push_str(bytes, false,
2551 prots[numprots].name,
2552 strlen(prots[numprots].name)+1,
2553 NULL);
2554 if (tevent_req_nomem(bytes, req)) {
2555 return tevent_req_post(req, ev);
2559 cnum = cli->cnum;
2561 cli->cnum = 0;
2562 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2563 talloc_get_size(bytes), bytes);
2564 cli->cnum = cnum;
2566 if (tevent_req_nomem(subreq, req)) {
2567 return tevent_req_post(req, ev);
2569 tevent_req_set_callback(subreq, cli_negprot_done, req);
2570 return req;
2573 static void cli_negprot_done(struct tevent_req *subreq)
2575 struct tevent_req *req = tevent_req_callback_data(
2576 subreq, struct tevent_req);
2577 struct cli_negprot_state *state = tevent_req_data(
2578 req, struct cli_negprot_state);
2579 struct cli_state *cli = state->cli;
2580 uint8_t wct;
2581 uint16_t *vwv;
2582 uint32_t num_bytes;
2583 uint8_t *bytes;
2584 NTSTATUS status;
2585 uint16_t protnum;
2586 uint8_t *inbuf;
2588 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2589 &num_bytes, &bytes);
2590 TALLOC_FREE(subreq);
2591 if (!NT_STATUS_IS_OK(status)) {
2592 tevent_req_nterror(req, status);
2593 return;
2596 protnum = SVAL(vwv, 0);
2598 if ((protnum >= ARRAY_SIZE(prots))
2599 || (prots[protnum].prot > cli->protocol)) {
2600 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2601 return;
2604 cli->protocol = prots[protnum].prot;
2606 if ((cli->protocol < PROTOCOL_NT1) &&
2607 client_is_signing_mandatory(cli)) {
2608 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2609 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2610 return;
2613 if (cli->protocol >= PROTOCOL_NT1) {
2614 struct timespec ts;
2615 bool negotiated_smb_signing = false;
2617 /* NT protocol */
2618 cli->sec_mode = CVAL(vwv + 1, 0);
2619 cli->max_mux = SVAL(vwv + 1, 1);
2620 cli->max_xmit = IVAL(vwv + 3, 1);
2621 cli->sesskey = IVAL(vwv + 7, 1);
2622 cli->serverzone = SVALS(vwv + 15, 1);
2623 cli->serverzone *= 60;
2624 /* this time arrives in real GMT */
2625 ts = interpret_long_date(((char *)(vwv+11))+1);
2626 cli->servertime = ts.tv_sec;
2627 cli->secblob = data_blob(bytes, num_bytes);
2628 cli->capabilities = IVAL(vwv + 9, 1);
2629 if (cli->capabilities & CAP_RAW_MODE) {
2630 cli->readbraw_supported = True;
2631 cli->writebraw_supported = True;
2633 /* work out if they sent us a workgroup */
2634 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2635 smb_buflen(cli->inbuf) > 8) {
2636 clistr_pull(cli->inbuf, cli->server_domain,
2637 bytes+8, sizeof(cli->server_domain),
2638 num_bytes-8,
2639 STR_UNICODE|STR_NOALIGN);
2643 * As signing is slow we only turn it on if either the client or
2644 * the server require it. JRA.
2647 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2648 /* Fail if server says signing is mandatory and we don't want to support it. */
2649 if (!client_is_signing_allowed(cli)) {
2650 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2651 tevent_req_nterror(req,
2652 NT_STATUS_ACCESS_DENIED);
2653 return;
2655 negotiated_smb_signing = true;
2656 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2657 /* Fail if client says signing is mandatory and the server doesn't support it. */
2658 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2659 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2660 tevent_req_nterror(req,
2661 NT_STATUS_ACCESS_DENIED);
2662 return;
2664 negotiated_smb_signing = true;
2665 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2666 negotiated_smb_signing = true;
2669 if (negotiated_smb_signing) {
2670 cli_set_signing_negotiated(cli);
2673 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2674 SAFE_FREE(cli->outbuf);
2675 SAFE_FREE(cli->inbuf);
2676 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2677 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2678 if (!cli->outbuf || !cli->inbuf) {
2679 tevent_req_nterror(req,
2680 NT_STATUS_NO_MEMORY);
2681 return;
2683 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2686 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2687 cli->use_spnego = False;
2688 cli->sec_mode = SVAL(vwv + 1, 0);
2689 cli->max_xmit = SVAL(vwv + 2, 0);
2690 cli->max_mux = SVAL(vwv + 3, 0);
2691 cli->sesskey = IVAL(vwv + 6, 0);
2692 cli->serverzone = SVALS(vwv + 10, 0);
2693 cli->serverzone *= 60;
2694 /* this time is converted to GMT by make_unix_date */
2695 cli->servertime = make_unix_date(
2696 (char *)(vwv + 8), cli->serverzone);
2697 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2698 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2699 cli->secblob = data_blob(bytes, num_bytes);
2700 } else {
2701 /* the old core protocol */
2702 cli->use_spnego = False;
2703 cli->sec_mode = 0;
2704 cli->serverzone = get_time_zone(time(NULL));
2707 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2709 /* a way to force ascii SMB */
2710 if (getenv("CLI_FORCE_ASCII"))
2711 cli->capabilities &= ~CAP_UNICODE;
2713 tevent_req_done(req);
2716 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2718 return tevent_req_simple_recv_ntstatus(req);
2721 NTSTATUS cli_negprot(struct cli_state *cli)
2723 TALLOC_CTX *frame = talloc_stackframe();
2724 struct event_context *ev;
2725 struct tevent_req *req;
2726 NTSTATUS status = NT_STATUS_OK;
2728 if (cli_has_async_calls(cli)) {
2730 * Can't use sync call while an async call is in flight
2732 status = NT_STATUS_INVALID_PARAMETER;
2733 goto fail;
2736 ev = event_context_init(frame);
2737 if (ev == NULL) {
2738 status = NT_STATUS_NO_MEMORY;
2739 goto fail;
2742 req = cli_negprot_send(frame, ev, cli);
2743 if (req == NULL) {
2744 status = NT_STATUS_NO_MEMORY;
2745 goto fail;
2748 if (!tevent_req_poll(req, ev)) {
2749 status = map_nt_error_from_unix(errno);
2750 goto fail;
2753 status = cli_negprot_recv(req);
2754 fail:
2755 TALLOC_FREE(frame);
2756 return status;
2759 /****************************************************************************
2760 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2761 ****************************************************************************/
2763 bool cli_session_request(struct cli_state *cli,
2764 struct nmb_name *calling, struct nmb_name *called)
2766 TALLOC_CTX *frame;
2767 uint8_t len_buf[4];
2768 struct iovec iov[3];
2769 ssize_t len;
2770 uint8_t *inbuf;
2771 int err;
2772 bool ret = false;
2774 /* 445 doesn't have session request */
2775 if (cli->port == 445)
2776 return True;
2778 memcpy(&(cli->calling), calling, sizeof(*calling));
2779 memcpy(&(cli->called ), called , sizeof(*called ));
2781 /* put in the destination name */
2783 frame = talloc_stackframe();
2785 iov[0].iov_base = len_buf;
2786 iov[0].iov_len = sizeof(len_buf);
2788 /* put in the destination name */
2790 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
2791 called->name_type);
2792 if (iov[1].iov_base == NULL) {
2793 goto fail;
2795 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
2796 talloc_get_size(iov[1].iov_base));
2798 /* and my name */
2800 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
2801 calling->name_type);
2802 if (iov[2].iov_base == NULL) {
2803 goto fail;
2805 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
2806 talloc_get_size(iov[2].iov_base));
2808 /* send a session request (RFC 1002) */
2809 /* setup the packet length
2810 * Remove four bytes from the length count, since the length
2811 * field in the NBT Session Service header counts the number
2812 * of bytes which follow. The cli_send_smb() function knows
2813 * about this and accounts for those four bytes.
2814 * CRH.
2817 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
2818 SCVAL(len_buf,0,0x81);
2820 len = write_data_iov(cli->fd, iov, 3);
2821 if (len == -1) {
2822 goto fail;
2824 len = read_smb(cli->fd, talloc_tos(), &inbuf, &err);
2825 if (len == -1) {
2826 errno = err;
2827 goto fail;
2830 if (CVAL(inbuf,0) == 0x84) {
2831 /* C. Hoch 9/14/95 Start */
2832 /* For information, here is the response structure.
2833 * We do the byte-twiddling to for portability.
2834 struct RetargetResponse{
2835 unsigned char type;
2836 unsigned char flags;
2837 int16 length;
2838 int32 ip_addr;
2839 int16 port;
2842 uint16_t port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9);
2843 struct in_addr dest_ip;
2844 NTSTATUS status;
2846 /* SESSION RETARGET */
2847 putip((char *)&dest_ip,inbuf+4);
2848 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2850 status = open_socket_out(&cli->dest_ss, port,
2851 LONG_CONNECT_TIMEOUT, &cli->fd);
2852 if (!NT_STATUS_IS_OK(status)) {
2853 goto fail;
2856 DEBUG(3,("Retargeted\n"));
2858 set_socket_options(cli->fd, lp_socket_options());
2860 /* Try again */
2862 static int depth;
2863 if (depth > 4) {
2864 DEBUG(0,("Retarget recursion - failing\n"));
2865 goto fail;
2867 depth++;
2868 ret = cli_session_request(cli, calling, called);
2869 depth--;
2870 goto done;
2872 } /* C. Hoch 9/14/95 End */
2874 if (CVAL(inbuf,0) != 0x82) {
2875 /* This is the wrong place to put the error... JRA. */
2876 cli->rap_error = CVAL(inbuf,4);
2877 goto fail;
2879 done:
2880 ret = true;
2881 fail:
2882 err = errno;
2883 TALLOC_FREE(frame);
2884 errno = err;
2885 return ret;
2888 struct fd_struct {
2889 int fd;
2892 static void smb_sock_connected(struct tevent_req *req)
2894 struct fd_struct *pfd = tevent_req_callback_data(
2895 req, struct fd_struct);
2896 int fd;
2897 NTSTATUS status;
2899 status = open_socket_out_defer_recv(req, &fd);
2900 if (NT_STATUS_IS_OK(status)) {
2901 pfd->fd = fd;
2905 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2906 uint16_t *port, int timeout, int *pfd)
2908 struct event_context *ev;
2909 struct tevent_req *r139, *r445;
2910 struct fd_struct *fd139, *fd445;
2911 NTSTATUS status = NT_STATUS_NO_MEMORY;
2913 if (*port != 0) {
2914 return open_socket_out(pss, *port, timeout, pfd);
2917 ev = event_context_init(talloc_tos());
2918 if (ev == NULL) {
2919 return NT_STATUS_NO_MEMORY;
2922 fd139 = talloc(ev, struct fd_struct);
2923 if (fd139 == NULL) {
2924 goto done;
2926 fd139->fd = -1;
2928 fd445 = talloc(ev, struct fd_struct);
2929 if (fd445 == NULL) {
2930 goto done;
2932 fd445->fd = -1;
2934 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2935 pss, 445, timeout);
2936 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2937 pss, 139, timeout);
2938 if ((r445 == NULL) || (r139 == NULL)) {
2939 goto done;
2941 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2942 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2944 while ((fd445->fd == -1) && (fd139->fd == -1)
2945 && (tevent_req_is_in_progress(r139)
2946 || tevent_req_is_in_progress(r445))) {
2947 event_loop_once(ev);
2950 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2951 close(fd139->fd);
2952 fd139->fd = -1;
2955 if (fd445->fd != -1) {
2956 *port = 445;
2957 *pfd = fd445->fd;
2958 status = NT_STATUS_OK;
2959 goto done;
2961 if (fd139->fd != -1) {
2962 *port = 139;
2963 *pfd = fd139->fd;
2964 status = NT_STATUS_OK;
2965 goto done;
2968 status = open_socket_out_defer_recv(r445, &fd445->fd);
2969 done:
2970 TALLOC_FREE(ev);
2971 return status;
2974 /****************************************************************************
2975 Open the client sockets.
2976 ****************************************************************************/
2978 NTSTATUS cli_connect(struct cli_state *cli,
2979 const char *host,
2980 struct sockaddr_storage *dest_ss)
2983 int name_type = 0x20;
2984 TALLOC_CTX *frame = talloc_stackframe();
2985 unsigned int num_addrs = 0;
2986 unsigned int i = 0;
2987 struct sockaddr_storage *ss_arr = NULL;
2988 char *p = NULL;
2990 /* reasonable default hostname */
2991 if (!host) {
2992 host = STAR_SMBSERVER;
2995 cli->desthost = talloc_strdup(cli, host);
2996 if (cli->desthost == NULL) {
2997 return NT_STATUS_NO_MEMORY;
3000 /* allow hostnames of the form NAME#xx and do a netbios lookup */
3001 if ((p = strchr(cli->desthost, '#'))) {
3002 name_type = strtol(p+1, NULL, 16);
3003 *p = 0;
3006 if (!dest_ss || is_zero_addr(dest_ss)) {
3007 NTSTATUS status =resolve_name_list(frame,
3008 cli->desthost,
3009 name_type,
3010 &ss_arr,
3011 &num_addrs);
3012 if (!NT_STATUS_IS_OK(status)) {
3013 TALLOC_FREE(frame);
3014 return NT_STATUS_BAD_NETWORK_NAME;
3016 } else {
3017 num_addrs = 1;
3018 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
3019 if (!ss_arr) {
3020 TALLOC_FREE(frame);
3021 return NT_STATUS_NO_MEMORY;
3023 *ss_arr = *dest_ss;
3026 for (i = 0; i < num_addrs; i++) {
3027 cli->dest_ss = ss_arr[i];
3028 if (getenv("LIBSMB_PROG")) {
3029 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
3030 } else {
3031 uint16_t port = cli->port;
3032 NTSTATUS status;
3033 status = open_smb_socket(&cli->dest_ss, &port,
3034 cli->timeout, &cli->fd);
3035 if (NT_STATUS_IS_OK(status)) {
3036 cli->port = port;
3039 if (cli->fd == -1) {
3040 char addr[INET6_ADDRSTRLEN];
3041 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
3042 DEBUG(2,("Error connecting to %s (%s)\n",
3043 dest_ss?addr:host,strerror(errno)));
3044 } else {
3045 /* Exit from loop on first connection. */
3046 break;
3050 if (cli->fd == -1) {
3051 TALLOC_FREE(frame);
3052 return map_nt_error_from_unix(errno);
3055 if (dest_ss) {
3056 *dest_ss = cli->dest_ss;
3059 set_socket_options(cli->fd, lp_socket_options());
3061 TALLOC_FREE(frame);
3062 return NT_STATUS_OK;
3066 establishes a connection to after the negprot.
3067 @param output_cli A fully initialised cli structure, non-null only on success
3068 @param dest_host The netbios name of the remote host
3069 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3070 @param port (optional) The destination port (0 for default)
3072 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3073 const char *my_name,
3074 const char *dest_host,
3075 struct sockaddr_storage *dest_ss, int port,
3076 int signing_state, int flags)
3078 NTSTATUS nt_status;
3079 struct nmb_name calling;
3080 struct nmb_name called;
3081 struct cli_state *cli;
3082 struct sockaddr_storage ss;
3084 if (!my_name)
3085 my_name = global_myname();
3087 if (!(cli = cli_initialise_ex(signing_state))) {
3088 return NT_STATUS_NO_MEMORY;
3091 make_nmb_name(&calling, my_name, 0x0);
3092 make_nmb_name(&called , dest_host, 0x20);
3094 cli_set_port(cli, port);
3095 cli_set_timeout(cli, 10000); /* 10 seconds. */
3097 if (dest_ss) {
3098 ss = *dest_ss;
3099 } else {
3100 zero_sockaddr(&ss);
3103 again:
3105 DEBUG(3,("Connecting to host=%s\n", dest_host));
3107 nt_status = cli_connect(cli, dest_host, &ss);
3108 if (!NT_STATUS_IS_OK(nt_status)) {
3109 char addr[INET6_ADDRSTRLEN];
3110 print_sockaddr(addr, sizeof(addr), &ss);
3111 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
3112 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
3113 cli_shutdown(cli);
3114 return nt_status;
3117 if (!cli_session_request(cli, &calling, &called)) {
3118 char *p;
3119 DEBUG(1,("session request to %s failed (%s)\n",
3120 called.name, cli_errstr(cli)));
3121 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
3122 *p = 0;
3123 goto again;
3125 if (strcmp(called.name, STAR_SMBSERVER)) {
3126 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
3127 goto again;
3129 return NT_STATUS_BAD_NETWORK_NAME;
3132 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
3133 cli->use_spnego = False;
3134 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
3135 cli->use_kerberos = True;
3137 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
3138 cli->use_kerberos) {
3139 cli->fallback_after_kerberos = true;
3141 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3142 cli->use_ccache = true;
3145 nt_status = cli_negprot(cli);
3146 if (!NT_STATUS_IS_OK(nt_status)) {
3147 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
3148 cli_shutdown(cli);
3149 return nt_status;
3152 *output_cli = cli;
3153 return NT_STATUS_OK;
3158 establishes a connection right up to doing tconX, password specified.
3159 @param output_cli A fully initialised cli structure, non-null only on success
3160 @param dest_host The netbios name of the remote host
3161 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3162 @param port (optional) The destination port (0 for default)
3163 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3164 @param service_type The 'type' of serivice.
3165 @param user Username, unix string
3166 @param domain User's domain
3167 @param password User's password, unencrypted unix string.
3170 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3171 const char *my_name,
3172 const char *dest_host,
3173 struct sockaddr_storage *dest_ss, int port,
3174 const char *service, const char *service_type,
3175 const char *user, const char *domain,
3176 const char *password, int flags,
3177 int signing_state)
3179 NTSTATUS nt_status;
3180 struct cli_state *cli = NULL;
3181 int pw_len = password ? strlen(password)+1 : 0;
3183 *output_cli = NULL;
3185 if (password == NULL) {
3186 password = "";
3189 nt_status = cli_start_connection(&cli, my_name, dest_host,
3190 dest_ss, port, signing_state,
3191 flags);
3193 if (!NT_STATUS_IS_OK(nt_status)) {
3194 return nt_status;
3197 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
3198 cli->use_level_II_oplocks =
3199 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
3201 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3202 pw_len, domain);
3203 if (!NT_STATUS_IS_OK(nt_status)) {
3205 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3206 DEBUG(1,("failed session setup with %s\n",
3207 nt_errstr(nt_status)));
3208 cli_shutdown(cli);
3209 return nt_status;
3212 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3213 if (!NT_STATUS_IS_OK(nt_status)) {
3214 DEBUG(1,("anonymous failed session setup with %s\n",
3215 nt_errstr(nt_status)));
3216 cli_shutdown(cli);
3217 return nt_status;
3221 if (service) {
3222 nt_status = cli_tcon_andx(cli, service, service_type, password,
3223 pw_len);
3224 if (!NT_STATUS_IS_OK(nt_status)) {
3225 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3226 cli_shutdown(cli);
3227 if (NT_STATUS_IS_OK(nt_status)) {
3228 nt_status = NT_STATUS_UNSUCCESSFUL;
3230 return nt_status;
3234 nt_status = cli_init_creds(cli, user, domain, password);
3235 if (!NT_STATUS_IS_OK(nt_status)) {
3236 cli_shutdown(cli);
3237 return nt_status;
3240 *output_cli = cli;
3241 return NT_STATUS_OK;
3244 /****************************************************************************
3245 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
3246 ****************************************************************************/
3248 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
3249 struct sockaddr_storage *pdest_ss)
3251 struct nmb_name calling, called;
3253 make_nmb_name(&calling, srchost, 0x0);
3256 * If the called name is an IP address
3257 * then use *SMBSERVER immediately.
3260 if(is_ipaddress(desthost)) {
3261 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
3262 } else {
3263 make_nmb_name(&called, desthost, 0x20);
3266 if (!cli_session_request(*ppcli, &calling, &called)) {
3267 NTSTATUS status;
3268 struct nmb_name smbservername;
3270 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
3273 * If the name wasn't *SMBSERVER then
3274 * try with *SMBSERVER if the first name fails.
3277 if (nmb_name_equal(&called, &smbservername)) {
3280 * The name used was *SMBSERVER, don't bother with another name.
3283 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
3284 with error %s.\n", desthost, cli_errstr(*ppcli) ));
3285 return False;
3288 /* Try again... */
3289 cli_shutdown(*ppcli);
3291 *ppcli = cli_initialise();
3292 if (!*ppcli) {
3293 /* Out of memory... */
3294 return False;
3297 status = cli_connect(*ppcli, desthost, pdest_ss);
3298 if (!NT_STATUS_IS_OK(status) ||
3299 !cli_session_request(*ppcli, &calling, &smbservername)) {
3300 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
3301 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
3302 return False;
3306 return True;
3309 /****************************************************************************
3310 Send an old style tcon.
3311 ****************************************************************************/
3312 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3313 const char *service, const char *pass, const char *dev,
3314 uint16 *max_xmit, uint16 *tid)
3316 struct tevent_req *req;
3317 uint16_t *ret_vwv;
3318 uint8_t *bytes;
3319 NTSTATUS status;
3321 if (!lp_client_plaintext_auth() && (*pass)) {
3322 DEBUG(1, ("Server requested plaintext password but 'client "
3323 "plaintext auth' is disabled\n"));
3324 return NT_STATUS_ACCESS_DENIED;
3327 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3328 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3329 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3330 service, strlen(service)+1, NULL);
3331 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3332 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3333 pass, strlen(pass)+1, NULL);
3334 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3335 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3336 dev, strlen(dev)+1, NULL);
3338 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3339 talloc_get_size(bytes), bytes, &req,
3340 2, NULL, &ret_vwv, NULL, NULL);
3341 if (!NT_STATUS_IS_OK(status)) {
3342 return status;
3345 *max_xmit = SVAL(ret_vwv + 0, 0);
3346 *tid = SVAL(ret_vwv + 1, 0);
3348 return NT_STATUS_OK;
3351 /* Return a cli_state pointing at the IPC$ share for the given server */
3353 struct cli_state *get_ipc_connect(char *server,
3354 struct sockaddr_storage *server_ss,
3355 const struct user_auth_info *user_info)
3357 struct cli_state *cli;
3358 NTSTATUS nt_status;
3359 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3361 if (user_info->use_kerberos) {
3362 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3365 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3366 user_info->username ? user_info->username : "",
3367 lp_workgroup(),
3368 user_info->password ? user_info->password : "",
3369 flags,
3370 Undefined);
3372 if (NT_STATUS_IS_OK(nt_status)) {
3373 return cli;
3374 } else if (is_ipaddress(server)) {
3375 /* windows 9* needs a correct NMB name for connections */
3376 fstring remote_name;
3378 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3379 cli = get_ipc_connect(remote_name, server_ss, user_info);
3380 if (cli)
3381 return cli;
3384 return NULL;
3388 * Given the IP address of a master browser on the network, return its
3389 * workgroup and connect to it.
3391 * This function is provided to allow additional processing beyond what
3392 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3393 * browsers and obtain each master browsers' list of domains (in case the
3394 * first master browser is recently on the network and has not yet
3395 * synchronized with other master browsers and therefore does not yet have the
3396 * entire network browse list)
3399 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3400 struct sockaddr_storage *mb_ip,
3401 const struct user_auth_info *user_info,
3402 char **pp_workgroup_out)
3404 char addr[INET6_ADDRSTRLEN];
3405 fstring name;
3406 struct cli_state *cli;
3407 struct sockaddr_storage server_ss;
3409 *pp_workgroup_out = NULL;
3411 print_sockaddr(addr, sizeof(addr), mb_ip);
3412 DEBUG(99, ("Looking up name of master browser %s\n",
3413 addr));
3416 * Do a name status query to find out the name of the master browser.
3417 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3418 * master browser will not respond to a wildcard query (or, at least,
3419 * an NT4 server acting as the domain master browser will not).
3421 * We might be able to use ONLY the query on MSBROWSE, but that's not
3422 * yet been tested with all Windows versions, so until it is, leave
3423 * the original wildcard query as the first choice and fall back to
3424 * MSBROWSE if the wildcard query fails.
3426 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3427 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3429 DEBUG(99, ("Could not retrieve name status for %s\n",
3430 addr));
3431 return NULL;
3434 if (!find_master_ip(name, &server_ss)) {
3435 DEBUG(99, ("Could not find master ip for %s\n", name));
3436 return NULL;
3439 *pp_workgroup_out = talloc_strdup(ctx, name);
3441 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3443 print_sockaddr(addr, sizeof(addr), &server_ss);
3444 cli = get_ipc_connect(addr, &server_ss, user_info);
3446 return cli;
3450 * Return the IP address and workgroup of a master browser on the network, and
3451 * connect to it.
3454 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3455 const struct user_auth_info *user_info,
3456 char **pp_workgroup_out)
3458 struct sockaddr_storage *ip_list;
3459 struct cli_state *cli;
3460 int i, count;
3461 NTSTATUS status;
3463 *pp_workgroup_out = NULL;
3465 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3467 /* Go looking for workgroups by broadcasting on the local network */
3469 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3470 &ip_list, &count);
3471 if (!NT_STATUS_IS_OK(status)) {
3472 DEBUG(99, ("No master browsers responded: %s\n",
3473 nt_errstr(status)));
3474 return False;
3477 for (i = 0; i < count; i++) {
3478 char addr[INET6_ADDRSTRLEN];
3479 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3480 DEBUG(99, ("Found master browser %s\n", addr));
3482 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3483 user_info, pp_workgroup_out);
3484 if (cli)
3485 return(cli);
3488 return NULL;