s3: Remove ip_sevice from get_ipc_connect_master_ip
[Samba.git] / source3 / libsmb / cliconnect.c
blobcb7b7d1bbda5248366ab4c2c95d665c80a686113
1 /*
2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
6 Copyright (C) Volker Lendecke 2011
7 Copyright (C) Jeremy Allison 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "popt_common.h"
25 #include "../libcli/auth/libcli_auth.h"
26 #include "../libcli/auth/spnego.h"
27 #include "smb_krb5.h"
28 #include "../libcli/auth/ntlmssp.h"
29 #include "libads/kerberos_proto.h"
30 #include "krb5_env.h"
31 #include "../lib/util/tevent_ntstatus.h"
32 #include "async_smb.h"
33 #include "libsmb/nmblib.h"
35 static const struct {
36 int prot;
37 const char name[24];
38 } prots[10] = {
39 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
40 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
41 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
42 {PROTOCOL_LANMAN1, "LANMAN1.0"},
43 {PROTOCOL_LANMAN2, "LM1.2X002"},
44 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
45 {PROTOCOL_LANMAN2, "LANMAN2.1"},
46 {PROTOCOL_LANMAN2, "Samba"},
47 {PROTOCOL_NT1, "NT LANMAN 1.0"},
48 {PROTOCOL_NT1, "NT LM 0.12"},
51 #define STAR_SMBSERVER "*SMBSERVER"
53 /********************************************************
54 Utility function to ensure we always return at least
55 a valid char * pointer to an empty string for the
56 cli->server_os, cli->server_type and cli->server_domain
57 strings.
58 *******************************************************/
60 static NTSTATUS smb_bytes_talloc_string(struct cli_state *cli,
61 char *inbuf,
62 char **dest,
63 uint8_t *src,
64 size_t srclen,
65 ssize_t *destlen)
67 *destlen = clistr_pull_talloc(cli,
68 inbuf,
69 SVAL(inbuf, smb_flg2),
70 dest,
71 (char *)src,
72 srclen,
73 STR_TERMINATE);
74 if (*destlen == -1) {
75 return NT_STATUS_NO_MEMORY;
78 if (*dest == NULL) {
79 *dest = talloc_strdup(cli, "");
80 if (*dest == NULL) {
81 return NT_STATUS_NO_MEMORY;
84 return NT_STATUS_OK;
87 /**
88 * Set the user session key for a connection
89 * @param cli The cli structure to add it too
90 * @param session_key The session key used. (A copy of this is taken for the cli struct)
94 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
96 cli->user_session_key = data_blob(session_key.data, session_key.length);
99 /****************************************************************************
100 Do an old lanman2 style session setup.
101 ****************************************************************************/
103 struct cli_session_setup_lanman2_state {
104 struct cli_state *cli;
105 uint16_t vwv[10];
106 const char *user;
109 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
111 static struct tevent_req *cli_session_setup_lanman2_send(
112 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
113 struct cli_state *cli, const char *user,
114 const char *pass, size_t passlen,
115 const char *workgroup)
117 struct tevent_req *req, *subreq;
118 struct cli_session_setup_lanman2_state *state;
119 DATA_BLOB lm_response = data_blob_null;
120 uint16_t *vwv;
121 uint8_t *bytes;
122 char *tmp;
124 req = tevent_req_create(mem_ctx, &state,
125 struct cli_session_setup_lanman2_state);
126 if (req == NULL) {
127 return NULL;
129 state->cli = cli;
130 state->user = user;
131 vwv = state->vwv;
134 * LANMAN servers predate NT status codes and Unicode and
135 * ignore those smb flags so we must disable the corresponding
136 * default capabilities that would otherwise cause the Unicode
137 * and NT Status flags to be set (and even returned by the
138 * server)
141 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
144 * if in share level security then don't send a password now
146 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
147 passlen = 0;
150 if (passlen > 0
151 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
152 && passlen != 24) {
154 * Encrypted mode needed, and non encrypted password
155 * supplied.
157 lm_response = data_blob(NULL, 24);
158 if (tevent_req_nomem(lm_response.data, req)) {
159 return tevent_req_post(req, ev);
162 if (!SMBencrypt(pass, cli->secblob.data,
163 (uint8_t *)lm_response.data)) {
164 DEBUG(1, ("Password is > 14 chars in length, and is "
165 "therefore incompatible with Lanman "
166 "authentication\n"));
167 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
168 return tevent_req_post(req, ev);
170 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
171 && passlen == 24) {
173 * Encrypted mode needed, and encrypted password
174 * supplied.
176 lm_response = data_blob(pass, passlen);
177 if (tevent_req_nomem(lm_response.data, req)) {
178 return tevent_req_post(req, ev);
180 } else if (passlen > 0) {
181 uint8_t *buf;
182 size_t converted_size;
184 * Plaintext mode needed, assume plaintext supplied.
186 buf = talloc_array(talloc_tos(), uint8_t, 0);
187 buf = smb_bytes_push_str(buf, cli_ucs2(cli), pass, passlen+1,
188 &converted_size);
189 if (tevent_req_nomem(buf, req)) {
190 return tevent_req_post(req, ev);
192 lm_response = data_blob(pass, passlen);
193 TALLOC_FREE(buf);
194 if (tevent_req_nomem(lm_response.data, req)) {
195 return tevent_req_post(req, ev);
199 SCVAL(vwv+0, 0, 0xff);
200 SCVAL(vwv+0, 1, 0);
201 SSVAL(vwv+1, 0, 0);
202 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
203 SSVAL(vwv+3, 0, 2);
204 SSVAL(vwv+4, 0, 1);
205 SIVAL(vwv+5, 0, cli->sesskey);
206 SSVAL(vwv+7, 0, lm_response.length);
208 bytes = talloc_array(state, uint8_t, lm_response.length);
209 if (tevent_req_nomem(bytes, req)) {
210 return tevent_req_post(req, ev);
212 if (lm_response.length != 0) {
213 memcpy(bytes, lm_response.data, lm_response.length);
215 data_blob_free(&lm_response);
217 tmp = talloc_strdup_upper(talloc_tos(), user);
218 if (tevent_req_nomem(tmp, req)) {
219 return tevent_req_post(req, ev);
221 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
222 NULL);
223 TALLOC_FREE(tmp);
225 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
226 if (tevent_req_nomem(tmp, req)) {
227 return tevent_req_post(req, ev);
229 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
230 NULL);
231 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
232 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
234 if (tevent_req_nomem(bytes, req)) {
235 return tevent_req_post(req, ev);
238 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
239 talloc_get_size(bytes), bytes);
240 if (tevent_req_nomem(subreq, req)) {
241 return tevent_req_post(req, ev);
243 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
244 return req;
247 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
249 struct tevent_req *req = tevent_req_callback_data(
250 subreq, struct tevent_req);
251 struct cli_session_setup_lanman2_state *state = tevent_req_data(
252 req, struct cli_session_setup_lanman2_state);
253 struct cli_state *cli = state->cli;
254 uint32_t num_bytes;
255 uint8_t *in;
256 char *inbuf;
257 uint8_t *bytes;
258 uint8_t *p;
259 NTSTATUS status;
260 ssize_t ret;
262 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
263 &num_bytes, &bytes);
264 TALLOC_FREE(subreq);
265 if (!NT_STATUS_IS_OK(status)) {
266 tevent_req_nterror(req, status);
267 return;
270 inbuf = (char *)in;
271 p = bytes;
273 cli->vuid = SVAL(inbuf, smb_uid);
275 status = smb_bytes_talloc_string(cli,
276 inbuf,
277 &cli->server_os,
279 bytes+num_bytes-p,
280 &ret);
282 if (!NT_STATUS_IS_OK(status)) {
283 tevent_req_nterror(req, status);
284 return;
286 p += ret;
288 status = smb_bytes_talloc_string(cli,
289 inbuf,
290 &cli->server_type,
292 bytes+num_bytes-p,
293 &ret);
295 if (!NT_STATUS_IS_OK(status)) {
296 tevent_req_nterror(req, status);
297 return;
299 p += ret;
301 status = smb_bytes_talloc_string(cli,
302 inbuf,
303 &cli->server_domain,
305 bytes+num_bytes-p,
306 &ret);
308 if (!NT_STATUS_IS_OK(status)) {
309 tevent_req_nterror(req, status);
310 return;
312 p += ret;
314 if (strstr(cli->server_type, "Samba")) {
315 cli->is_samba = True;
317 status = cli_set_username(cli, state->user);
318 if (tevent_req_nterror(req, status)) {
319 return;
321 tevent_req_done(req);
324 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
326 return tevent_req_simple_recv_ntstatus(req);
329 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
330 const char *pass, size_t passlen,
331 const char *workgroup)
333 TALLOC_CTX *frame = talloc_stackframe();
334 struct event_context *ev;
335 struct tevent_req *req;
336 NTSTATUS status = NT_STATUS_NO_MEMORY;
338 if (cli_has_async_calls(cli)) {
340 * Can't use sync call while an async call is in flight
342 status = NT_STATUS_INVALID_PARAMETER;
343 goto fail;
345 ev = event_context_init(frame);
346 if (ev == NULL) {
347 goto fail;
349 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
350 workgroup);
351 if (req == NULL) {
352 goto fail;
354 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
355 goto fail;
357 status = cli_session_setup_lanman2_recv(req);
358 fail:
359 TALLOC_FREE(frame);
360 if (!NT_STATUS_IS_OK(status)) {
361 cli_set_error(cli, status);
363 return status;
366 /****************************************************************************
367 Work out suitable capabilities to offer the server.
368 ****************************************************************************/
370 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
372 uint32 capabilities = CAP_NT_SMBS;
374 if (!cli->force_dos_errors)
375 capabilities |= CAP_STATUS32;
377 if (cli->use_level_II_oplocks)
378 capabilities |= CAP_LEVEL_II_OPLOCKS;
380 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
381 return capabilities;
384 /****************************************************************************
385 Do a NT1 guest session setup.
386 ****************************************************************************/
388 struct cli_session_setup_guest_state {
389 struct cli_state *cli;
390 uint16_t vwv[13];
391 struct iovec bytes;
394 static void cli_session_setup_guest_done(struct tevent_req *subreq);
396 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
397 struct event_context *ev,
398 struct cli_state *cli,
399 struct tevent_req **psmbreq)
401 struct tevent_req *req, *subreq;
402 struct cli_session_setup_guest_state *state;
403 uint16_t *vwv;
404 uint8_t *bytes;
406 req = tevent_req_create(mem_ctx, &state,
407 struct cli_session_setup_guest_state);
408 if (req == NULL) {
409 return NULL;
411 state->cli = cli;
412 vwv = state->vwv;
414 SCVAL(vwv+0, 0, 0xFF);
415 SCVAL(vwv+0, 1, 0);
416 SSVAL(vwv+1, 0, 0);
417 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
418 SSVAL(vwv+3, 0, 2);
419 SSVAL(vwv+4, 0, cli->pid);
420 SIVAL(vwv+5, 0, cli->sesskey);
421 SSVAL(vwv+7, 0, 0);
422 SSVAL(vwv+8, 0, 0);
423 SSVAL(vwv+9, 0, 0);
424 SSVAL(vwv+10, 0, 0);
425 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
427 bytes = talloc_array(state, uint8_t, 0);
429 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
430 NULL);
431 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
432 NULL);
433 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
434 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
436 if (bytes == NULL) {
437 TALLOC_FREE(req);
438 return NULL;
441 state->bytes.iov_base = (void *)bytes;
442 state->bytes.iov_len = talloc_get_size(bytes);
444 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
445 1, &state->bytes);
446 if (subreq == NULL) {
447 TALLOC_FREE(req);
448 return NULL;
450 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
451 *psmbreq = subreq;
452 return req;
455 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
456 struct event_context *ev,
457 struct cli_state *cli)
459 struct tevent_req *req, *subreq;
460 NTSTATUS status;
462 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
463 if (req == NULL) {
464 return NULL;
467 status = cli_smb_req_send(subreq);
468 if (NT_STATUS_IS_OK(status)) {
469 tevent_req_nterror(req, status);
470 return tevent_req_post(req, ev);
472 return req;
475 static void cli_session_setup_guest_done(struct tevent_req *subreq)
477 struct tevent_req *req = tevent_req_callback_data(
478 subreq, struct tevent_req);
479 struct cli_session_setup_guest_state *state = tevent_req_data(
480 req, struct cli_session_setup_guest_state);
481 struct cli_state *cli = state->cli;
482 uint32_t num_bytes;
483 uint8_t *in;
484 char *inbuf;
485 uint8_t *bytes;
486 uint8_t *p;
487 NTSTATUS status;
488 ssize_t ret;
490 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
491 &num_bytes, &bytes);
492 TALLOC_FREE(subreq);
493 if (!NT_STATUS_IS_OK(status)) {
494 tevent_req_nterror(req, status);
495 return;
498 inbuf = (char *)in;
499 p = bytes;
501 cli->vuid = SVAL(inbuf, smb_uid);
503 status = smb_bytes_talloc_string(cli,
504 inbuf,
505 &cli->server_os,
507 bytes+num_bytes-p,
508 &ret);
510 if (!NT_STATUS_IS_OK(status)) {
511 tevent_req_nterror(req, status);
512 return;
514 p += ret;
516 status = smb_bytes_talloc_string(cli,
517 inbuf,
518 &cli->server_type,
520 bytes+num_bytes-p,
521 &ret);
523 if (!NT_STATUS_IS_OK(status)) {
524 tevent_req_nterror(req, status);
525 return;
527 p += ret;
529 status = smb_bytes_talloc_string(cli,
530 inbuf,
531 &cli->server_domain,
533 bytes+num_bytes-p,
534 &ret);
536 if (!NT_STATUS_IS_OK(status)) {
537 tevent_req_nterror(req, status);
538 return;
540 p += ret;
542 if (strstr(cli->server_type, "Samba")) {
543 cli->is_samba = True;
546 status = cli_set_username(cli, "");
547 if (!NT_STATUS_IS_OK(status)) {
548 tevent_req_nterror(req, status);
549 return;
551 tevent_req_done(req);
554 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
556 return tevent_req_simple_recv_ntstatus(req);
559 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
561 TALLOC_CTX *frame = talloc_stackframe();
562 struct event_context *ev;
563 struct tevent_req *req;
564 NTSTATUS status = NT_STATUS_OK;
566 if (cli_has_async_calls(cli)) {
568 * Can't use sync call while an async call is in flight
570 status = NT_STATUS_INVALID_PARAMETER;
571 goto fail;
574 ev = event_context_init(frame);
575 if (ev == NULL) {
576 status = NT_STATUS_NO_MEMORY;
577 goto fail;
580 req = cli_session_setup_guest_send(frame, ev, cli);
581 if (req == NULL) {
582 status = NT_STATUS_NO_MEMORY;
583 goto fail;
586 if (!tevent_req_poll(req, ev)) {
587 status = map_nt_error_from_unix(errno);
588 goto fail;
591 status = cli_session_setup_guest_recv(req);
592 fail:
593 TALLOC_FREE(frame);
594 if (!NT_STATUS_IS_OK(status)) {
595 cli_set_error(cli, status);
597 return status;
600 /****************************************************************************
601 Do a NT1 plaintext session setup.
602 ****************************************************************************/
604 struct cli_session_setup_plain_state {
605 struct cli_state *cli;
606 uint16_t vwv[13];
607 const char *user;
610 static void cli_session_setup_plain_done(struct tevent_req *subreq);
612 static struct tevent_req *cli_session_setup_plain_send(
613 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
614 struct cli_state *cli,
615 const char *user, const char *pass, const char *workgroup)
617 struct tevent_req *req, *subreq;
618 struct cli_session_setup_plain_state *state;
619 uint16_t *vwv;
620 uint8_t *bytes;
621 size_t passlen;
622 char *version;
624 req = tevent_req_create(mem_ctx, &state,
625 struct cli_session_setup_plain_state);
626 if (req == NULL) {
627 return NULL;
629 state->cli = cli;
630 state->user = user;
631 vwv = state->vwv;
633 SCVAL(vwv+0, 0, 0xff);
634 SCVAL(vwv+0, 1, 0);
635 SSVAL(vwv+1, 0, 0);
636 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
637 SSVAL(vwv+3, 0, 2);
638 SSVAL(vwv+4, 0, cli->pid);
639 SIVAL(vwv+5, 0, cli->sesskey);
640 SSVAL(vwv+7, 0, 0);
641 SSVAL(vwv+8, 0, 0);
642 SSVAL(vwv+9, 0, 0);
643 SSVAL(vwv+10, 0, 0);
644 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
646 bytes = talloc_array(state, uint8_t, 0);
647 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
648 &passlen);
649 if (tevent_req_nomem(bytes, req)) {
650 return tevent_req_post(req, ev);
652 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
654 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
655 user, strlen(user)+1, NULL);
656 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
657 workgroup, strlen(workgroup)+1, NULL);
658 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
659 "Unix", 5, NULL);
661 version = talloc_asprintf(talloc_tos(), "Samba %s",
662 samba_version_string());
663 if (tevent_req_nomem(version, req)){
664 return tevent_req_post(req, ev);
666 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
667 version, strlen(version)+1, NULL);
668 TALLOC_FREE(version);
670 if (tevent_req_nomem(bytes, req)) {
671 return tevent_req_post(req, ev);
674 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
675 talloc_get_size(bytes), bytes);
676 if (tevent_req_nomem(subreq, req)) {
677 return tevent_req_post(req, ev);
679 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
680 return req;
683 static void cli_session_setup_plain_done(struct tevent_req *subreq)
685 struct tevent_req *req = tevent_req_callback_data(
686 subreq, struct tevent_req);
687 struct cli_session_setup_plain_state *state = tevent_req_data(
688 req, struct cli_session_setup_plain_state);
689 struct cli_state *cli = state->cli;
690 uint32_t num_bytes;
691 uint8_t *in;
692 char *inbuf;
693 uint8_t *bytes;
694 uint8_t *p;
695 NTSTATUS status;
696 ssize_t ret;
698 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
699 &num_bytes, &bytes);
700 TALLOC_FREE(subreq);
701 if (tevent_req_nterror(req, status)) {
702 return;
705 inbuf = (char *)in;
706 p = bytes;
708 cli->vuid = SVAL(inbuf, smb_uid);
710 status = smb_bytes_talloc_string(cli,
711 inbuf,
712 &cli->server_os,
714 bytes+num_bytes-p,
715 &ret);
717 if (!NT_STATUS_IS_OK(status)) {
718 tevent_req_nterror(req, status);
719 return;
721 p += ret;
723 status = smb_bytes_talloc_string(cli,
724 inbuf,
725 &cli->server_type,
727 bytes+num_bytes-p,
728 &ret);
730 if (!NT_STATUS_IS_OK(status)) {
731 tevent_req_nterror(req, status);
732 return;
734 p += ret;
736 status = smb_bytes_talloc_string(cli,
737 inbuf,
738 &cli->server_domain,
740 bytes+num_bytes-p,
741 &ret);
743 if (!NT_STATUS_IS_OK(status)) {
744 tevent_req_nterror(req, status);
745 return;
747 p += ret;
749 status = cli_set_username(cli, state->user);
750 if (tevent_req_nterror(req, status)) {
751 return;
753 if (strstr(cli->server_type, "Samba")) {
754 cli->is_samba = True;
756 tevent_req_done(req);
759 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
761 return tevent_req_simple_recv_ntstatus(req);
764 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
765 const char *user, const char *pass,
766 const char *workgroup)
768 TALLOC_CTX *frame = talloc_stackframe();
769 struct event_context *ev;
770 struct tevent_req *req;
771 NTSTATUS status = NT_STATUS_NO_MEMORY;
773 if (cli_has_async_calls(cli)) {
775 * Can't use sync call while an async call is in flight
777 status = NT_STATUS_INVALID_PARAMETER;
778 goto fail;
780 ev = event_context_init(frame);
781 if (ev == NULL) {
782 goto fail;
784 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
785 workgroup);
786 if (req == NULL) {
787 goto fail;
789 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
790 goto fail;
792 status = cli_session_setup_plain_recv(req);
793 fail:
794 TALLOC_FREE(frame);
795 if (!NT_STATUS_IS_OK(status)) {
796 cli_set_error(cli, status);
798 return status;
801 /****************************************************************************
802 do a NT1 NTLM/LM encrypted session setup - for when extended security
803 is not negotiated.
804 @param cli client state to create do session setup on
805 @param user username
806 @param pass *either* cleartext password (passlen !=24) or LM response.
807 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
808 @param workgroup The user's domain.
809 ****************************************************************************/
811 struct cli_session_setup_nt1_state {
812 struct cli_state *cli;
813 uint16_t vwv[13];
814 DATA_BLOB response;
815 DATA_BLOB session_key;
816 const char *user;
819 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
821 static struct tevent_req *cli_session_setup_nt1_send(
822 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
823 struct cli_state *cli, const char *user,
824 const char *pass, size_t passlen,
825 const char *ntpass, size_t ntpasslen,
826 const char *workgroup)
828 struct tevent_req *req, *subreq;
829 struct cli_session_setup_nt1_state *state;
830 DATA_BLOB lm_response = data_blob_null;
831 DATA_BLOB nt_response = data_blob_null;
832 DATA_BLOB session_key = data_blob_null;
833 uint16_t *vwv;
834 uint8_t *bytes;
835 char *workgroup_upper;
837 req = tevent_req_create(mem_ctx, &state,
838 struct cli_session_setup_nt1_state);
839 if (req == NULL) {
840 return NULL;
842 state->cli = cli;
843 state->user = user;
844 vwv = state->vwv;
846 if (passlen == 0) {
847 /* do nothing - guest login */
848 } else if (passlen != 24) {
849 if (lp_client_ntlmv2_auth()) {
850 DATA_BLOB server_chal;
851 DATA_BLOB names_blob;
853 server_chal = data_blob(cli->secblob.data,
854 MIN(cli->secblob.length, 8));
855 if (tevent_req_nomem(server_chal.data, req)) {
856 return tevent_req_post(req, ev);
860 * note that the 'workgroup' here is a best
861 * guess - we don't know the server's domain
862 * at this point. The 'server name' is also
863 * dodgy...
865 names_blob = NTLMv2_generate_names_blob(
866 NULL, cli->called.name, workgroup);
868 if (tevent_req_nomem(names_blob.data, req)) {
869 return tevent_req_post(req, ev);
872 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
873 &server_chal, &names_blob,
874 &lm_response, &nt_response,
875 NULL, &session_key)) {
876 data_blob_free(&names_blob);
877 data_blob_free(&server_chal);
878 tevent_req_nterror(
879 req, NT_STATUS_ACCESS_DENIED);
880 return tevent_req_post(req, ev);
882 data_blob_free(&names_blob);
883 data_blob_free(&server_chal);
885 } else {
886 uchar nt_hash[16];
887 E_md4hash(pass, nt_hash);
889 #ifdef LANMAN_ONLY
890 nt_response = data_blob_null;
891 #else
892 nt_response = data_blob(NULL, 24);
893 if (tevent_req_nomem(nt_response.data, req)) {
894 return tevent_req_post(req, ev);
897 SMBNTencrypt(pass, cli->secblob.data,
898 nt_response.data);
899 #endif
900 /* non encrypted password supplied. Ignore ntpass. */
901 if (lp_client_lanman_auth()) {
903 lm_response = data_blob(NULL, 24);
904 if (tevent_req_nomem(lm_response.data, req)) {
905 return tevent_req_post(req, ev);
908 if (!SMBencrypt(pass,cli->secblob.data,
909 lm_response.data)) {
911 * Oops, the LM response is
912 * invalid, just put the NT
913 * response there instead
915 data_blob_free(&lm_response);
916 lm_response = data_blob(
917 nt_response.data,
918 nt_response.length);
920 } else {
922 * LM disabled, place NT# in LM field
923 * instead
925 lm_response = data_blob(
926 nt_response.data, nt_response.length);
929 if (tevent_req_nomem(lm_response.data, req)) {
930 return tevent_req_post(req, ev);
933 session_key = data_blob(NULL, 16);
934 if (tevent_req_nomem(session_key.data, req)) {
935 return tevent_req_post(req, ev);
937 #ifdef LANMAN_ONLY
938 E_deshash(pass, session_key.data);
939 memset(&session_key.data[8], '\0', 8);
940 #else
941 SMBsesskeygen_ntv1(nt_hash, session_key.data);
942 #endif
944 cli_temp_set_signing(cli);
945 } else {
946 /* pre-encrypted password supplied. Only used for
947 security=server, can't do
948 signing because we don't have original key */
950 lm_response = data_blob(pass, passlen);
951 if (tevent_req_nomem(lm_response.data, req)) {
952 return tevent_req_post(req, ev);
955 nt_response = data_blob(ntpass, ntpasslen);
956 if (tevent_req_nomem(nt_response.data, req)) {
957 return tevent_req_post(req, ev);
961 #ifdef LANMAN_ONLY
962 state->response = data_blob_talloc(
963 state, lm_response.data, lm_response.length);
964 #else
965 state->response = data_blob_talloc(
966 state, nt_response.data, nt_response.length);
967 #endif
968 if (tevent_req_nomem(state->response.data, req)) {
969 return tevent_req_post(req, ev);
972 if (session_key.data) {
973 state->session_key = data_blob_talloc(
974 state, session_key.data, session_key.length);
975 if (tevent_req_nomem(state->session_key.data, req)) {
976 return tevent_req_post(req, ev);
979 data_blob_free(&session_key);
981 SCVAL(vwv+0, 0, 0xff);
982 SCVAL(vwv+0, 1, 0);
983 SSVAL(vwv+1, 0, 0);
984 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
985 SSVAL(vwv+3, 0, 2);
986 SSVAL(vwv+4, 0, cli->pid);
987 SIVAL(vwv+5, 0, cli->sesskey);
988 SSVAL(vwv+7, 0, lm_response.length);
989 SSVAL(vwv+8, 0, nt_response.length);
990 SSVAL(vwv+9, 0, 0);
991 SSVAL(vwv+10, 0, 0);
992 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
994 bytes = talloc_array(state, uint8_t,
995 lm_response.length + nt_response.length);
996 if (tevent_req_nomem(bytes, req)) {
997 return tevent_req_post(req, ev);
999 if (lm_response.length != 0) {
1000 memcpy(bytes, lm_response.data, lm_response.length);
1002 if (nt_response.length != 0) {
1003 memcpy(bytes + lm_response.length,
1004 nt_response.data, nt_response.length);
1006 data_blob_free(&lm_response);
1007 data_blob_free(&nt_response);
1009 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1010 user, strlen(user)+1, NULL);
1013 * Upper case here might help some NTLMv2 implementations
1015 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
1016 if (tevent_req_nomem(workgroup_upper, req)) {
1017 return tevent_req_post(req, ev);
1019 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1020 workgroup_upper, strlen(workgroup_upper)+1,
1021 NULL);
1022 TALLOC_FREE(workgroup_upper);
1024 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
1025 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
1026 if (tevent_req_nomem(bytes, req)) {
1027 return tevent_req_post(req, ev);
1030 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1031 talloc_get_size(bytes), bytes);
1032 if (tevent_req_nomem(subreq, req)) {
1033 return tevent_req_post(req, ev);
1035 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1036 return req;
1039 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1041 struct tevent_req *req = tevent_req_callback_data(
1042 subreq, struct tevent_req);
1043 struct cli_session_setup_nt1_state *state = tevent_req_data(
1044 req, struct cli_session_setup_nt1_state);
1045 struct cli_state *cli = state->cli;
1046 uint32_t num_bytes;
1047 uint8_t *in;
1048 char *inbuf;
1049 uint8_t *bytes;
1050 uint8_t *p;
1051 NTSTATUS status;
1052 ssize_t ret;
1054 status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
1055 &num_bytes, &bytes);
1056 TALLOC_FREE(subreq);
1057 if (!NT_STATUS_IS_OK(status)) {
1058 tevent_req_nterror(req, status);
1059 return;
1062 inbuf = (char *)in;
1063 p = bytes;
1065 cli->vuid = SVAL(inbuf, smb_uid);
1067 status = smb_bytes_talloc_string(cli,
1068 inbuf,
1069 &cli->server_os,
1071 bytes+num_bytes-p,
1072 &ret);
1073 if (!NT_STATUS_IS_OK(status)) {
1074 tevent_req_nterror(req, status);
1075 return;
1077 p += ret;
1079 status = smb_bytes_talloc_string(cli,
1080 inbuf,
1081 &cli->server_type,
1083 bytes+num_bytes-p,
1084 &ret);
1085 if (!NT_STATUS_IS_OK(status)) {
1086 tevent_req_nterror(req, status);
1087 return;
1089 p += ret;
1091 status = smb_bytes_talloc_string(cli,
1092 inbuf,
1093 &cli->server_domain,
1095 bytes+num_bytes-p,
1096 &ret);
1097 if (!NT_STATUS_IS_OK(status)) {
1098 tevent_req_nterror(req, status);
1099 return;
1101 p += ret;
1103 if (strstr(cli->server_type, "Samba")) {
1104 cli->is_samba = True;
1107 status = cli_set_username(cli, state->user);
1108 if (tevent_req_nterror(req, status)) {
1109 return;
1111 if (cli_simple_set_signing(cli, state->session_key, state->response)
1112 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1113 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1114 return;
1116 if (state->session_key.data) {
1117 /* Have plaintext orginal */
1118 cli_set_session_key(cli, state->session_key);
1120 tevent_req_done(req);
1123 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1125 return tevent_req_simple_recv_ntstatus(req);
1128 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1129 const char *pass, size_t passlen,
1130 const char *ntpass, size_t ntpasslen,
1131 const char *workgroup)
1133 TALLOC_CTX *frame = talloc_stackframe();
1134 struct event_context *ev;
1135 struct tevent_req *req;
1136 NTSTATUS status = NT_STATUS_NO_MEMORY;
1138 if (cli_has_async_calls(cli)) {
1140 * Can't use sync call while an async call is in flight
1142 status = NT_STATUS_INVALID_PARAMETER;
1143 goto fail;
1145 ev = event_context_init(frame);
1146 if (ev == NULL) {
1147 goto fail;
1149 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1150 ntpass, ntpasslen, workgroup);
1151 if (req == NULL) {
1152 goto fail;
1154 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1155 goto fail;
1157 status = cli_session_setup_nt1_recv(req);
1158 fail:
1159 TALLOC_FREE(frame);
1160 if (!NT_STATUS_IS_OK(status)) {
1161 cli_set_error(cli, status);
1163 return status;
1166 /* The following is calculated from :
1167 * (smb_size-4) = 35
1168 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1169 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1170 * end of packet.
1173 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1175 struct cli_sesssetup_blob_state {
1176 struct tevent_context *ev;
1177 struct cli_state *cli;
1178 DATA_BLOB blob;
1179 uint16_t max_blob_size;
1180 uint16_t vwv[12];
1181 uint8_t *buf;
1183 NTSTATUS status;
1184 char *inbuf;
1185 DATA_BLOB ret_blob;
1188 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1189 struct tevent_req **psubreq);
1190 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1192 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1193 struct tevent_context *ev,
1194 struct cli_state *cli,
1195 DATA_BLOB blob)
1197 struct tevent_req *req, *subreq;
1198 struct cli_sesssetup_blob_state *state;
1200 req = tevent_req_create(mem_ctx, &state,
1201 struct cli_sesssetup_blob_state);
1202 if (req == NULL) {
1203 return NULL;
1205 state->ev = ev;
1206 state->blob = blob;
1207 state->cli = cli;
1209 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
1210 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1211 "(was %u, need minimum %u)\n",
1212 (unsigned int)cli->max_xmit,
1213 BASE_SESSSETUP_BLOB_PACKET_SIZE));
1214 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1215 return tevent_req_post(req, ev);
1217 state->max_blob_size =
1218 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
1220 if (!cli_sesssetup_blob_next(state, &subreq)) {
1221 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1222 return tevent_req_post(req, ev);
1224 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1225 return req;
1228 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1229 struct tevent_req **psubreq)
1231 struct tevent_req *subreq;
1232 uint16_t thistime;
1234 SCVAL(state->vwv+0, 0, 0xFF);
1235 SCVAL(state->vwv+0, 1, 0);
1236 SSVAL(state->vwv+1, 0, 0);
1237 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1238 SSVAL(state->vwv+3, 0, 2);
1239 SSVAL(state->vwv+4, 0, 1);
1240 SIVAL(state->vwv+5, 0, 0);
1242 thistime = MIN(state->blob.length, state->max_blob_size);
1243 SSVAL(state->vwv+7, 0, thistime);
1245 SSVAL(state->vwv+8, 0, 0);
1246 SSVAL(state->vwv+9, 0, 0);
1247 SIVAL(state->vwv+10, 0,
1248 cli_session_setup_capabilities(state->cli)
1249 | CAP_EXTENDED_SECURITY);
1251 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1252 thistime);
1253 if (state->buf == NULL) {
1254 return false;
1256 state->blob.data += thistime;
1257 state->blob.length -= thistime;
1259 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1260 "Unix", 5, NULL);
1261 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1262 "Samba", 6, NULL);
1263 if (state->buf == NULL) {
1264 return false;
1266 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1267 12, state->vwv,
1268 talloc_get_size(state->buf), state->buf);
1269 if (subreq == NULL) {
1270 return false;
1272 *psubreq = subreq;
1273 return true;
1276 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1278 struct tevent_req *req = tevent_req_callback_data(
1279 subreq, struct tevent_req);
1280 struct cli_sesssetup_blob_state *state = tevent_req_data(
1281 req, struct cli_sesssetup_blob_state);
1282 struct cli_state *cli = state->cli;
1283 uint8_t wct;
1284 uint16_t *vwv;
1285 uint32_t num_bytes;
1286 uint8_t *bytes;
1287 NTSTATUS status;
1288 uint8_t *p;
1289 uint16_t blob_length;
1290 uint8_t *inbuf;
1291 ssize_t ret;
1293 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
1294 &num_bytes, &bytes);
1295 TALLOC_FREE(subreq);
1296 if (!NT_STATUS_IS_OK(status)
1297 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1298 tevent_req_nterror(req, status);
1299 return;
1302 state->status = status;
1303 TALLOC_FREE(state->buf);
1305 state->inbuf = (char *)inbuf;
1306 cli->vuid = SVAL(state->inbuf, smb_uid);
1308 blob_length = SVAL(vwv+3, 0);
1309 if (blob_length > num_bytes) {
1310 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1311 return;
1313 state->ret_blob = data_blob_const(bytes, blob_length);
1315 p = bytes + blob_length;
1317 status = smb_bytes_talloc_string(cli,
1318 (char *)inbuf,
1319 &cli->server_os,
1321 bytes+num_bytes-p,
1322 &ret);
1324 if (!NT_STATUS_IS_OK(status)) {
1325 tevent_req_nterror(req, status);
1326 return;
1328 p += ret;
1330 status = smb_bytes_talloc_string(cli,
1331 (char *)inbuf,
1332 &cli->server_type,
1334 bytes+num_bytes-p,
1335 &ret);
1337 if (!NT_STATUS_IS_OK(status)) {
1338 tevent_req_nterror(req, status);
1339 return;
1341 p += ret;
1343 status = smb_bytes_talloc_string(cli,
1344 (char *)inbuf,
1345 &cli->server_domain,
1347 bytes+num_bytes-p,
1348 &ret);
1350 if (!NT_STATUS_IS_OK(status)) {
1351 tevent_req_nterror(req, status);
1352 return;
1354 p += ret;
1356 if (strstr(cli->server_type, "Samba")) {
1357 cli->is_samba = True;
1360 if (state->blob.length != 0) {
1362 * More to send
1364 if (!cli_sesssetup_blob_next(state, &subreq)) {
1365 tevent_req_nomem(NULL, req);
1366 return;
1368 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1369 return;
1371 tevent_req_done(req);
1374 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1375 TALLOC_CTX *mem_ctx,
1376 DATA_BLOB *pblob,
1377 char **pinbuf)
1379 struct cli_sesssetup_blob_state *state = tevent_req_data(
1380 req, struct cli_sesssetup_blob_state);
1381 NTSTATUS status;
1382 char *inbuf;
1384 if (tevent_req_is_nterror(req, &status)) {
1385 state->cli->vuid = 0;
1386 return status;
1389 inbuf = talloc_move(mem_ctx, &state->inbuf);
1390 if (pblob != NULL) {
1391 *pblob = state->ret_blob;
1393 if (pinbuf != NULL) {
1394 *pinbuf = inbuf;
1396 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1397 return state->status;
1400 #ifdef HAVE_KRB5
1402 /****************************************************************************
1403 Use in-memory credentials cache
1404 ****************************************************************************/
1406 static void use_in_memory_ccache(void) {
1407 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1410 /****************************************************************************
1411 Do a spnego/kerberos encrypted session setup.
1412 ****************************************************************************/
1414 struct cli_session_setup_kerberos_state {
1415 struct cli_state *cli;
1416 DATA_BLOB negTokenTarg;
1417 DATA_BLOB session_key_krb5;
1418 ADS_STATUS ads_status;
1421 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1423 static struct tevent_req *cli_session_setup_kerberos_send(
1424 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1425 const char *principal, const char *workgroup)
1427 struct tevent_req *req, *subreq;
1428 struct cli_session_setup_kerberos_state *state;
1429 int rc;
1431 DEBUG(2,("Doing kerberos session setup\n"));
1433 req = tevent_req_create(mem_ctx, &state,
1434 struct cli_session_setup_kerberos_state);
1435 if (req == NULL) {
1436 return NULL;
1438 state->cli = cli;
1439 state->ads_status = ADS_SUCCESS;
1441 cli_temp_set_signing(cli);
1444 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1445 * we have to acquire a ticket. To be fixed later :-)
1447 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1448 &state->session_key_krb5, 0, NULL);
1449 if (rc) {
1450 DEBUG(1, ("cli_session_setup_kerberos: "
1451 "spnego_gen_krb5_negTokenInit failed: %s\n",
1452 error_message(rc)));
1453 state->ads_status = ADS_ERROR_KRB5(rc);
1454 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1455 return tevent_req_post(req, ev);
1458 #if 0
1459 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1460 state->negTokenTarg.length);
1461 #endif
1463 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1464 if (tevent_req_nomem(subreq, req)) {
1465 return tevent_req_post(req, ev);
1467 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1468 return req;
1471 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1473 struct tevent_req *req = tevent_req_callback_data(
1474 subreq, struct tevent_req);
1475 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1476 req, struct cli_session_setup_kerberos_state);
1477 char *inbuf = NULL;
1478 NTSTATUS status;
1480 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
1481 if (!NT_STATUS_IS_OK(status)) {
1482 TALLOC_FREE(subreq);
1483 tevent_req_nterror(req, status);
1484 return;
1487 cli_set_session_key(state->cli, state->session_key_krb5);
1489 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
1490 data_blob_null)
1491 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1492 TALLOC_FREE(subreq);
1493 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1494 return;
1496 TALLOC_FREE(subreq);
1497 tevent_req_done(req);
1500 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1502 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1503 req, struct cli_session_setup_kerberos_state);
1504 NTSTATUS status;
1506 if (tevent_req_is_nterror(req, &status)) {
1507 return ADS_ERROR_NT(status);
1509 return state->ads_status;
1512 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1513 const char *principal,
1514 const char *workgroup)
1516 struct tevent_context *ev;
1517 struct tevent_req *req;
1518 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1520 if (cli_has_async_calls(cli)) {
1521 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1523 ev = tevent_context_init(talloc_tos());
1524 if (ev == NULL) {
1525 goto fail;
1527 req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
1528 workgroup);
1529 if (req == NULL) {
1530 goto fail;
1532 if (!tevent_req_poll(req, ev)) {
1533 status = ADS_ERROR_SYSTEM(errno);
1534 goto fail;
1536 status = cli_session_setup_kerberos_recv(req);
1537 fail:
1538 TALLOC_FREE(ev);
1539 return status;
1541 #endif /* HAVE_KRB5 */
1543 /****************************************************************************
1544 Do a spnego/NTLMSSP encrypted session setup.
1545 ****************************************************************************/
1547 struct cli_session_setup_ntlmssp_state {
1548 struct tevent_context *ev;
1549 struct cli_state *cli;
1550 struct ntlmssp_state *ntlmssp_state;
1551 int turn;
1552 DATA_BLOB blob_out;
1555 static int cli_session_setup_ntlmssp_state_destructor(
1556 struct cli_session_setup_ntlmssp_state *state)
1558 if (state->ntlmssp_state != NULL) {
1559 TALLOC_FREE(state->ntlmssp_state);
1561 return 0;
1564 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1566 static struct tevent_req *cli_session_setup_ntlmssp_send(
1567 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1568 const char *user, const char *pass, const char *domain)
1570 struct tevent_req *req, *subreq;
1571 struct cli_session_setup_ntlmssp_state *state;
1572 NTSTATUS status;
1573 DATA_BLOB blob_out;
1574 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1576 req = tevent_req_create(mem_ctx, &state,
1577 struct cli_session_setup_ntlmssp_state);
1578 if (req == NULL) {
1579 return NULL;
1581 state->ev = ev;
1582 state->cli = cli;
1583 state->turn = 1;
1585 state->ntlmssp_state = NULL;
1586 talloc_set_destructor(
1587 state, cli_session_setup_ntlmssp_state_destructor);
1589 cli_temp_set_signing(cli);
1591 status = ntlmssp_client_start(state,
1592 global_myname(),
1593 lp_workgroup(),
1594 lp_client_ntlmv2_auth(),
1595 &state->ntlmssp_state);
1596 if (!NT_STATUS_IS_OK(status)) {
1597 goto fail;
1599 ntlmssp_want_feature(state->ntlmssp_state,
1600 NTLMSSP_FEATURE_SESSION_KEY);
1601 if (cli->use_ccache) {
1602 ntlmssp_want_feature(state->ntlmssp_state,
1603 NTLMSSP_FEATURE_CCACHE);
1605 status = ntlmssp_set_username(state->ntlmssp_state, user);
1606 if (!NT_STATUS_IS_OK(status)) {
1607 goto fail;
1609 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 goto fail;
1613 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 goto fail;
1617 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1618 &blob_out);
1619 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1620 goto fail;
1623 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1624 data_blob_free(&blob_out);
1626 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1627 if (tevent_req_nomem(subreq, req)) {
1628 return tevent_req_post(req, ev);
1630 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1631 return req;
1632 fail:
1633 tevent_req_nterror(req, status);
1634 return tevent_req_post(req, ev);
1637 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1639 struct tevent_req *req = tevent_req_callback_data(
1640 subreq, struct tevent_req);
1641 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1642 req, struct cli_session_setup_ntlmssp_state);
1643 DATA_BLOB blob_in, msg_in, blob_out;
1644 char *inbuf = NULL;
1645 bool parse_ret;
1646 NTSTATUS status;
1648 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1649 &inbuf);
1650 TALLOC_FREE(subreq);
1651 data_blob_free(&state->blob_out);
1653 if (NT_STATUS_IS_OK(status)) {
1654 if (state->cli->server_domain[0] == '\0') {
1655 TALLOC_FREE(state->cli->server_domain);
1656 state->cli->server_domain = talloc_strdup(state->cli,
1657 state->ntlmssp_state->server.netbios_domain);
1658 if (state->cli->server_domain == NULL) {
1659 TALLOC_FREE(subreq);
1660 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1661 return;
1664 cli_set_session_key(
1665 state->cli, state->ntlmssp_state->session_key);
1667 if (cli_simple_set_signing(
1668 state->cli, state->ntlmssp_state->session_key,
1669 data_blob_null)
1670 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1671 TALLOC_FREE(subreq);
1672 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1673 return;
1675 TALLOC_FREE(subreq);
1676 TALLOC_FREE(state->ntlmssp_state);
1677 tevent_req_done(req);
1678 return;
1680 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1681 tevent_req_nterror(req, status);
1682 return;
1685 if (blob_in.length == 0) {
1686 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1687 return;
1690 if ((state->turn == 1)
1691 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1692 DATA_BLOB tmp_blob = data_blob_null;
1693 /* the server might give us back two challenges */
1694 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1695 &tmp_blob);
1696 data_blob_free(&tmp_blob);
1697 } else {
1698 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1699 OID_NTLMSSP, &msg_in);
1701 state->turn += 1;
1703 if (!parse_ret) {
1704 DEBUG(3,("Failed to parse auth response\n"));
1705 if (NT_STATUS_IS_OK(status)
1706 || NT_STATUS_EQUAL(status,
1707 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1708 tevent_req_nterror(
1709 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1710 return;
1714 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1716 if (!NT_STATUS_IS_OK(status)
1717 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1718 TALLOC_FREE(subreq);
1719 TALLOC_FREE(state->ntlmssp_state);
1720 tevent_req_nterror(req, status);
1721 return;
1724 state->blob_out = spnego_gen_auth(state, blob_out);
1725 TALLOC_FREE(subreq);
1726 if (tevent_req_nomem(state->blob_out.data, req)) {
1727 return;
1730 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1731 state->blob_out);
1732 if (tevent_req_nomem(subreq, req)) {
1733 return;
1735 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1738 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1740 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1741 req, struct cli_session_setup_ntlmssp_state);
1742 NTSTATUS status;
1744 if (tevent_req_is_nterror(req, &status)) {
1745 state->cli->vuid = 0;
1746 return status;
1748 return NT_STATUS_OK;
1751 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1752 const char *user,
1753 const char *pass,
1754 const char *domain)
1756 struct tevent_context *ev;
1757 struct tevent_req *req;
1758 NTSTATUS status = NT_STATUS_NO_MEMORY;
1760 if (cli_has_async_calls(cli)) {
1761 return NT_STATUS_INVALID_PARAMETER;
1763 ev = tevent_context_init(talloc_tos());
1764 if (ev == NULL) {
1765 goto fail;
1767 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1768 if (req == NULL) {
1769 goto fail;
1771 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1772 goto fail;
1774 status = cli_session_setup_ntlmssp_recv(req);
1775 fail:
1776 TALLOC_FREE(ev);
1777 if (!NT_STATUS_IS_OK(status)) {
1778 cli_set_error(cli, status);
1780 return status;
1783 /****************************************************************************
1784 Do a spnego encrypted session setup.
1786 user_domain: The shortname of the domain the user/machine is a member of.
1787 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1788 ****************************************************************************/
1790 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1791 const char *pass, const char *user_domain,
1792 const char * dest_realm)
1794 char *principal = NULL;
1795 char *OIDs[ASN1_MAX_OIDS];
1796 int i;
1797 DATA_BLOB blob;
1798 const char *p = NULL;
1799 char *account = NULL;
1800 NTSTATUS status;
1802 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1804 /* the server might not even do spnego */
1805 if (cli->secblob.length <= 16) {
1806 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1807 goto ntlmssp;
1810 #if 0
1811 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1812 #endif
1814 /* there is 16 bytes of GUID before the real spnego packet starts */
1815 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1817 /* The server sent us the first part of the SPNEGO exchange in the
1818 * negprot reply. It is WRONG to depend on the principal sent in the
1819 * negprot reply, but right now we do it. If we don't receive one,
1820 * we try to best guess, then fall back to NTLM. */
1821 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1822 OIDs[0] == NULL) {
1823 data_blob_free(&blob);
1824 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1826 data_blob_free(&blob);
1828 /* make sure the server understands kerberos */
1829 for (i=0;OIDs[i];i++) {
1830 if (i == 0)
1831 DEBUG(3,("got OID=%s\n", OIDs[i]));
1832 else
1833 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1834 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1835 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1836 cli->got_kerberos_mechanism = True;
1838 talloc_free(OIDs[i]);
1841 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1843 status = cli_set_username(cli, user);
1844 if (!NT_STATUS_IS_OK(status)) {
1845 TALLOC_FREE(principal);
1846 return ADS_ERROR_NT(status);
1849 #ifdef HAVE_KRB5
1850 /* If password is set we reauthenticate to kerberos server
1851 * and do not store results */
1853 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1854 ADS_STATUS rc;
1856 if (pass && *pass) {
1857 int ret;
1859 use_in_memory_ccache();
1860 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1862 if (ret){
1863 TALLOC_FREE(principal);
1864 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1865 if (cli->fallback_after_kerberos)
1866 goto ntlmssp;
1867 return ADS_ERROR_KRB5(ret);
1871 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1873 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1874 TALLOC_FREE(principal);
1877 if (principal == NULL &&
1878 !is_ipaddress(cli->desthost) &&
1879 !strequal(STAR_SMBSERVER,
1880 cli->desthost)) {
1881 char *realm = NULL;
1882 char *host = NULL;
1883 DEBUG(3,("cli_session_setup_spnego: using target "
1884 "hostname not SPNEGO principal\n"));
1886 host = strchr_m(cli->desthost, '.');
1887 if (dest_realm) {
1888 realm = SMB_STRDUP(dest_realm);
1889 strupper_m(realm);
1890 } else {
1891 if (host) {
1892 /* DNS name. */
1893 realm = kerberos_get_realm_from_hostname(cli->desthost);
1894 } else {
1895 /* NetBIOS name - use our realm. */
1896 realm = kerberos_get_default_realm_from_ccache();
1900 if (realm && *realm) {
1901 principal = talloc_asprintf(talloc_tos(),
1902 "cifs/%s@%s",
1903 cli->desthost,
1904 realm);
1905 if (!principal) {
1906 SAFE_FREE(realm);
1907 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1909 DEBUG(3,("cli_session_setup_spnego: guessed "
1910 "server principal=%s\n",
1911 principal ? principal : "<null>"));
1913 SAFE_FREE(realm);
1916 if (principal) {
1917 rc = cli_session_setup_kerberos(cli, principal,
1918 dest_realm);
1919 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1920 TALLOC_FREE(principal);
1921 return rc;
1925 #endif
1927 TALLOC_FREE(principal);
1929 ntlmssp:
1931 account = talloc_strdup(talloc_tos(), user);
1932 if (!account) {
1933 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1936 /* when falling back to ntlmssp while authenticating with a machine
1937 * account strip off the realm - gd */
1939 if ((p = strchr_m(user, '@')) != NULL) {
1940 account[PTR_DIFF(p,user)] = '\0';
1943 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1946 /****************************************************************************
1947 Send a session setup. The username and workgroup is in UNIX character
1948 format and must be converted to DOS codepage format before sending. If the
1949 password is in plaintext, the same should be done.
1950 ****************************************************************************/
1952 NTSTATUS cli_session_setup(struct cli_state *cli,
1953 const char *user,
1954 const char *pass, int passlen,
1955 const char *ntpass, int ntpasslen,
1956 const char *workgroup)
1958 char *p;
1959 char *user2;
1961 if (user) {
1962 user2 = talloc_strdup(talloc_tos(), user);
1963 } else {
1964 user2 = talloc_strdup(talloc_tos(), "");
1966 if (user2 == NULL) {
1967 return NT_STATUS_NO_MEMORY;
1970 if (!workgroup) {
1971 workgroup = "";
1974 /* allow for workgroups as part of the username */
1975 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1976 (p=strchr_m(user2,*lp_winbind_separator()))) {
1977 *p = 0;
1978 user = p+1;
1979 workgroup = user2;
1982 if (cli->protocol < PROTOCOL_LANMAN1) {
1983 return NT_STATUS_OK;
1986 /* now work out what sort of session setup we are going to
1987 do. I have split this into separate functions to make the
1988 flow a bit easier to understand (tridge) */
1990 /* if its an older server then we have to use the older request format */
1992 if (cli->protocol < PROTOCOL_NT1) {
1993 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1994 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
1995 " or 'client ntlmv2 auth = yes'\n"));
1996 return NT_STATUS_ACCESS_DENIED;
1999 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2000 !lp_client_plaintext_auth() && (*pass)) {
2001 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2002 " or 'client ntlmv2 auth = yes'\n"));
2003 return NT_STATUS_ACCESS_DENIED;
2006 return cli_session_setup_lanman2(cli, user, pass, passlen,
2007 workgroup);
2010 /* if no user is supplied then we have to do an anonymous connection.
2011 passwords are ignored */
2013 if (!user || !*user)
2014 return cli_session_setup_guest(cli);
2016 /* if the server is share level then send a plaintext null
2017 password at this point. The password is sent in the tree
2018 connect */
2020 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2021 return cli_session_setup_plain(cli, user, "", workgroup);
2023 /* if the server doesn't support encryption then we have to use
2024 plaintext. The second password is ignored */
2026 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2027 if (!lp_client_plaintext_auth() && (*pass)) {
2028 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2029 " or 'client ntlmv2 auth = yes'\n"));
2030 return NT_STATUS_ACCESS_DENIED;
2032 return cli_session_setup_plain(cli, user, pass, workgroup);
2035 /* if the server supports extended security then use SPNEGO */
2037 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
2038 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2039 workgroup, NULL);
2040 if (!ADS_ERR_OK(status)) {
2041 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2042 return ads_ntstatus(status);
2044 } else {
2045 NTSTATUS status;
2047 /* otherwise do a NT1 style session setup */
2048 status = cli_session_setup_nt1(cli, user, pass, passlen,
2049 ntpass, ntpasslen, workgroup);
2050 if (!NT_STATUS_IS_OK(status)) {
2051 DEBUG(3,("cli_session_setup: NT1 session setup "
2052 "failed: %s\n", nt_errstr(status)));
2053 return status;
2057 if (strstr(cli->server_type, "Samba")) {
2058 cli->is_samba = True;
2061 return NT_STATUS_OK;
2064 /****************************************************************************
2065 Send a uloggoff.
2066 *****************************************************************************/
2068 struct cli_ulogoff_state {
2069 struct cli_state *cli;
2070 uint16_t vwv[3];
2073 static void cli_ulogoff_done(struct tevent_req *subreq);
2075 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2076 struct tevent_context *ev,
2077 struct cli_state *cli)
2079 struct tevent_req *req, *subreq;
2080 struct cli_ulogoff_state *state;
2082 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2083 if (req == NULL) {
2084 return NULL;
2086 state->cli = cli;
2088 SCVAL(state->vwv+0, 0, 0xFF);
2089 SCVAL(state->vwv+1, 0, 0);
2090 SSVAL(state->vwv+2, 0, 0);
2092 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2093 0, NULL);
2094 if (tevent_req_nomem(subreq, req)) {
2095 return tevent_req_post(req, ev);
2097 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2098 return req;
2101 static void cli_ulogoff_done(struct tevent_req *subreq)
2103 struct tevent_req *req = tevent_req_callback_data(
2104 subreq, struct tevent_req);
2105 struct cli_ulogoff_state *state = tevent_req_data(
2106 req, struct cli_ulogoff_state);
2107 NTSTATUS status;
2109 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2110 if (!NT_STATUS_IS_OK(status)) {
2111 tevent_req_nterror(req, status);
2112 return;
2114 state->cli->vuid = -1;
2115 tevent_req_done(req);
2118 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2120 return tevent_req_simple_recv_ntstatus(req);
2123 NTSTATUS cli_ulogoff(struct cli_state *cli)
2125 struct tevent_context *ev;
2126 struct tevent_req *req;
2127 NTSTATUS status = NT_STATUS_NO_MEMORY;
2129 if (cli_has_async_calls(cli)) {
2130 return NT_STATUS_INVALID_PARAMETER;
2132 ev = tevent_context_init(talloc_tos());
2133 if (ev == NULL) {
2134 goto fail;
2136 req = cli_ulogoff_send(ev, ev, cli);
2137 if (req == NULL) {
2138 goto fail;
2140 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2141 goto fail;
2143 status = cli_ulogoff_recv(req);
2144 fail:
2145 TALLOC_FREE(ev);
2146 if (!NT_STATUS_IS_OK(status)) {
2147 cli_set_error(cli, status);
2149 return status;
2152 /****************************************************************************
2153 Send a tconX.
2154 ****************************************************************************/
2156 struct cli_tcon_andx_state {
2157 struct cli_state *cli;
2158 uint16_t vwv[4];
2159 struct iovec bytes;
2162 static void cli_tcon_andx_done(struct tevent_req *subreq);
2164 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2165 struct event_context *ev,
2166 struct cli_state *cli,
2167 const char *share, const char *dev,
2168 const char *pass, int passlen,
2169 struct tevent_req **psmbreq)
2171 struct tevent_req *req, *subreq;
2172 struct cli_tcon_andx_state *state;
2173 uint8_t p24[24];
2174 uint16_t *vwv;
2175 char *tmp = NULL;
2176 uint8_t *bytes;
2178 *psmbreq = NULL;
2180 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2181 if (req == NULL) {
2182 return NULL;
2184 state->cli = cli;
2185 vwv = state->vwv;
2187 cli->share = talloc_strdup(cli, share);
2188 if (!cli->share) {
2189 return NULL;
2192 /* in user level security don't send a password now */
2193 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2194 passlen = 1;
2195 pass = "";
2196 } else if (pass == NULL) {
2197 DEBUG(1, ("Server not using user level security and no "
2198 "password supplied.\n"));
2199 goto access_denied;
2202 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2203 *pass && passlen != 24) {
2204 if (!lp_client_lanman_auth()) {
2205 DEBUG(1, ("Server requested LANMAN password "
2206 "(share-level security) but "
2207 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2208 goto access_denied;
2212 * Non-encrypted passwords - convert to DOS codepage before
2213 * encryption.
2215 SMBencrypt(pass, cli->secblob.data, p24);
2216 passlen = 24;
2217 pass = (const char *)p24;
2218 } else {
2219 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2220 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2221 == 0) {
2222 char *tmp_pass;
2224 if (!lp_client_plaintext_auth() && (*pass)) {
2225 DEBUG(1, ("Server requested plaintext "
2226 "password but "
2227 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2228 goto access_denied;
2232 * Non-encrypted passwords - convert to DOS codepage
2233 * before using.
2235 tmp_pass = talloc_array(talloc_tos(), char, 128);
2236 if (tmp_pass == NULL) {
2237 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2238 return tevent_req_post(req, ev);
2240 passlen = clistr_push(cli,
2241 tmp_pass,
2242 pass,
2243 talloc_get_size(tmp_pass),
2244 STR_TERMINATE);
2245 if (passlen == -1) {
2246 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2247 return tevent_req_post(req, ev);
2249 pass = tmp_pass;
2253 SCVAL(vwv+0, 0, 0xFF);
2254 SCVAL(vwv+0, 1, 0);
2255 SSVAL(vwv+1, 0, 0);
2256 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2257 SSVAL(vwv+3, 0, passlen);
2259 if (passlen && pass) {
2260 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2261 } else {
2262 bytes = talloc_array(state, uint8_t, 0);
2266 * Add the sharename
2268 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2269 cli->desthost, share);
2270 if (tmp == NULL) {
2271 TALLOC_FREE(req);
2272 return NULL;
2274 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2275 NULL);
2276 TALLOC_FREE(tmp);
2279 * Add the devicetype
2281 tmp = talloc_strdup_upper(talloc_tos(), dev);
2282 if (tmp == NULL) {
2283 TALLOC_FREE(req);
2284 return NULL;
2286 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2287 TALLOC_FREE(tmp);
2289 if (bytes == NULL) {
2290 TALLOC_FREE(req);
2291 return NULL;
2294 state->bytes.iov_base = (void *)bytes;
2295 state->bytes.iov_len = talloc_get_size(bytes);
2297 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2298 1, &state->bytes);
2299 if (subreq == NULL) {
2300 TALLOC_FREE(req);
2301 return NULL;
2303 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2304 *psmbreq = subreq;
2305 return req;
2307 access_denied:
2308 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2309 return tevent_req_post(req, ev);
2312 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2313 struct event_context *ev,
2314 struct cli_state *cli,
2315 const char *share, const char *dev,
2316 const char *pass, int passlen)
2318 struct tevent_req *req, *subreq;
2319 NTSTATUS status;
2321 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2322 &subreq);
2323 if (req == NULL) {
2324 return NULL;
2326 if (subreq == NULL) {
2327 return req;
2329 status = cli_smb_req_send(subreq);
2330 if (!NT_STATUS_IS_OK(status)) {
2331 tevent_req_nterror(req, status);
2332 return tevent_req_post(req, ev);
2334 return req;
2337 static void cli_tcon_andx_done(struct tevent_req *subreq)
2339 struct tevent_req *req = tevent_req_callback_data(
2340 subreq, struct tevent_req);
2341 struct cli_tcon_andx_state *state = tevent_req_data(
2342 req, struct cli_tcon_andx_state);
2343 struct cli_state *cli = state->cli;
2344 uint8_t *in;
2345 char *inbuf;
2346 uint8_t wct;
2347 uint16_t *vwv;
2348 uint32_t num_bytes;
2349 uint8_t *bytes;
2350 NTSTATUS status;
2352 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2353 &num_bytes, &bytes);
2354 TALLOC_FREE(subreq);
2355 if (!NT_STATUS_IS_OK(status)) {
2356 tevent_req_nterror(req, status);
2357 return;
2360 inbuf = (char *)in;
2362 if (num_bytes) {
2363 if (clistr_pull_talloc(cli,
2364 inbuf,
2365 SVAL(inbuf, smb_flg2),
2366 &cli->dev,
2367 bytes,
2368 num_bytes,
2369 STR_TERMINATE|STR_ASCII) == -1) {
2370 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2371 return;
2373 } else {
2374 cli->dev = talloc_strdup(cli, "");
2375 if (cli->dev == NULL) {
2376 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2377 return;
2381 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
2382 /* almost certainly win95 - enable bug fixes */
2383 cli->win95 = True;
2387 * Make sure that we have the optional support 16-bit field. WCT > 2.
2388 * Avoids issues when connecting to Win9x boxes sharing files
2391 cli->dfsroot = false;
2393 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
2394 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2397 cli->cnum = SVAL(inbuf,smb_tid);
2398 tevent_req_done(req);
2401 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2403 return tevent_req_simple_recv_ntstatus(req);
2406 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2407 const char *dev, const char *pass, int passlen)
2409 TALLOC_CTX *frame = talloc_stackframe();
2410 struct event_context *ev;
2411 struct tevent_req *req;
2412 NTSTATUS status = NT_STATUS_OK;
2414 if (cli_has_async_calls(cli)) {
2416 * Can't use sync call while an async call is in flight
2418 status = NT_STATUS_INVALID_PARAMETER;
2419 goto fail;
2422 ev = event_context_init(frame);
2423 if (ev == NULL) {
2424 status = NT_STATUS_NO_MEMORY;
2425 goto fail;
2428 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2429 if (req == NULL) {
2430 status = NT_STATUS_NO_MEMORY;
2431 goto fail;
2434 if (!tevent_req_poll(req, ev)) {
2435 status = map_nt_error_from_unix(errno);
2436 goto fail;
2439 status = cli_tcon_andx_recv(req);
2440 fail:
2441 TALLOC_FREE(frame);
2442 if (!NT_STATUS_IS_OK(status)) {
2443 cli_set_error(cli, status);
2445 return status;
2448 /****************************************************************************
2449 Send a tree disconnect.
2450 ****************************************************************************/
2452 struct cli_tdis_state {
2453 struct cli_state *cli;
2456 static void cli_tdis_done(struct tevent_req *subreq);
2458 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2459 struct tevent_context *ev,
2460 struct cli_state *cli)
2462 struct tevent_req *req, *subreq;
2463 struct cli_tdis_state *state;
2465 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2466 if (req == NULL) {
2467 return NULL;
2469 state->cli = cli;
2471 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2472 if (tevent_req_nomem(subreq, req)) {
2473 return tevent_req_post(req, ev);
2475 tevent_req_set_callback(subreq, cli_tdis_done, req);
2476 return req;
2479 static void cli_tdis_done(struct tevent_req *subreq)
2481 struct tevent_req *req = tevent_req_callback_data(
2482 subreq, struct tevent_req);
2483 struct cli_tdis_state *state = tevent_req_data(
2484 req, struct cli_tdis_state);
2485 NTSTATUS status;
2487 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2488 TALLOC_FREE(subreq);
2489 if (!NT_STATUS_IS_OK(status)) {
2490 tevent_req_nterror(req, status);
2491 return;
2493 state->cli->cnum = -1;
2494 tevent_req_done(req);
2497 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2499 return tevent_req_simple_recv_ntstatus(req);
2502 NTSTATUS cli_tdis(struct cli_state *cli)
2504 struct tevent_context *ev;
2505 struct tevent_req *req;
2506 NTSTATUS status = NT_STATUS_NO_MEMORY;
2508 if (cli_has_async_calls(cli)) {
2509 return NT_STATUS_INVALID_PARAMETER;
2511 ev = tevent_context_init(talloc_tos());
2512 if (ev == NULL) {
2513 goto fail;
2515 req = cli_tdis_send(ev, ev, cli);
2516 if (req == NULL) {
2517 goto fail;
2519 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2520 goto fail;
2522 status = cli_tdis_recv(req);
2523 fail:
2524 TALLOC_FREE(ev);
2525 if (!NT_STATUS_IS_OK(status)) {
2526 cli_set_error(cli, status);
2528 return status;
2531 /****************************************************************************
2532 Send a negprot command.
2533 ****************************************************************************/
2535 struct cli_negprot_state {
2536 struct cli_state *cli;
2539 static void cli_negprot_done(struct tevent_req *subreq);
2541 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2542 struct event_context *ev,
2543 struct cli_state *cli)
2545 struct tevent_req *req, *subreq;
2546 struct cli_negprot_state *state;
2547 uint8_t *bytes = NULL;
2548 int numprots;
2549 uint16_t cnum;
2551 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2552 if (req == NULL) {
2553 return NULL;
2555 state->cli = cli;
2557 if (cli->protocol < PROTOCOL_NT1)
2558 cli->use_spnego = False;
2560 /* setup the protocol strings */
2561 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2562 uint8_t c = 2;
2563 if (prots[numprots].prot > cli->protocol) {
2564 break;
2566 bytes = (uint8_t *)talloc_append_blob(
2567 state, bytes, data_blob_const(&c, sizeof(c)));
2568 if (tevent_req_nomem(bytes, req)) {
2569 return tevent_req_post(req, ev);
2571 bytes = smb_bytes_push_str(bytes, false,
2572 prots[numprots].name,
2573 strlen(prots[numprots].name)+1,
2574 NULL);
2575 if (tevent_req_nomem(bytes, req)) {
2576 return tevent_req_post(req, ev);
2580 cnum = cli->cnum;
2582 cli->cnum = 0;
2583 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2584 talloc_get_size(bytes), bytes);
2585 cli->cnum = cnum;
2587 if (tevent_req_nomem(subreq, req)) {
2588 return tevent_req_post(req, ev);
2590 tevent_req_set_callback(subreq, cli_negprot_done, req);
2591 return req;
2594 static void cli_negprot_done(struct tevent_req *subreq)
2596 struct tevent_req *req = tevent_req_callback_data(
2597 subreq, struct tevent_req);
2598 struct cli_negprot_state *state = tevent_req_data(
2599 req, struct cli_negprot_state);
2600 struct cli_state *cli = state->cli;
2601 uint8_t wct;
2602 uint16_t *vwv;
2603 uint32_t num_bytes;
2604 uint8_t *bytes;
2605 NTSTATUS status;
2606 uint16_t protnum;
2607 uint8_t *inbuf;
2609 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2610 &num_bytes, &bytes);
2611 TALLOC_FREE(subreq);
2612 if (!NT_STATUS_IS_OK(status)) {
2613 tevent_req_nterror(req, status);
2614 return;
2617 protnum = SVAL(vwv, 0);
2619 if ((protnum >= ARRAY_SIZE(prots))
2620 || (prots[protnum].prot > cli->protocol)) {
2621 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2622 return;
2625 cli->protocol = prots[protnum].prot;
2627 if ((cli->protocol < PROTOCOL_NT1) &&
2628 client_is_signing_mandatory(cli)) {
2629 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2630 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2631 return;
2634 if (cli->protocol >= PROTOCOL_NT1) {
2635 struct timespec ts;
2636 bool negotiated_smb_signing = false;
2638 /* NT protocol */
2639 cli->sec_mode = CVAL(vwv + 1, 0);
2640 cli->max_mux = SVAL(vwv + 1, 1);
2641 cli->max_xmit = IVAL(vwv + 3, 1);
2642 cli->sesskey = IVAL(vwv + 7, 1);
2643 cli->serverzone = SVALS(vwv + 15, 1);
2644 cli->serverzone *= 60;
2645 /* this time arrives in real GMT */
2646 ts = interpret_long_date(((char *)(vwv+11))+1);
2647 cli->servertime = ts.tv_sec;
2648 cli->secblob = data_blob(bytes, num_bytes);
2649 cli->capabilities = IVAL(vwv + 9, 1);
2650 if (cli->capabilities & CAP_RAW_MODE) {
2651 cli->readbraw_supported = True;
2652 cli->writebraw_supported = True;
2654 /* work out if they sent us a workgroup */
2655 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2656 smb_buflen(cli->inbuf) > 8) {
2657 clistr_pull(cli->inbuf, cli->server_domain,
2658 bytes+8, sizeof(cli->server_domain),
2659 num_bytes-8,
2660 STR_UNICODE|STR_NOALIGN);
2664 * As signing is slow we only turn it on if either the client or
2665 * the server require it. JRA.
2668 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2669 /* Fail if server says signing is mandatory and we don't want to support it. */
2670 if (!client_is_signing_allowed(cli)) {
2671 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2672 tevent_req_nterror(req,
2673 NT_STATUS_ACCESS_DENIED);
2674 return;
2676 negotiated_smb_signing = true;
2677 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2678 /* Fail if client says signing is mandatory and the server doesn't support it. */
2679 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2680 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2681 tevent_req_nterror(req,
2682 NT_STATUS_ACCESS_DENIED);
2683 return;
2685 negotiated_smb_signing = true;
2686 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2687 negotiated_smb_signing = true;
2690 if (negotiated_smb_signing) {
2691 cli_set_signing_negotiated(cli);
2694 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2695 SAFE_FREE(cli->outbuf);
2696 SAFE_FREE(cli->inbuf);
2697 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2698 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2699 if (!cli->outbuf || !cli->inbuf) {
2700 tevent_req_nterror(req,
2701 NT_STATUS_NO_MEMORY);
2702 return;
2704 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2707 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2708 cli->use_spnego = False;
2709 cli->sec_mode = SVAL(vwv + 1, 0);
2710 cli->max_xmit = SVAL(vwv + 2, 0);
2711 cli->max_mux = SVAL(vwv + 3, 0);
2712 cli->sesskey = IVAL(vwv + 6, 0);
2713 cli->serverzone = SVALS(vwv + 10, 0);
2714 cli->serverzone *= 60;
2715 /* this time is converted to GMT by make_unix_date */
2716 cli->servertime = make_unix_date(
2717 (char *)(vwv + 8), cli->serverzone);
2718 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2719 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2720 cli->secblob = data_blob(bytes, num_bytes);
2721 } else {
2722 /* the old core protocol */
2723 cli->use_spnego = False;
2724 cli->sec_mode = 0;
2725 cli->serverzone = get_time_zone(time(NULL));
2728 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2730 /* a way to force ascii SMB */
2731 if (getenv("CLI_FORCE_ASCII"))
2732 cli->capabilities &= ~CAP_UNICODE;
2734 tevent_req_done(req);
2737 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2739 return tevent_req_simple_recv_ntstatus(req);
2742 NTSTATUS cli_negprot(struct cli_state *cli)
2744 TALLOC_CTX *frame = talloc_stackframe();
2745 struct event_context *ev;
2746 struct tevent_req *req;
2747 NTSTATUS status = NT_STATUS_OK;
2749 if (cli_has_async_calls(cli)) {
2751 * Can't use sync call while an async call is in flight
2753 status = NT_STATUS_INVALID_PARAMETER;
2754 goto fail;
2757 ev = event_context_init(frame);
2758 if (ev == NULL) {
2759 status = NT_STATUS_NO_MEMORY;
2760 goto fail;
2763 req = cli_negprot_send(frame, ev, cli);
2764 if (req == NULL) {
2765 status = NT_STATUS_NO_MEMORY;
2766 goto fail;
2769 if (!tevent_req_poll(req, ev)) {
2770 status = map_nt_error_from_unix(errno);
2771 goto fail;
2774 status = cli_negprot_recv(req);
2775 fail:
2776 TALLOC_FREE(frame);
2777 if (!NT_STATUS_IS_OK(status)) {
2778 cli_set_error(cli, status);
2780 return status;
2783 /****************************************************************************
2784 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2785 ****************************************************************************/
2787 bool cli_session_request(struct cli_state *cli,
2788 struct nmb_name *calling, struct nmb_name *called)
2790 char *p;
2791 int len = 4;
2792 int namelen = 0;
2793 char *tmp;
2795 /* 445 doesn't have session request */
2796 if (cli->port == 445)
2797 return True;
2799 memcpy(&(cli->calling), calling, sizeof(*calling));
2800 memcpy(&(cli->called ), called , sizeof(*called ));
2802 /* put in the destination name */
2804 tmp = name_mangle(talloc_tos(), cli->called.name,
2805 cli->called.name_type);
2806 if (tmp == NULL) {
2807 return false;
2810 p = cli->outbuf+len;
2811 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2812 if (namelen > 0) {
2813 memcpy(p, tmp, namelen);
2814 len += namelen;
2816 TALLOC_FREE(tmp);
2818 /* and my name */
2820 tmp = name_mangle(talloc_tos(), cli->calling.name,
2821 cli->calling.name_type);
2822 if (tmp == NULL) {
2823 return false;
2826 p = cli->outbuf+len;
2827 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2828 if (namelen > 0) {
2829 memcpy(p, tmp, namelen);
2830 len += namelen;
2832 TALLOC_FREE(tmp);
2834 /* send a session request (RFC 1002) */
2835 /* setup the packet length
2836 * Remove four bytes from the length count, since the length
2837 * field in the NBT Session Service header counts the number
2838 * of bytes which follow. The cli_send_smb() function knows
2839 * about this and accounts for those four bytes.
2840 * CRH.
2842 len -= 4;
2843 _smb_setlen(cli->outbuf,len);
2844 SCVAL(cli->outbuf,0,0x81);
2846 cli_send_smb(cli);
2847 DEBUG(5,("Sent session request\n"));
2849 if (!cli_receive_smb(cli))
2850 return False;
2852 if (CVAL(cli->inbuf,0) == 0x84) {
2853 /* C. Hoch 9/14/95 Start */
2854 /* For information, here is the response structure.
2855 * We do the byte-twiddling to for portability.
2856 struct RetargetResponse{
2857 unsigned char type;
2858 unsigned char flags;
2859 int16 length;
2860 int32 ip_addr;
2861 int16 port;
2864 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2865 struct in_addr dest_ip;
2866 NTSTATUS status;
2868 /* SESSION RETARGET */
2869 putip((char *)&dest_ip,cli->inbuf+4);
2870 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2872 status = open_socket_out(&cli->dest_ss, port,
2873 LONG_CONNECT_TIMEOUT, &cli->fd);
2874 if (!NT_STATUS_IS_OK(status)) {
2875 return False;
2878 DEBUG(3,("Retargeted\n"));
2880 set_socket_options(cli->fd, lp_socket_options());
2882 /* Try again */
2884 static int depth;
2885 bool ret;
2886 if (depth > 4) {
2887 DEBUG(0,("Retarget recursion - failing\n"));
2888 return False;
2890 depth++;
2891 ret = cli_session_request(cli, calling, called);
2892 depth--;
2893 return ret;
2895 } /* C. Hoch 9/14/95 End */
2897 if (CVAL(cli->inbuf,0) != 0x82) {
2898 /* This is the wrong place to put the error... JRA. */
2899 cli->rap_error = CVAL(cli->inbuf,4);
2900 return False;
2902 return(True);
2905 struct fd_struct {
2906 int fd;
2909 static void smb_sock_connected(struct tevent_req *req)
2911 struct fd_struct *pfd = tevent_req_callback_data(
2912 req, struct fd_struct);
2913 int fd;
2914 NTSTATUS status;
2916 status = open_socket_out_defer_recv(req, &fd);
2917 if (NT_STATUS_IS_OK(status)) {
2918 pfd->fd = fd;
2922 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2923 uint16_t *port, int timeout, int *pfd)
2925 struct event_context *ev;
2926 struct tevent_req *r139, *r445;
2927 struct fd_struct *fd139, *fd445;
2928 NTSTATUS status = NT_STATUS_NO_MEMORY;
2930 if (*port != 0) {
2931 return open_socket_out(pss, *port, timeout, pfd);
2934 ev = event_context_init(talloc_tos());
2935 if (ev == NULL) {
2936 return NT_STATUS_NO_MEMORY;
2939 fd139 = talloc(ev, struct fd_struct);
2940 if (fd139 == NULL) {
2941 goto done;
2943 fd139->fd = -1;
2945 fd445 = talloc(ev, struct fd_struct);
2946 if (fd445 == NULL) {
2947 goto done;
2949 fd445->fd = -1;
2951 r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2952 pss, 445, timeout);
2953 r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2954 pss, 139, timeout);
2955 if ((r445 == NULL) || (r139 == NULL)) {
2956 goto done;
2958 tevent_req_set_callback(r445, smb_sock_connected, fd445);
2959 tevent_req_set_callback(r139, smb_sock_connected, fd139);
2961 while ((fd445->fd == -1) && (fd139->fd == -1)
2962 && (tevent_req_is_in_progress(r139)
2963 || tevent_req_is_in_progress(r445))) {
2964 event_loop_once(ev);
2967 if ((fd139->fd != -1) && (fd445->fd != -1)) {
2968 close(fd139->fd);
2969 fd139->fd = -1;
2972 if (fd445->fd != -1) {
2973 *port = 445;
2974 *pfd = fd445->fd;
2975 status = NT_STATUS_OK;
2976 goto done;
2978 if (fd139->fd != -1) {
2979 *port = 139;
2980 *pfd = fd139->fd;
2981 status = NT_STATUS_OK;
2982 goto done;
2985 status = open_socket_out_defer_recv(r445, &fd445->fd);
2986 done:
2987 TALLOC_FREE(ev);
2988 return status;
2991 /****************************************************************************
2992 Open the client sockets.
2993 ****************************************************************************/
2995 NTSTATUS cli_connect(struct cli_state *cli,
2996 const char *host,
2997 struct sockaddr_storage *dest_ss)
3000 int name_type = 0x20;
3001 TALLOC_CTX *frame = talloc_stackframe();
3002 unsigned int num_addrs = 0;
3003 unsigned int i = 0;
3004 struct sockaddr_storage *ss_arr = NULL;
3005 char *p = NULL;
3007 /* reasonable default hostname */
3008 if (!host) {
3009 host = STAR_SMBSERVER;
3012 cli->desthost = talloc_strdup(cli, host);
3013 if (cli->desthost == NULL) {
3014 return NT_STATUS_NO_MEMORY;
3017 /* allow hostnames of the form NAME#xx and do a netbios lookup */
3018 if ((p = strchr(cli->desthost, '#'))) {
3019 name_type = strtol(p+1, NULL, 16);
3020 *p = 0;
3023 if (!dest_ss || is_zero_addr(dest_ss)) {
3024 NTSTATUS status =resolve_name_list(frame,
3025 cli->desthost,
3026 name_type,
3027 &ss_arr,
3028 &num_addrs);
3029 if (!NT_STATUS_IS_OK(status)) {
3030 TALLOC_FREE(frame);
3031 return NT_STATUS_BAD_NETWORK_NAME;
3033 } else {
3034 num_addrs = 1;
3035 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
3036 if (!ss_arr) {
3037 TALLOC_FREE(frame);
3038 return NT_STATUS_NO_MEMORY;
3040 *ss_arr = *dest_ss;
3043 for (i = 0; i < num_addrs; i++) {
3044 cli->dest_ss = ss_arr[i];
3045 if (getenv("LIBSMB_PROG")) {
3046 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
3047 } else {
3048 uint16_t port = cli->port;
3049 NTSTATUS status;
3050 status = open_smb_socket(&cli->dest_ss, &port,
3051 cli->timeout, &cli->fd);
3052 if (NT_STATUS_IS_OK(status)) {
3053 cli->port = port;
3056 if (cli->fd == -1) {
3057 char addr[INET6_ADDRSTRLEN];
3058 print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
3059 DEBUG(2,("Error connecting to %s (%s)\n",
3060 dest_ss?addr:host,strerror(errno)));
3061 } else {
3062 /* Exit from loop on first connection. */
3063 break;
3067 if (cli->fd == -1) {
3068 TALLOC_FREE(frame);
3069 return map_nt_error_from_unix(errno);
3072 if (dest_ss) {
3073 *dest_ss = cli->dest_ss;
3076 set_socket_options(cli->fd, lp_socket_options());
3078 TALLOC_FREE(frame);
3079 return NT_STATUS_OK;
3083 establishes a connection to after the negprot.
3084 @param output_cli A fully initialised cli structure, non-null only on success
3085 @param dest_host The netbios name of the remote host
3086 @param dest_ss (optional) The the destination IP, NULL for name based lookup
3087 @param port (optional) The destination port (0 for default)
3089 NTSTATUS cli_start_connection(struct cli_state **output_cli,
3090 const char *my_name,
3091 const char *dest_host,
3092 struct sockaddr_storage *dest_ss, int port,
3093 int signing_state, int flags)
3095 NTSTATUS nt_status;
3096 struct nmb_name calling;
3097 struct nmb_name called;
3098 struct cli_state *cli;
3099 struct sockaddr_storage ss;
3101 if (!my_name)
3102 my_name = global_myname();
3104 if (!(cli = cli_initialise_ex(signing_state))) {
3105 return NT_STATUS_NO_MEMORY;
3108 make_nmb_name(&calling, my_name, 0x0);
3109 make_nmb_name(&called , dest_host, 0x20);
3111 cli_set_port(cli, port);
3112 cli_set_timeout(cli, 10000); /* 10 seconds. */
3114 if (dest_ss) {
3115 ss = *dest_ss;
3116 } else {
3117 zero_sockaddr(&ss);
3120 again:
3122 DEBUG(3,("Connecting to host=%s\n", dest_host));
3124 nt_status = cli_connect(cli, dest_host, &ss);
3125 if (!NT_STATUS_IS_OK(nt_status)) {
3126 char addr[INET6_ADDRSTRLEN];
3127 print_sockaddr(addr, sizeof(addr), &ss);
3128 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
3129 nmb_namestr(&called), addr, nt_errstr(nt_status) ));
3130 cli_shutdown(cli);
3131 return nt_status;
3134 if (!cli_session_request(cli, &calling, &called)) {
3135 char *p;
3136 DEBUG(1,("session request to %s failed (%s)\n",
3137 called.name, cli_errstr(cli)));
3138 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
3139 *p = 0;
3140 goto again;
3142 if (strcmp(called.name, STAR_SMBSERVER)) {
3143 make_nmb_name(&called , STAR_SMBSERVER, 0x20);
3144 goto again;
3146 return NT_STATUS_BAD_NETWORK_NAME;
3149 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
3150 cli->use_spnego = False;
3151 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
3152 cli->use_kerberos = True;
3154 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
3155 cli->use_kerberos) {
3156 cli->fallback_after_kerberos = true;
3158 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
3159 cli->use_ccache = true;
3162 nt_status = cli_negprot(cli);
3163 if (!NT_STATUS_IS_OK(nt_status)) {
3164 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
3165 cli_shutdown(cli);
3166 return nt_status;
3169 *output_cli = cli;
3170 return NT_STATUS_OK;
3175 establishes a connection right up to doing tconX, password specified.
3176 @param output_cli A fully initialised cli structure, non-null only on success
3177 @param dest_host The netbios name of the remote host
3178 @param dest_ip (optional) The the destination IP, NULL for name based lookup
3179 @param port (optional) The destination port (0 for default)
3180 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
3181 @param service_type The 'type' of serivice.
3182 @param user Username, unix string
3183 @param domain User's domain
3184 @param password User's password, unencrypted unix string.
3187 NTSTATUS cli_full_connection(struct cli_state **output_cli,
3188 const char *my_name,
3189 const char *dest_host,
3190 struct sockaddr_storage *dest_ss, int port,
3191 const char *service, const char *service_type,
3192 const char *user, const char *domain,
3193 const char *password, int flags,
3194 int signing_state)
3196 NTSTATUS nt_status;
3197 struct cli_state *cli = NULL;
3198 int pw_len = password ? strlen(password)+1 : 0;
3200 *output_cli = NULL;
3202 if (password == NULL) {
3203 password = "";
3206 nt_status = cli_start_connection(&cli, my_name, dest_host,
3207 dest_ss, port, signing_state,
3208 flags);
3210 if (!NT_STATUS_IS_OK(nt_status)) {
3211 return nt_status;
3214 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
3215 cli->use_level_II_oplocks =
3216 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
3218 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3219 pw_len, domain);
3220 if (!NT_STATUS_IS_OK(nt_status)) {
3222 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3223 DEBUG(1,("failed session setup with %s\n",
3224 nt_errstr(nt_status)));
3225 cli_shutdown(cli);
3226 return nt_status;
3229 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3230 if (!NT_STATUS_IS_OK(nt_status)) {
3231 DEBUG(1,("anonymous failed session setup with %s\n",
3232 nt_errstr(nt_status)));
3233 cli_shutdown(cli);
3234 return nt_status;
3238 if (service) {
3239 nt_status = cli_tcon_andx(cli, service, service_type, password,
3240 pw_len);
3241 if (!NT_STATUS_IS_OK(nt_status)) {
3242 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3243 cli_shutdown(cli);
3244 if (NT_STATUS_IS_OK(nt_status)) {
3245 nt_status = NT_STATUS_UNSUCCESSFUL;
3247 return nt_status;
3251 nt_status = cli_init_creds(cli, user, domain, password);
3252 if (!NT_STATUS_IS_OK(nt_status)) {
3253 cli_shutdown(cli);
3254 return nt_status;
3257 *output_cli = cli;
3258 return NT_STATUS_OK;
3261 /****************************************************************************
3262 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
3263 ****************************************************************************/
3265 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
3266 struct sockaddr_storage *pdest_ss)
3268 struct nmb_name calling, called;
3270 make_nmb_name(&calling, srchost, 0x0);
3273 * If the called name is an IP address
3274 * then use *SMBSERVER immediately.
3277 if(is_ipaddress(desthost)) {
3278 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
3279 } else {
3280 make_nmb_name(&called, desthost, 0x20);
3283 if (!cli_session_request(*ppcli, &calling, &called)) {
3284 NTSTATUS status;
3285 struct nmb_name smbservername;
3287 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
3290 * If the name wasn't *SMBSERVER then
3291 * try with *SMBSERVER if the first name fails.
3294 if (nmb_name_equal(&called, &smbservername)) {
3297 * The name used was *SMBSERVER, don't bother with another name.
3300 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
3301 with error %s.\n", desthost, cli_errstr(*ppcli) ));
3302 return False;
3305 /* Try again... */
3306 cli_shutdown(*ppcli);
3308 *ppcli = cli_initialise();
3309 if (!*ppcli) {
3310 /* Out of memory... */
3311 return False;
3314 status = cli_connect(*ppcli, desthost, pdest_ss);
3315 if (!NT_STATUS_IS_OK(status) ||
3316 !cli_session_request(*ppcli, &calling, &smbservername)) {
3317 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
3318 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
3319 return False;
3323 return True;
3326 /****************************************************************************
3327 Send an old style tcon.
3328 ****************************************************************************/
3329 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3330 const char *service, const char *pass, const char *dev,
3331 uint16 *max_xmit, uint16 *tid)
3333 struct tevent_req *req;
3334 uint16_t *ret_vwv;
3335 uint8_t *bytes;
3336 NTSTATUS status;
3338 if (!lp_client_plaintext_auth() && (*pass)) {
3339 DEBUG(1, ("Server requested plaintext password but 'client "
3340 "plaintext auth' is disabled\n"));
3341 return NT_STATUS_ACCESS_DENIED;
3344 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3345 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3346 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3347 service, strlen(service)+1, NULL);
3348 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3349 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3350 pass, strlen(pass)+1, NULL);
3351 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3352 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3353 dev, strlen(dev)+1, NULL);
3355 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3356 talloc_get_size(bytes), bytes, &req,
3357 2, NULL, &ret_vwv, NULL, NULL);
3358 if (!NT_STATUS_IS_OK(status)) {
3359 return status;
3362 *max_xmit = SVAL(ret_vwv + 0, 0);
3363 *tid = SVAL(ret_vwv + 1, 0);
3365 return NT_STATUS_OK;
3368 /* Return a cli_state pointing at the IPC$ share for the given server */
3370 struct cli_state *get_ipc_connect(char *server,
3371 struct sockaddr_storage *server_ss,
3372 const struct user_auth_info *user_info)
3374 struct cli_state *cli;
3375 NTSTATUS nt_status;
3376 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3378 if (user_info->use_kerberos) {
3379 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3382 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3383 user_info->username ? user_info->username : "",
3384 lp_workgroup(),
3385 user_info->password ? user_info->password : "",
3386 flags,
3387 Undefined);
3389 if (NT_STATUS_IS_OK(nt_status)) {
3390 return cli;
3391 } else if (is_ipaddress(server)) {
3392 /* windows 9* needs a correct NMB name for connections */
3393 fstring remote_name;
3395 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3396 cli = get_ipc_connect(remote_name, server_ss, user_info);
3397 if (cli)
3398 return cli;
3401 return NULL;
3405 * Given the IP address of a master browser on the network, return its
3406 * workgroup and connect to it.
3408 * This function is provided to allow additional processing beyond what
3409 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3410 * browsers and obtain each master browsers' list of domains (in case the
3411 * first master browser is recently on the network and has not yet
3412 * synchronized with other master browsers and therefore does not yet have the
3413 * entire network browse list)
3416 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3417 struct sockaddr_storage *mb_ip,
3418 const struct user_auth_info *user_info,
3419 char **pp_workgroup_out)
3421 char addr[INET6_ADDRSTRLEN];
3422 fstring name;
3423 struct cli_state *cli;
3424 struct sockaddr_storage server_ss;
3426 *pp_workgroup_out = NULL;
3428 print_sockaddr(addr, sizeof(addr), mb_ip);
3429 DEBUG(99, ("Looking up name of master browser %s\n",
3430 addr));
3433 * Do a name status query to find out the name of the master browser.
3434 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3435 * master browser will not respond to a wildcard query (or, at least,
3436 * an NT4 server acting as the domain master browser will not).
3438 * We might be able to use ONLY the query on MSBROWSE, but that's not
3439 * yet been tested with all Windows versions, so until it is, leave
3440 * the original wildcard query as the first choice and fall back to
3441 * MSBROWSE if the wildcard query fails.
3443 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3444 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3446 DEBUG(99, ("Could not retrieve name status for %s\n",
3447 addr));
3448 return NULL;
3451 if (!find_master_ip(name, &server_ss)) {
3452 DEBUG(99, ("Could not find master ip for %s\n", name));
3453 return NULL;
3456 *pp_workgroup_out = talloc_strdup(ctx, name);
3458 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3460 print_sockaddr(addr, sizeof(addr), &server_ss);
3461 cli = get_ipc_connect(addr, &server_ss, user_info);
3463 return cli;
3467 * Return the IP address and workgroup of a master browser on the network, and
3468 * connect to it.
3471 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3472 const struct user_auth_info *user_info,
3473 char **pp_workgroup_out)
3475 struct ip_service *ip_list;
3476 struct cli_state *cli;
3477 int i, count;
3479 *pp_workgroup_out = NULL;
3481 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3483 /* Go looking for workgroups by broadcasting on the local network */
3485 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
3486 &count))) {
3487 DEBUG(99, ("No master browsers responded\n"));
3488 return False;
3491 for (i = 0; i < count; i++) {
3492 char addr[INET6_ADDRSTRLEN];
3493 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
3494 DEBUG(99, ("Found master browser %s\n", addr));
3496 cli = get_ipc_connect_master_ip(ctx, &ip_list[i].ss,
3497 user_info, pp_workgroup_out);
3498 if (cli)
3499 return(cli);
3502 return NULL;