Remove another fstring in this code.
[Samba.git] / source3 / libsmb / cliconnect.c
blob5abaa4f4ff3e02b86b5764ff934de9bc24b8d17c
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 "popt_common.h"
25 #include "../libcli/auth/libcli_auth.h"
26 #include "../libcli/auth/spnego.h"
27 #include "smb_krb5.h"
28 #include "../libcli/auth/ntlmssp.h"
29 #include "libads/kerberos_proto.h"
30 #include "krb5_env.h"
31 #include "async_smb.h"
32 #include "libsmb/nmblib.h"
34 static const struct {
35 int prot;
36 const char name[24];
37 } prots[10] = {
38 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
39 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
40 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
41 {PROTOCOL_LANMAN1, "LANMAN1.0"},
42 {PROTOCOL_LANMAN2, "LM1.2X002"},
43 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
44 {PROTOCOL_LANMAN2, "LANMAN2.1"},
45 {PROTOCOL_LANMAN2, "Samba"},
46 {PROTOCOL_NT1, "NT LANMAN 1.0"},
47 {PROTOCOL_NT1, "NT LM 0.12"},
50 #define STAR_SMBSERVER "*SMBSERVER"
52 /********************************************************
53 Utility function to ensure we always return at least
54 a valid char * pointer to an empty string for the
55 cli->server_os, cli->server_type and cli->server_domain
56 strings.
57 *******************************************************/
59 static NTSTATUS smb_bytes_talloc_string(struct cli_state *cli,
60 char *inbuf,
61 char **dest,
62 uint8_t *src,
63 size_t srclen,
64 ssize_t *destlen)
66 *destlen = clistr_pull_talloc(cli,
67 inbuf,
68 SVAL(inbuf, smb_flg2),
69 dest,
70 (char *)src,
71 srclen,
72 STR_TERMINATE);
73 if (*destlen == -1) {
74 return NT_STATUS_NO_MEMORY;
77 if (*dest == NULL) {
78 *dest = talloc_strdup(cli, "");
79 if (*dest == NULL) {
80 return NT_STATUS_NO_MEMORY;
83 return NT_STATUS_OK;
86 /**
87 * Set the user session key for a connection
88 * @param cli The cli structure to add it too
89 * @param session_key The session key used. (A copy of this is taken for the cli struct)
93 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
95 cli->user_session_key = data_blob(session_key.data, session_key.length);
98 /****************************************************************************
99 Do an old lanman2 style session setup.
100 ****************************************************************************/
102 struct cli_session_setup_lanman2_state {
103 struct cli_state *cli;
104 uint16_t vwv[10];
105 const char *user;
108 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
110 static struct tevent_req *cli_session_setup_lanman2_send(
111 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
112 struct cli_state *cli, const char *user,
113 const char *pass, size_t passlen,
114 const char *workgroup)
116 struct tevent_req *req, *subreq;
117 struct cli_session_setup_lanman2_state *state;
118 DATA_BLOB lm_response = data_blob_null;
119 uint16_t *vwv;
120 uint8_t *bytes;
121 char *tmp;
123 req = tevent_req_create(mem_ctx, &state,
124 struct cli_session_setup_lanman2_state);
125 if (req == NULL) {
126 return NULL;
128 state->cli = cli;
129 state->user = user;
130 vwv = state->vwv;
133 * LANMAN servers predate NT status codes and Unicode and
134 * ignore those smb flags so we must disable the corresponding
135 * default capabilities that would otherwise cause the Unicode
136 * and NT Status flags to be set (and even returned by the
137 * server)
140 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
143 * if in share level security then don't send a password now
145 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
146 passlen = 0;
149 if (passlen > 0
150 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
151 && passlen != 24) {
153 * Encrypted mode needed, and non encrypted password
154 * supplied.
156 lm_response = data_blob(NULL, 24);
157 if (tevent_req_nomem(lm_response.data, req)) {
158 return tevent_req_post(req, ev);
161 if (!SMBencrypt(pass, cli->secblob.data,
162 (uint8_t *)lm_response.data)) {
163 DEBUG(1, ("Password is > 14 chars in length, and is "
164 "therefore incompatible with Lanman "
165 "authentication\n"));
166 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
167 return tevent_req_post(req, ev);
169 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
170 && passlen == 24) {
172 * Encrypted mode needed, and encrypted password
173 * supplied.
175 lm_response = data_blob(pass, passlen);
176 if (tevent_req_nomem(lm_response.data, req)) {
177 return tevent_req_post(req, ev);
179 } else if (passlen > 0) {
180 uint8_t *buf;
181 size_t converted_size;
183 * Plaintext mode needed, assume plaintext supplied.
185 buf = talloc_array(talloc_tos(), uint8_t, 0);
186 buf = smb_bytes_push_str(buf, cli_ucs2(cli), pass, passlen+1,
187 &converted_size);
188 if (tevent_req_nomem(buf, req)) {
189 return tevent_req_post(req, ev);
191 lm_response = data_blob(pass, passlen);
192 TALLOC_FREE(buf);
193 if (tevent_req_nomem(lm_response.data, req)) {
194 return tevent_req_post(req, ev);
198 SCVAL(vwv+0, 0, 0xff);
199 SCVAL(vwv+0, 1, 0);
200 SSVAL(vwv+1, 0, 0);
201 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
202 SSVAL(vwv+3, 0, 2);
203 SSVAL(vwv+4, 0, 1);
204 SIVAL(vwv+5, 0, cli->sesskey);
205 SSVAL(vwv+7, 0, lm_response.length);
207 bytes = talloc_array(state, uint8_t, lm_response.length);
208 if (tevent_req_nomem(bytes, req)) {
209 return tevent_req_post(req, ev);
211 if (lm_response.length != 0) {
212 memcpy(bytes, lm_response.data, lm_response.length);
214 data_blob_free(&lm_response);
216 tmp = talloc_strdup_upper(talloc_tos(), user);
217 if (tevent_req_nomem(tmp, req)) {
218 return tevent_req_post(req, ev);
220 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
221 NULL);
222 TALLOC_FREE(tmp);
224 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
225 if (tevent_req_nomem(tmp, req)) {
226 return tevent_req_post(req, ev);
228 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
229 NULL);
230 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
231 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
233 if (tevent_req_nomem(bytes, req)) {
234 return tevent_req_post(req, ev);
237 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
238 talloc_get_size(bytes), bytes);
239 if (tevent_req_nomem(subreq, req)) {
240 return tevent_req_post(req, ev);
242 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
243 return req;
246 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
248 struct tevent_req *req = tevent_req_callback_data(
249 subreq, struct tevent_req);
250 struct cli_session_setup_lanman2_state *state = tevent_req_data(
251 req, struct cli_session_setup_lanman2_state);
252 struct cli_state *cli = state->cli;
253 uint32_t num_bytes;
254 uint8_t *in;
255 char *inbuf;
256 uint8_t *bytes;
257 uint8_t *p;
258 NTSTATUS status;
259 ssize_t ret;
261 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
262 &num_bytes, &bytes);
263 TALLOC_FREE(subreq);
264 if (!NT_STATUS_IS_OK(status)) {
265 tevent_req_nterror(req, status);
266 return;
269 inbuf = (char *)in;
270 p = bytes;
272 cli->vuid = SVAL(inbuf, smb_uid);
274 status = smb_bytes_talloc_string(cli,
275 inbuf,
276 &cli->server_os,
278 bytes+num_bytes-p,
279 &ret);
281 if (!NT_STATUS_IS_OK(status)) {
282 tevent_req_nterror(req, status);
283 return;
285 p += ret;
287 status = smb_bytes_talloc_string(cli,
288 inbuf,
289 &cli->server_type,
291 bytes+num_bytes-p,
292 &ret);
294 if (!NT_STATUS_IS_OK(status)) {
295 tevent_req_nterror(req, status);
296 return;
298 p += ret;
300 status = smb_bytes_talloc_string(cli,
301 inbuf,
302 &cli->server_domain,
304 bytes+num_bytes-p,
305 &ret);
307 if (!NT_STATUS_IS_OK(status)) {
308 tevent_req_nterror(req, status);
309 return;
311 p += ret;
313 if (strstr(cli->server_type, "Samba")) {
314 cli->is_samba = True;
316 status = cli_set_username(cli, state->user);
317 if (tevent_req_nterror(req, status)) {
318 return;
320 tevent_req_done(req);
323 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
325 return tevent_req_simple_recv_ntstatus(req);
328 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
329 const char *pass, size_t passlen,
330 const char *workgroup)
332 TALLOC_CTX *frame = talloc_stackframe();
333 struct event_context *ev;
334 struct tevent_req *req;
335 NTSTATUS status = NT_STATUS_NO_MEMORY;
337 if (cli_has_async_calls(cli)) {
339 * Can't use sync call while an async call is in flight
341 status = NT_STATUS_INVALID_PARAMETER;
342 goto fail;
344 ev = event_context_init(frame);
345 if (ev == NULL) {
346 goto fail;
348 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
349 workgroup);
350 if (req == NULL) {
351 goto fail;
353 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
354 goto fail;
356 status = cli_session_setup_lanman2_recv(req);
357 fail:
358 TALLOC_FREE(frame);
359 if (!NT_STATUS_IS_OK(status)) {
360 cli_set_error(cli, status);
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 if (!NT_STATUS_IS_OK(status)) {
594 cli_set_error(cli, status);
596 return status;
599 /****************************************************************************
600 Do a NT1 plaintext session setup.
601 ****************************************************************************/
603 struct cli_session_setup_plain_state {
604 struct cli_state *cli;
605 uint16_t vwv[13];
606 const char *user;
609 static void cli_session_setup_plain_done(struct tevent_req *subreq);
611 static struct tevent_req *cli_session_setup_plain_send(
612 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
613 struct cli_state *cli,
614 const char *user, const char *pass, const char *workgroup)
616 struct tevent_req *req, *subreq;
617 struct cli_session_setup_plain_state *state;
618 uint16_t *vwv;
619 uint8_t *bytes;
620 size_t passlen;
621 char *version;
623 req = tevent_req_create(mem_ctx, &state,
624 struct cli_session_setup_plain_state);
625 if (req == NULL) {
626 return NULL;
628 state->cli = cli;
629 state->user = user;
630 vwv = state->vwv;
632 SCVAL(vwv+0, 0, 0xff);
633 SCVAL(vwv+0, 1, 0);
634 SSVAL(vwv+1, 0, 0);
635 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
636 SSVAL(vwv+3, 0, 2);
637 SSVAL(vwv+4, 0, cli->pid);
638 SIVAL(vwv+5, 0, cli->sesskey);
639 SSVAL(vwv+7, 0, 0);
640 SSVAL(vwv+8, 0, 0);
641 SSVAL(vwv+9, 0, 0);
642 SSVAL(vwv+10, 0, 0);
643 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
645 bytes = talloc_array(state, uint8_t, 0);
646 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
647 &passlen);
648 if (tevent_req_nomem(bytes, req)) {
649 return tevent_req_post(req, ev);
651 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
653 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
654 user, strlen(user)+1, NULL);
655 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
656 workgroup, strlen(workgroup)+1, NULL);
657 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
658 "Unix", 5, NULL);
660 version = talloc_asprintf(talloc_tos(), "Samba %s",
661 samba_version_string());
662 if (tevent_req_nomem(version, req)){
663 return tevent_req_post(req, ev);
665 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
666 version, strlen(version)+1, NULL);
667 TALLOC_FREE(version);
669 if (tevent_req_nomem(bytes, req)) {
670 return tevent_req_post(req, ev);
673 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
674 talloc_get_size(bytes), bytes);
675 if (tevent_req_nomem(subreq, req)) {
676 return tevent_req_post(req, ev);
678 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
679 return req;
682 static void cli_session_setup_plain_done(struct tevent_req *subreq)
684 struct tevent_req *req = tevent_req_callback_data(
685 subreq, struct tevent_req);
686 struct cli_session_setup_plain_state *state = tevent_req_data(
687 req, struct cli_session_setup_plain_state);
688 struct cli_state *cli = state->cli;
689 uint32_t num_bytes;
690 uint8_t *in;
691 char *inbuf;
692 uint8_t *bytes;
693 uint8_t *p;
694 NTSTATUS status;
695 ssize_t ret;
697 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
698 &num_bytes, &bytes);
699 TALLOC_FREE(subreq);
700 if (tevent_req_nterror(req, status)) {
701 return;
704 inbuf = (char *)in;
705 p = bytes;
707 cli->vuid = SVAL(inbuf, smb_uid);
709 status = smb_bytes_talloc_string(cli,
710 inbuf,
711 &cli->server_os,
713 bytes+num_bytes-p,
714 &ret);
716 if (!NT_STATUS_IS_OK(status)) {
717 tevent_req_nterror(req, status);
718 return;
720 p += ret;
722 status = smb_bytes_talloc_string(cli,
723 inbuf,
724 &cli->server_type,
726 bytes+num_bytes-p,
727 &ret);
729 if (!NT_STATUS_IS_OK(status)) {
730 tevent_req_nterror(req, status);
731 return;
733 p += ret;
735 status = smb_bytes_talloc_string(cli,
736 inbuf,
737 &cli->server_domain,
739 bytes+num_bytes-p,
740 &ret);
742 if (!NT_STATUS_IS_OK(status)) {
743 tevent_req_nterror(req, status);
744 return;
746 p += ret;
748 status = cli_set_username(cli, state->user);
749 if (tevent_req_nterror(req, status)) {
750 return;
752 if (strstr(cli->server_type, "Samba")) {
753 cli->is_samba = True;
755 tevent_req_done(req);
758 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
760 return tevent_req_simple_recv_ntstatus(req);
763 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
764 const char *user, const char *pass,
765 const char *workgroup)
767 TALLOC_CTX *frame = talloc_stackframe();
768 struct event_context *ev;
769 struct tevent_req *req;
770 NTSTATUS status = NT_STATUS_NO_MEMORY;
772 if (cli_has_async_calls(cli)) {
774 * Can't use sync call while an async call is in flight
776 status = NT_STATUS_INVALID_PARAMETER;
777 goto fail;
779 ev = event_context_init(frame);
780 if (ev == NULL) {
781 goto fail;
783 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
784 workgroup);
785 if (req == NULL) {
786 goto fail;
788 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
789 goto fail;
791 status = cli_session_setup_plain_recv(req);
792 fail:
793 TALLOC_FREE(frame);
794 if (!NT_STATUS_IS_OK(status)) {
795 cli_set_error(cli, status);
797 return status;
800 /****************************************************************************
801 do a NT1 NTLM/LM encrypted session setup - for when extended security
802 is not negotiated.
803 @param cli client state to create do session setup on
804 @param user username
805 @param pass *either* cleartext password (passlen !=24) or LM response.
806 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
807 @param workgroup The user's domain.
808 ****************************************************************************/
810 struct cli_session_setup_nt1_state {
811 struct cli_state *cli;
812 uint16_t vwv[13];
813 DATA_BLOB response;
814 DATA_BLOB session_key;
815 const char *user;
818 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
820 static struct tevent_req *cli_session_setup_nt1_send(
821 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
822 struct cli_state *cli, const char *user,
823 const char *pass, size_t passlen,
824 const char *ntpass, size_t ntpasslen,
825 const char *workgroup)
827 struct tevent_req *req, *subreq;
828 struct cli_session_setup_nt1_state *state;
829 DATA_BLOB lm_response = data_blob_null;
830 DATA_BLOB nt_response = data_blob_null;
831 DATA_BLOB session_key = data_blob_null;
832 uint16_t *vwv;
833 uint8_t *bytes;
834 char *workgroup_upper;
836 req = tevent_req_create(mem_ctx, &state,
837 struct cli_session_setup_nt1_state);
838 if (req == NULL) {
839 return NULL;
841 state->cli = cli;
842 state->user = user;
843 vwv = state->vwv;
845 if (passlen == 0) {
846 /* do nothing - guest login */
847 } else if (passlen != 24) {
848 if (lp_client_ntlmv2_auth()) {
849 DATA_BLOB server_chal;
850 DATA_BLOB names_blob;
852 server_chal = data_blob(cli->secblob.data,
853 MIN(cli->secblob.length, 8));
854 if (tevent_req_nomem(server_chal.data, req)) {
855 return tevent_req_post(req, ev);
859 * note that the 'workgroup' here is a best
860 * guess - we don't know the server's domain
861 * at this point. The 'server name' is also
862 * dodgy...
864 names_blob = NTLMv2_generate_names_blob(
865 NULL, cli->called.name, workgroup);
867 if (tevent_req_nomem(names_blob.data, req)) {
868 return tevent_req_post(req, ev);
871 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
872 &server_chal, &names_blob,
873 &lm_response, &nt_response,
874 NULL, &session_key)) {
875 data_blob_free(&names_blob);
876 data_blob_free(&server_chal);
877 tevent_req_nterror(
878 req, NT_STATUS_ACCESS_DENIED);
879 return tevent_req_post(req, ev);
881 data_blob_free(&names_blob);
882 data_blob_free(&server_chal);
884 } else {
885 uchar nt_hash[16];
886 E_md4hash(pass, nt_hash);
888 #ifdef LANMAN_ONLY
889 nt_response = data_blob_null;
890 #else
891 nt_response = data_blob(NULL, 24);
892 if (tevent_req_nomem(nt_response.data, req)) {
893 return tevent_req_post(req, ev);
896 SMBNTencrypt(pass, cli->secblob.data,
897 nt_response.data);
898 #endif
899 /* non encrypted password supplied. Ignore ntpass. */
900 if (lp_client_lanman_auth()) {
902 lm_response = data_blob(NULL, 24);
903 if (tevent_req_nomem(lm_response.data, req)) {
904 return tevent_req_post(req, ev);
907 if (!SMBencrypt(pass,cli->secblob.data,
908 lm_response.data)) {
910 * Oops, the LM response is
911 * invalid, just put the NT
912 * response there instead
914 data_blob_free(&lm_response);
915 lm_response = data_blob(
916 nt_response.data,
917 nt_response.length);
919 } else {
921 * LM disabled, place NT# in LM field
922 * instead
924 lm_response = data_blob(
925 nt_response.data, nt_response.length);
928 if (tevent_req_nomem(lm_response.data, req)) {
929 return tevent_req_post(req, ev);
932 session_key = data_blob(NULL, 16);
933 if (tevent_req_nomem(session_key.data, req)) {
934 return tevent_req_post(req, ev);
936 #ifdef LANMAN_ONLY
937 E_deshash(pass, session_key.data);
938 memset(&session_key.data[8], '\0', 8);
939 #else
940 SMBsesskeygen_ntv1(nt_hash, session_key.data);
941 #endif
943 cli_temp_set_signing(cli);
944 } else {
945 /* pre-encrypted password supplied. Only used for
946 security=server, can't do
947 signing because we don't have original key */
949 lm_response = data_blob(pass, passlen);
950 if (tevent_req_nomem(lm_response.data, req)) {
951 return tevent_req_post(req, ev);
954 nt_response = data_blob(ntpass, ntpasslen);
955 if (tevent_req_nomem(nt_response.data, req)) {
956 return tevent_req_post(req, ev);
960 #ifdef LANMAN_ONLY
961 state->response = data_blob_talloc(
962 state, lm_response.data, lm_response.length);
963 #else
964 state->response = data_blob_talloc(
965 state, nt_response.data, nt_response.length);
966 #endif
967 if (tevent_req_nomem(state->response.data, req)) {
968 return tevent_req_post(req, ev);
971 if (session_key.data) {
972 state->session_key = data_blob_talloc(
973 state, session_key.data, session_key.length);
974 if (tevent_req_nomem(state->session_key.data, req)) {
975 return tevent_req_post(req, ev);
978 data_blob_free(&session_key);
980 SCVAL(vwv+0, 0, 0xff);
981 SCVAL(vwv+0, 1, 0);
982 SSVAL(vwv+1, 0, 0);
983 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
984 SSVAL(vwv+3, 0, 2);
985 SSVAL(vwv+4, 0, cli->pid);
986 SIVAL(vwv+5, 0, cli->sesskey);
987 SSVAL(vwv+7, 0, lm_response.length);
988 SSVAL(vwv+8, 0, nt_response.length);
989 SSVAL(vwv+9, 0, 0);
990 SSVAL(vwv+10, 0, 0);
991 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
993 bytes = talloc_array(state, uint8_t,
994 lm_response.length + nt_response.length);
995 if (tevent_req_nomem(bytes, req)) {
996 return tevent_req_post(req, ev);
998 if (lm_response.length != 0) {
999 memcpy(bytes, lm_response.data, lm_response.length);
1001 if (nt_response.length != 0) {
1002 memcpy(bytes + lm_response.length,
1003 nt_response.data, nt_response.length);
1005 data_blob_free(&lm_response);
1006 data_blob_free(&nt_response);
1008 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1009 user, strlen(user)+1, NULL);
1012 * Upper case here might help some NTLMv2 implementations
1014 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
1015 if (tevent_req_nomem(workgroup_upper, req)) {
1016 return tevent_req_post(req, ev);
1018 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1019 workgroup_upper, strlen(workgroup_upper)+1,
1020 NULL);
1021 TALLOC_FREE(workgroup_upper);
1023 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
1024 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
1025 if (tevent_req_nomem(bytes, req)) {
1026 return tevent_req_post(req, ev);
1029 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1030 talloc_get_size(bytes), bytes);
1031 if (tevent_req_nomem(subreq, req)) {
1032 return tevent_req_post(req, ev);
1034 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1035 return req;
1038 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1040 struct tevent_req *req = tevent_req_callback_data(
1041 subreq, struct tevent_req);
1042 struct cli_session_setup_nt1_state *state = tevent_req_data(
1043 req, struct cli_session_setup_nt1_state);
1044 struct cli_state *cli = state->cli;
1045 uint32_t num_bytes;
1046 uint8_t *in;
1047 char *inbuf;
1048 uint8_t *bytes;
1049 uint8_t *p;
1050 NTSTATUS status;
1051 ssize_t ret;
1053 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
1054 &num_bytes, &bytes);
1055 TALLOC_FREE(subreq);
1056 if (!NT_STATUS_IS_OK(status)) {
1057 tevent_req_nterror(req, status);
1058 return;
1061 inbuf = (char *)in;
1062 p = bytes;
1064 cli->vuid = SVAL(inbuf, smb_uid);
1066 status = smb_bytes_talloc_string(cli,
1067 inbuf,
1068 &cli->server_os,
1070 bytes+num_bytes-p,
1071 &ret);
1072 if (!NT_STATUS_IS_OK(status)) {
1073 tevent_req_nterror(req, status);
1074 return;
1076 p += ret;
1078 status = smb_bytes_talloc_string(cli,
1079 inbuf,
1080 &cli->server_type,
1082 bytes+num_bytes-p,
1083 &ret);
1084 if (!NT_STATUS_IS_OK(status)) {
1085 tevent_req_nterror(req, status);
1086 return;
1088 p += ret;
1090 status = smb_bytes_talloc_string(cli,
1091 inbuf,
1092 &cli->server_domain,
1094 bytes+num_bytes-p,
1095 &ret);
1096 if (!NT_STATUS_IS_OK(status)) {
1097 tevent_req_nterror(req, status);
1098 return;
1100 p += ret;
1102 if (strstr(cli->server_type, "Samba")) {
1103 cli->is_samba = True;
1106 status = cli_set_username(cli, state->user);
1107 if (tevent_req_nterror(req, status)) {
1108 return;
1110 if (cli_simple_set_signing(cli, state->session_key, state->response)
1111 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1112 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1113 return;
1115 if (state->session_key.data) {
1116 /* Have plaintext orginal */
1117 cli_set_session_key(cli, state->session_key);
1119 tevent_req_done(req);
1122 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1124 return tevent_req_simple_recv_ntstatus(req);
1127 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1128 const char *pass, size_t passlen,
1129 const char *ntpass, size_t ntpasslen,
1130 const char *workgroup)
1132 TALLOC_CTX *frame = talloc_stackframe();
1133 struct event_context *ev;
1134 struct tevent_req *req;
1135 NTSTATUS status = NT_STATUS_NO_MEMORY;
1137 if (cli_has_async_calls(cli)) {
1139 * Can't use sync call while an async call is in flight
1141 status = NT_STATUS_INVALID_PARAMETER;
1142 goto fail;
1144 ev = event_context_init(frame);
1145 if (ev == NULL) {
1146 goto fail;
1148 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1149 ntpass, ntpasslen, workgroup);
1150 if (req == NULL) {
1151 goto fail;
1153 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1154 goto fail;
1156 status = cli_session_setup_nt1_recv(req);
1157 fail:
1158 TALLOC_FREE(frame);
1159 if (!NT_STATUS_IS_OK(status)) {
1160 cli_set_error(cli, status);
1162 return status;
1165 /* The following is calculated from :
1166 * (smb_size-4) = 35
1167 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1168 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1169 * end of packet.
1172 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1174 struct cli_sesssetup_blob_state {
1175 struct tevent_context *ev;
1176 struct cli_state *cli;
1177 DATA_BLOB blob;
1178 uint16_t max_blob_size;
1179 uint16_t vwv[12];
1180 uint8_t *buf;
1182 NTSTATUS status;
1183 char *inbuf;
1184 DATA_BLOB ret_blob;
1187 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1188 struct tevent_req **psubreq);
1189 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1191 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1192 struct tevent_context *ev,
1193 struct cli_state *cli,
1194 DATA_BLOB blob)
1196 struct tevent_req *req, *subreq;
1197 struct cli_sesssetup_blob_state *state;
1199 req = tevent_req_create(mem_ctx, &state,
1200 struct cli_sesssetup_blob_state);
1201 if (req == NULL) {
1202 return NULL;
1204 state->ev = ev;
1205 state->blob = blob;
1206 state->cli = cli;
1208 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
1209 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1210 "(was %u, need minimum %u)\n",
1211 (unsigned int)cli->max_xmit,
1212 BASE_SESSSETUP_BLOB_PACKET_SIZE));
1213 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1214 return tevent_req_post(req, ev);
1216 state->max_blob_size =
1217 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
1219 if (!cli_sesssetup_blob_next(state, &subreq)) {
1220 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1221 return tevent_req_post(req, ev);
1223 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1224 return req;
1227 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1228 struct tevent_req **psubreq)
1230 struct tevent_req *subreq;
1231 uint16_t thistime;
1233 SCVAL(state->vwv+0, 0, 0xFF);
1234 SCVAL(state->vwv+0, 1, 0);
1235 SSVAL(state->vwv+1, 0, 0);
1236 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1237 SSVAL(state->vwv+3, 0, 2);
1238 SSVAL(state->vwv+4, 0, 1);
1239 SIVAL(state->vwv+5, 0, 0);
1241 thistime = MIN(state->blob.length, state->max_blob_size);
1242 SSVAL(state->vwv+7, 0, thistime);
1244 SSVAL(state->vwv+8, 0, 0);
1245 SSVAL(state->vwv+9, 0, 0);
1246 SIVAL(state->vwv+10, 0,
1247 cli_session_setup_capabilities(state->cli)
1248 | CAP_EXTENDED_SECURITY);
1250 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1251 thistime);
1252 if (state->buf == NULL) {
1253 return false;
1255 state->blob.data += thistime;
1256 state->blob.length -= thistime;
1258 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1259 "Unix", 5, NULL);
1260 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1261 "Samba", 6, NULL);
1262 if (state->buf == NULL) {
1263 return false;
1265 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1266 12, state->vwv,
1267 talloc_get_size(state->buf), state->buf);
1268 if (subreq == NULL) {
1269 return false;
1271 *psubreq = subreq;
1272 return true;
1275 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1277 struct tevent_req *req = tevent_req_callback_data(
1278 subreq, struct tevent_req);
1279 struct cli_sesssetup_blob_state *state = tevent_req_data(
1280 req, struct cli_sesssetup_blob_state);
1281 struct cli_state *cli = state->cli;
1282 uint8_t wct;
1283 uint16_t *vwv;
1284 uint32_t num_bytes;
1285 uint8_t *bytes;
1286 NTSTATUS status;
1287 uint8_t *p;
1288 uint16_t blob_length;
1289 uint8_t *inbuf;
1290 ssize_t ret;
1292 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
1293 &num_bytes, &bytes);
1294 TALLOC_FREE(subreq);
1295 if (!NT_STATUS_IS_OK(status)
1296 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1297 tevent_req_nterror(req, status);
1298 return;
1301 state->status = status;
1302 TALLOC_FREE(state->buf);
1304 state->inbuf = (char *)inbuf;
1305 cli->vuid = SVAL(state->inbuf, smb_uid);
1307 blob_length = SVAL(vwv+3, 0);
1308 if (blob_length > num_bytes) {
1309 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1310 return;
1312 state->ret_blob = data_blob_const(bytes, blob_length);
1314 p = bytes + blob_length;
1316 status = smb_bytes_talloc_string(cli,
1317 (char *)inbuf,
1318 &cli->server_os,
1320 bytes+num_bytes-p,
1321 &ret);
1323 if (!NT_STATUS_IS_OK(status)) {
1324 tevent_req_nterror(req, status);
1325 return;
1327 p += ret;
1329 status = smb_bytes_talloc_string(cli,
1330 (char *)inbuf,
1331 &cli->server_type,
1333 bytes+num_bytes-p,
1334 &ret);
1336 if (!NT_STATUS_IS_OK(status)) {
1337 tevent_req_nterror(req, status);
1338 return;
1340 p += ret;
1342 status = smb_bytes_talloc_string(cli,
1343 (char *)inbuf,
1344 &cli->server_domain,
1346 bytes+num_bytes-p,
1347 &ret);
1349 if (!NT_STATUS_IS_OK(status)) {
1350 tevent_req_nterror(req, status);
1351 return;
1353 p += ret;
1355 if (strstr(cli->server_type, "Samba")) {
1356 cli->is_samba = True;
1359 if (state->blob.length != 0) {
1361 * More to send
1363 if (!cli_sesssetup_blob_next(state, &subreq)) {
1364 tevent_req_nomem(NULL, req);
1365 return;
1367 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1368 return;
1370 tevent_req_done(req);
1373 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1374 TALLOC_CTX *mem_ctx,
1375 DATA_BLOB *pblob,
1376 char **pinbuf)
1378 struct cli_sesssetup_blob_state *state = tevent_req_data(
1379 req, struct cli_sesssetup_blob_state);
1380 NTSTATUS status;
1381 char *inbuf;
1383 if (tevent_req_is_nterror(req, &status)) {
1384 state->cli->vuid = 0;
1385 return status;
1388 inbuf = talloc_move(mem_ctx, &state->inbuf);
1389 if (pblob != NULL) {
1390 *pblob = state->ret_blob;
1392 if (pinbuf != NULL) {
1393 *pinbuf = inbuf;
1395 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1396 return state->status;
1399 #ifdef HAVE_KRB5
1401 /****************************************************************************
1402 Use in-memory credentials cache
1403 ****************************************************************************/
1405 static void use_in_memory_ccache(void) {
1406 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1409 /****************************************************************************
1410 Do a spnego/kerberos encrypted session setup.
1411 ****************************************************************************/
1413 struct cli_session_setup_kerberos_state {
1414 struct cli_state *cli;
1415 DATA_BLOB negTokenTarg;
1416 DATA_BLOB session_key_krb5;
1417 ADS_STATUS ads_status;
1420 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1422 static struct tevent_req *cli_session_setup_kerberos_send(
1423 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1424 const char *principal, const char *workgroup)
1426 struct tevent_req *req, *subreq;
1427 struct cli_session_setup_kerberos_state *state;
1428 int rc;
1430 DEBUG(2,("Doing kerberos session setup\n"));
1432 req = tevent_req_create(mem_ctx, &state,
1433 struct cli_session_setup_kerberos_state);
1434 if (req == NULL) {
1435 return NULL;
1437 state->cli = cli;
1438 state->ads_status = ADS_SUCCESS;
1440 cli_temp_set_signing(cli);
1443 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1444 * we have to acquire a ticket. To be fixed later :-)
1446 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1447 &state->session_key_krb5, 0, NULL);
1448 if (rc) {
1449 DEBUG(1, ("cli_session_setup_kerberos: "
1450 "spnego_gen_krb5_negTokenInit failed: %s\n",
1451 error_message(rc)));
1452 state->ads_status = ADS_ERROR_KRB5(rc);
1453 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1454 return tevent_req_post(req, ev);
1457 #if 0
1458 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1459 state->negTokenTarg.length);
1460 #endif
1462 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1463 if (tevent_req_nomem(subreq, req)) {
1464 return tevent_req_post(req, ev);
1466 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1467 return req;
1470 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1472 struct tevent_req *req = tevent_req_callback_data(
1473 subreq, struct tevent_req);
1474 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1475 req, struct cli_session_setup_kerberos_state);
1476 char *inbuf = NULL;
1477 NTSTATUS status;
1479 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
1480 if (!NT_STATUS_IS_OK(status)) {
1481 TALLOC_FREE(subreq);
1482 tevent_req_nterror(req, status);
1483 return;
1486 cli_set_session_key(state->cli, state->session_key_krb5);
1488 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
1489 data_blob_null)
1490 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1491 TALLOC_FREE(subreq);
1492 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1493 return;
1495 TALLOC_FREE(subreq);
1496 tevent_req_done(req);
1499 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1501 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1502 req, struct cli_session_setup_kerberos_state);
1503 NTSTATUS status;
1505 if (tevent_req_is_nterror(req, &status)) {
1506 return ADS_ERROR_NT(status);
1508 return state->ads_status;
1511 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1512 const char *principal,
1513 const char *workgroup)
1515 struct tevent_context *ev;
1516 struct tevent_req *req;
1517 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1519 if (cli_has_async_calls(cli)) {
1520 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1522 ev = tevent_context_init(talloc_tos());
1523 if (ev == NULL) {
1524 goto fail;
1526 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
1527 workgroup);
1528 if (req == NULL) {
1529 goto fail;
1531 if (!tevent_req_poll(req, ev)) {
1532 status = ADS_ERROR_SYSTEM(errno);
1533 goto fail;
1535 status = cli_session_setup_kerberos_recv(req);
1536 fail:
1537 TALLOC_FREE(ev);
1538 return status;
1540 #endif /* HAVE_KRB5 */
1542 /****************************************************************************
1543 Do a spnego/NTLMSSP encrypted session setup.
1544 ****************************************************************************/
1546 struct cli_session_setup_ntlmssp_state {
1547 struct tevent_context *ev;
1548 struct cli_state *cli;
1549 struct ntlmssp_state *ntlmssp_state;
1550 int turn;
1551 DATA_BLOB blob_out;
1554 static int cli_session_setup_ntlmssp_state_destructor(
1555 struct cli_session_setup_ntlmssp_state *state)
1557 if (state->ntlmssp_state != NULL) {
1558 TALLOC_FREE(state->ntlmssp_state);
1560 return 0;
1563 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1565 static struct tevent_req *cli_session_setup_ntlmssp_send(
1566 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1567 const char *user, const char *pass, const char *domain)
1569 struct tevent_req *req, *subreq;
1570 struct cli_session_setup_ntlmssp_state *state;
1571 NTSTATUS status;
1572 DATA_BLOB blob_out;
1573 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1575 req = tevent_req_create(mem_ctx, &state,
1576 struct cli_session_setup_ntlmssp_state);
1577 if (req == NULL) {
1578 return NULL;
1580 state->ev = ev;
1581 state->cli = cli;
1582 state->turn = 1;
1584 state->ntlmssp_state = NULL;
1585 talloc_set_destructor(
1586 state, cli_session_setup_ntlmssp_state_destructor);
1588 cli_temp_set_signing(cli);
1590 status = ntlmssp_client_start(state,
1591 global_myname(),
1592 lp_workgroup(),
1593 lp_client_ntlmv2_auth(),
1594 &state->ntlmssp_state);
1595 if (!NT_STATUS_IS_OK(status)) {
1596 goto fail;
1598 ntlmssp_want_feature(state->ntlmssp_state,
1599 NTLMSSP_FEATURE_SESSION_KEY);
1600 if (cli->use_ccache) {
1601 ntlmssp_want_feature(state->ntlmssp_state,
1602 NTLMSSP_FEATURE_CCACHE);
1604 status = ntlmssp_set_username(state->ntlmssp_state, user);
1605 if (!NT_STATUS_IS_OK(status)) {
1606 goto fail;
1608 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1609 if (!NT_STATUS_IS_OK(status)) {
1610 goto fail;
1612 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1613 if (!NT_STATUS_IS_OK(status)) {
1614 goto fail;
1616 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1617 &blob_out);
1618 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1619 goto fail;
1622 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1623 data_blob_free(&blob_out);
1625 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1626 if (tevent_req_nomem(subreq, req)) {
1627 return tevent_req_post(req, ev);
1629 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1630 return req;
1631 fail:
1632 tevent_req_nterror(req, status);
1633 return tevent_req_post(req, ev);
1636 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1638 struct tevent_req *req = tevent_req_callback_data(
1639 subreq, struct tevent_req);
1640 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1641 req, struct cli_session_setup_ntlmssp_state);
1642 DATA_BLOB blob_in, msg_in, blob_out;
1643 char *inbuf = NULL;
1644 bool parse_ret;
1645 NTSTATUS status;
1647 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1648 &inbuf);
1649 TALLOC_FREE(subreq);
1650 data_blob_free(&state->blob_out);
1652 if (NT_STATUS_IS_OK(status)) {
1653 if (state->cli->server_domain[0] == '\0') {
1654 TALLOC_FREE(state->cli->server_domain);
1655 state->cli->server_domain = talloc_strdup(state->cli,
1656 state->ntlmssp_state->server.netbios_domain);
1657 if (state->cli->server_domain == NULL) {
1658 TALLOC_FREE(subreq);
1659 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1660 return;
1663 cli_set_session_key(
1664 state->cli, state->ntlmssp_state->session_key);
1666 if (cli_simple_set_signing(
1667 state->cli, state->ntlmssp_state->session_key,
1668 data_blob_null)
1669 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1670 TALLOC_FREE(subreq);
1671 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1672 return;
1674 TALLOC_FREE(subreq);
1675 TALLOC_FREE(state->ntlmssp_state);
1676 tevent_req_done(req);
1677 return;
1679 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1680 tevent_req_nterror(req, status);
1681 return;
1684 if (blob_in.length == 0) {
1685 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1686 return;
1689 if ((state->turn == 1)
1690 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1691 DATA_BLOB tmp_blob = data_blob_null;
1692 /* the server might give us back two challenges */
1693 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1694 &tmp_blob);
1695 data_blob_free(&tmp_blob);
1696 } else {
1697 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1698 OID_NTLMSSP, &msg_in);
1700 state->turn += 1;
1702 if (!parse_ret) {
1703 DEBUG(3,("Failed to parse auth response\n"));
1704 if (NT_STATUS_IS_OK(status)
1705 || NT_STATUS_EQUAL(status,
1706 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1707 tevent_req_nterror(
1708 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1709 return;
1713 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1715 if (!NT_STATUS_IS_OK(status)
1716 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1717 TALLOC_FREE(subreq);
1718 TALLOC_FREE(state->ntlmssp_state);
1719 tevent_req_nterror(req, status);
1720 return;
1723 state->blob_out = spnego_gen_auth(state, blob_out);
1724 TALLOC_FREE(subreq);
1725 if (tevent_req_nomem(state->blob_out.data, req)) {
1726 return;
1729 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1730 state->blob_out);
1731 if (tevent_req_nomem(subreq, req)) {
1732 return;
1734 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1737 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1739 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1740 req, struct cli_session_setup_ntlmssp_state);
1741 NTSTATUS status;
1743 if (tevent_req_is_nterror(req, &status)) {
1744 state->cli->vuid = 0;
1745 return status;
1747 return NT_STATUS_OK;
1750 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1751 const char *user,
1752 const char *pass,
1753 const char *domain)
1755 struct tevent_context *ev;
1756 struct tevent_req *req;
1757 NTSTATUS status = NT_STATUS_NO_MEMORY;
1759 if (cli_has_async_calls(cli)) {
1760 return NT_STATUS_INVALID_PARAMETER;
1762 ev = tevent_context_init(talloc_tos());
1763 if (ev == NULL) {
1764 goto fail;
1766 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1767 if (req == NULL) {
1768 goto fail;
1770 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1771 goto fail;
1773 status = cli_session_setup_ntlmssp_recv(req);
1774 fail:
1775 TALLOC_FREE(ev);
1776 if (!NT_STATUS_IS_OK(status)) {
1777 cli_set_error(cli, status);
1779 return status;
1782 /****************************************************************************
1783 Do a spnego encrypted session setup.
1785 user_domain: The shortname of the domain the user/machine is a member of.
1786 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1787 ****************************************************************************/
1789 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1790 const char *pass, const char *user_domain,
1791 const char * dest_realm)
1793 char *principal = NULL;
1794 char *OIDs[ASN1_MAX_OIDS];
1795 int i;
1796 DATA_BLOB blob;
1797 const char *p = NULL;
1798 char *account = NULL;
1799 NTSTATUS status;
1801 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1803 /* the server might not even do spnego */
1804 if (cli->secblob.length <= 16) {
1805 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1806 goto ntlmssp;
1809 #if 0
1810 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1811 #endif
1813 /* there is 16 bytes of GUID before the real spnego packet starts */
1814 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1816 /* The server sent us the first part of the SPNEGO exchange in the
1817 * negprot reply. It is WRONG to depend on the principal sent in the
1818 * negprot reply, but right now we do it. If we don't receive one,
1819 * we try to best guess, then fall back to NTLM. */
1820 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1821 OIDs[0] == NULL) {
1822 data_blob_free(&blob);
1823 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1825 data_blob_free(&blob);
1827 /* make sure the server understands kerberos */
1828 for (i=0;OIDs[i];i++) {
1829 if (i == 0)
1830 DEBUG(3,("got OID=%s\n", OIDs[i]));
1831 else
1832 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1833 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1834 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1835 cli->got_kerberos_mechanism = True;
1837 talloc_free(OIDs[i]);
1840 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1842 status = cli_set_username(cli, user);
1843 if (!NT_STATUS_IS_OK(status)) {
1844 TALLOC_FREE(principal);
1845 return ADS_ERROR_NT(status);
1848 #ifdef HAVE_KRB5
1849 /* If password is set we reauthenticate to kerberos server
1850 * and do not store results */
1852 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1853 ADS_STATUS rc;
1855 if (pass && *pass) {
1856 int ret;
1858 use_in_memory_ccache();
1859 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1861 if (ret){
1862 TALLOC_FREE(principal);
1863 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1864 if (cli->fallback_after_kerberos)
1865 goto ntlmssp;
1866 return ADS_ERROR_KRB5(ret);
1870 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1872 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1873 TALLOC_FREE(principal);
1876 if (principal == NULL &&
1877 !is_ipaddress(cli->desthost) &&
1878 !strequal(STAR_SMBSERVER,
1879 cli->desthost)) {
1880 char *realm = NULL;
1881 char *host = NULL;
1882 DEBUG(3,("cli_session_setup_spnego: using target "
1883 "hostname not SPNEGO principal\n"));
1885 host = strchr_m(cli->desthost, '.');
1886 if (dest_realm) {
1887 realm = SMB_STRDUP(dest_realm);
1888 strupper_m(realm);
1889 } else {
1890 if (host) {
1891 /* DNS name. */
1892 realm = kerberos_get_realm_from_hostname(cli->desthost);
1893 } else {
1894 /* NetBIOS name - use our realm. */
1895 realm = kerberos_get_default_realm_from_ccache();
1899 if (realm && *realm) {
1900 principal = talloc_asprintf(talloc_tos(),
1901 "cifs/%s@%s",
1902 cli->desthost,
1903 realm);
1904 if (!principal) {
1905 SAFE_FREE(realm);
1906 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1908 DEBUG(3,("cli_session_setup_spnego: guessed "
1909 "server principal=%s\n",
1910 principal ? principal : "<null>"));
1912 SAFE_FREE(realm);
1915 if (principal) {
1916 rc = cli_session_setup_kerberos(cli, principal,
1917 dest_realm);
1918 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1919 TALLOC_FREE(principal);
1920 return rc;
1924 #endif
1926 TALLOC_FREE(principal);
1928 ntlmssp:
1930 account = talloc_strdup(talloc_tos(), user);
1931 if (!account) {
1932 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1935 /* when falling back to ntlmssp while authenticating with a machine
1936 * account strip off the realm - gd */
1938 if ((p = strchr_m(user, '@')) != NULL) {
1939 account[PTR_DIFF(p,user)] = '\0';
1942 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1945 /****************************************************************************
1946 Send a session setup. The username and workgroup is in UNIX character
1947 format and must be converted to DOS codepage format before sending. If the
1948 password is in plaintext, the same should be done.
1949 ****************************************************************************/
1951 NTSTATUS cli_session_setup(struct cli_state *cli,
1952 const char *user,
1953 const char *pass, int passlen,
1954 const char *ntpass, int ntpasslen,
1955 const char *workgroup)
1957 char *p;
1958 char *user2;
1960 if (user) {
1961 user2 = talloc_strdup(talloc_tos(), user);
1962 } else {
1963 user2 = talloc_strdup(talloc_tos(), "");
1965 if (user2 == NULL) {
1966 return NT_STATUS_NO_MEMORY;
1969 if (!workgroup) {
1970 workgroup = "";
1973 /* allow for workgroups as part of the username */
1974 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1975 (p=strchr_m(user2,*lp_winbind_separator()))) {
1976 *p = 0;
1977 user = p+1;
1978 workgroup = user2;
1981 if (cli->protocol < PROTOCOL_LANMAN1) {
1982 return NT_STATUS_OK;
1985 /* now work out what sort of session setup we are going to
1986 do. I have split this into separate functions to make the
1987 flow a bit easier to understand (tridge) */
1989 /* if its an older server then we have to use the older request format */
1991 if (cli->protocol < PROTOCOL_NT1) {
1992 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1993 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
1994 " or 'client ntlmv2 auth = yes'\n"));
1995 return NT_STATUS_ACCESS_DENIED;
1998 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1999 !lp_client_plaintext_auth() && (*pass)) {
2000 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2001 " or 'client ntlmv2 auth = yes'\n"));
2002 return NT_STATUS_ACCESS_DENIED;
2005 return cli_session_setup_lanman2(cli, user, pass, passlen,
2006 workgroup);
2009 /* if no user is supplied then we have to do an anonymous connection.
2010 passwords are ignored */
2012 if (!user || !*user)
2013 return cli_session_setup_guest(cli);
2015 /* if the server is share level then send a plaintext null
2016 password at this point. The password is sent in the tree
2017 connect */
2019 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2020 return cli_session_setup_plain(cli, user, "", workgroup);
2022 /* if the server doesn't support encryption then we have to use
2023 plaintext. The second password is ignored */
2025 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2026 if (!lp_client_plaintext_auth() && (*pass)) {
2027 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2028 " or 'client ntlmv2 auth = yes'\n"));
2029 return NT_STATUS_ACCESS_DENIED;
2031 return cli_session_setup_plain(cli, user, pass, workgroup);
2034 /* if the server supports extended security then use SPNEGO */
2036 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
2037 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2038 workgroup, NULL);
2039 if (!ADS_ERR_OK(status)) {
2040 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2041 return ads_ntstatus(status);
2043 } else {
2044 NTSTATUS status;
2046 /* otherwise do a NT1 style session setup */
2047 status = cli_session_setup_nt1(cli, user, pass, passlen,
2048 ntpass, ntpasslen, workgroup);
2049 if (!NT_STATUS_IS_OK(status)) {
2050 DEBUG(3,("cli_session_setup: NT1 session setup "
2051 "failed: %s\n", nt_errstr(status)));
2052 return status;
2056 if (strstr(cli->server_type, "Samba")) {
2057 cli->is_samba = True;
2060 return NT_STATUS_OK;
2063 /****************************************************************************
2064 Send a uloggoff.
2065 *****************************************************************************/
2067 struct cli_ulogoff_state {
2068 struct cli_state *cli;
2069 uint16_t vwv[3];
2072 static void cli_ulogoff_done(struct tevent_req *subreq);
2074 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2075 struct tevent_context *ev,
2076 struct cli_state *cli)
2078 struct tevent_req *req, *subreq;
2079 struct cli_ulogoff_state *state;
2081 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2082 if (req == NULL) {
2083 return NULL;
2085 state->cli = cli;
2087 SCVAL(state->vwv+0, 0, 0xFF);
2088 SCVAL(state->vwv+1, 0, 0);
2089 SSVAL(state->vwv+2, 0, 0);
2091 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2092 0, NULL);
2093 if (tevent_req_nomem(subreq, req)) {
2094 return tevent_req_post(req, ev);
2096 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2097 return req;
2100 static void cli_ulogoff_done(struct tevent_req *subreq)
2102 struct tevent_req *req = tevent_req_callback_data(
2103 subreq, struct tevent_req);
2104 struct cli_ulogoff_state *state = tevent_req_data(
2105 req, struct cli_ulogoff_state);
2106 NTSTATUS status;
2108 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2109 if (!NT_STATUS_IS_OK(status)) {
2110 tevent_req_nterror(req, status);
2111 return;
2113 state->cli->vuid = -1;
2114 tevent_req_done(req);
2117 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2119 return tevent_req_simple_recv_ntstatus(req);
2122 NTSTATUS cli_ulogoff(struct cli_state *cli)
2124 struct tevent_context *ev;
2125 struct tevent_req *req;
2126 NTSTATUS status = NT_STATUS_NO_MEMORY;
2128 if (cli_has_async_calls(cli)) {
2129 return NT_STATUS_INVALID_PARAMETER;
2131 ev = tevent_context_init(talloc_tos());
2132 if (ev == NULL) {
2133 goto fail;
2135 req = cli_ulogoff_send(ev, ev, cli);
2136 if (req == NULL) {
2137 goto fail;
2139 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2140 goto fail;
2142 status = cli_ulogoff_recv(req);
2143 fail:
2144 TALLOC_FREE(ev);
2145 if (!NT_STATUS_IS_OK(status)) {
2146 cli_set_error(cli, status);
2148 return status;
2151 /****************************************************************************
2152 Send a tconX.
2153 ****************************************************************************/
2155 struct cli_tcon_andx_state {
2156 struct cli_state *cli;
2157 uint16_t vwv[4];
2158 struct iovec bytes;
2161 static void cli_tcon_andx_done(struct tevent_req *subreq);
2163 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2164 struct event_context *ev,
2165 struct cli_state *cli,
2166 const char *share, const char *dev,
2167 const char *pass, int passlen,
2168 struct tevent_req **psmbreq)
2170 struct tevent_req *req, *subreq;
2171 struct cli_tcon_andx_state *state;
2172 uint8_t p24[24];
2173 uint16_t *vwv;
2174 char *tmp = NULL;
2175 uint8_t *bytes;
2177 *psmbreq = NULL;
2179 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2180 if (req == NULL) {
2181 return NULL;
2183 state->cli = cli;
2184 vwv = state->vwv;
2186 cli->share = talloc_strdup(cli, share);
2187 if (!cli->share) {
2188 return NULL;
2191 /* in user level security don't send a password now */
2192 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2193 passlen = 1;
2194 pass = "";
2195 } else if (pass == NULL) {
2196 DEBUG(1, ("Server not using user level security and no "
2197 "password supplied.\n"));
2198 goto access_denied;
2201 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2202 *pass && passlen != 24) {
2203 if (!lp_client_lanman_auth()) {
2204 DEBUG(1, ("Server requested LANMAN password "
2205 "(share-level security) but "
2206 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2207 goto access_denied;
2211 * Non-encrypted passwords - convert to DOS codepage before
2212 * encryption.
2214 SMBencrypt(pass, cli->secblob.data, p24);
2215 passlen = 24;
2216 pass = (const char *)p24;
2217 } else {
2218 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2219 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2220 == 0) {
2221 char *tmp_pass;
2223 if (!lp_client_plaintext_auth() && (*pass)) {
2224 DEBUG(1, ("Server requested plaintext "
2225 "password but "
2226 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2227 goto access_denied;
2231 * Non-encrypted passwords - convert to DOS codepage
2232 * before using.
2234 tmp_pass = talloc_array(talloc_tos(), char, 128);
2235 if (tmp_pass == NULL) {
2236 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2237 return tevent_req_post(req, ev);
2239 passlen = clistr_push(cli,
2240 tmp_pass,
2241 pass,
2242 talloc_get_size(tmp_pass),
2243 STR_TERMINATE);
2244 if (passlen == -1) {
2245 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2246 return tevent_req_post(req, ev);
2248 pass = tmp_pass;
2252 SCVAL(vwv+0, 0, 0xFF);
2253 SCVAL(vwv+0, 1, 0);
2254 SSVAL(vwv+1, 0, 0);
2255 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2256 SSVAL(vwv+3, 0, passlen);
2258 if (passlen && pass) {
2259 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2260 } else {
2261 bytes = talloc_array(state, uint8_t, 0);
2265 * Add the sharename
2267 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2268 cli->desthost, share);
2269 if (tmp == NULL) {
2270 TALLOC_FREE(req);
2271 return NULL;
2273 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2274 NULL);
2275 TALLOC_FREE(tmp);
2278 * Add the devicetype
2280 tmp = talloc_strdup_upper(talloc_tos(), dev);
2281 if (tmp == NULL) {
2282 TALLOC_FREE(req);
2283 return NULL;
2285 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2286 TALLOC_FREE(tmp);
2288 if (bytes == NULL) {
2289 TALLOC_FREE(req);
2290 return NULL;
2293 state->bytes.iov_base = (void *)bytes;
2294 state->bytes.iov_len = talloc_get_size(bytes);
2296 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2297 1, &state->bytes);
2298 if (subreq == NULL) {
2299 TALLOC_FREE(req);
2300 return NULL;
2302 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2303 *psmbreq = subreq;
2304 return req;
2306 access_denied:
2307 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2308 return tevent_req_post(req, ev);
2311 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2312 struct event_context *ev,
2313 struct cli_state *cli,
2314 const char *share, const char *dev,
2315 const char *pass, int passlen)
2317 struct tevent_req *req, *subreq;
2318 NTSTATUS status;
2320 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2321 &subreq);
2322 if (req == NULL) {
2323 return NULL;
2325 if (subreq == NULL) {
2326 return req;
2328 status = cli_smb_req_send(subreq);
2329 if (!NT_STATUS_IS_OK(status)) {
2330 tevent_req_nterror(req, status);
2331 return tevent_req_post(req, ev);
2333 return req;
2336 static void cli_tcon_andx_done(struct tevent_req *subreq)
2338 struct tevent_req *req = tevent_req_callback_data(
2339 subreq, struct tevent_req);
2340 struct cli_tcon_andx_state *state = tevent_req_data(
2341 req, struct cli_tcon_andx_state);
2342 struct cli_state *cli = state->cli;
2343 uint8_t *in;
2344 char *inbuf;
2345 uint8_t wct;
2346 uint16_t *vwv;
2347 uint32_t num_bytes;
2348 uint8_t *bytes;
2349 NTSTATUS status;
2351 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2352 &num_bytes, &bytes);
2353 TALLOC_FREE(subreq);
2354 if (!NT_STATUS_IS_OK(status)) {
2355 tevent_req_nterror(req, status);
2356 return;
2359 inbuf = (char *)in;
2361 if (num_bytes) {
2362 if (clistr_pull_talloc(cli,
2363 inbuf,
2364 SVAL(inbuf, smb_flg2),
2365 &cli->dev,
2366 bytes,
2367 num_bytes,
2368 STR_TERMINATE|STR_ASCII) == -1) {
2369 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2370 return;
2372 } else {
2373 cli->dev = talloc_strdup(cli, "");
2374 if (cli->dev == NULL) {
2375 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2376 return;
2380 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
2381 /* almost certainly win95 - enable bug fixes */
2382 cli->win95 = True;
2386 * Make sure that we have the optional support 16-bit field. WCT > 2.
2387 * Avoids issues when connecting to Win9x boxes sharing files
2390 cli->dfsroot = false;
2392 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
2393 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2396 cli->cnum = SVAL(inbuf,smb_tid);
2397 tevent_req_done(req);
2400 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2402 return tevent_req_simple_recv_ntstatus(req);
2405 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2406 const char *dev, const char *pass, int passlen)
2408 TALLOC_CTX *frame = talloc_stackframe();
2409 struct event_context *ev;
2410 struct tevent_req *req;
2411 NTSTATUS status = NT_STATUS_OK;
2413 if (cli_has_async_calls(cli)) {
2415 * Can't use sync call while an async call is in flight
2417 status = NT_STATUS_INVALID_PARAMETER;
2418 goto fail;
2421 ev = event_context_init(frame);
2422 if (ev == NULL) {
2423 status = NT_STATUS_NO_MEMORY;
2424 goto fail;
2427 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2428 if (req == NULL) {
2429 status = NT_STATUS_NO_MEMORY;
2430 goto fail;
2433 if (!tevent_req_poll(req, ev)) {
2434 status = map_nt_error_from_unix(errno);
2435 goto fail;
2438 status = cli_tcon_andx_recv(req);
2439 fail:
2440 TALLOC_FREE(frame);
2441 if (!NT_STATUS_IS_OK(status)) {
2442 cli_set_error(cli, status);
2444 return status;
2447 /****************************************************************************
2448 Send a tree disconnect.
2449 ****************************************************************************/
2451 struct cli_tdis_state {
2452 struct cli_state *cli;
2455 static void cli_tdis_done(struct tevent_req *subreq);
2457 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2458 struct tevent_context *ev,
2459 struct cli_state *cli)
2461 struct tevent_req *req, *subreq;
2462 struct cli_tdis_state *state;
2464 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2465 if (req == NULL) {
2466 return NULL;
2468 state->cli = cli;
2470 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2471 if (tevent_req_nomem(subreq, req)) {
2472 return tevent_req_post(req, ev);
2474 tevent_req_set_callback(subreq, cli_tdis_done, req);
2475 return req;
2478 static void cli_tdis_done(struct tevent_req *subreq)
2480 struct tevent_req *req = tevent_req_callback_data(
2481 subreq, struct tevent_req);
2482 struct cli_tdis_state *state = tevent_req_data(
2483 req, struct cli_tdis_state);
2484 NTSTATUS status;
2486 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2487 TALLOC_FREE(subreq);
2488 if (!NT_STATUS_IS_OK(status)) {
2489 tevent_req_nterror(req, status);
2490 return;
2492 state->cli->cnum = -1;
2493 tevent_req_done(req);
2496 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2498 return tevent_req_simple_recv_ntstatus(req);
2501 NTSTATUS cli_tdis(struct cli_state *cli)
2503 struct tevent_context *ev;
2504 struct tevent_req *req;
2505 NTSTATUS status = NT_STATUS_NO_MEMORY;
2507 if (cli_has_async_calls(cli)) {
2508 return NT_STATUS_INVALID_PARAMETER;
2510 ev = tevent_context_init(talloc_tos());
2511 if (ev == NULL) {
2512 goto fail;
2514 req = cli_tdis_send(ev, ev, cli);
2515 if (req == NULL) {
2516 goto fail;
2518 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2519 goto fail;
2521 status = cli_tdis_recv(req);
2522 fail:
2523 TALLOC_FREE(ev);
2524 if (!NT_STATUS_IS_OK(status)) {
2525 cli_set_error(cli, status);
2527 return status;
2530 /****************************************************************************
2531 Send a negprot command.
2532 ****************************************************************************/
2534 struct cli_negprot_state {
2535 struct cli_state *cli;
2538 static void cli_negprot_done(struct tevent_req *subreq);
2540 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2541 struct event_context *ev,
2542 struct cli_state *cli)
2544 struct tevent_req *req, *subreq;
2545 struct cli_negprot_state *state;
2546 uint8_t *bytes = NULL;
2547 int numprots;
2548 uint16_t cnum;
2550 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2551 if (req == NULL) {
2552 return NULL;
2554 state->cli = cli;
2556 if (cli->protocol < PROTOCOL_NT1)
2557 cli->use_spnego = False;
2559 /* setup the protocol strings */
2560 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2561 uint8_t c = 2;
2562 if (prots[numprots].prot > cli->protocol) {
2563 break;
2565 bytes = (uint8_t *)talloc_append_blob(
2566 state, bytes, data_blob_const(&c, sizeof(c)));
2567 if (tevent_req_nomem(bytes, req)) {
2568 return tevent_req_post(req, ev);
2570 bytes = smb_bytes_push_str(bytes, false,
2571 prots[numprots].name,
2572 strlen(prots[numprots].name)+1,
2573 NULL);
2574 if (tevent_req_nomem(bytes, req)) {
2575 return tevent_req_post(req, ev);
2579 cnum = cli->cnum;
2581 cli->cnum = 0;
2582 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2583 talloc_get_size(bytes), bytes);
2584 cli->cnum = cnum;
2586 if (tevent_req_nomem(subreq, req)) {
2587 return tevent_req_post(req, ev);
2589 tevent_req_set_callback(subreq, cli_negprot_done, req);
2590 return req;
2593 static void cli_negprot_done(struct tevent_req *subreq)
2595 struct tevent_req *req = tevent_req_callback_data(
2596 subreq, struct tevent_req);
2597 struct cli_negprot_state *state = tevent_req_data(
2598 req, struct cli_negprot_state);
2599 struct cli_state *cli = state->cli;
2600 uint8_t wct;
2601 uint16_t *vwv;
2602 uint32_t num_bytes;
2603 uint8_t *bytes;
2604 NTSTATUS status;
2605 uint16_t protnum;
2606 uint8_t *inbuf;
2608 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2609 &num_bytes, &bytes);
2610 TALLOC_FREE(subreq);
2611 if (!NT_STATUS_IS_OK(status)) {
2612 tevent_req_nterror(req, status);
2613 return;
2616 protnum = SVAL(vwv, 0);
2618 if ((protnum >= ARRAY_SIZE(prots))
2619 || (prots[protnum].prot > cli->protocol)) {
2620 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2621 return;
2624 cli->protocol = prots[protnum].prot;
2626 if ((cli->protocol < PROTOCOL_NT1) &&
2627 client_is_signing_mandatory(cli)) {
2628 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2629 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2630 return;
2633 if (cli->protocol >= PROTOCOL_NT1) {
2634 struct timespec ts;
2635 bool negotiated_smb_signing = false;
2637 /* NT protocol */
2638 cli->sec_mode = CVAL(vwv + 1, 0);
2639 cli->max_mux = SVAL(vwv + 1, 1);
2640 cli->max_xmit = IVAL(vwv + 3, 1);
2641 cli->sesskey = IVAL(vwv + 7, 1);
2642 cli->serverzone = SVALS(vwv + 15, 1);
2643 cli->serverzone *= 60;
2644 /* this time arrives in real GMT */
2645 ts = interpret_long_date(((char *)(vwv+11))+1);
2646 cli->servertime = ts.tv_sec;
2647 cli->secblob = data_blob(bytes, num_bytes);
2648 cli->capabilities = IVAL(vwv + 9, 1);
2649 if (cli->capabilities & CAP_RAW_MODE) {
2650 cli->readbraw_supported = True;
2651 cli->writebraw_supported = True;
2653 /* work out if they sent us a workgroup */
2654 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2655 smb_buflen(cli->inbuf) > 8) {
2656 clistr_pull(cli->inbuf, cli->server_domain,
2657 bytes+8, sizeof(cli->server_domain),
2658 num_bytes-8,
2659 STR_UNICODE|STR_NOALIGN);
2663 * As signing is slow we only turn it on if either the client or
2664 * the server require it. JRA.
2667 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2668 /* Fail if server says signing is mandatory and we don't want to support it. */
2669 if (!client_is_signing_allowed(cli)) {
2670 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2671 tevent_req_nterror(req,
2672 NT_STATUS_ACCESS_DENIED);
2673 return;
2675 negotiated_smb_signing = true;
2676 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2677 /* Fail if client says signing is mandatory and the server doesn't support it. */
2678 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2679 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2680 tevent_req_nterror(req,
2681 NT_STATUS_ACCESS_DENIED);
2682 return;
2684 negotiated_smb_signing = true;
2685 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2686 negotiated_smb_signing = true;
2689 if (negotiated_smb_signing) {
2690 cli_set_signing_negotiated(cli);
2693 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2694 SAFE_FREE(cli->outbuf);
2695 SAFE_FREE(cli->inbuf);
2696 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2697 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2698 if (!cli->outbuf || !cli->inbuf) {
2699 tevent_req_nterror(req,
2700 NT_STATUS_NO_MEMORY);
2701 return;
2703 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2706 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2707 cli->use_spnego = False;
2708 cli->sec_mode = SVAL(vwv + 1, 0);
2709 cli->max_xmit = SVAL(vwv + 2, 0);
2710 cli->max_mux = SVAL(vwv + 3, 0);
2711 cli->sesskey = IVAL(vwv + 6, 0);
2712 cli->serverzone = SVALS(vwv + 10, 0);
2713 cli->serverzone *= 60;
2714 /* this time is converted to GMT by make_unix_date */
2715 cli->servertime = make_unix_date(
2716 (char *)(vwv + 8), cli->serverzone);
2717 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2718 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2719 cli->secblob = data_blob(bytes, num_bytes);
2720 } else {
2721 /* the old core protocol */
2722 cli->use_spnego = False;
2723 cli->sec_mode = 0;
2724 cli->serverzone = get_time_zone(time(NULL));
2727 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2729 /* a way to force ascii SMB */
2730 if (getenv("CLI_FORCE_ASCII"))
2731 cli->capabilities &= ~CAP_UNICODE;
2733 tevent_req_done(req);
2736 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2738 return tevent_req_simple_recv_ntstatus(req);
2741 NTSTATUS cli_negprot(struct cli_state *cli)
2743 TALLOC_CTX *frame = talloc_stackframe();
2744 struct event_context *ev;
2745 struct tevent_req *req;
2746 NTSTATUS status = NT_STATUS_OK;
2748 if (cli_has_async_calls(cli)) {
2750 * Can't use sync call while an async call is in flight
2752 status = NT_STATUS_INVALID_PARAMETER;
2753 goto fail;
2756 ev = event_context_init(frame);
2757 if (ev == NULL) {
2758 status = NT_STATUS_NO_MEMORY;
2759 goto fail;
2762 req = cli_negprot_send(frame, ev, cli);
2763 if (req == NULL) {
2764 status = NT_STATUS_NO_MEMORY;
2765 goto fail;
2768 if (!tevent_req_poll(req, ev)) {
2769 status = map_nt_error_from_unix(errno);
2770 goto fail;
2773 status = cli_negprot_recv(req);
2774 fail:
2775 TALLOC_FREE(frame);
2776 if (!NT_STATUS_IS_OK(status)) {
2777 cli_set_error(cli, status);
2779 return status;
2782 /****************************************************************************
2783 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2784 ****************************************************************************/
2786 bool cli_session_request(struct cli_state *cli,
2787 struct nmb_name *calling, struct nmb_name *called)
2789 char *p;
2790 int len = 4;
2791 int namelen = 0;
2792 char *tmp;
2794 /* 445 doesn't have session request */
2795 if (cli->port == 445)
2796 return True;
2798 memcpy(&(cli->calling), calling, sizeof(*calling));
2799 memcpy(&(cli->called ), called , sizeof(*called ));
2801 /* put in the destination name */
2803 tmp = name_mangle(talloc_tos(), cli->called.name,
2804 cli->called.name_type);
2805 if (tmp == NULL) {
2806 return false;
2809 p = cli->outbuf+len;
2810 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2811 if (namelen > 0) {
2812 memcpy(p, tmp, namelen);
2813 len += namelen;
2815 TALLOC_FREE(tmp);
2817 /* and my name */
2819 tmp = name_mangle(talloc_tos(), cli->calling.name,
2820 cli->calling.name_type);
2821 if (tmp == NULL) {
2822 return false;
2825 p = cli->outbuf+len;
2826 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2827 if (namelen > 0) {
2828 memcpy(p, tmp, namelen);
2829 len += namelen;
2831 TALLOC_FREE(tmp);
2833 /* send a session request (RFC 1002) */
2834 /* setup the packet length
2835 * Remove four bytes from the length count, since the length
2836 * field in the NBT Session Service header counts the number
2837 * of bytes which follow. The cli_send_smb() function knows
2838 * about this and accounts for those four bytes.
2839 * CRH.
2841 len -= 4;
2842 _smb_setlen(cli->outbuf,len);
2843 SCVAL(cli->outbuf,0,0x81);
2845 cli_send_smb(cli);
2846 DEBUG(5,("Sent session request\n"));
2848 if (!cli_receive_smb(cli))
2849 return False;
2851 if (CVAL(cli->inbuf,0) == 0x84) {
2852 /* C. Hoch 9/14/95 Start */
2853 /* For information, here is the response structure.
2854 * We do the byte-twiddling to for portability.
2855 struct RetargetResponse{
2856 unsigned char type;
2857 unsigned char flags;
2858 int16 length;
2859 int32 ip_addr;
2860 int16 port;
2863 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2864 struct in_addr dest_ip;
2865 NTSTATUS status;
2867 /* SESSION RETARGET */
2868 putip((char *)&dest_ip,cli->inbuf+4);
2869 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2871 status = open_socket_out(&cli->dest_ss, port,
2872 LONG_CONNECT_TIMEOUT, &cli->fd);
2873 if (!NT_STATUS_IS_OK(status)) {
2874 return False;
2877 DEBUG(3,("Retargeted\n"));
2879 set_socket_options(cli->fd, lp_socket_options());
2881 /* Try again */
2883 static int depth;
2884 bool ret;
2885 if (depth > 4) {
2886 DEBUG(0,("Retarget recursion - failing\n"));
2887 return False;
2889 depth++;
2890 ret = cli_session_request(cli, calling, called);
2891 depth--;
2892 return ret;
2894 } /* C. Hoch 9/14/95 End */
2896 if (CVAL(cli->inbuf,0) != 0x82) {
2897 /* This is the wrong place to put the error... JRA. */
2898 cli->rap_error = CVAL(cli->inbuf,4);
2899 return False;
2901 return(True);
2904 struct fd_struct {
2905 int fd;
2908 static void smb_sock_connected(struct tevent_req *req)
2910 struct fd_struct *pfd = tevent_req_callback_data(
2911 req, struct fd_struct);
2912 int fd;
2913 NTSTATUS status;
2915 status = open_socket_out_defer_recv(req, &fd);
2916 if (NT_STATUS_IS_OK(status)) {
2917 pfd->fd = fd;
2921 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2922 uint16_t *port, int timeout, int *pfd)
2924 struct event_context *ev;
2925 struct tevent_req *r139, *r445;
2926 struct fd_struct *fd139, *fd445;
2927 NTSTATUS status = NT_STATUS_NO_MEMORY;
2929 if (*port != 0) {
2930 return open_socket_out(pss, *port, timeout, pfd);
2933 ev = event_context_init(talloc_tos());
2934 if (ev == NULL) {
2935 return NT_STATUS_NO_MEMORY;
2938 fd139 = talloc(ev, struct fd_struct);
2939 if (fd139 == NULL) {
2940 goto done;
2942 fd139->fd = -1;
2944 fd445 = talloc(ev, struct fd_struct);
2945 if (fd445 == NULL) {
2946 goto done;
2948 fd445->fd = -1;
2950 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2951 pss, 445, timeout);
2952 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2953 pss, 139, timeout);
2954 if ((r445 == NULL) || (r139 == NULL)) {
2955 goto done;
2957 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2958 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2960 while ((fd445->fd == -1) && (fd139->fd == -1)
2961 && (tevent_req_is_in_progress(r139)
2962 || tevent_req_is_in_progress(r445))) {
2963 event_loop_once(ev);
2966 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2967 close(fd139->fd);
2968 fd139->fd = -1;
2971 if (fd445->fd != -1) {
2972 *port = 445;
2973 *pfd = fd445->fd;
2974 status = NT_STATUS_OK;
2975 goto done;
2977 if (fd139->fd != -1) {
2978 *port = 139;
2979 *pfd = fd139->fd;
2980 status = NT_STATUS_OK;
2981 goto done;
2984 status = open_socket_out_defer_recv(r445, &fd445->fd);
2985 done:
2986 TALLOC_FREE(ev);
2987 return status;
2990 /****************************************************************************
2991 Open the client sockets.
2992 ****************************************************************************/
2994 NTSTATUS cli_connect(struct cli_state *cli,
2995 const char *host,
2996 struct sockaddr_storage *dest_ss)
2999 int name_type = 0x20;
3000 TALLOC_CTX *frame = talloc_stackframe();
3001 unsigned int num_addrs = 0;
3002 unsigned int i = 0;
3003 struct sockaddr_storage *ss_arr = NULL;
3004 char *p = NULL;
3006 /* reasonable default hostname */
3007 if (!host) {
3008 host = STAR_SMBSERVER;
3011 cli->desthost = talloc_strdup(cli, host);
3012 if (cli->desthost == NULL) {
3013 return NT_STATUS_NO_MEMORY;
3016 /* allow hostnames of the form NAME#xx and do a netbios lookup */
3017 if ((p = strchr(cli->desthost, '#'))) {
3018 name_type = strtol(p+1, NULL, 16);
3019 *p = 0;
3022 if (!dest_ss || is_zero_addr(dest_ss)) {
3023 NTSTATUS status =resolve_name_list(frame,
3024 cli->desthost,
3025 name_type,
3026 &ss_arr,
3027 &num_addrs);
3028 if (!NT_STATUS_IS_OK(status)) {
3029 TALLOC_FREE(frame);
3030 return NT_STATUS_BAD_NETWORK_NAME;
3032 } else {
3033 num_addrs = 1;
3034 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
3035 if (!ss_arr) {
3036 TALLOC_FREE(frame);
3037 return NT_STATUS_NO_MEMORY;
3039 *ss_arr = *dest_ss;
3042 for (i = 0; i < num_addrs; i++) {
3043 cli->dest_ss = ss_arr[i];
3044 if (getenv("LIBSMB_PROG")) {
3045 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
3046 } else {
3047 uint16_t port = cli->port;
3048 NTSTATUS status;
3049 status = open_smb_socket(&cli->dest_ss, &port,
3050 cli->timeout, &cli->fd);
3051 if (NT_STATUS_IS_OK(status)) {
3052 cli->port = port;
3055 if (cli->fd == -1) {
3056 char addr[INET6_ADDRSTRLEN];
3057 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
3058 DEBUG(2,("Error connecting to %s (%s)\n",
3059 dest_ss?addr:host,strerror(errno)));
3060 } else {
3061 /* Exit from loop on first connection. */
3062 break;
3066 if (cli->fd == -1) {
3067 TALLOC_FREE(frame);
3068 return map_nt_error_from_unix(errno);
3071 if (dest_ss) {
3072 *dest_ss = cli->dest_ss;
3075 set_socket_options(cli->fd, lp_socket_options());
3077 TALLOC_FREE(frame);
3078 return NT_STATUS_OK;
3082 establishes a connection to after the negprot.
3083 @param output_cli A fully initialised cli structure, non-null only on success
3084 @param dest_host The netbios name of the remote host
3085 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3086 @param port (optional) The destination port (0 for default)
3088 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3089 const char *my_name,
3090 const char *dest_host,
3091 struct sockaddr_storage *dest_ss, int port,
3092 int signing_state, int flags)
3094 NTSTATUS nt_status;
3095 struct nmb_name calling;
3096 struct nmb_name called;
3097 struct cli_state *cli;
3098 struct sockaddr_storage ss;
3100 if (!my_name)
3101 my_name = global_myname();
3103 if (!(cli = cli_initialise_ex(signing_state))) {
3104 return NT_STATUS_NO_MEMORY;
3107 make_nmb_name(&calling, my_name, 0x0);
3108 make_nmb_name(&called , dest_host, 0x20);
3110 cli_set_port(cli, port);
3111 cli_set_timeout(cli, 10000); /* 10 seconds. */
3113 if (dest_ss) {
3114 ss = *dest_ss;
3115 } else {
3116 zero_sockaddr(&ss);
3119 again:
3121 DEBUG(3,("Connecting to host=%s\n", dest_host));
3123 nt_status = cli_connect(cli, dest_host, &ss);
3124 if (!NT_STATUS_IS_OK(nt_status)) {
3125 char addr[INET6_ADDRSTRLEN];
3126 print_sockaddr(addr, sizeof(addr), &ss);
3127 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
3128 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
3129 cli_shutdown(cli);
3130 return nt_status;
3133 if (!cli_session_request(cli, &calling, &called)) {
3134 char *p;
3135 DEBUG(1,("session request to %s failed (%s)\n",
3136 called.name, cli_errstr(cli)));
3137 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
3138 *p = 0;
3139 goto again;
3141 if (strcmp(called.name, STAR_SMBSERVER)) {
3142 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
3143 goto again;
3145 return NT_STATUS_BAD_NETWORK_NAME;
3148 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
3149 cli->use_spnego = False;
3150 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
3151 cli->use_kerberos = True;
3153 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
3154 cli->use_kerberos) {
3155 cli->fallback_after_kerberos = true;
3157 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3158 cli->use_ccache = true;
3161 nt_status = cli_negprot(cli);
3162 if (!NT_STATUS_IS_OK(nt_status)) {
3163 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
3164 cli_shutdown(cli);
3165 return nt_status;
3168 *output_cli = cli;
3169 return NT_STATUS_OK;
3174 establishes a connection right up to doing tconX, password specified.
3175 @param output_cli A fully initialised cli structure, non-null only on success
3176 @param dest_host The netbios name of the remote host
3177 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3178 @param port (optional) The destination port (0 for default)
3179 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3180 @param service_type The 'type' of serivice.
3181 @param user Username, unix string
3182 @param domain User's domain
3183 @param password User's password, unencrypted unix string.
3186 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3187 const char *my_name,
3188 const char *dest_host,
3189 struct sockaddr_storage *dest_ss, int port,
3190 const char *service, const char *service_type,
3191 const char *user, const char *domain,
3192 const char *password, int flags,
3193 int signing_state)
3195 NTSTATUS nt_status;
3196 struct cli_state *cli = NULL;
3197 int pw_len = password ? strlen(password)+1 : 0;
3199 *output_cli = NULL;
3201 if (password == NULL) {
3202 password = "";
3205 nt_status = cli_start_connection(&cli, my_name, dest_host,
3206 dest_ss, port, signing_state,
3207 flags);
3209 if (!NT_STATUS_IS_OK(nt_status)) {
3210 return nt_status;
3213 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
3214 cli->use_level_II_oplocks =
3215 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
3217 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3218 pw_len, domain);
3219 if (!NT_STATUS_IS_OK(nt_status)) {
3221 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3222 DEBUG(1,("failed session setup with %s\n",
3223 nt_errstr(nt_status)));
3224 cli_shutdown(cli);
3225 return nt_status;
3228 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3229 if (!NT_STATUS_IS_OK(nt_status)) {
3230 DEBUG(1,("anonymous failed session setup with %s\n",
3231 nt_errstr(nt_status)));
3232 cli_shutdown(cli);
3233 return nt_status;
3237 if (service) {
3238 nt_status = cli_tcon_andx(cli, service, service_type, password,
3239 pw_len);
3240 if (!NT_STATUS_IS_OK(nt_status)) {
3241 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3242 cli_shutdown(cli);
3243 if (NT_STATUS_IS_OK(nt_status)) {
3244 nt_status = NT_STATUS_UNSUCCESSFUL;
3246 return nt_status;
3250 nt_status = cli_init_creds(cli, user, domain, password);
3251 if (!NT_STATUS_IS_OK(nt_status)) {
3252 cli_shutdown(cli);
3253 return nt_status;
3256 *output_cli = cli;
3257 return NT_STATUS_OK;
3260 /****************************************************************************
3261 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
3262 ****************************************************************************/
3264 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
3265 struct sockaddr_storage *pdest_ss)
3267 struct nmb_name calling, called;
3269 make_nmb_name(&calling, srchost, 0x0);
3272 * If the called name is an IP address
3273 * then use *SMBSERVER immediately.
3276 if(is_ipaddress(desthost)) {
3277 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
3278 } else {
3279 make_nmb_name(&called, desthost, 0x20);
3282 if (!cli_session_request(*ppcli, &calling, &called)) {
3283 NTSTATUS status;
3284 struct nmb_name smbservername;
3286 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
3289 * If the name wasn't *SMBSERVER then
3290 * try with *SMBSERVER if the first name fails.
3293 if (nmb_name_equal(&called, &smbservername)) {
3296 * The name used was *SMBSERVER, don't bother with another name.
3299 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
3300 with error %s.\n", desthost, cli_errstr(*ppcli) ));
3301 return False;
3304 /* Try again... */
3305 cli_shutdown(*ppcli);
3307 *ppcli = cli_initialise();
3308 if (!*ppcli) {
3309 /* Out of memory... */
3310 return False;
3313 status = cli_connect(*ppcli, desthost, pdest_ss);
3314 if (!NT_STATUS_IS_OK(status) ||
3315 !cli_session_request(*ppcli, &calling, &smbservername)) {
3316 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
3317 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
3318 return False;
3322 return True;
3325 /****************************************************************************
3326 Send an old style tcon.
3327 ****************************************************************************/
3328 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3329 const char *service, const char *pass, const char *dev,
3330 uint16 *max_xmit, uint16 *tid)
3332 struct tevent_req *req;
3333 uint16_t *ret_vwv;
3334 uint8_t *bytes;
3335 NTSTATUS status;
3337 if (!lp_client_plaintext_auth() && (*pass)) {
3338 DEBUG(1, ("Server requested plaintext password but 'client "
3339 "plaintext auth' is disabled\n"));
3340 return NT_STATUS_ACCESS_DENIED;
3343 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3344 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3345 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3346 service, strlen(service)+1, NULL);
3347 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3348 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3349 pass, strlen(pass)+1, NULL);
3350 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3351 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3352 dev, strlen(dev)+1, NULL);
3354 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3355 talloc_get_size(bytes), bytes, &req,
3356 2, NULL, &ret_vwv, NULL, NULL);
3357 if (!NT_STATUS_IS_OK(status)) {
3358 return status;
3361 *max_xmit = SVAL(ret_vwv + 0, 0);
3362 *tid = SVAL(ret_vwv + 1, 0);
3364 return NT_STATUS_OK;
3367 /* Return a cli_state pointing at the IPC$ share for the given server */
3369 struct cli_state *get_ipc_connect(char *server,
3370 struct sockaddr_storage *server_ss,
3371 const struct user_auth_info *user_info)
3373 struct cli_state *cli;
3374 NTSTATUS nt_status;
3375 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3377 if (user_info->use_kerberos) {
3378 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3381 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3382 user_info->username ? user_info->username : "",
3383 lp_workgroup(),
3384 user_info->password ? user_info->password : "",
3385 flags,
3386 Undefined);
3388 if (NT_STATUS_IS_OK(nt_status)) {
3389 return cli;
3390 } else if (is_ipaddress(server)) {
3391 /* windows 9* needs a correct NMB name for connections */
3392 fstring remote_name;
3394 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3395 cli = get_ipc_connect(remote_name, server_ss, user_info);
3396 if (cli)
3397 return cli;
3400 return NULL;
3404 * Given the IP address of a master browser on the network, return its
3405 * workgroup and connect to it.
3407 * This function is provided to allow additional processing beyond what
3408 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3409 * browsers and obtain each master browsers' list of domains (in case the
3410 * first master browser is recently on the network and has not yet
3411 * synchronized with other master browsers and therefore does not yet have the
3412 * entire network browse list)
3415 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3416 struct ip_service *mb_ip,
3417 const struct user_auth_info *user_info,
3418 char **pp_workgroup_out)
3420 char addr[INET6_ADDRSTRLEN];
3421 fstring name;
3422 struct cli_state *cli;
3423 struct sockaddr_storage server_ss;
3425 *pp_workgroup_out = NULL;
3427 print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
3428 DEBUG(99, ("Looking up name of master browser %s\n",
3429 addr));
3432 * Do a name status query to find out the name of the master browser.
3433 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3434 * master browser will not respond to a wildcard query (or, at least,
3435 * an NT4 server acting as the domain master browser will not).
3437 * We might be able to use ONLY the query on MSBROWSE, but that's not
3438 * yet been tested with all Windows versions, so until it is, leave
3439 * the original wildcard query as the first choice and fall back to
3440 * MSBROWSE if the wildcard query fails.
3442 if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
3443 !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
3445 DEBUG(99, ("Could not retrieve name status for %s\n",
3446 addr));
3447 return NULL;
3450 if (!find_master_ip(name, &server_ss)) {
3451 DEBUG(99, ("Could not find master ip for %s\n", name));
3452 return NULL;
3455 *pp_workgroup_out = talloc_strdup(ctx, name);
3457 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3459 print_sockaddr(addr, sizeof(addr), &server_ss);
3460 cli = get_ipc_connect(addr, &server_ss, user_info);
3462 return cli;
3466 * Return the IP address and workgroup of a master browser on the network, and
3467 * connect to it.
3470 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3471 const struct user_auth_info *user_info,
3472 char **pp_workgroup_out)
3474 struct ip_service *ip_list;
3475 struct cli_state *cli;
3476 int i, count;
3478 *pp_workgroup_out = NULL;
3480 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3482 /* Go looking for workgroups by broadcasting on the local network */
3484 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
3485 &count))) {
3486 DEBUG(99, ("No master browsers responded\n"));
3487 return False;
3490 for (i = 0; i < count; i++) {
3491 char addr[INET6_ADDRSTRLEN];
3492 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
3493 DEBUG(99, ("Found master browser %s\n", addr));
3495 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3496 user_info, pp_workgroup_out);
3497 if (cli)
3498 return(cli);
3501 return NULL;