check_parent_exists() can change errno. Ensure we preserve it across calls.
[Samba.git] / source3 / libsmb / cliconnect.c
blob8653ba7d0857769425d0da8437352f44dbfbb852
1 /*
2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
6 Copyright (C) Volker Lendecke 2011
7 Copyright (C) Jeremy Allison 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "libsmb/libsmb.h"
25 #include "popt_common.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
28 #include "smb_krb5.h"
29 #include "../libcli/auth/ntlmssp.h"
30 #include "libads/kerberos_proto.h"
31 #include "krb5_env.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "async_smb.h"
34 #include "libsmb/nmblib.h"
36 static const struct {
37 int prot;
38 const char name[24];
39 } prots[10] = {
40 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
41 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
42 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
43 {PROTOCOL_LANMAN1, "LANMAN1.0"},
44 {PROTOCOL_LANMAN2, "LM1.2X002"},
45 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
46 {PROTOCOL_LANMAN2, "LANMAN2.1"},
47 {PROTOCOL_LANMAN2, "Samba"},
48 {PROTOCOL_NT1, "NT LANMAN 1.0"},
49 {PROTOCOL_NT1, "NT LM 0.12"},
52 #define STAR_SMBSERVER "*SMBSERVER"
54 /********************************************************
55 Utility function to ensure we always return at least
56 a valid char * pointer to an empty string for the
57 cli->server_os, cli->server_type and cli->server_domain
58 strings.
59 *******************************************************/
61 static NTSTATUS smb_bytes_talloc_string(struct cli_state *cli,
62 char *inbuf,
63 char **dest,
64 uint8_t *src,
65 size_t srclen,
66 ssize_t *destlen)
68 *destlen = clistr_pull_talloc(cli,
69 inbuf,
70 SVAL(inbuf, smb_flg2),
71 dest,
72 (char *)src,
73 srclen,
74 STR_TERMINATE);
75 if (*destlen == -1) {
76 return NT_STATUS_NO_MEMORY;
79 if (*dest == NULL) {
80 *dest = talloc_strdup(cli, "");
81 if (*dest == NULL) {
82 return NT_STATUS_NO_MEMORY;
85 return NT_STATUS_OK;
88 /**
89 * Set the user session key for a connection
90 * @param cli The cli structure to add it too
91 * @param session_key The session key used. (A copy of this is taken for the cli struct)
95 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
97 cli->user_session_key = data_blob(NULL, 16);
98 data_blob_clear(&cli->user_session_key);
99 memcpy(cli->user_session_key.data, session_key.data, MIN(session_key.length, 16));
102 /****************************************************************************
103 Do an old lanman2 style session setup.
104 ****************************************************************************/
106 struct cli_session_setup_lanman2_state {
107 struct cli_state *cli;
108 uint16_t vwv[10];
109 const char *user;
112 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
114 static struct tevent_req *cli_session_setup_lanman2_send(
115 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
116 struct cli_state *cli, const char *user,
117 const char *pass, size_t passlen,
118 const char *workgroup)
120 struct tevent_req *req, *subreq;
121 struct cli_session_setup_lanman2_state *state;
122 DATA_BLOB lm_response = data_blob_null;
123 uint16_t *vwv;
124 uint8_t *bytes;
125 char *tmp;
127 req = tevent_req_create(mem_ctx, &state,
128 struct cli_session_setup_lanman2_state);
129 if (req == NULL) {
130 return NULL;
132 state->cli = cli;
133 state->user = user;
134 vwv = state->vwv;
137 * LANMAN servers predate NT status codes and Unicode and
138 * ignore those smb flags so we must disable the corresponding
139 * default capabilities that would otherwise cause the Unicode
140 * and NT Status flags to be set (and even returned by the
141 * server)
144 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
147 * if in share level security then don't send a password now
149 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
150 passlen = 0;
153 if (passlen > 0
154 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
155 && passlen != 24) {
157 * Encrypted mode needed, and non encrypted password
158 * supplied.
160 lm_response = data_blob(NULL, 24);
161 if (tevent_req_nomem(lm_response.data, req)) {
162 return tevent_req_post(req, ev);
165 if (!SMBencrypt(pass, cli->secblob.data,
166 (uint8_t *)lm_response.data)) {
167 DEBUG(1, ("Password is > 14 chars in length, and is "
168 "therefore incompatible with Lanman "
169 "authentication\n"));
170 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
171 return tevent_req_post(req, ev);
173 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
174 && passlen == 24) {
176 * Encrypted mode needed, and encrypted password
177 * supplied.
179 lm_response = data_blob(pass, passlen);
180 if (tevent_req_nomem(lm_response.data, req)) {
181 return tevent_req_post(req, ev);
183 } else if (passlen > 0) {
184 uint8_t *buf;
185 size_t converted_size;
187 * Plaintext mode needed, assume plaintext supplied.
189 buf = talloc_array(talloc_tos(), uint8_t, 0);
190 buf = smb_bytes_push_str(buf, cli_ucs2(cli), pass, passlen+1,
191 &converted_size);
192 if (tevent_req_nomem(buf, req)) {
193 return tevent_req_post(req, ev);
195 lm_response = data_blob(pass, passlen);
196 TALLOC_FREE(buf);
197 if (tevent_req_nomem(lm_response.data, req)) {
198 return tevent_req_post(req, ev);
202 SCVAL(vwv+0, 0, 0xff);
203 SCVAL(vwv+0, 1, 0);
204 SSVAL(vwv+1, 0, 0);
205 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
206 SSVAL(vwv+3, 0, 2);
207 SSVAL(vwv+4, 0, 1);
208 SIVAL(vwv+5, 0, cli->sesskey);
209 SSVAL(vwv+7, 0, lm_response.length);
211 bytes = talloc_array(state, uint8_t, lm_response.length);
212 if (tevent_req_nomem(bytes, req)) {
213 return tevent_req_post(req, ev);
215 if (lm_response.length != 0) {
216 memcpy(bytes, lm_response.data, lm_response.length);
218 data_blob_free(&lm_response);
220 tmp = talloc_strdup_upper(talloc_tos(), user);
221 if (tevent_req_nomem(tmp, req)) {
222 return tevent_req_post(req, ev);
224 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
225 NULL);
226 TALLOC_FREE(tmp);
228 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
229 if (tevent_req_nomem(tmp, req)) {
230 return tevent_req_post(req, ev);
232 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
233 NULL);
234 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
235 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
237 if (tevent_req_nomem(bytes, req)) {
238 return tevent_req_post(req, ev);
241 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
242 talloc_get_size(bytes), bytes);
243 if (tevent_req_nomem(subreq, req)) {
244 return tevent_req_post(req, ev);
246 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
247 return req;
250 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
252 struct tevent_req *req = tevent_req_callback_data(
253 subreq, struct tevent_req);
254 struct cli_session_setup_lanman2_state *state = tevent_req_data(
255 req, struct cli_session_setup_lanman2_state);
256 struct cli_state *cli = state->cli;
257 uint32_t num_bytes;
258 uint8_t *in;
259 char *inbuf;
260 uint8_t *bytes;
261 uint8_t *p;
262 NTSTATUS status;
263 ssize_t ret;
264 uint8_t wct;
265 uint16_t *vwv;
267 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
268 &num_bytes, &bytes);
269 TALLOC_FREE(subreq);
270 if (!NT_STATUS_IS_OK(status)) {
271 tevent_req_nterror(req, status);
272 return;
275 inbuf = (char *)in;
276 p = bytes;
278 cli->vuid = SVAL(inbuf, smb_uid);
279 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
281 status = smb_bytes_talloc_string(cli,
282 inbuf,
283 &cli->server_os,
285 bytes+num_bytes-p,
286 &ret);
288 if (!NT_STATUS_IS_OK(status)) {
289 tevent_req_nterror(req, status);
290 return;
292 p += ret;
294 status = smb_bytes_talloc_string(cli,
295 inbuf,
296 &cli->server_type,
298 bytes+num_bytes-p,
299 &ret);
301 if (!NT_STATUS_IS_OK(status)) {
302 tevent_req_nterror(req, status);
303 return;
305 p += ret;
307 status = smb_bytes_talloc_string(cli,
308 inbuf,
309 &cli->server_domain,
311 bytes+num_bytes-p,
312 &ret);
314 if (!NT_STATUS_IS_OK(status)) {
315 tevent_req_nterror(req, status);
316 return;
318 p += ret;
320 if (strstr(cli->server_type, "Samba")) {
321 cli->is_samba = True;
323 status = cli_set_username(cli, state->user);
324 if (tevent_req_nterror(req, status)) {
325 return;
327 tevent_req_done(req);
330 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
332 return tevent_req_simple_recv_ntstatus(req);
335 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
336 const char *pass, size_t passlen,
337 const char *workgroup)
339 TALLOC_CTX *frame = talloc_stackframe();
340 struct event_context *ev;
341 struct tevent_req *req;
342 NTSTATUS status = NT_STATUS_NO_MEMORY;
344 if (cli_has_async_calls(cli)) {
346 * Can't use sync call while an async call is in flight
348 status = NT_STATUS_INVALID_PARAMETER;
349 goto fail;
351 ev = event_context_init(frame);
352 if (ev == NULL) {
353 goto fail;
355 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
356 workgroup);
357 if (req == NULL) {
358 goto fail;
360 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
361 goto fail;
363 status = cli_session_setup_lanman2_recv(req);
364 fail:
365 TALLOC_FREE(frame);
366 return status;
369 /****************************************************************************
370 Work out suitable capabilities to offer the server.
371 ****************************************************************************/
373 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
375 uint32 capabilities = CAP_NT_SMBS;
377 if (!cli->force_dos_errors)
378 capabilities |= CAP_STATUS32;
380 if (cli->use_level_II_oplocks)
381 capabilities |= CAP_LEVEL_II_OPLOCKS;
383 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
384 return capabilities;
387 /****************************************************************************
388 Do a NT1 guest session setup.
389 ****************************************************************************/
391 struct cli_session_setup_guest_state {
392 struct cli_state *cli;
393 uint16_t vwv[13];
394 struct iovec bytes;
397 static void cli_session_setup_guest_done(struct tevent_req *subreq);
399 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
400 struct event_context *ev,
401 struct cli_state *cli,
402 struct tevent_req **psmbreq)
404 struct tevent_req *req, *subreq;
405 struct cli_session_setup_guest_state *state;
406 uint16_t *vwv;
407 uint8_t *bytes;
409 req = tevent_req_create(mem_ctx, &state,
410 struct cli_session_setup_guest_state);
411 if (req == NULL) {
412 return NULL;
414 state->cli = cli;
415 vwv = state->vwv;
417 SCVAL(vwv+0, 0, 0xFF);
418 SCVAL(vwv+0, 1, 0);
419 SSVAL(vwv+1, 0, 0);
420 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
421 SSVAL(vwv+3, 0, 2);
422 SSVAL(vwv+4, 0, cli->pid);
423 SIVAL(vwv+5, 0, cli->sesskey);
424 SSVAL(vwv+7, 0, 0);
425 SSVAL(vwv+8, 0, 0);
426 SSVAL(vwv+9, 0, 0);
427 SSVAL(vwv+10, 0, 0);
428 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
430 bytes = talloc_array(state, uint8_t, 0);
432 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
433 NULL);
434 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
435 NULL);
436 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
437 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
439 if (bytes == NULL) {
440 TALLOC_FREE(req);
441 return NULL;
444 state->bytes.iov_base = (void *)bytes;
445 state->bytes.iov_len = talloc_get_size(bytes);
447 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
448 1, &state->bytes);
449 if (subreq == NULL) {
450 TALLOC_FREE(req);
451 return NULL;
453 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
454 *psmbreq = subreq;
455 return req;
458 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
459 struct event_context *ev,
460 struct cli_state *cli)
462 struct tevent_req *req, *subreq;
463 NTSTATUS status;
465 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
466 if (req == NULL) {
467 return NULL;
470 status = cli_smb_req_send(subreq);
471 if (NT_STATUS_IS_OK(status)) {
472 tevent_req_nterror(req, status);
473 return tevent_req_post(req, ev);
475 return req;
478 static void cli_session_setup_guest_done(struct tevent_req *subreq)
480 struct tevent_req *req = tevent_req_callback_data(
481 subreq, struct tevent_req);
482 struct cli_session_setup_guest_state *state = tevent_req_data(
483 req, struct cli_session_setup_guest_state);
484 struct cli_state *cli = state->cli;
485 uint32_t num_bytes;
486 uint8_t *in;
487 char *inbuf;
488 uint8_t *bytes;
489 uint8_t *p;
490 NTSTATUS status;
491 ssize_t ret;
492 uint8_t wct;
493 uint16_t *vwv;
495 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
496 &num_bytes, &bytes);
497 TALLOC_FREE(subreq);
498 if (!NT_STATUS_IS_OK(status)) {
499 tevent_req_nterror(req, status);
500 return;
503 inbuf = (char *)in;
504 p = bytes;
506 cli->vuid = SVAL(inbuf, smb_uid);
507 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
509 status = smb_bytes_talloc_string(cli,
510 inbuf,
511 &cli->server_os,
513 bytes+num_bytes-p,
514 &ret);
516 if (!NT_STATUS_IS_OK(status)) {
517 tevent_req_nterror(req, status);
518 return;
520 p += ret;
522 status = smb_bytes_talloc_string(cli,
523 inbuf,
524 &cli->server_type,
526 bytes+num_bytes-p,
527 &ret);
529 if (!NT_STATUS_IS_OK(status)) {
530 tevent_req_nterror(req, status);
531 return;
533 p += ret;
535 status = smb_bytes_talloc_string(cli,
536 inbuf,
537 &cli->server_domain,
539 bytes+num_bytes-p,
540 &ret);
542 if (!NT_STATUS_IS_OK(status)) {
543 tevent_req_nterror(req, status);
544 return;
546 p += ret;
548 if (strstr(cli->server_type, "Samba")) {
549 cli->is_samba = True;
552 status = cli_set_username(cli, "");
553 if (!NT_STATUS_IS_OK(status)) {
554 tevent_req_nterror(req, status);
555 return;
557 tevent_req_done(req);
560 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
562 return tevent_req_simple_recv_ntstatus(req);
565 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
567 TALLOC_CTX *frame = talloc_stackframe();
568 struct event_context *ev;
569 struct tevent_req *req;
570 NTSTATUS status = NT_STATUS_OK;
572 if (cli_has_async_calls(cli)) {
574 * Can't use sync call while an async call is in flight
576 status = NT_STATUS_INVALID_PARAMETER;
577 goto fail;
580 ev = event_context_init(frame);
581 if (ev == NULL) {
582 status = NT_STATUS_NO_MEMORY;
583 goto fail;
586 req = cli_session_setup_guest_send(frame, ev, cli);
587 if (req == NULL) {
588 status = NT_STATUS_NO_MEMORY;
589 goto fail;
592 if (!tevent_req_poll(req, ev)) {
593 status = map_nt_error_from_unix(errno);
594 goto fail;
597 status = cli_session_setup_guest_recv(req);
598 fail:
599 TALLOC_FREE(frame);
600 return status;
603 /****************************************************************************
604 Do a NT1 plaintext session setup.
605 ****************************************************************************/
607 struct cli_session_setup_plain_state {
608 struct cli_state *cli;
609 uint16_t vwv[13];
610 const char *user;
613 static void cli_session_setup_plain_done(struct tevent_req *subreq);
615 static struct tevent_req *cli_session_setup_plain_send(
616 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
617 struct cli_state *cli,
618 const char *user, const char *pass, const char *workgroup)
620 struct tevent_req *req, *subreq;
621 struct cli_session_setup_plain_state *state;
622 uint16_t *vwv;
623 uint8_t *bytes;
624 size_t passlen;
625 char *version;
627 req = tevent_req_create(mem_ctx, &state,
628 struct cli_session_setup_plain_state);
629 if (req == NULL) {
630 return NULL;
632 state->cli = cli;
633 state->user = user;
634 vwv = state->vwv;
636 SCVAL(vwv+0, 0, 0xff);
637 SCVAL(vwv+0, 1, 0);
638 SSVAL(vwv+1, 0, 0);
639 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
640 SSVAL(vwv+3, 0, 2);
641 SSVAL(vwv+4, 0, cli->pid);
642 SIVAL(vwv+5, 0, cli->sesskey);
643 SSVAL(vwv+7, 0, 0);
644 SSVAL(vwv+8, 0, 0);
645 SSVAL(vwv+9, 0, 0);
646 SSVAL(vwv+10, 0, 0);
647 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
649 bytes = talloc_array(state, uint8_t, 0);
650 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
651 &passlen);
652 if (tevent_req_nomem(bytes, req)) {
653 return tevent_req_post(req, ev);
655 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
657 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
658 user, strlen(user)+1, NULL);
659 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
660 workgroup, strlen(workgroup)+1, NULL);
661 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
662 "Unix", 5, NULL);
664 version = talloc_asprintf(talloc_tos(), "Samba %s",
665 samba_version_string());
666 if (tevent_req_nomem(version, req)){
667 return tevent_req_post(req, ev);
669 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
670 version, strlen(version)+1, NULL);
671 TALLOC_FREE(version);
673 if (tevent_req_nomem(bytes, req)) {
674 return tevent_req_post(req, ev);
677 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
678 talloc_get_size(bytes), bytes);
679 if (tevent_req_nomem(subreq, req)) {
680 return tevent_req_post(req, ev);
682 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
683 return req;
686 static void cli_session_setup_plain_done(struct tevent_req *subreq)
688 struct tevent_req *req = tevent_req_callback_data(
689 subreq, struct tevent_req);
690 struct cli_session_setup_plain_state *state = tevent_req_data(
691 req, struct cli_session_setup_plain_state);
692 struct cli_state *cli = state->cli;
693 uint32_t num_bytes;
694 uint8_t *in;
695 char *inbuf;
696 uint8_t *bytes;
697 uint8_t *p;
698 NTSTATUS status;
699 ssize_t ret;
700 uint8_t wct;
701 uint16_t *vwv;
703 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
704 &num_bytes, &bytes);
705 TALLOC_FREE(subreq);
706 if (tevent_req_nterror(req, status)) {
707 return;
710 inbuf = (char *)in;
711 p = bytes;
713 cli->vuid = SVAL(inbuf, smb_uid);
714 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
716 status = smb_bytes_talloc_string(cli,
717 inbuf,
718 &cli->server_os,
720 bytes+num_bytes-p,
721 &ret);
723 if (!NT_STATUS_IS_OK(status)) {
724 tevent_req_nterror(req, status);
725 return;
727 p += ret;
729 status = smb_bytes_talloc_string(cli,
730 inbuf,
731 &cli->server_type,
733 bytes+num_bytes-p,
734 &ret);
736 if (!NT_STATUS_IS_OK(status)) {
737 tevent_req_nterror(req, status);
738 return;
740 p += ret;
742 status = smb_bytes_talloc_string(cli,
743 inbuf,
744 &cli->server_domain,
746 bytes+num_bytes-p,
747 &ret);
749 if (!NT_STATUS_IS_OK(status)) {
750 tevent_req_nterror(req, status);
751 return;
753 p += ret;
755 status = cli_set_username(cli, state->user);
756 if (tevent_req_nterror(req, status)) {
757 return;
759 if (strstr(cli->server_type, "Samba")) {
760 cli->is_samba = True;
762 tevent_req_done(req);
765 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
767 return tevent_req_simple_recv_ntstatus(req);
770 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
771 const char *user, const char *pass,
772 const char *workgroup)
774 TALLOC_CTX *frame = talloc_stackframe();
775 struct event_context *ev;
776 struct tevent_req *req;
777 NTSTATUS status = NT_STATUS_NO_MEMORY;
779 if (cli_has_async_calls(cli)) {
781 * Can't use sync call while an async call is in flight
783 status = NT_STATUS_INVALID_PARAMETER;
784 goto fail;
786 ev = event_context_init(frame);
787 if (ev == NULL) {
788 goto fail;
790 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
791 workgroup);
792 if (req == NULL) {
793 goto fail;
795 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
796 goto fail;
798 status = cli_session_setup_plain_recv(req);
799 fail:
800 TALLOC_FREE(frame);
801 return status;
804 /****************************************************************************
805 do a NT1 NTLM/LM encrypted session setup - for when extended security
806 is not negotiated.
807 @param cli client state to create do session setup on
808 @param user username
809 @param pass *either* cleartext password (passlen !=24) or LM response.
810 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
811 @param workgroup The user's domain.
812 ****************************************************************************/
814 struct cli_session_setup_nt1_state {
815 struct cli_state *cli;
816 uint16_t vwv[13];
817 DATA_BLOB response;
818 DATA_BLOB session_key;
819 const char *user;
822 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
824 static struct tevent_req *cli_session_setup_nt1_send(
825 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
826 struct cli_state *cli, const char *user,
827 const char *pass, size_t passlen,
828 const char *ntpass, size_t ntpasslen,
829 const char *workgroup)
831 struct tevent_req *req, *subreq;
832 struct cli_session_setup_nt1_state *state;
833 DATA_BLOB lm_response = data_blob_null;
834 DATA_BLOB nt_response = data_blob_null;
835 DATA_BLOB session_key = data_blob_null;
836 uint16_t *vwv;
837 uint8_t *bytes;
838 char *workgroup_upper;
840 req = tevent_req_create(mem_ctx, &state,
841 struct cli_session_setup_nt1_state);
842 if (req == NULL) {
843 return NULL;
845 state->cli = cli;
846 state->user = user;
847 vwv = state->vwv;
849 if (passlen == 0) {
850 /* do nothing - guest login */
851 } else if (passlen != 24) {
852 if (lp_client_ntlmv2_auth()) {
853 DATA_BLOB server_chal;
854 DATA_BLOB names_blob;
856 server_chal = data_blob(cli->secblob.data,
857 MIN(cli->secblob.length, 8));
858 if (tevent_req_nomem(server_chal.data, req)) {
859 return tevent_req_post(req, ev);
863 * note that the 'workgroup' here is a best
864 * guess - we don't know the server's domain
865 * at this point. The 'server name' is also
866 * dodgy...
868 names_blob = NTLMv2_generate_names_blob(
869 NULL, cli->called.name, workgroup);
871 if (tevent_req_nomem(names_blob.data, req)) {
872 return tevent_req_post(req, ev);
875 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
876 &server_chal, &names_blob,
877 &lm_response, &nt_response,
878 NULL, &session_key)) {
879 data_blob_free(&names_blob);
880 data_blob_free(&server_chal);
881 tevent_req_nterror(
882 req, NT_STATUS_ACCESS_DENIED);
883 return tevent_req_post(req, ev);
885 data_blob_free(&names_blob);
886 data_blob_free(&server_chal);
888 } else {
889 uchar nt_hash[16];
890 E_md4hash(pass, nt_hash);
892 #ifdef LANMAN_ONLY
893 nt_response = data_blob_null;
894 #else
895 nt_response = data_blob(NULL, 24);
896 if (tevent_req_nomem(nt_response.data, req)) {
897 return tevent_req_post(req, ev);
900 SMBNTencrypt(pass, cli->secblob.data,
901 nt_response.data);
902 #endif
903 /* non encrypted password supplied. Ignore ntpass. */
904 if (lp_client_lanman_auth()) {
906 lm_response = data_blob(NULL, 24);
907 if (tevent_req_nomem(lm_response.data, req)) {
908 return tevent_req_post(req, ev);
911 if (!SMBencrypt(pass,cli->secblob.data,
912 lm_response.data)) {
914 * Oops, the LM response is
915 * invalid, just put the NT
916 * response there instead
918 data_blob_free(&lm_response);
919 lm_response = data_blob(
920 nt_response.data,
921 nt_response.length);
923 } else {
925 * LM disabled, place NT# in LM field
926 * instead
928 lm_response = data_blob(
929 nt_response.data, nt_response.length);
932 if (tevent_req_nomem(lm_response.data, req)) {
933 return tevent_req_post(req, ev);
936 session_key = data_blob(NULL, 16);
937 if (tevent_req_nomem(session_key.data, req)) {
938 return tevent_req_post(req, ev);
940 #ifdef LANMAN_ONLY
941 E_deshash(pass, session_key.data);
942 memset(&session_key.data[8], '\0', 8);
943 #else
944 SMBsesskeygen_ntv1(nt_hash, session_key.data);
945 #endif
947 cli_temp_set_signing(cli);
948 } else {
949 /* pre-encrypted password supplied. Only used for
950 security=server, can't do
951 signing because we don't have original key */
953 lm_response = data_blob(pass, passlen);
954 if (tevent_req_nomem(lm_response.data, req)) {
955 return tevent_req_post(req, ev);
958 nt_response = data_blob(ntpass, ntpasslen);
959 if (tevent_req_nomem(nt_response.data, req)) {
960 return tevent_req_post(req, ev);
964 #ifdef LANMAN_ONLY
965 state->response = data_blob_talloc(
966 state, lm_response.data, lm_response.length);
967 #else
968 state->response = data_blob_talloc(
969 state, nt_response.data, nt_response.length);
970 #endif
971 if (tevent_req_nomem(state->response.data, req)) {
972 return tevent_req_post(req, ev);
975 if (session_key.data) {
976 state->session_key = data_blob_talloc(
977 state, session_key.data, session_key.length);
978 if (tevent_req_nomem(state->session_key.data, req)) {
979 return tevent_req_post(req, ev);
982 data_blob_free(&session_key);
984 SCVAL(vwv+0, 0, 0xff);
985 SCVAL(vwv+0, 1, 0);
986 SSVAL(vwv+1, 0, 0);
987 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
988 SSVAL(vwv+3, 0, 2);
989 SSVAL(vwv+4, 0, cli->pid);
990 SIVAL(vwv+5, 0, cli->sesskey);
991 SSVAL(vwv+7, 0, lm_response.length);
992 SSVAL(vwv+8, 0, nt_response.length);
993 SSVAL(vwv+9, 0, 0);
994 SSVAL(vwv+10, 0, 0);
995 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
997 bytes = talloc_array(state, uint8_t,
998 lm_response.length + nt_response.length);
999 if (tevent_req_nomem(bytes, req)) {
1000 return tevent_req_post(req, ev);
1002 if (lm_response.length != 0) {
1003 memcpy(bytes, lm_response.data, lm_response.length);
1005 if (nt_response.length != 0) {
1006 memcpy(bytes + lm_response.length,
1007 nt_response.data, nt_response.length);
1009 data_blob_free(&lm_response);
1010 data_blob_free(&nt_response);
1012 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1013 user, strlen(user)+1, NULL);
1016 * Upper case here might help some NTLMv2 implementations
1018 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
1019 if (tevent_req_nomem(workgroup_upper, req)) {
1020 return tevent_req_post(req, ev);
1022 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1023 workgroup_upper, strlen(workgroup_upper)+1,
1024 NULL);
1025 TALLOC_FREE(workgroup_upper);
1027 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
1028 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
1029 if (tevent_req_nomem(bytes, req)) {
1030 return tevent_req_post(req, ev);
1033 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1034 talloc_get_size(bytes), bytes);
1035 if (tevent_req_nomem(subreq, req)) {
1036 return tevent_req_post(req, ev);
1038 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1039 return req;
1042 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1044 struct tevent_req *req = tevent_req_callback_data(
1045 subreq, struct tevent_req);
1046 struct cli_session_setup_nt1_state *state = tevent_req_data(
1047 req, struct cli_session_setup_nt1_state);
1048 struct cli_state *cli = state->cli;
1049 uint32_t num_bytes;
1050 uint8_t *in;
1051 char *inbuf;
1052 uint8_t *bytes;
1053 uint8_t *p;
1054 NTSTATUS status;
1055 ssize_t ret;
1056 uint8_t wct;
1057 uint16_t *vwv;
1059 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
1060 &num_bytes, &bytes);
1061 TALLOC_FREE(subreq);
1062 if (!NT_STATUS_IS_OK(status)) {
1063 tevent_req_nterror(req, status);
1064 return;
1067 inbuf = (char *)in;
1068 p = bytes;
1070 cli->vuid = SVAL(inbuf, smb_uid);
1071 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1073 status = smb_bytes_talloc_string(cli,
1074 inbuf,
1075 &cli->server_os,
1077 bytes+num_bytes-p,
1078 &ret);
1079 if (!NT_STATUS_IS_OK(status)) {
1080 tevent_req_nterror(req, status);
1081 return;
1083 p += ret;
1085 status = smb_bytes_talloc_string(cli,
1086 inbuf,
1087 &cli->server_type,
1089 bytes+num_bytes-p,
1090 &ret);
1091 if (!NT_STATUS_IS_OK(status)) {
1092 tevent_req_nterror(req, status);
1093 return;
1095 p += ret;
1097 status = smb_bytes_talloc_string(cli,
1098 inbuf,
1099 &cli->server_domain,
1101 bytes+num_bytes-p,
1102 &ret);
1103 if (!NT_STATUS_IS_OK(status)) {
1104 tevent_req_nterror(req, status);
1105 return;
1107 p += ret;
1109 if (strstr(cli->server_type, "Samba")) {
1110 cli->is_samba = True;
1113 status = cli_set_username(cli, state->user);
1114 if (tevent_req_nterror(req, status)) {
1115 return;
1117 if (cli_simple_set_signing(cli, state->session_key, state->response)
1118 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1119 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1120 return;
1122 if (state->session_key.data) {
1123 /* Have plaintext orginal */
1124 cli_set_session_key(cli, state->session_key);
1126 tevent_req_done(req);
1129 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1131 return tevent_req_simple_recv_ntstatus(req);
1134 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1135 const char *pass, size_t passlen,
1136 const char *ntpass, size_t ntpasslen,
1137 const char *workgroup)
1139 TALLOC_CTX *frame = talloc_stackframe();
1140 struct event_context *ev;
1141 struct tevent_req *req;
1142 NTSTATUS status = NT_STATUS_NO_MEMORY;
1144 if (cli_has_async_calls(cli)) {
1146 * Can't use sync call while an async call is in flight
1148 status = NT_STATUS_INVALID_PARAMETER;
1149 goto fail;
1151 ev = event_context_init(frame);
1152 if (ev == NULL) {
1153 goto fail;
1155 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1156 ntpass, ntpasslen, workgroup);
1157 if (req == NULL) {
1158 goto fail;
1160 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1161 goto fail;
1163 status = cli_session_setup_nt1_recv(req);
1164 fail:
1165 TALLOC_FREE(frame);
1166 return status;
1169 /* The following is calculated from :
1170 * (smb_size-4) = 35
1171 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1172 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1173 * end of packet.
1176 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1178 struct cli_sesssetup_blob_state {
1179 struct tevent_context *ev;
1180 struct cli_state *cli;
1181 DATA_BLOB blob;
1182 uint16_t max_blob_size;
1183 uint16_t vwv[12];
1184 uint8_t *buf;
1186 NTSTATUS status;
1187 char *inbuf;
1188 DATA_BLOB ret_blob;
1191 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1192 struct tevent_req **psubreq);
1193 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1195 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1196 struct tevent_context *ev,
1197 struct cli_state *cli,
1198 DATA_BLOB blob)
1200 struct tevent_req *req, *subreq;
1201 struct cli_sesssetup_blob_state *state;
1203 req = tevent_req_create(mem_ctx, &state,
1204 struct cli_sesssetup_blob_state);
1205 if (req == NULL) {
1206 return NULL;
1208 state->ev = ev;
1209 state->blob = blob;
1210 state->cli = cli;
1212 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
1213 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1214 "(was %u, need minimum %u)\n",
1215 (unsigned int)cli->max_xmit,
1216 BASE_SESSSETUP_BLOB_PACKET_SIZE));
1217 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1218 return tevent_req_post(req, ev);
1220 state->max_blob_size =
1221 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
1223 if (!cli_sesssetup_blob_next(state, &subreq)) {
1224 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1225 return tevent_req_post(req, ev);
1227 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1228 return req;
1231 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1232 struct tevent_req **psubreq)
1234 struct tevent_req *subreq;
1235 uint16_t thistime;
1237 SCVAL(state->vwv+0, 0, 0xFF);
1238 SCVAL(state->vwv+0, 1, 0);
1239 SSVAL(state->vwv+1, 0, 0);
1240 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1241 SSVAL(state->vwv+3, 0, 2);
1242 SSVAL(state->vwv+4, 0, 1);
1243 SIVAL(state->vwv+5, 0, 0);
1245 thistime = MIN(state->blob.length, state->max_blob_size);
1246 SSVAL(state->vwv+7, 0, thistime);
1248 SSVAL(state->vwv+8, 0, 0);
1249 SSVAL(state->vwv+9, 0, 0);
1250 SIVAL(state->vwv+10, 0,
1251 cli_session_setup_capabilities(state->cli)
1252 | CAP_EXTENDED_SECURITY);
1254 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1255 thistime);
1256 if (state->buf == NULL) {
1257 return false;
1259 state->blob.data += thistime;
1260 state->blob.length -= thistime;
1262 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1263 "Unix", 5, NULL);
1264 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1265 "Samba", 6, NULL);
1266 if (state->buf == NULL) {
1267 return false;
1269 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1270 12, state->vwv,
1271 talloc_get_size(state->buf), state->buf);
1272 if (subreq == NULL) {
1273 return false;
1275 *psubreq = subreq;
1276 return true;
1279 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1281 struct tevent_req *req = tevent_req_callback_data(
1282 subreq, struct tevent_req);
1283 struct cli_sesssetup_blob_state *state = tevent_req_data(
1284 req, struct cli_sesssetup_blob_state);
1285 struct cli_state *cli = state->cli;
1286 uint8_t wct;
1287 uint16_t *vwv;
1288 uint32_t num_bytes;
1289 uint8_t *bytes;
1290 NTSTATUS status;
1291 uint8_t *p;
1292 uint16_t blob_length;
1293 uint8_t *inbuf;
1294 ssize_t ret;
1296 status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
1297 &num_bytes, &bytes);
1298 TALLOC_FREE(subreq);
1299 if (!NT_STATUS_IS_OK(status)
1300 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1301 tevent_req_nterror(req, status);
1302 return;
1305 state->status = status;
1306 TALLOC_FREE(state->buf);
1308 state->inbuf = (char *)inbuf;
1309 cli->vuid = SVAL(state->inbuf, smb_uid);
1310 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1312 blob_length = SVAL(vwv+3, 0);
1313 if (blob_length > num_bytes) {
1314 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1315 return;
1317 state->ret_blob = data_blob_const(bytes, blob_length);
1319 p = bytes + blob_length;
1321 status = smb_bytes_talloc_string(cli,
1322 (char *)inbuf,
1323 &cli->server_os,
1325 bytes+num_bytes-p,
1326 &ret);
1328 if (!NT_STATUS_IS_OK(status)) {
1329 tevent_req_nterror(req, status);
1330 return;
1332 p += ret;
1334 status = smb_bytes_talloc_string(cli,
1335 (char *)inbuf,
1336 &cli->server_type,
1338 bytes+num_bytes-p,
1339 &ret);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 tevent_req_nterror(req, status);
1343 return;
1345 p += ret;
1347 status = smb_bytes_talloc_string(cli,
1348 (char *)inbuf,
1349 &cli->server_domain,
1351 bytes+num_bytes-p,
1352 &ret);
1354 if (!NT_STATUS_IS_OK(status)) {
1355 tevent_req_nterror(req, status);
1356 return;
1358 p += ret;
1360 if (strstr(cli->server_type, "Samba")) {
1361 cli->is_samba = True;
1364 if (state->blob.length != 0) {
1366 * More to send
1368 if (!cli_sesssetup_blob_next(state, &subreq)) {
1369 tevent_req_nomem(NULL, req);
1370 return;
1372 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1373 return;
1375 tevent_req_done(req);
1378 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1379 TALLOC_CTX *mem_ctx,
1380 DATA_BLOB *pblob,
1381 char **pinbuf)
1383 struct cli_sesssetup_blob_state *state = tevent_req_data(
1384 req, struct cli_sesssetup_blob_state);
1385 NTSTATUS status;
1386 char *inbuf;
1388 if (tevent_req_is_nterror(req, &status)) {
1389 state->cli->vuid = 0;
1390 return status;
1393 inbuf = talloc_move(mem_ctx, &state->inbuf);
1394 if (pblob != NULL) {
1395 *pblob = state->ret_blob;
1397 if (pinbuf != NULL) {
1398 *pinbuf = inbuf;
1400 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1401 return state->status;
1404 #ifdef HAVE_KRB5
1406 /****************************************************************************
1407 Use in-memory credentials cache
1408 ****************************************************************************/
1410 static void use_in_memory_ccache(void) {
1411 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1414 /****************************************************************************
1415 Do a spnego/kerberos encrypted session setup.
1416 ****************************************************************************/
1418 struct cli_session_setup_kerberos_state {
1419 struct cli_state *cli;
1420 DATA_BLOB negTokenTarg;
1421 DATA_BLOB session_key_krb5;
1422 ADS_STATUS ads_status;
1425 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1427 static struct tevent_req *cli_session_setup_kerberos_send(
1428 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1429 const char *principal, const char *workgroup)
1431 struct tevent_req *req, *subreq;
1432 struct cli_session_setup_kerberos_state *state;
1433 int rc;
1435 DEBUG(2,("Doing kerberos session setup\n"));
1437 req = tevent_req_create(mem_ctx, &state,
1438 struct cli_session_setup_kerberos_state);
1439 if (req == NULL) {
1440 return NULL;
1442 state->cli = cli;
1443 state->ads_status = ADS_SUCCESS;
1445 cli_temp_set_signing(cli);
1448 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1449 * we have to acquire a ticket. To be fixed later :-)
1451 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1452 &state->session_key_krb5, 0, NULL);
1453 if (rc) {
1454 DEBUG(1, ("cli_session_setup_kerberos: "
1455 "spnego_gen_krb5_negTokenInit failed: %s\n",
1456 error_message(rc)));
1457 state->ads_status = ADS_ERROR_KRB5(rc);
1458 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1459 return tevent_req_post(req, ev);
1462 #if 0
1463 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1464 state->negTokenTarg.length);
1465 #endif
1467 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1468 if (tevent_req_nomem(subreq, req)) {
1469 return tevent_req_post(req, ev);
1471 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1472 return req;
1475 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1477 struct tevent_req *req = tevent_req_callback_data(
1478 subreq, struct tevent_req);
1479 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1480 req, struct cli_session_setup_kerberos_state);
1481 char *inbuf = NULL;
1482 NTSTATUS status;
1484 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
1485 if (!NT_STATUS_IS_OK(status)) {
1486 TALLOC_FREE(subreq);
1487 tevent_req_nterror(req, status);
1488 return;
1491 cli_set_session_key(state->cli, state->session_key_krb5);
1493 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
1494 data_blob_null)
1495 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1496 TALLOC_FREE(subreq);
1497 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1498 return;
1500 TALLOC_FREE(subreq);
1501 tevent_req_done(req);
1504 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1506 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1507 req, struct cli_session_setup_kerberos_state);
1508 NTSTATUS status;
1510 if (tevent_req_is_nterror(req, &status)) {
1511 return ADS_ERROR_NT(status);
1513 return state->ads_status;
1516 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1517 const char *principal,
1518 const char *workgroup)
1520 struct tevent_context *ev;
1521 struct tevent_req *req;
1522 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1524 if (cli_has_async_calls(cli)) {
1525 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1527 ev = tevent_context_init(talloc_tos());
1528 if (ev == NULL) {
1529 goto fail;
1531 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
1532 workgroup);
1533 if (req == NULL) {
1534 goto fail;
1536 if (!tevent_req_poll(req, ev)) {
1537 status = ADS_ERROR_SYSTEM(errno);
1538 goto fail;
1540 status = cli_session_setup_kerberos_recv(req);
1541 fail:
1542 TALLOC_FREE(ev);
1543 return status;
1545 #endif /* HAVE_KRB5 */
1547 /****************************************************************************
1548 Do a spnego/NTLMSSP encrypted session setup.
1549 ****************************************************************************/
1551 struct cli_session_setup_ntlmssp_state {
1552 struct tevent_context *ev;
1553 struct cli_state *cli;
1554 struct ntlmssp_state *ntlmssp_state;
1555 int turn;
1556 DATA_BLOB blob_out;
1559 static int cli_session_setup_ntlmssp_state_destructor(
1560 struct cli_session_setup_ntlmssp_state *state)
1562 if (state->ntlmssp_state != NULL) {
1563 TALLOC_FREE(state->ntlmssp_state);
1565 return 0;
1568 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1570 static struct tevent_req *cli_session_setup_ntlmssp_send(
1571 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1572 const char *user, const char *pass, const char *domain)
1574 struct tevent_req *req, *subreq;
1575 struct cli_session_setup_ntlmssp_state *state;
1576 NTSTATUS status;
1577 DATA_BLOB blob_out;
1578 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1580 req = tevent_req_create(mem_ctx, &state,
1581 struct cli_session_setup_ntlmssp_state);
1582 if (req == NULL) {
1583 return NULL;
1585 state->ev = ev;
1586 state->cli = cli;
1587 state->turn = 1;
1589 state->ntlmssp_state = NULL;
1590 talloc_set_destructor(
1591 state, cli_session_setup_ntlmssp_state_destructor);
1593 cli_temp_set_signing(cli);
1595 status = ntlmssp_client_start(state,
1596 global_myname(),
1597 lp_workgroup(),
1598 lp_client_ntlmv2_auth(),
1599 &state->ntlmssp_state);
1600 if (!NT_STATUS_IS_OK(status)) {
1601 goto fail;
1603 ntlmssp_want_feature(state->ntlmssp_state,
1604 NTLMSSP_FEATURE_SESSION_KEY);
1605 if (cli->use_ccache) {
1606 ntlmssp_want_feature(state->ntlmssp_state,
1607 NTLMSSP_FEATURE_CCACHE);
1609 status = ntlmssp_set_username(state->ntlmssp_state, user);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 goto fail;
1613 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 goto fail;
1617 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1618 if (!NT_STATUS_IS_OK(status)) {
1619 goto fail;
1621 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1622 &blob_out);
1623 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1624 goto fail;
1627 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1628 data_blob_free(&blob_out);
1630 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1631 if (tevent_req_nomem(subreq, req)) {
1632 return tevent_req_post(req, ev);
1634 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1635 return req;
1636 fail:
1637 tevent_req_nterror(req, status);
1638 return tevent_req_post(req, ev);
1641 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1643 struct tevent_req *req = tevent_req_callback_data(
1644 subreq, struct tevent_req);
1645 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1646 req, struct cli_session_setup_ntlmssp_state);
1647 DATA_BLOB blob_in, msg_in, blob_out;
1648 char *inbuf = NULL;
1649 bool parse_ret;
1650 NTSTATUS status;
1652 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1653 &inbuf);
1654 TALLOC_FREE(subreq);
1655 data_blob_free(&state->blob_out);
1657 if (NT_STATUS_IS_OK(status)) {
1658 if (state->cli->server_domain[0] == '\0') {
1659 TALLOC_FREE(state->cli->server_domain);
1660 state->cli->server_domain = talloc_strdup(state->cli,
1661 state->ntlmssp_state->server.netbios_domain);
1662 if (state->cli->server_domain == NULL) {
1663 TALLOC_FREE(subreq);
1664 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1665 return;
1668 cli_set_session_key(
1669 state->cli, state->ntlmssp_state->session_key);
1671 if (cli_simple_set_signing(
1672 state->cli, state->ntlmssp_state->session_key,
1673 data_blob_null)
1674 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1675 TALLOC_FREE(subreq);
1676 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1677 return;
1679 TALLOC_FREE(subreq);
1680 TALLOC_FREE(state->ntlmssp_state);
1681 tevent_req_done(req);
1682 return;
1684 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1685 tevent_req_nterror(req, status);
1686 return;
1689 if (blob_in.length == 0) {
1690 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1691 return;
1694 if ((state->turn == 1)
1695 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1696 DATA_BLOB tmp_blob = data_blob_null;
1697 /* the server might give us back two challenges */
1698 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1699 &tmp_blob);
1700 data_blob_free(&tmp_blob);
1701 } else {
1702 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1703 OID_NTLMSSP, &msg_in);
1705 state->turn += 1;
1707 if (!parse_ret) {
1708 DEBUG(3,("Failed to parse auth response\n"));
1709 if (NT_STATUS_IS_OK(status)
1710 || NT_STATUS_EQUAL(status,
1711 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1712 tevent_req_nterror(
1713 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1714 return;
1718 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1720 if (!NT_STATUS_IS_OK(status)
1721 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1722 TALLOC_FREE(subreq);
1723 TALLOC_FREE(state->ntlmssp_state);
1724 tevent_req_nterror(req, status);
1725 return;
1728 state->blob_out = spnego_gen_auth(state, blob_out);
1729 TALLOC_FREE(subreq);
1730 if (tevent_req_nomem(state->blob_out.data, req)) {
1731 return;
1734 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1735 state->blob_out);
1736 if (tevent_req_nomem(subreq, req)) {
1737 return;
1739 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1742 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1744 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1745 req, struct cli_session_setup_ntlmssp_state);
1746 NTSTATUS status;
1748 if (tevent_req_is_nterror(req, &status)) {
1749 state->cli->vuid = 0;
1750 return status;
1752 return NT_STATUS_OK;
1755 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1756 const char *user,
1757 const char *pass,
1758 const char *domain)
1760 struct tevent_context *ev;
1761 struct tevent_req *req;
1762 NTSTATUS status = NT_STATUS_NO_MEMORY;
1764 if (cli_has_async_calls(cli)) {
1765 return NT_STATUS_INVALID_PARAMETER;
1767 ev = tevent_context_init(talloc_tos());
1768 if (ev == NULL) {
1769 goto fail;
1771 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1772 if (req == NULL) {
1773 goto fail;
1775 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1776 goto fail;
1778 status = cli_session_setup_ntlmssp_recv(req);
1779 fail:
1780 TALLOC_FREE(ev);
1781 return status;
1784 /****************************************************************************
1785 Do a spnego encrypted session setup.
1787 user_domain: The shortname of the domain the user/machine is a member of.
1788 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1789 ****************************************************************************/
1791 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1792 const char *pass, const char *user_domain,
1793 const char * dest_realm)
1795 char *principal = NULL;
1796 char *OIDs[ASN1_MAX_OIDS];
1797 int i;
1798 DATA_BLOB blob;
1799 const char *p = NULL;
1800 char *account = NULL;
1801 NTSTATUS status;
1803 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1805 /* the server might not even do spnego */
1806 if (cli->secblob.length <= 16) {
1807 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1808 goto ntlmssp;
1811 #if 0
1812 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1813 #endif
1815 /* there is 16 bytes of GUID before the real spnego packet starts */
1816 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1818 /* The server sent us the first part of the SPNEGO exchange in the
1819 * negprot reply. It is WRONG to depend on the principal sent in the
1820 * negprot reply, but right now we do it. If we don't receive one,
1821 * we try to best guess, then fall back to NTLM. */
1822 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1823 OIDs[0] == NULL) {
1824 data_blob_free(&blob);
1825 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1827 data_blob_free(&blob);
1829 /* make sure the server understands kerberos */
1830 for (i=0;OIDs[i];i++) {
1831 if (i == 0)
1832 DEBUG(3,("got OID=%s\n", OIDs[i]));
1833 else
1834 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1835 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1836 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1837 cli->got_kerberos_mechanism = True;
1839 talloc_free(OIDs[i]);
1842 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1844 status = cli_set_username(cli, user);
1845 if (!NT_STATUS_IS_OK(status)) {
1846 TALLOC_FREE(principal);
1847 return ADS_ERROR_NT(status);
1850 #ifdef HAVE_KRB5
1851 /* If password is set we reauthenticate to kerberos server
1852 * and do not store results */
1854 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1855 ADS_STATUS rc;
1857 if (pass && *pass) {
1858 int ret;
1860 use_in_memory_ccache();
1861 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1863 if (ret){
1864 TALLOC_FREE(principal);
1865 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1866 if (cli->fallback_after_kerberos)
1867 goto ntlmssp;
1868 return ADS_ERROR_KRB5(ret);
1872 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1874 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1875 TALLOC_FREE(principal);
1878 if (principal == NULL &&
1879 !is_ipaddress(cli->desthost) &&
1880 !strequal(STAR_SMBSERVER,
1881 cli->desthost)) {
1882 char *realm = NULL;
1883 char *host = NULL;
1884 DEBUG(3,("cli_session_setup_spnego: using target "
1885 "hostname not SPNEGO principal\n"));
1887 host = strchr_m(cli->desthost, '.');
1888 if (dest_realm) {
1889 realm = SMB_STRDUP(dest_realm);
1890 if (!realm) {
1891 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1893 strupper_m(realm);
1894 } else {
1895 if (host) {
1896 /* DNS name. */
1897 realm = kerberos_get_realm_from_hostname(cli->desthost);
1898 } else {
1899 /* NetBIOS name - use our realm. */
1900 realm = kerberos_get_default_realm_from_ccache();
1904 if (realm == NULL || *realm == '\0') {
1905 realm = SMB_STRDUP(lp_realm());
1906 if (!realm) {
1907 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1909 strupper_m(realm);
1910 DEBUG(3,("cli_session_setup_spnego: cannot "
1911 "get realm from dest_realm %s, "
1912 "desthost %s. Using default "
1913 "smb.conf realm %s\n",
1914 dest_realm ? dest_realm : "<null>",
1915 cli->desthost,
1916 realm));
1919 principal = talloc_asprintf(talloc_tos(),
1920 "cifs/%s@%s",
1921 cli->desthost,
1922 realm);
1923 if (!principal) {
1924 SAFE_FREE(realm);
1925 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1927 DEBUG(3,("cli_session_setup_spnego: guessed "
1928 "server principal=%s\n",
1929 principal ? principal : "<null>"));
1931 SAFE_FREE(realm);
1934 if (principal) {
1935 rc = cli_session_setup_kerberos(cli, principal,
1936 dest_realm);
1937 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1938 TALLOC_FREE(principal);
1939 return rc;
1943 #endif
1945 TALLOC_FREE(principal);
1947 ntlmssp:
1949 account = talloc_strdup(talloc_tos(), user);
1950 if (!account) {
1951 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1954 /* when falling back to ntlmssp while authenticating with a machine
1955 * account strip off the realm - gd */
1957 if ((p = strchr_m(user, '@')) != NULL) {
1958 account[PTR_DIFF(p,user)] = '\0';
1961 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1964 /****************************************************************************
1965 Send a session setup. The username and workgroup is in UNIX character
1966 format and must be converted to DOS codepage format before sending. If the
1967 password is in plaintext, the same should be done.
1968 ****************************************************************************/
1970 NTSTATUS cli_session_setup(struct cli_state *cli,
1971 const char *user,
1972 const char *pass, int passlen,
1973 const char *ntpass, int ntpasslen,
1974 const char *workgroup)
1976 char *p;
1977 char *user2;
1979 if (user) {
1980 user2 = talloc_strdup(talloc_tos(), user);
1981 } else {
1982 user2 = talloc_strdup(talloc_tos(), "");
1984 if (user2 == NULL) {
1985 return NT_STATUS_NO_MEMORY;
1988 if (!workgroup) {
1989 workgroup = "";
1992 /* allow for workgroups as part of the username */
1993 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1994 (p=strchr_m(user2,*lp_winbind_separator()))) {
1995 *p = 0;
1996 user = p+1;
1997 strupper_m(user2);
1998 workgroup = user2;
2001 if (cli->protocol < PROTOCOL_LANMAN1) {
2003 * Ensure cli->server_domain,
2004 * cli->server_os and cli->server_type
2005 * are valid pointers.
2007 cli->server_domain = talloc_strdup(cli, "");
2008 cli->server_os = talloc_strdup(cli, "");
2009 cli->server_type = talloc_strdup(cli, "");
2010 if (cli->server_domain == NULL ||
2011 cli->server_os == NULL ||
2012 cli->server_type == NULL) {
2013 return NT_STATUS_NO_MEMORY;
2015 return NT_STATUS_OK;
2018 /* now work out what sort of session setup we are going to
2019 do. I have split this into separate functions to make the
2020 flow a bit easier to understand (tridge) */
2022 /* if its an older server then we have to use the older request format */
2024 if (cli->protocol < PROTOCOL_NT1) {
2025 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2026 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2027 " or 'client ntlmv2 auth = yes'\n"));
2028 return NT_STATUS_ACCESS_DENIED;
2031 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2032 !lp_client_plaintext_auth() && (*pass)) {
2033 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2034 " or 'client ntlmv2 auth = yes'\n"));
2035 return NT_STATUS_ACCESS_DENIED;
2038 return cli_session_setup_lanman2(cli, user, pass, passlen,
2039 workgroup);
2042 /* if no user is supplied then we have to do an anonymous connection.
2043 passwords are ignored */
2045 if (!user || !*user)
2046 return cli_session_setup_guest(cli);
2048 /* if the server is share level then send a plaintext null
2049 password at this point. The password is sent in the tree
2050 connect */
2052 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2053 return cli_session_setup_plain(cli, user, "", workgroup);
2055 /* if the server doesn't support encryption then we have to use
2056 plaintext. The second password is ignored */
2058 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2059 if (!lp_client_plaintext_auth() && (*pass)) {
2060 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2061 " or 'client ntlmv2 auth = yes'\n"));
2062 return NT_STATUS_ACCESS_DENIED;
2064 return cli_session_setup_plain(cli, user, pass, workgroup);
2067 /* if the server supports extended security then use SPNEGO */
2069 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
2070 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2071 workgroup, NULL);
2072 if (!ADS_ERR_OK(status)) {
2073 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2074 return ads_ntstatus(status);
2076 } else {
2077 NTSTATUS status;
2079 /* otherwise do a NT1 style session setup */
2080 status = cli_session_setup_nt1(cli, user, pass, passlen,
2081 ntpass, ntpasslen, workgroup);
2082 if (!NT_STATUS_IS_OK(status)) {
2083 DEBUG(3,("cli_session_setup: NT1 session setup "
2084 "failed: %s\n", nt_errstr(status)));
2085 return status;
2089 if (strstr(cli->server_type, "Samba")) {
2090 cli->is_samba = True;
2093 return NT_STATUS_OK;
2096 /****************************************************************************
2097 Send a uloggoff.
2098 *****************************************************************************/
2100 struct cli_ulogoff_state {
2101 struct cli_state *cli;
2102 uint16_t vwv[3];
2105 static void cli_ulogoff_done(struct tevent_req *subreq);
2107 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2108 struct tevent_context *ev,
2109 struct cli_state *cli)
2111 struct tevent_req *req, *subreq;
2112 struct cli_ulogoff_state *state;
2114 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2115 if (req == NULL) {
2116 return NULL;
2118 state->cli = cli;
2120 SCVAL(state->vwv+0, 0, 0xFF);
2121 SCVAL(state->vwv+1, 0, 0);
2122 SSVAL(state->vwv+2, 0, 0);
2124 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2125 0, NULL);
2126 if (tevent_req_nomem(subreq, req)) {
2127 return tevent_req_post(req, ev);
2129 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2130 return req;
2133 static void cli_ulogoff_done(struct tevent_req *subreq)
2135 struct tevent_req *req = tevent_req_callback_data(
2136 subreq, struct tevent_req);
2137 struct cli_ulogoff_state *state = tevent_req_data(
2138 req, struct cli_ulogoff_state);
2139 NTSTATUS status;
2141 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2142 if (!NT_STATUS_IS_OK(status)) {
2143 tevent_req_nterror(req, status);
2144 return;
2146 state->cli->vuid = -1;
2147 tevent_req_done(req);
2150 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2152 return tevent_req_simple_recv_ntstatus(req);
2155 NTSTATUS cli_ulogoff(struct cli_state *cli)
2157 struct tevent_context *ev;
2158 struct tevent_req *req;
2159 NTSTATUS status = NT_STATUS_NO_MEMORY;
2161 if (cli_has_async_calls(cli)) {
2162 return NT_STATUS_INVALID_PARAMETER;
2164 ev = tevent_context_init(talloc_tos());
2165 if (ev == NULL) {
2166 goto fail;
2168 req = cli_ulogoff_send(ev, ev, cli);
2169 if (req == NULL) {
2170 goto fail;
2172 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2173 goto fail;
2175 status = cli_ulogoff_recv(req);
2176 fail:
2177 TALLOC_FREE(ev);
2178 return status;
2181 /****************************************************************************
2182 Send a tconX.
2183 ****************************************************************************/
2185 struct cli_tcon_andx_state {
2186 struct cli_state *cli;
2187 uint16_t vwv[4];
2188 struct iovec bytes;
2191 static void cli_tcon_andx_done(struct tevent_req *subreq);
2193 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2194 struct event_context *ev,
2195 struct cli_state *cli,
2196 const char *share, const char *dev,
2197 const char *pass, int passlen,
2198 struct tevent_req **psmbreq)
2200 struct tevent_req *req, *subreq;
2201 struct cli_tcon_andx_state *state;
2202 uint8_t p24[24];
2203 uint16_t *vwv;
2204 char *tmp = NULL;
2205 uint8_t *bytes;
2207 *psmbreq = NULL;
2209 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2210 if (req == NULL) {
2211 return NULL;
2213 state->cli = cli;
2214 vwv = state->vwv;
2216 cli->share = talloc_strdup(cli, share);
2217 if (!cli->share) {
2218 return NULL;
2221 /* in user level security don't send a password now */
2222 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2223 passlen = 1;
2224 pass = "";
2225 } else if (pass == NULL) {
2226 DEBUG(1, ("Server not using user level security and no "
2227 "password supplied.\n"));
2228 goto access_denied;
2231 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2232 *pass && passlen != 24) {
2233 if (!lp_client_lanman_auth()) {
2234 DEBUG(1, ("Server requested LANMAN password "
2235 "(share-level security) but "
2236 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2237 goto access_denied;
2241 * Non-encrypted passwords - convert to DOS codepage before
2242 * encryption.
2244 SMBencrypt(pass, cli->secblob.data, p24);
2245 passlen = 24;
2246 pass = (const char *)p24;
2247 } else {
2248 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2249 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2250 == 0) {
2251 char *tmp_pass;
2253 if (!lp_client_plaintext_auth() && (*pass)) {
2254 DEBUG(1, ("Server requested plaintext "
2255 "password but "
2256 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2257 goto access_denied;
2261 * Non-encrypted passwords - convert to DOS codepage
2262 * before using.
2264 tmp_pass = talloc_array(talloc_tos(), char, 128);
2265 if (tmp_pass == NULL) {
2266 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2267 return tevent_req_post(req, ev);
2269 passlen = clistr_push(cli,
2270 tmp_pass,
2271 pass,
2272 talloc_get_size(tmp_pass),
2273 STR_TERMINATE);
2274 if (passlen == -1) {
2275 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2276 return tevent_req_post(req, ev);
2278 pass = tmp_pass;
2282 SCVAL(vwv+0, 0, 0xFF);
2283 SCVAL(vwv+0, 1, 0);
2284 SSVAL(vwv+1, 0, 0);
2285 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2286 SSVAL(vwv+3, 0, passlen);
2288 if (passlen && pass) {
2289 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2290 } else {
2291 bytes = talloc_array(state, uint8_t, 0);
2295 * Add the sharename
2297 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2298 cli->desthost, share);
2299 if (tmp == NULL) {
2300 TALLOC_FREE(req);
2301 return NULL;
2303 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2304 NULL);
2305 TALLOC_FREE(tmp);
2308 * Add the devicetype
2310 tmp = talloc_strdup_upper(talloc_tos(), dev);
2311 if (tmp == NULL) {
2312 TALLOC_FREE(req);
2313 return NULL;
2315 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2316 TALLOC_FREE(tmp);
2318 if (bytes == NULL) {
2319 TALLOC_FREE(req);
2320 return NULL;
2323 state->bytes.iov_base = (void *)bytes;
2324 state->bytes.iov_len = talloc_get_size(bytes);
2326 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2327 1, &state->bytes);
2328 if (subreq == NULL) {
2329 TALLOC_FREE(req);
2330 return NULL;
2332 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2333 *psmbreq = subreq;
2334 return req;
2336 access_denied:
2337 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2338 return tevent_req_post(req, ev);
2341 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2342 struct event_context *ev,
2343 struct cli_state *cli,
2344 const char *share, const char *dev,
2345 const char *pass, int passlen)
2347 struct tevent_req *req, *subreq;
2348 NTSTATUS status;
2350 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2351 &subreq);
2352 if (req == NULL) {
2353 return NULL;
2355 if (subreq == NULL) {
2356 return req;
2358 status = cli_smb_req_send(subreq);
2359 if (!NT_STATUS_IS_OK(status)) {
2360 tevent_req_nterror(req, status);
2361 return tevent_req_post(req, ev);
2363 return req;
2366 static void cli_tcon_andx_done(struct tevent_req *subreq)
2368 struct tevent_req *req = tevent_req_callback_data(
2369 subreq, struct tevent_req);
2370 struct cli_tcon_andx_state *state = tevent_req_data(
2371 req, struct cli_tcon_andx_state);
2372 struct cli_state *cli = state->cli;
2373 uint8_t *in;
2374 char *inbuf;
2375 uint8_t wct;
2376 uint16_t *vwv;
2377 uint32_t num_bytes;
2378 uint8_t *bytes;
2379 NTSTATUS status;
2381 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2382 &num_bytes, &bytes);
2383 TALLOC_FREE(subreq);
2384 if (!NT_STATUS_IS_OK(status)) {
2385 tevent_req_nterror(req, status);
2386 return;
2389 inbuf = (char *)in;
2391 if (num_bytes) {
2392 if (clistr_pull_talloc(cli,
2393 inbuf,
2394 SVAL(inbuf, smb_flg2),
2395 &cli->dev,
2396 bytes,
2397 num_bytes,
2398 STR_TERMINATE|STR_ASCII) == -1) {
2399 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2400 return;
2402 } else {
2403 cli->dev = talloc_strdup(cli, "");
2404 if (cli->dev == NULL) {
2405 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2406 return;
2410 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
2411 /* almost certainly win95 - enable bug fixes */
2412 cli->win95 = True;
2416 * Make sure that we have the optional support 16-bit field. WCT > 2.
2417 * Avoids issues when connecting to Win9x boxes sharing files
2420 cli->dfsroot = false;
2422 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
2423 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2426 cli->cnum = SVAL(inbuf,smb_tid);
2427 tevent_req_done(req);
2430 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2432 return tevent_req_simple_recv_ntstatus(req);
2435 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2436 const char *dev, const char *pass, int passlen)
2438 TALLOC_CTX *frame = talloc_stackframe();
2439 struct event_context *ev;
2440 struct tevent_req *req;
2441 NTSTATUS status = NT_STATUS_OK;
2443 if (cli_has_async_calls(cli)) {
2445 * Can't use sync call while an async call is in flight
2447 status = NT_STATUS_INVALID_PARAMETER;
2448 goto fail;
2451 ev = event_context_init(frame);
2452 if (ev == NULL) {
2453 status = NT_STATUS_NO_MEMORY;
2454 goto fail;
2457 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2458 if (req == NULL) {
2459 status = NT_STATUS_NO_MEMORY;
2460 goto fail;
2463 if (!tevent_req_poll(req, ev)) {
2464 status = map_nt_error_from_unix(errno);
2465 goto fail;
2468 status = cli_tcon_andx_recv(req);
2469 fail:
2470 TALLOC_FREE(frame);
2471 return status;
2474 /****************************************************************************
2475 Send a tree disconnect.
2476 ****************************************************************************/
2478 struct cli_tdis_state {
2479 struct cli_state *cli;
2482 static void cli_tdis_done(struct tevent_req *subreq);
2484 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2485 struct tevent_context *ev,
2486 struct cli_state *cli)
2488 struct tevent_req *req, *subreq;
2489 struct cli_tdis_state *state;
2491 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2492 if (req == NULL) {
2493 return NULL;
2495 state->cli = cli;
2497 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2498 if (tevent_req_nomem(subreq, req)) {
2499 return tevent_req_post(req, ev);
2501 tevent_req_set_callback(subreq, cli_tdis_done, req);
2502 return req;
2505 static void cli_tdis_done(struct tevent_req *subreq)
2507 struct tevent_req *req = tevent_req_callback_data(
2508 subreq, struct tevent_req);
2509 struct cli_tdis_state *state = tevent_req_data(
2510 req, struct cli_tdis_state);
2511 NTSTATUS status;
2513 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2514 TALLOC_FREE(subreq);
2515 if (!NT_STATUS_IS_OK(status)) {
2516 tevent_req_nterror(req, status);
2517 return;
2519 state->cli->cnum = -1;
2520 tevent_req_done(req);
2523 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2525 return tevent_req_simple_recv_ntstatus(req);
2528 NTSTATUS cli_tdis(struct cli_state *cli)
2530 struct tevent_context *ev;
2531 struct tevent_req *req;
2532 NTSTATUS status = NT_STATUS_NO_MEMORY;
2534 if (cli_has_async_calls(cli)) {
2535 return NT_STATUS_INVALID_PARAMETER;
2537 ev = tevent_context_init(talloc_tos());
2538 if (ev == NULL) {
2539 goto fail;
2541 req = cli_tdis_send(ev, ev, cli);
2542 if (req == NULL) {
2543 goto fail;
2545 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2546 goto fail;
2548 status = cli_tdis_recv(req);
2549 fail:
2550 TALLOC_FREE(ev);
2551 return status;
2554 /****************************************************************************
2555 Send a negprot command.
2556 ****************************************************************************/
2558 struct cli_negprot_state {
2559 struct cli_state *cli;
2562 static void cli_negprot_done(struct tevent_req *subreq);
2564 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2565 struct event_context *ev,
2566 struct cli_state *cli)
2568 struct tevent_req *req, *subreq;
2569 struct cli_negprot_state *state;
2570 uint8_t *bytes = NULL;
2571 int numprots;
2572 uint16_t cnum;
2574 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2575 if (req == NULL) {
2576 return NULL;
2578 state->cli = cli;
2580 if (cli->protocol < PROTOCOL_NT1)
2581 cli->use_spnego = False;
2583 /* setup the protocol strings */
2584 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2585 uint8_t c = 2;
2586 if (prots[numprots].prot > cli->protocol) {
2587 break;
2589 bytes = (uint8_t *)talloc_append_blob(
2590 state, bytes, data_blob_const(&c, sizeof(c)));
2591 if (tevent_req_nomem(bytes, req)) {
2592 return tevent_req_post(req, ev);
2594 bytes = smb_bytes_push_str(bytes, false,
2595 prots[numprots].name,
2596 strlen(prots[numprots].name)+1,
2597 NULL);
2598 if (tevent_req_nomem(bytes, req)) {
2599 return tevent_req_post(req, ev);
2603 cnum = cli->cnum;
2605 cli->cnum = 0;
2606 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2607 talloc_get_size(bytes), bytes);
2608 cli->cnum = cnum;
2610 if (tevent_req_nomem(subreq, req)) {
2611 return tevent_req_post(req, ev);
2613 tevent_req_set_callback(subreq, cli_negprot_done, req);
2614 return req;
2617 static void cli_negprot_done(struct tevent_req *subreq)
2619 struct tevent_req *req = tevent_req_callback_data(
2620 subreq, struct tevent_req);
2621 struct cli_negprot_state *state = tevent_req_data(
2622 req, struct cli_negprot_state);
2623 struct cli_state *cli = state->cli;
2624 uint8_t wct;
2625 uint16_t *vwv;
2626 uint32_t num_bytes;
2627 uint8_t *bytes;
2628 NTSTATUS status;
2629 uint16_t protnum;
2630 uint8_t *inbuf;
2632 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2633 &num_bytes, &bytes);
2634 TALLOC_FREE(subreq);
2635 if (!NT_STATUS_IS_OK(status)) {
2636 tevent_req_nterror(req, status);
2637 return;
2640 protnum = SVAL(vwv, 0);
2642 if ((protnum >= ARRAY_SIZE(prots))
2643 || (prots[protnum].prot > cli->protocol)) {
2644 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2645 return;
2648 cli->protocol = prots[protnum].prot;
2650 if ((cli->protocol < PROTOCOL_NT1) &&
2651 client_is_signing_mandatory(cli)) {
2652 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2653 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2654 return;
2657 if (cli->protocol >= PROTOCOL_NT1) {
2658 struct timespec ts;
2659 bool negotiated_smb_signing = false;
2660 DATA_BLOB blob = data_blob_null;
2662 if (wct != 0x11) {
2663 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2664 return;
2667 /* NT protocol */
2668 cli->sec_mode = CVAL(vwv + 1, 0);
2669 cli->max_mux = SVAL(vwv + 1, 1);
2670 cli->max_xmit = IVAL(vwv + 3, 1);
2671 cli->sesskey = IVAL(vwv + 7, 1);
2672 cli->serverzone = SVALS(vwv + 15, 1);
2673 cli->serverzone *= 60;
2674 /* this time arrives in real GMT */
2675 ts = interpret_long_date(((char *)(vwv+11))+1);
2676 cli->servertime = ts.tv_sec;
2677 cli->secblob = data_blob(bytes, num_bytes);
2678 cli->capabilities = IVAL(vwv + 9, 1);
2679 if (cli->capabilities & CAP_RAW_MODE) {
2680 cli->readbraw_supported = True;
2681 cli->writebraw_supported = True;
2683 /* work out if they sent us a workgroup */
2684 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2685 smb_buflen(inbuf) > 8) {
2686 blob = data_blob_const(bytes + 8, num_bytes - 8);
2689 if (blob.length > 0) {
2690 ssize_t ret;
2691 char *server_domain = NULL;
2693 ret = clistr_pull_talloc(cli,
2694 (const char *)inbuf,
2695 SVAL(inbuf, smb_flg2),
2696 &server_domain,
2697 (char *)blob.data,
2698 blob.length,
2699 STR_TERMINATE|
2700 STR_UNICODE|
2701 STR_NOALIGN);
2702 if (ret == -1) {
2703 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2704 return;
2706 if (server_domain) {
2707 cli->server_domain = server_domain;
2712 * As signing is slow we only turn it on if either the client or
2713 * the server require it. JRA.
2716 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2717 /* Fail if server says signing is mandatory and we don't want to support it. */
2718 if (!client_is_signing_allowed(cli)) {
2719 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2720 tevent_req_nterror(req,
2721 NT_STATUS_ACCESS_DENIED);
2722 return;
2724 negotiated_smb_signing = true;
2725 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2726 /* Fail if client says signing is mandatory and the server doesn't support it. */
2727 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2728 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2729 tevent_req_nterror(req,
2730 NT_STATUS_ACCESS_DENIED);
2731 return;
2733 negotiated_smb_signing = true;
2734 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2735 negotiated_smb_signing = true;
2738 if (negotiated_smb_signing) {
2739 cli_set_signing_negotiated(cli);
2742 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2743 SAFE_FREE(cli->outbuf);
2744 SAFE_FREE(cli->inbuf);
2745 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2746 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2747 if (!cli->outbuf || !cli->inbuf) {
2748 tevent_req_nterror(req,
2749 NT_STATUS_NO_MEMORY);
2750 return;
2752 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2755 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2756 if (wct != 0x0D) {
2757 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2758 return;
2761 cli->use_spnego = False;
2762 cli->sec_mode = SVAL(vwv + 1, 0);
2763 cli->max_xmit = SVAL(vwv + 2, 0);
2764 cli->max_mux = SVAL(vwv + 3, 0);
2765 cli->sesskey = IVAL(vwv + 6, 0);
2766 cli->serverzone = SVALS(vwv + 10, 0);
2767 cli->serverzone *= 60;
2768 /* this time is converted to GMT by make_unix_date */
2769 cli->servertime = make_unix_date(
2770 (char *)(vwv + 8), cli->serverzone);
2771 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2772 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2773 cli->secblob = data_blob(bytes, num_bytes);
2774 } else {
2775 /* the old core protocol */
2776 cli->use_spnego = False;
2777 cli->sec_mode = 0;
2778 cli->serverzone = get_time_zone(time(NULL));
2781 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2783 /* a way to force ascii SMB */
2784 if (getenv("CLI_FORCE_ASCII"))
2785 cli->capabilities &= ~CAP_UNICODE;
2787 tevent_req_done(req);
2790 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2792 return tevent_req_simple_recv_ntstatus(req);
2795 NTSTATUS cli_negprot(struct cli_state *cli)
2797 TALLOC_CTX *frame = talloc_stackframe();
2798 struct event_context *ev;
2799 struct tevent_req *req;
2800 NTSTATUS status = NT_STATUS_OK;
2802 if (cli_has_async_calls(cli)) {
2804 * Can't use sync call while an async call is in flight
2806 status = NT_STATUS_INVALID_PARAMETER;
2807 goto fail;
2810 ev = event_context_init(frame);
2811 if (ev == NULL) {
2812 status = NT_STATUS_NO_MEMORY;
2813 goto fail;
2816 req = cli_negprot_send(frame, ev, cli);
2817 if (req == NULL) {
2818 status = NT_STATUS_NO_MEMORY;
2819 goto fail;
2822 if (!tevent_req_poll(req, ev)) {
2823 status = map_nt_error_from_unix(errno);
2824 goto fail;
2827 status = cli_negprot_recv(req);
2828 fail:
2829 TALLOC_FREE(frame);
2830 return status;
2833 /****************************************************************************
2834 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2835 ****************************************************************************/
2837 bool cli_session_request(struct cli_state *cli,
2838 struct nmb_name *calling, struct nmb_name *called)
2840 char *p;
2841 int len = 4;
2842 int namelen = 0;
2843 char *tmp;
2845 /* 445 doesn't have session request */
2846 if (cli->port == 445)
2847 return True;
2849 memcpy(&(cli->calling), calling, sizeof(*calling));
2850 memcpy(&(cli->called ), called , sizeof(*called ));
2852 /* put in the destination name */
2854 tmp = name_mangle(talloc_tos(), cli->called.name,
2855 cli->called.name_type);
2856 if (tmp == NULL) {
2857 return false;
2860 p = cli->outbuf+len;
2861 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2862 if (namelen > 0) {
2863 memcpy(p, tmp, namelen);
2864 len += namelen;
2866 TALLOC_FREE(tmp);
2868 /* and my name */
2870 tmp = name_mangle(talloc_tos(), cli->calling.name,
2871 cli->calling.name_type);
2872 if (tmp == NULL) {
2873 return false;
2876 p = cli->outbuf+len;
2877 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2878 if (namelen > 0) {
2879 memcpy(p, tmp, namelen);
2880 len += namelen;
2882 TALLOC_FREE(tmp);
2884 /* send a session request (RFC 1002) */
2885 /* setup the packet length
2886 * Remove four bytes from the length count, since the length
2887 * field in the NBT Session Service header counts the number
2888 * of bytes which follow. The cli_send_smb() function knows
2889 * about this and accounts for those four bytes.
2890 * CRH.
2892 len -= 4;
2893 _smb_setlen(cli->outbuf,len);
2894 SCVAL(cli->outbuf,0,0x81);
2896 cli_send_smb(cli);
2897 DEBUG(5,("Sent session request\n"));
2899 if (!cli_receive_smb(cli))
2900 return False;
2902 if (CVAL(cli->inbuf,0) == 0x84) {
2903 /* C. Hoch 9/14/95 Start */
2904 /* For information, here is the response structure.
2905 * We do the byte-twiddling to for portability.
2906 struct RetargetResponse{
2907 unsigned char type;
2908 unsigned char flags;
2909 int16 length;
2910 int32 ip_addr;
2911 int16 port;
2914 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2915 struct in_addr dest_ip;
2916 NTSTATUS status;
2918 /* SESSION RETARGET */
2919 putip((char *)&dest_ip,cli->inbuf+4);
2920 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2922 status = open_socket_out(&cli->dest_ss, port,
2923 LONG_CONNECT_TIMEOUT, &cli->fd);
2924 if (!NT_STATUS_IS_OK(status)) {
2925 return False;
2928 DEBUG(3,("Retargeted\n"));
2930 set_socket_options(cli->fd, lp_socket_options());
2932 /* Try again */
2934 static int depth;
2935 bool ret;
2936 if (depth > 4) {
2937 DEBUG(0,("Retarget recursion - failing\n"));
2938 return False;
2940 depth++;
2941 ret = cli_session_request(cli, calling, called);
2942 depth--;
2943 return ret;
2945 } /* C. Hoch 9/14/95 End */
2947 if (CVAL(cli->inbuf,0) != 0x82) {
2948 /* This is the wrong place to put the error... JRA. */
2949 cli->rap_error = CVAL(cli->inbuf,4);
2950 return False;
2952 return(True);
2955 struct fd_struct {
2956 int fd;
2959 static void smb_sock_connected(struct tevent_req *req)
2961 struct fd_struct *pfd = tevent_req_callback_data(
2962 req, struct fd_struct);
2963 int fd;
2964 NTSTATUS status;
2966 status = open_socket_out_defer_recv(req, &fd);
2967 if (NT_STATUS_IS_OK(status)) {
2968 pfd->fd = fd;
2972 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2973 uint16_t *port, int timeout, int *pfd)
2975 struct event_context *ev;
2976 struct tevent_req *r139, *r445;
2977 struct fd_struct *fd139, *fd445;
2978 NTSTATUS status = NT_STATUS_NO_MEMORY;
2980 if (*port != 0) {
2981 return open_socket_out(pss, *port, timeout, pfd);
2984 ev = event_context_init(talloc_tos());
2985 if (ev == NULL) {
2986 return NT_STATUS_NO_MEMORY;
2989 fd139 = talloc(ev, struct fd_struct);
2990 if (fd139 == NULL) {
2991 goto done;
2993 fd139->fd = -1;
2995 fd445 = talloc(ev, struct fd_struct);
2996 if (fd445 == NULL) {
2997 goto done;
2999 fd445->fd = -1;
3001 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
3002 pss, 445, timeout);
3003 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
3004 pss, 139, timeout);
3005 if ((r445 == NULL) || (r139 == NULL)) {
3006 goto done;
3008 tevent_req_set_callback(r445, smb_sock_connected, fd445);
3009 tevent_req_set_callback(r139, smb_sock_connected, fd139);
3011 while ((fd445->fd == -1) && (fd139->fd == -1)
3012 && (tevent_req_is_in_progress(r139)
3013 || tevent_req_is_in_progress(r445))) {
3014 event_loop_once(ev);
3017 if ((fd139->fd != -1) && (fd445->fd != -1)) {
3018 close(fd139->fd);
3019 fd139->fd = -1;
3022 if (fd445->fd != -1) {
3023 *port = 445;
3024 *pfd = fd445->fd;
3025 status = NT_STATUS_OK;
3026 goto done;
3028 if (fd139->fd != -1) {
3029 *port = 139;
3030 *pfd = fd139->fd;
3031 status = NT_STATUS_OK;
3032 goto done;
3035 status = open_socket_out_defer_recv(r445, &fd445->fd);
3036 done:
3037 TALLOC_FREE(ev);
3038 return status;
3041 /****************************************************************************
3042 Open the client sockets.
3043 ****************************************************************************/
3045 NTSTATUS cli_connect(struct cli_state *cli,
3046 const char *host,
3047 struct sockaddr_storage *dest_ss)
3050 int name_type = 0x20;
3051 TALLOC_CTX *frame = talloc_stackframe();
3052 unsigned int num_addrs = 0;
3053 unsigned int i = 0;
3054 struct sockaddr_storage *ss_arr = NULL;
3055 char *p = NULL;
3057 /* reasonable default hostname */
3058 if (!host) {
3059 host = STAR_SMBSERVER;
3062 cli->desthost = talloc_strdup(cli, host);
3063 if (cli->desthost == NULL) {
3064 return NT_STATUS_NO_MEMORY;
3067 /* allow hostnames of the form NAME#xx and do a netbios lookup */
3068 if ((p = strchr(cli->desthost, '#'))) {
3069 name_type = strtol(p+1, NULL, 16);
3070 *p = 0;
3073 if (!dest_ss || is_zero_addr(dest_ss)) {
3074 NTSTATUS status =resolve_name_list(frame,
3075 cli->desthost,
3076 name_type,
3077 &ss_arr,
3078 &num_addrs);
3079 if (!NT_STATUS_IS_OK(status)) {
3080 TALLOC_FREE(frame);
3081 return NT_STATUS_BAD_NETWORK_NAME;
3083 } else {
3084 num_addrs = 1;
3085 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
3086 if (!ss_arr) {
3087 TALLOC_FREE(frame);
3088 return NT_STATUS_NO_MEMORY;
3090 *ss_arr = *dest_ss;
3093 for (i = 0; i < num_addrs; i++) {
3094 cli->dest_ss = ss_arr[i];
3095 if (getenv("LIBSMB_PROG")) {
3096 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
3097 } else {
3098 uint16_t port = cli->port;
3099 NTSTATUS status;
3100 status = open_smb_socket(&cli->dest_ss, &port,
3101 cli->timeout, &cli->fd);
3102 if (NT_STATUS_IS_OK(status)) {
3103 cli->port = port;
3106 if (cli->fd == -1) {
3107 char addr[INET6_ADDRSTRLEN];
3108 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
3109 DEBUG(2,("Error connecting to %s (%s)\n",
3110 dest_ss?addr:host,strerror(errno)));
3111 } else {
3112 /* Exit from loop on first connection. */
3113 break;
3117 if (cli->fd == -1) {
3118 TALLOC_FREE(frame);
3119 return map_nt_error_from_unix(errno);
3122 if (dest_ss) {
3123 *dest_ss = cli->dest_ss;
3126 set_socket_options(cli->fd, lp_socket_options());
3128 TALLOC_FREE(frame);
3129 return NT_STATUS_OK;
3133 establishes a connection to after the negprot.
3134 @param output_cli A fully initialised cli structure, non-null only on success
3135 @param dest_host The netbios name of the remote host
3136 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3137 @param port (optional) The destination port (0 for default)
3139 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3140 const char *my_name,
3141 const char *dest_host,
3142 struct sockaddr_storage *dest_ss, int port,
3143 int signing_state, int flags)
3145 NTSTATUS nt_status;
3146 struct nmb_name calling;
3147 struct nmb_name called;
3148 struct cli_state *cli;
3149 struct sockaddr_storage ss;
3151 if (!my_name)
3152 my_name = global_myname();
3154 if (!(cli = cli_initialise_ex(signing_state))) {
3155 return NT_STATUS_NO_MEMORY;
3158 make_nmb_name(&calling, my_name, 0x0);
3159 make_nmb_name(&called , dest_host, 0x20);
3161 cli_set_port(cli, port);
3162 cli_set_timeout(cli, 10000); /* 10 seconds. */
3164 if (dest_ss) {
3165 ss = *dest_ss;
3166 } else {
3167 zero_sockaddr(&ss);
3170 again:
3172 DEBUG(3,("Connecting to host=%s\n", dest_host));
3174 nt_status = cli_connect(cli, dest_host, &ss);
3175 if (!NT_STATUS_IS_OK(nt_status)) {
3176 char addr[INET6_ADDRSTRLEN];
3177 print_sockaddr(addr, sizeof(addr), &ss);
3178 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
3179 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
3180 cli_shutdown(cli);
3181 return nt_status;
3184 if (!cli_session_request(cli, &calling, &called)) {
3185 char *p;
3186 DEBUG(1,("session request to %s failed (%s)\n",
3187 called.name, cli_errstr(cli)));
3188 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
3189 *p = 0;
3190 goto again;
3192 if (strcmp(called.name, STAR_SMBSERVER)) {
3193 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
3194 goto again;
3196 return NT_STATUS_BAD_NETWORK_NAME;
3199 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
3200 cli->use_spnego = False;
3201 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
3202 cli->use_kerberos = True;
3204 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
3205 cli->use_kerberos) {
3206 cli->fallback_after_kerberos = true;
3208 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3209 cli->use_ccache = true;
3212 nt_status = cli_negprot(cli);
3213 if (!NT_STATUS_IS_OK(nt_status)) {
3214 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
3215 cli_shutdown(cli);
3216 return nt_status;
3219 *output_cli = cli;
3220 return NT_STATUS_OK;
3225 establishes a connection right up to doing tconX, password specified.
3226 @param output_cli A fully initialised cli structure, non-null only on success
3227 @param dest_host The netbios name of the remote host
3228 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3229 @param port (optional) The destination port (0 for default)
3230 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3231 @param service_type The 'type' of serivice.
3232 @param user Username, unix string
3233 @param domain User's domain
3234 @param password User's password, unencrypted unix string.
3237 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3238 const char *my_name,
3239 const char *dest_host,
3240 struct sockaddr_storage *dest_ss, int port,
3241 const char *service, const char *service_type,
3242 const char *user, const char *domain,
3243 const char *password, int flags,
3244 int signing_state)
3246 NTSTATUS nt_status;
3247 struct cli_state *cli = NULL;
3248 int pw_len = password ? strlen(password)+1 : 0;
3250 *output_cli = NULL;
3252 if (password == NULL) {
3253 password = "";
3256 nt_status = cli_start_connection(&cli, my_name, dest_host,
3257 dest_ss, port, signing_state,
3258 flags);
3260 if (!NT_STATUS_IS_OK(nt_status)) {
3261 return nt_status;
3264 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
3265 cli->use_level_II_oplocks =
3266 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
3268 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3269 pw_len, domain);
3270 if (!NT_STATUS_IS_OK(nt_status)) {
3272 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3273 DEBUG(1,("failed session setup with %s\n",
3274 nt_errstr(nt_status)));
3275 cli_shutdown(cli);
3276 return nt_status;
3279 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3280 if (!NT_STATUS_IS_OK(nt_status)) {
3281 DEBUG(1,("anonymous failed session setup with %s\n",
3282 nt_errstr(nt_status)));
3283 cli_shutdown(cli);
3284 return nt_status;
3288 if (service) {
3289 nt_status = cli_tcon_andx(cli, service, service_type, password,
3290 pw_len);
3291 if (!NT_STATUS_IS_OK(nt_status)) {
3292 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3293 cli_shutdown(cli);
3294 if (NT_STATUS_IS_OK(nt_status)) {
3295 nt_status = NT_STATUS_UNSUCCESSFUL;
3297 return nt_status;
3301 nt_status = cli_init_creds(cli, user, domain, password);
3302 if (!NT_STATUS_IS_OK(nt_status)) {
3303 cli_shutdown(cli);
3304 return nt_status;
3307 *output_cli = cli;
3308 return NT_STATUS_OK;
3311 /****************************************************************************
3312 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
3313 ****************************************************************************/
3315 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
3316 struct sockaddr_storage *pdest_ss)
3318 struct nmb_name calling, called;
3320 make_nmb_name(&calling, srchost, 0x0);
3323 * If the called name is an IP address
3324 * then use *SMBSERVER immediately.
3327 if(is_ipaddress(desthost)) {
3328 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
3329 } else {
3330 make_nmb_name(&called, desthost, 0x20);
3333 if (!cli_session_request(*ppcli, &calling, &called)) {
3334 NTSTATUS status;
3335 struct nmb_name smbservername;
3337 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
3340 * If the name wasn't *SMBSERVER then
3341 * try with *SMBSERVER if the first name fails.
3344 if (nmb_name_equal(&called, &smbservername)) {
3347 * The name used was *SMBSERVER, don't bother with another name.
3350 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
3351 with error %s.\n", desthost, cli_errstr(*ppcli) ));
3352 return False;
3355 /* Try again... */
3356 cli_shutdown(*ppcli);
3358 *ppcli = cli_initialise();
3359 if (!*ppcli) {
3360 /* Out of memory... */
3361 return False;
3364 status = cli_connect(*ppcli, desthost, pdest_ss);
3365 if (!NT_STATUS_IS_OK(status) ||
3366 !cli_session_request(*ppcli, &calling, &smbservername)) {
3367 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
3368 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
3369 return False;
3373 return True;
3376 /****************************************************************************
3377 Send an old style tcon.
3378 ****************************************************************************/
3379 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3380 const char *service, const char *pass, const char *dev,
3381 uint16 *max_xmit, uint16 *tid)
3383 struct tevent_req *req;
3384 uint16_t *ret_vwv;
3385 uint8_t *bytes;
3386 NTSTATUS status;
3388 if (!lp_client_plaintext_auth() && (*pass)) {
3389 DEBUG(1, ("Server requested plaintext password but 'client "
3390 "plaintext auth' is disabled\n"));
3391 return NT_STATUS_ACCESS_DENIED;
3394 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3395 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3396 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3397 service, strlen(service)+1, NULL);
3398 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3399 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3400 pass, strlen(pass)+1, NULL);
3401 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3402 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3403 dev, strlen(dev)+1, NULL);
3405 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3406 talloc_get_size(bytes), bytes, &req,
3407 2, NULL, &ret_vwv, NULL, NULL);
3408 if (!NT_STATUS_IS_OK(status)) {
3409 return status;
3412 *max_xmit = SVAL(ret_vwv + 0, 0);
3413 *tid = SVAL(ret_vwv + 1, 0);
3415 return NT_STATUS_OK;
3418 /* Return a cli_state pointing at the IPC$ share for the given server */
3420 struct cli_state *get_ipc_connect(char *server,
3421 struct sockaddr_storage *server_ss,
3422 const struct user_auth_info *user_info)
3424 struct cli_state *cli;
3425 NTSTATUS nt_status;
3426 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3428 if (user_info->use_kerberos) {
3429 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3432 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3433 user_info->username ? user_info->username : "",
3434 lp_workgroup(),
3435 user_info->password ? user_info->password : "",
3436 flags,
3437 Undefined);
3439 if (NT_STATUS_IS_OK(nt_status)) {
3440 return cli;
3441 } else if (is_ipaddress(server)) {
3442 /* windows 9* needs a correct NMB name for connections */
3443 fstring remote_name;
3445 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3446 cli = get_ipc_connect(remote_name, server_ss, user_info);
3447 if (cli)
3448 return cli;
3451 return NULL;
3455 * Given the IP address of a master browser on the network, return its
3456 * workgroup and connect to it.
3458 * This function is provided to allow additional processing beyond what
3459 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3460 * browsers and obtain each master browsers' list of domains (in case the
3461 * first master browser is recently on the network and has not yet
3462 * synchronized with other master browsers and therefore does not yet have the
3463 * entire network browse list)
3466 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3467 struct sockaddr_storage *mb_ip,
3468 const struct user_auth_info *user_info,
3469 char **pp_workgroup_out)
3471 char addr[INET6_ADDRSTRLEN];
3472 fstring name;
3473 struct cli_state *cli;
3474 struct sockaddr_storage server_ss;
3476 *pp_workgroup_out = NULL;
3478 print_sockaddr(addr, sizeof(addr), mb_ip);
3479 DEBUG(99, ("Looking up name of master browser %s\n",
3480 addr));
3483 * Do a name status query to find out the name of the master browser.
3484 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3485 * master browser will not respond to a wildcard query (or, at least,
3486 * an NT4 server acting as the domain master browser will not).
3488 * We might be able to use ONLY the query on MSBROWSE, but that's not
3489 * yet been tested with all Windows versions, so until it is, leave
3490 * the original wildcard query as the first choice and fall back to
3491 * MSBROWSE if the wildcard query fails.
3493 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3494 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3496 DEBUG(99, ("Could not retrieve name status for %s\n",
3497 addr));
3498 return NULL;
3501 if (!find_master_ip(name, &server_ss)) {
3502 DEBUG(99, ("Could not find master ip for %s\n", name));
3503 return NULL;
3506 *pp_workgroup_out = talloc_strdup(ctx, name);
3508 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3510 print_sockaddr(addr, sizeof(addr), &server_ss);
3511 cli = get_ipc_connect(addr, &server_ss, user_info);
3513 return cli;
3517 * Return the IP address and workgroup of a master browser on the network, and
3518 * connect to it.
3521 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3522 const struct user_auth_info *user_info,
3523 char **pp_workgroup_out)
3525 struct sockaddr_storage *ip_list;
3526 struct cli_state *cli;
3527 int i, count;
3528 NTSTATUS status;
3530 *pp_workgroup_out = NULL;
3532 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3534 /* Go looking for workgroups by broadcasting on the local network */
3536 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3537 &ip_list, &count);
3538 if (!NT_STATUS_IS_OK(status)) {
3539 DEBUG(99, ("No master browsers responded: %s\n",
3540 nt_errstr(status)));
3541 return False;
3544 for (i = 0; i < count; i++) {
3545 char addr[INET6_ADDRSTRLEN];
3546 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3547 DEBUG(99, ("Found master browser %s\n", addr));
3549 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3550 user_info, pp_workgroup_out);
3551 if (cli)
3552 return(cli);
3555 return NULL;