s3:smbd: use PROTOCOL_SMB2_02 instead PROTOCOL_SMB2
[Samba/gebeck_regimport.git] / source3 / libsmb / cliconnect.c
blobe5d8700d598e9505d394cd3ebe512596a8de768e
1 /*
2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Bartlett 2001-2003
6 Copyright (C) Volker Lendecke 2011
7 Copyright (C) Jeremy Allison 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "libsmb/libsmb.h"
25 #include "popt_common.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../libcli/auth/spnego.h"
28 #include "smb_krb5.h"
29 #include "../libcli/auth/ntlmssp.h"
30 #include "libads/kerberos_proto.h"
31 #include "krb5_env.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "async_smb.h"
34 #include "libsmb/nmblib.h"
35 #include "read_smb.h"
37 static const struct {
38 int prot;
39 const char name[24];
40 } prots[10] = {
41 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
42 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
43 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
44 {PROTOCOL_LANMAN1, "LANMAN1.0"},
45 {PROTOCOL_LANMAN2, "LM1.2X002"},
46 {PROTOCOL_LANMAN2, "DOS LANMAN2.1"},
47 {PROTOCOL_LANMAN2, "LANMAN2.1"},
48 {PROTOCOL_LANMAN2, "Samba"},
49 {PROTOCOL_NT1, "NT LANMAN 1.0"},
50 {PROTOCOL_NT1, "NT LM 0.12"},
53 #define STAR_SMBSERVER "*SMBSERVER"
55 /********************************************************
56 Utility function to ensure we always return at least
57 a valid char * pointer to an empty string for the
58 cli->server_os, cli->server_type and cli->server_domain
59 strings.
60 *******************************************************/
62 static NTSTATUS smb_bytes_talloc_string(struct cli_state *cli,
63 char *inbuf,
64 char **dest,
65 uint8_t *src,
66 size_t srclen,
67 ssize_t *destlen)
69 *destlen = clistr_pull_talloc(cli,
70 inbuf,
71 SVAL(inbuf, smb_flg2),
72 dest,
73 (char *)src,
74 srclen,
75 STR_TERMINATE);
76 if (*destlen == -1) {
77 return NT_STATUS_NO_MEMORY;
80 if (*dest == NULL) {
81 *dest = talloc_strdup(cli, "");
82 if (*dest == NULL) {
83 return NT_STATUS_NO_MEMORY;
86 return NT_STATUS_OK;
89 /**
90 * Set the user session key for a connection
91 * @param cli The cli structure to add it too
92 * @param session_key The session key used. (A copy of this is taken for the cli struct)
96 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
98 cli->user_session_key = data_blob(session_key.data, session_key.length);
101 /****************************************************************************
102 Do an old lanman2 style session setup.
103 ****************************************************************************/
105 struct cli_session_setup_lanman2_state {
106 struct cli_state *cli;
107 uint16_t vwv[10];
108 const char *user;
111 static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
113 static struct tevent_req *cli_session_setup_lanman2_send(
114 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
115 struct cli_state *cli, const char *user,
116 const char *pass, size_t passlen,
117 const char *workgroup)
119 struct tevent_req *req, *subreq;
120 struct cli_session_setup_lanman2_state *state;
121 DATA_BLOB lm_response = data_blob_null;
122 uint16_t *vwv;
123 uint8_t *bytes;
124 char *tmp;
126 req = tevent_req_create(mem_ctx, &state,
127 struct cli_session_setup_lanman2_state);
128 if (req == NULL) {
129 return NULL;
131 state->cli = cli;
132 state->user = user;
133 vwv = state->vwv;
136 * LANMAN servers predate NT status codes and Unicode and
137 * ignore those smb flags so we must disable the corresponding
138 * default capabilities that would otherwise cause the Unicode
139 * and NT Status flags to be set (and even returned by the
140 * server)
143 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
146 * if in share level security then don't send a password now
148 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
149 passlen = 0;
152 if (passlen > 0
153 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
154 && passlen != 24) {
156 * Encrypted mode needed, and non encrypted password
157 * supplied.
159 lm_response = data_blob(NULL, 24);
160 if (tevent_req_nomem(lm_response.data, req)) {
161 return tevent_req_post(req, ev);
164 if (!SMBencrypt(pass, cli->secblob.data,
165 (uint8_t *)lm_response.data)) {
166 DEBUG(1, ("Password is > 14 chars in length, and is "
167 "therefore incompatible with Lanman "
168 "authentication\n"));
169 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
170 return tevent_req_post(req, ev);
172 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
173 && passlen == 24) {
175 * Encrypted mode needed, and encrypted password
176 * supplied.
178 lm_response = data_blob(pass, passlen);
179 if (tevent_req_nomem(lm_response.data, req)) {
180 return tevent_req_post(req, ev);
182 } else if (passlen > 0) {
183 uint8_t *buf;
184 size_t converted_size;
186 * Plaintext mode needed, assume plaintext supplied.
188 buf = talloc_array(talloc_tos(), uint8_t, 0);
189 buf = smb_bytes_push_str(buf, cli_ucs2(cli), pass, passlen+1,
190 &converted_size);
191 if (tevent_req_nomem(buf, req)) {
192 return tevent_req_post(req, ev);
194 lm_response = data_blob(pass, passlen);
195 TALLOC_FREE(buf);
196 if (tevent_req_nomem(lm_response.data, req)) {
197 return tevent_req_post(req, ev);
201 SCVAL(vwv+0, 0, 0xff);
202 SCVAL(vwv+0, 1, 0);
203 SSVAL(vwv+1, 0, 0);
204 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
205 SSVAL(vwv+3, 0, 2);
206 SSVAL(vwv+4, 0, 1);
207 SIVAL(vwv+5, 0, cli->sesskey);
208 SSVAL(vwv+7, 0, lm_response.length);
210 bytes = talloc_array(state, uint8_t, lm_response.length);
211 if (tevent_req_nomem(bytes, req)) {
212 return tevent_req_post(req, ev);
214 if (lm_response.length != 0) {
215 memcpy(bytes, lm_response.data, lm_response.length);
217 data_blob_free(&lm_response);
219 tmp = talloc_strdup_upper(talloc_tos(), user);
220 if (tevent_req_nomem(tmp, req)) {
221 return tevent_req_post(req, ev);
223 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
224 NULL);
225 TALLOC_FREE(tmp);
227 tmp = talloc_strdup_upper(talloc_tos(), workgroup);
228 if (tevent_req_nomem(tmp, req)) {
229 return tevent_req_post(req, ev);
231 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
232 NULL);
233 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
234 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
236 if (tevent_req_nomem(bytes, req)) {
237 return tevent_req_post(req, ev);
240 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
241 talloc_get_size(bytes), bytes);
242 if (tevent_req_nomem(subreq, req)) {
243 return tevent_req_post(req, ev);
245 tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
246 return req;
249 static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
251 struct tevent_req *req = tevent_req_callback_data(
252 subreq, struct tevent_req);
253 struct cli_session_setup_lanman2_state *state = tevent_req_data(
254 req, struct cli_session_setup_lanman2_state);
255 struct cli_state *cli = state->cli;
256 uint32_t num_bytes;
257 uint8_t *in;
258 char *inbuf;
259 uint8_t *bytes;
260 uint8_t *p;
261 NTSTATUS status;
262 ssize_t ret;
263 uint8_t wct;
264 uint16_t *vwv;
266 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
267 &num_bytes, &bytes);
268 TALLOC_FREE(subreq);
269 if (!NT_STATUS_IS_OK(status)) {
270 tevent_req_nterror(req, status);
271 return;
274 inbuf = (char *)in;
275 p = bytes;
277 cli->vuid = SVAL(inbuf, smb_uid);
278 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
280 status = smb_bytes_talloc_string(cli,
281 inbuf,
282 &cli->server_os,
284 bytes+num_bytes-p,
285 &ret);
287 if (!NT_STATUS_IS_OK(status)) {
288 tevent_req_nterror(req, status);
289 return;
291 p += ret;
293 status = smb_bytes_talloc_string(cli,
294 inbuf,
295 &cli->server_type,
297 bytes+num_bytes-p,
298 &ret);
300 if (!NT_STATUS_IS_OK(status)) {
301 tevent_req_nterror(req, status);
302 return;
304 p += ret;
306 status = smb_bytes_talloc_string(cli,
307 inbuf,
308 &cli->server_domain,
310 bytes+num_bytes-p,
311 &ret);
313 if (!NT_STATUS_IS_OK(status)) {
314 tevent_req_nterror(req, status);
315 return;
317 p += ret;
319 if (strstr(cli->server_type, "Samba")) {
320 cli->is_samba = True;
322 status = cli_set_username(cli, state->user);
323 if (tevent_req_nterror(req, status)) {
324 return;
326 tevent_req_done(req);
329 static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
331 return tevent_req_simple_recv_ntstatus(req);
334 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
335 const char *pass, size_t passlen,
336 const char *workgroup)
338 TALLOC_CTX *frame = talloc_stackframe();
339 struct event_context *ev;
340 struct tevent_req *req;
341 NTSTATUS status = NT_STATUS_NO_MEMORY;
343 if (cli_has_async_calls(cli)) {
345 * Can't use sync call while an async call is in flight
347 status = NT_STATUS_INVALID_PARAMETER;
348 goto fail;
350 ev = event_context_init(frame);
351 if (ev == NULL) {
352 goto fail;
354 req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
355 workgroup);
356 if (req == NULL) {
357 goto fail;
359 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
360 goto fail;
362 status = cli_session_setup_lanman2_recv(req);
363 fail:
364 TALLOC_FREE(frame);
365 return status;
368 /****************************************************************************
369 Work out suitable capabilities to offer the server.
370 ****************************************************************************/
372 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
374 uint32 capabilities = CAP_NT_SMBS;
376 if (!cli->force_dos_errors)
377 capabilities |= CAP_STATUS32;
379 if (cli->use_level_II_oplocks)
380 capabilities |= CAP_LEVEL_II_OPLOCKS;
382 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
383 return capabilities;
386 /****************************************************************************
387 Do a NT1 guest session setup.
388 ****************************************************************************/
390 struct cli_session_setup_guest_state {
391 struct cli_state *cli;
392 uint16_t vwv[13];
393 struct iovec bytes;
396 static void cli_session_setup_guest_done(struct tevent_req *subreq);
398 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
399 struct event_context *ev,
400 struct cli_state *cli,
401 struct tevent_req **psmbreq)
403 struct tevent_req *req, *subreq;
404 struct cli_session_setup_guest_state *state;
405 uint16_t *vwv;
406 uint8_t *bytes;
408 req = tevent_req_create(mem_ctx, &state,
409 struct cli_session_setup_guest_state);
410 if (req == NULL) {
411 return NULL;
413 state->cli = cli;
414 vwv = state->vwv;
416 SCVAL(vwv+0, 0, 0xFF);
417 SCVAL(vwv+0, 1, 0);
418 SSVAL(vwv+1, 0, 0);
419 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
420 SSVAL(vwv+3, 0, 2);
421 SSVAL(vwv+4, 0, cli->pid);
422 SIVAL(vwv+5, 0, cli->sesskey);
423 SSVAL(vwv+7, 0, 0);
424 SSVAL(vwv+8, 0, 0);
425 SSVAL(vwv+9, 0, 0);
426 SSVAL(vwv+10, 0, 0);
427 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
429 bytes = talloc_array(state, uint8_t, 0);
431 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */
432 NULL);
433 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
434 NULL);
435 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
436 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
438 if (bytes == NULL) {
439 TALLOC_FREE(req);
440 return NULL;
443 state->bytes.iov_base = (void *)bytes;
444 state->bytes.iov_len = talloc_get_size(bytes);
446 subreq = cli_smb_req_create(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
447 1, &state->bytes);
448 if (subreq == NULL) {
449 TALLOC_FREE(req);
450 return NULL;
452 tevent_req_set_callback(subreq, cli_session_setup_guest_done, req);
453 *psmbreq = subreq;
454 return req;
457 struct tevent_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
458 struct event_context *ev,
459 struct cli_state *cli)
461 struct tevent_req *req, *subreq;
462 NTSTATUS status;
464 req = cli_session_setup_guest_create(mem_ctx, ev, cli, &subreq);
465 if (req == NULL) {
466 return NULL;
469 status = cli_smb_req_send(subreq);
470 if (NT_STATUS_IS_OK(status)) {
471 tevent_req_nterror(req, status);
472 return tevent_req_post(req, ev);
474 return req;
477 static void cli_session_setup_guest_done(struct tevent_req *subreq)
479 struct tevent_req *req = tevent_req_callback_data(
480 subreq, struct tevent_req);
481 struct cli_session_setup_guest_state *state = tevent_req_data(
482 req, struct cli_session_setup_guest_state);
483 struct cli_state *cli = state->cli;
484 uint32_t num_bytes;
485 uint8_t *in;
486 char *inbuf;
487 uint8_t *bytes;
488 uint8_t *p;
489 NTSTATUS status;
490 ssize_t ret;
491 uint8_t wct;
492 uint16_t *vwv;
494 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
495 &num_bytes, &bytes);
496 TALLOC_FREE(subreq);
497 if (!NT_STATUS_IS_OK(status)) {
498 tevent_req_nterror(req, status);
499 return;
502 inbuf = (char *)in;
503 p = bytes;
505 cli->vuid = SVAL(inbuf, smb_uid);
506 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
508 status = smb_bytes_talloc_string(cli,
509 inbuf,
510 &cli->server_os,
512 bytes+num_bytes-p,
513 &ret);
515 if (!NT_STATUS_IS_OK(status)) {
516 tevent_req_nterror(req, status);
517 return;
519 p += ret;
521 status = smb_bytes_talloc_string(cli,
522 inbuf,
523 &cli->server_type,
525 bytes+num_bytes-p,
526 &ret);
528 if (!NT_STATUS_IS_OK(status)) {
529 tevent_req_nterror(req, status);
530 return;
532 p += ret;
534 status = smb_bytes_talloc_string(cli,
535 inbuf,
536 &cli->server_domain,
538 bytes+num_bytes-p,
539 &ret);
541 if (!NT_STATUS_IS_OK(status)) {
542 tevent_req_nterror(req, status);
543 return;
545 p += ret;
547 if (strstr(cli->server_type, "Samba")) {
548 cli->is_samba = True;
551 status = cli_set_username(cli, "");
552 if (!NT_STATUS_IS_OK(status)) {
553 tevent_req_nterror(req, status);
554 return;
556 tevent_req_done(req);
559 NTSTATUS cli_session_setup_guest_recv(struct tevent_req *req)
561 return tevent_req_simple_recv_ntstatus(req);
564 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
566 TALLOC_CTX *frame = talloc_stackframe();
567 struct event_context *ev;
568 struct tevent_req *req;
569 NTSTATUS status = NT_STATUS_OK;
571 if (cli_has_async_calls(cli)) {
573 * Can't use sync call while an async call is in flight
575 status = NT_STATUS_INVALID_PARAMETER;
576 goto fail;
579 ev = event_context_init(frame);
580 if (ev == NULL) {
581 status = NT_STATUS_NO_MEMORY;
582 goto fail;
585 req = cli_session_setup_guest_send(frame, ev, cli);
586 if (req == NULL) {
587 status = NT_STATUS_NO_MEMORY;
588 goto fail;
591 if (!tevent_req_poll(req, ev)) {
592 status = map_nt_error_from_unix(errno);
593 goto fail;
596 status = cli_session_setup_guest_recv(req);
597 fail:
598 TALLOC_FREE(frame);
599 return status;
602 /****************************************************************************
603 Do a NT1 plaintext session setup.
604 ****************************************************************************/
606 struct cli_session_setup_plain_state {
607 struct cli_state *cli;
608 uint16_t vwv[13];
609 const char *user;
612 static void cli_session_setup_plain_done(struct tevent_req *subreq);
614 static struct tevent_req *cli_session_setup_plain_send(
615 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
616 struct cli_state *cli,
617 const char *user, const char *pass, const char *workgroup)
619 struct tevent_req *req, *subreq;
620 struct cli_session_setup_plain_state *state;
621 uint16_t *vwv;
622 uint8_t *bytes;
623 size_t passlen;
624 char *version;
626 req = tevent_req_create(mem_ctx, &state,
627 struct cli_session_setup_plain_state);
628 if (req == NULL) {
629 return NULL;
631 state->cli = cli;
632 state->user = user;
633 vwv = state->vwv;
635 SCVAL(vwv+0, 0, 0xff);
636 SCVAL(vwv+0, 1, 0);
637 SSVAL(vwv+1, 0, 0);
638 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
639 SSVAL(vwv+3, 0, 2);
640 SSVAL(vwv+4, 0, cli->pid);
641 SIVAL(vwv+5, 0, cli->sesskey);
642 SSVAL(vwv+7, 0, 0);
643 SSVAL(vwv+8, 0, 0);
644 SSVAL(vwv+9, 0, 0);
645 SSVAL(vwv+10, 0, 0);
646 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
648 bytes = talloc_array(state, uint8_t, 0);
649 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
650 &passlen);
651 if (tevent_req_nomem(bytes, req)) {
652 return tevent_req_post(req, ev);
654 SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
656 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
657 user, strlen(user)+1, NULL);
658 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
659 workgroup, strlen(workgroup)+1, NULL);
660 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
661 "Unix", 5, NULL);
663 version = talloc_asprintf(talloc_tos(), "Samba %s",
664 samba_version_string());
665 if (tevent_req_nomem(version, req)){
666 return tevent_req_post(req, ev);
668 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
669 version, strlen(version)+1, NULL);
670 TALLOC_FREE(version);
672 if (tevent_req_nomem(bytes, req)) {
673 return tevent_req_post(req, ev);
676 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
677 talloc_get_size(bytes), bytes);
678 if (tevent_req_nomem(subreq, req)) {
679 return tevent_req_post(req, ev);
681 tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
682 return req;
685 static void cli_session_setup_plain_done(struct tevent_req *subreq)
687 struct tevent_req *req = tevent_req_callback_data(
688 subreq, struct tevent_req);
689 struct cli_session_setup_plain_state *state = tevent_req_data(
690 req, struct cli_session_setup_plain_state);
691 struct cli_state *cli = state->cli;
692 uint32_t num_bytes;
693 uint8_t *in;
694 char *inbuf;
695 uint8_t *bytes;
696 uint8_t *p;
697 NTSTATUS status;
698 ssize_t ret;
699 uint8_t wct;
700 uint16_t *vwv;
702 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
703 &num_bytes, &bytes);
704 TALLOC_FREE(subreq);
705 if (tevent_req_nterror(req, status)) {
706 return;
709 inbuf = (char *)in;
710 p = bytes;
712 cli->vuid = SVAL(inbuf, smb_uid);
713 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
715 status = smb_bytes_talloc_string(cli,
716 inbuf,
717 &cli->server_os,
719 bytes+num_bytes-p,
720 &ret);
722 if (!NT_STATUS_IS_OK(status)) {
723 tevent_req_nterror(req, status);
724 return;
726 p += ret;
728 status = smb_bytes_talloc_string(cli,
729 inbuf,
730 &cli->server_type,
732 bytes+num_bytes-p,
733 &ret);
735 if (!NT_STATUS_IS_OK(status)) {
736 tevent_req_nterror(req, status);
737 return;
739 p += ret;
741 status = smb_bytes_talloc_string(cli,
742 inbuf,
743 &cli->server_domain,
745 bytes+num_bytes-p,
746 &ret);
748 if (!NT_STATUS_IS_OK(status)) {
749 tevent_req_nterror(req, status);
750 return;
752 p += ret;
754 status = cli_set_username(cli, state->user);
755 if (tevent_req_nterror(req, status)) {
756 return;
758 if (strstr(cli->server_type, "Samba")) {
759 cli->is_samba = True;
761 tevent_req_done(req);
764 static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
766 return tevent_req_simple_recv_ntstatus(req);
769 static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
770 const char *user, const char *pass,
771 const char *workgroup)
773 TALLOC_CTX *frame = talloc_stackframe();
774 struct event_context *ev;
775 struct tevent_req *req;
776 NTSTATUS status = NT_STATUS_NO_MEMORY;
778 if (cli_has_async_calls(cli)) {
780 * Can't use sync call while an async call is in flight
782 status = NT_STATUS_INVALID_PARAMETER;
783 goto fail;
785 ev = event_context_init(frame);
786 if (ev == NULL) {
787 goto fail;
789 req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
790 workgroup);
791 if (req == NULL) {
792 goto fail;
794 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
795 goto fail;
797 status = cli_session_setup_plain_recv(req);
798 fail:
799 TALLOC_FREE(frame);
800 return status;
803 /****************************************************************************
804 do a NT1 NTLM/LM encrypted session setup - for when extended security
805 is not negotiated.
806 @param cli client state to create do session setup on
807 @param user username
808 @param pass *either* cleartext password (passlen !=24) or LM response.
809 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
810 @param workgroup The user's domain.
811 ****************************************************************************/
813 struct cli_session_setup_nt1_state {
814 struct cli_state *cli;
815 uint16_t vwv[13];
816 DATA_BLOB response;
817 DATA_BLOB session_key;
818 const char *user;
821 static void cli_session_setup_nt1_done(struct tevent_req *subreq);
823 static struct tevent_req *cli_session_setup_nt1_send(
824 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
825 struct cli_state *cli, const char *user,
826 const char *pass, size_t passlen,
827 const char *ntpass, size_t ntpasslen,
828 const char *workgroup)
830 struct tevent_req *req, *subreq;
831 struct cli_session_setup_nt1_state *state;
832 DATA_BLOB lm_response = data_blob_null;
833 DATA_BLOB nt_response = data_blob_null;
834 DATA_BLOB session_key = data_blob_null;
835 uint16_t *vwv;
836 uint8_t *bytes;
837 char *workgroup_upper;
839 req = tevent_req_create(mem_ctx, &state,
840 struct cli_session_setup_nt1_state);
841 if (req == NULL) {
842 return NULL;
844 state->cli = cli;
845 state->user = user;
846 vwv = state->vwv;
848 if (passlen == 0) {
849 /* do nothing - guest login */
850 } else if (passlen != 24) {
851 if (lp_client_ntlmv2_auth()) {
852 DATA_BLOB server_chal;
853 DATA_BLOB names_blob;
855 server_chal = data_blob(cli->secblob.data,
856 MIN(cli->secblob.length, 8));
857 if (tevent_req_nomem(server_chal.data, req)) {
858 return tevent_req_post(req, ev);
862 * note that the 'workgroup' here is a best
863 * guess - we don't know the server's domain
864 * at this point. The 'server name' is also
865 * dodgy...
867 names_blob = NTLMv2_generate_names_blob(
868 NULL, cli->called.name, workgroup);
870 if (tevent_req_nomem(names_blob.data, req)) {
871 return tevent_req_post(req, ev);
874 if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
875 &server_chal, &names_blob,
876 &lm_response, &nt_response,
877 NULL, &session_key)) {
878 data_blob_free(&names_blob);
879 data_blob_free(&server_chal);
880 tevent_req_nterror(
881 req, NT_STATUS_ACCESS_DENIED);
882 return tevent_req_post(req, ev);
884 data_blob_free(&names_blob);
885 data_blob_free(&server_chal);
887 } else {
888 uchar nt_hash[16];
889 E_md4hash(pass, nt_hash);
891 #ifdef LANMAN_ONLY
892 nt_response = data_blob_null;
893 #else
894 nt_response = data_blob(NULL, 24);
895 if (tevent_req_nomem(nt_response.data, req)) {
896 return tevent_req_post(req, ev);
899 SMBNTencrypt(pass, cli->secblob.data,
900 nt_response.data);
901 #endif
902 /* non encrypted password supplied. Ignore ntpass. */
903 if (lp_client_lanman_auth()) {
905 lm_response = data_blob(NULL, 24);
906 if (tevent_req_nomem(lm_response.data, req)) {
907 return tevent_req_post(req, ev);
910 if (!SMBencrypt(pass,cli->secblob.data,
911 lm_response.data)) {
913 * Oops, the LM response is
914 * invalid, just put the NT
915 * response there instead
917 data_blob_free(&lm_response);
918 lm_response = data_blob(
919 nt_response.data,
920 nt_response.length);
922 } else {
924 * LM disabled, place NT# in LM field
925 * instead
927 lm_response = data_blob(
928 nt_response.data, nt_response.length);
931 if (tevent_req_nomem(lm_response.data, req)) {
932 return tevent_req_post(req, ev);
935 session_key = data_blob(NULL, 16);
936 if (tevent_req_nomem(session_key.data, req)) {
937 return tevent_req_post(req, ev);
939 #ifdef LANMAN_ONLY
940 E_deshash(pass, session_key.data);
941 memset(&session_key.data[8], '\0', 8);
942 #else
943 SMBsesskeygen_ntv1(nt_hash, session_key.data);
944 #endif
946 cli_temp_set_signing(cli);
947 } else {
948 /* pre-encrypted password supplied. Only used for
949 security=server, can't do
950 signing because we don't have original key */
952 lm_response = data_blob(pass, passlen);
953 if (tevent_req_nomem(lm_response.data, req)) {
954 return tevent_req_post(req, ev);
957 nt_response = data_blob(ntpass, ntpasslen);
958 if (tevent_req_nomem(nt_response.data, req)) {
959 return tevent_req_post(req, ev);
963 #ifdef LANMAN_ONLY
964 state->response = data_blob_talloc(
965 state, lm_response.data, lm_response.length);
966 #else
967 state->response = data_blob_talloc(
968 state, nt_response.data, nt_response.length);
969 #endif
970 if (tevent_req_nomem(state->response.data, req)) {
971 return tevent_req_post(req, ev);
974 if (session_key.data) {
975 state->session_key = data_blob_talloc(
976 state, session_key.data, session_key.length);
977 if (tevent_req_nomem(state->session_key.data, req)) {
978 return tevent_req_post(req, ev);
981 data_blob_free(&session_key);
983 SCVAL(vwv+0, 0, 0xff);
984 SCVAL(vwv+0, 1, 0);
985 SSVAL(vwv+1, 0, 0);
986 SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
987 SSVAL(vwv+3, 0, 2);
988 SSVAL(vwv+4, 0, cli->pid);
989 SIVAL(vwv+5, 0, cli->sesskey);
990 SSVAL(vwv+7, 0, lm_response.length);
991 SSVAL(vwv+8, 0, nt_response.length);
992 SSVAL(vwv+9, 0, 0);
993 SSVAL(vwv+10, 0, 0);
994 SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
996 bytes = talloc_array(state, uint8_t,
997 lm_response.length + nt_response.length);
998 if (tevent_req_nomem(bytes, req)) {
999 return tevent_req_post(req, ev);
1001 if (lm_response.length != 0) {
1002 memcpy(bytes, lm_response.data, lm_response.length);
1004 if (nt_response.length != 0) {
1005 memcpy(bytes + lm_response.length,
1006 nt_response.data, nt_response.length);
1008 data_blob_free(&lm_response);
1009 data_blob_free(&nt_response);
1011 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1012 user, strlen(user)+1, NULL);
1015 * Upper case here might help some NTLMv2 implementations
1017 workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
1018 if (tevent_req_nomem(workgroup_upper, req)) {
1019 return tevent_req_post(req, ev);
1021 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1022 workgroup_upper, strlen(workgroup_upper)+1,
1023 NULL);
1024 TALLOC_FREE(workgroup_upper);
1026 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
1027 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
1028 if (tevent_req_nomem(bytes, req)) {
1029 return tevent_req_post(req, ev);
1032 subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
1033 talloc_get_size(bytes), bytes);
1034 if (tevent_req_nomem(subreq, req)) {
1035 return tevent_req_post(req, ev);
1037 tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
1038 return req;
1041 static void cli_session_setup_nt1_done(struct tevent_req *subreq)
1043 struct tevent_req *req = tevent_req_callback_data(
1044 subreq, struct tevent_req);
1045 struct cli_session_setup_nt1_state *state = tevent_req_data(
1046 req, struct cli_session_setup_nt1_state);
1047 struct cli_state *cli = state->cli;
1048 uint32_t num_bytes;
1049 uint8_t *in;
1050 char *inbuf;
1051 uint8_t *bytes;
1052 uint8_t *p;
1053 NTSTATUS status;
1054 ssize_t ret;
1055 uint8_t wct;
1056 uint16_t *vwv;
1058 status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
1059 &num_bytes, &bytes);
1060 TALLOC_FREE(subreq);
1061 if (!NT_STATUS_IS_OK(status)) {
1062 tevent_req_nterror(req, status);
1063 return;
1066 inbuf = (char *)in;
1067 p = bytes;
1069 cli->vuid = SVAL(inbuf, smb_uid);
1070 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1072 status = smb_bytes_talloc_string(cli,
1073 inbuf,
1074 &cli->server_os,
1076 bytes+num_bytes-p,
1077 &ret);
1078 if (!NT_STATUS_IS_OK(status)) {
1079 tevent_req_nterror(req, status);
1080 return;
1082 p += ret;
1084 status = smb_bytes_talloc_string(cli,
1085 inbuf,
1086 &cli->server_type,
1088 bytes+num_bytes-p,
1089 &ret);
1090 if (!NT_STATUS_IS_OK(status)) {
1091 tevent_req_nterror(req, status);
1092 return;
1094 p += ret;
1096 status = smb_bytes_talloc_string(cli,
1097 inbuf,
1098 &cli->server_domain,
1100 bytes+num_bytes-p,
1101 &ret);
1102 if (!NT_STATUS_IS_OK(status)) {
1103 tevent_req_nterror(req, status);
1104 return;
1106 p += ret;
1108 if (strstr(cli->server_type, "Samba")) {
1109 cli->is_samba = True;
1112 status = cli_set_username(cli, state->user);
1113 if (tevent_req_nterror(req, status)) {
1114 return;
1116 if (cli_simple_set_signing(cli, state->session_key, state->response)
1117 && !cli_check_sign_mac(cli, (char *)in, 1)) {
1118 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1119 return;
1121 if (state->session_key.data) {
1122 /* Have plaintext orginal */
1123 cli_set_session_key(cli, state->session_key);
1125 tevent_req_done(req);
1128 static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
1130 return tevent_req_simple_recv_ntstatus(req);
1133 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
1134 const char *pass, size_t passlen,
1135 const char *ntpass, size_t ntpasslen,
1136 const char *workgroup)
1138 TALLOC_CTX *frame = talloc_stackframe();
1139 struct event_context *ev;
1140 struct tevent_req *req;
1141 NTSTATUS status = NT_STATUS_NO_MEMORY;
1143 if (cli_has_async_calls(cli)) {
1145 * Can't use sync call while an async call is in flight
1147 status = NT_STATUS_INVALID_PARAMETER;
1148 goto fail;
1150 ev = event_context_init(frame);
1151 if (ev == NULL) {
1152 goto fail;
1154 req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
1155 ntpass, ntpasslen, workgroup);
1156 if (req == NULL) {
1157 goto fail;
1159 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1160 goto fail;
1162 status = cli_session_setup_nt1_recv(req);
1163 fail:
1164 TALLOC_FREE(frame);
1165 return status;
1168 /* The following is calculated from :
1169 * (smb_size-4) = 35
1170 * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
1171 * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
1172 * end of packet.
1175 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
1177 struct cli_sesssetup_blob_state {
1178 struct tevent_context *ev;
1179 struct cli_state *cli;
1180 DATA_BLOB blob;
1181 uint16_t max_blob_size;
1182 uint16_t vwv[12];
1183 uint8_t *buf;
1185 NTSTATUS status;
1186 char *inbuf;
1187 DATA_BLOB ret_blob;
1190 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1191 struct tevent_req **psubreq);
1192 static void cli_sesssetup_blob_done(struct tevent_req *subreq);
1194 static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
1195 struct tevent_context *ev,
1196 struct cli_state *cli,
1197 DATA_BLOB blob)
1199 struct tevent_req *req, *subreq;
1200 struct cli_sesssetup_blob_state *state;
1202 req = tevent_req_create(mem_ctx, &state,
1203 struct cli_sesssetup_blob_state);
1204 if (req == NULL) {
1205 return NULL;
1207 state->ev = ev;
1208 state->blob = blob;
1209 state->cli = cli;
1211 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
1212 DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
1213 "(was %u, need minimum %u)\n",
1214 (unsigned int)cli->max_xmit,
1215 BASE_SESSSETUP_BLOB_PACKET_SIZE));
1216 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1217 return tevent_req_post(req, ev);
1219 state->max_blob_size =
1220 MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
1222 if (!cli_sesssetup_blob_next(state, &subreq)) {
1223 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1224 return tevent_req_post(req, ev);
1226 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1227 return req;
1230 static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
1231 struct tevent_req **psubreq)
1233 struct tevent_req *subreq;
1234 uint16_t thistime;
1236 SCVAL(state->vwv+0, 0, 0xFF);
1237 SCVAL(state->vwv+0, 1, 0);
1238 SSVAL(state->vwv+1, 0, 0);
1239 SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
1240 SSVAL(state->vwv+3, 0, 2);
1241 SSVAL(state->vwv+4, 0, 1);
1242 SIVAL(state->vwv+5, 0, 0);
1244 thistime = MIN(state->blob.length, state->max_blob_size);
1245 SSVAL(state->vwv+7, 0, thistime);
1247 SSVAL(state->vwv+8, 0, 0);
1248 SSVAL(state->vwv+9, 0, 0);
1249 SIVAL(state->vwv+10, 0,
1250 cli_session_setup_capabilities(state->cli)
1251 | CAP_EXTENDED_SECURITY);
1253 state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
1254 thistime);
1255 if (state->buf == NULL) {
1256 return false;
1258 state->blob.data += thistime;
1259 state->blob.length -= thistime;
1261 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1262 "Unix", 5, NULL);
1263 state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
1264 "Samba", 6, NULL);
1265 if (state->buf == NULL) {
1266 return false;
1268 subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
1269 12, state->vwv,
1270 talloc_get_size(state->buf), state->buf);
1271 if (subreq == NULL) {
1272 return false;
1274 *psubreq = subreq;
1275 return true;
1278 static void cli_sesssetup_blob_done(struct tevent_req *subreq)
1280 struct tevent_req *req = tevent_req_callback_data(
1281 subreq, struct tevent_req);
1282 struct cli_sesssetup_blob_state *state = tevent_req_data(
1283 req, struct cli_sesssetup_blob_state);
1284 struct cli_state *cli = state->cli;
1285 uint8_t wct;
1286 uint16_t *vwv;
1287 uint32_t num_bytes;
1288 uint8_t *bytes;
1289 NTSTATUS status;
1290 uint8_t *p;
1291 uint16_t blob_length;
1292 uint8_t *inbuf;
1293 ssize_t ret;
1295 status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
1296 &num_bytes, &bytes);
1297 TALLOC_FREE(subreq);
1298 if (!NT_STATUS_IS_OK(status)
1299 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1300 tevent_req_nterror(req, status);
1301 return;
1304 state->status = status;
1305 TALLOC_FREE(state->buf);
1307 state->inbuf = (char *)inbuf;
1308 cli->vuid = SVAL(state->inbuf, smb_uid);
1309 cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
1311 blob_length = SVAL(vwv+3, 0);
1312 if (blob_length > num_bytes) {
1313 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1314 return;
1316 state->ret_blob = data_blob_const(bytes, blob_length);
1318 p = bytes + blob_length;
1320 status = smb_bytes_talloc_string(cli,
1321 (char *)inbuf,
1322 &cli->server_os,
1324 bytes+num_bytes-p,
1325 &ret);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 tevent_req_nterror(req, status);
1329 return;
1331 p += ret;
1333 status = smb_bytes_talloc_string(cli,
1334 (char *)inbuf,
1335 &cli->server_type,
1337 bytes+num_bytes-p,
1338 &ret);
1340 if (!NT_STATUS_IS_OK(status)) {
1341 tevent_req_nterror(req, status);
1342 return;
1344 p += ret;
1346 status = smb_bytes_talloc_string(cli,
1347 (char *)inbuf,
1348 &cli->server_domain,
1350 bytes+num_bytes-p,
1351 &ret);
1353 if (!NT_STATUS_IS_OK(status)) {
1354 tevent_req_nterror(req, status);
1355 return;
1357 p += ret;
1359 if (strstr(cli->server_type, "Samba")) {
1360 cli->is_samba = True;
1363 if (state->blob.length != 0) {
1365 * More to send
1367 if (!cli_sesssetup_blob_next(state, &subreq)) {
1368 tevent_req_oom(req);
1369 return;
1371 tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
1372 return;
1374 tevent_req_done(req);
1377 static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
1378 TALLOC_CTX *mem_ctx,
1379 DATA_BLOB *pblob,
1380 char **pinbuf)
1382 struct cli_sesssetup_blob_state *state = tevent_req_data(
1383 req, struct cli_sesssetup_blob_state);
1384 NTSTATUS status;
1385 char *inbuf;
1387 if (tevent_req_is_nterror(req, &status)) {
1388 state->cli->vuid = 0;
1389 return status;
1392 inbuf = talloc_move(mem_ctx, &state->inbuf);
1393 if (pblob != NULL) {
1394 *pblob = state->ret_blob;
1396 if (pinbuf != NULL) {
1397 *pinbuf = inbuf;
1399 /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
1400 return state->status;
1403 #ifdef HAVE_KRB5
1405 /****************************************************************************
1406 Use in-memory credentials cache
1407 ****************************************************************************/
1409 static void use_in_memory_ccache(void) {
1410 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
1413 /****************************************************************************
1414 Do a spnego/kerberos encrypted session setup.
1415 ****************************************************************************/
1417 struct cli_session_setup_kerberos_state {
1418 struct cli_state *cli;
1419 DATA_BLOB negTokenTarg;
1420 DATA_BLOB session_key_krb5;
1421 ADS_STATUS ads_status;
1424 static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
1426 static struct tevent_req *cli_session_setup_kerberos_send(
1427 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1428 const char *principal)
1430 struct tevent_req *req, *subreq;
1431 struct cli_session_setup_kerberos_state *state;
1432 int rc;
1434 DEBUG(2,("Doing kerberos session setup\n"));
1436 req = tevent_req_create(mem_ctx, &state,
1437 struct cli_session_setup_kerberos_state);
1438 if (req == NULL) {
1439 return NULL;
1441 state->cli = cli;
1442 state->ads_status = ADS_SUCCESS;
1444 cli_temp_set_signing(cli);
1447 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
1448 * we have to acquire a ticket. To be fixed later :-)
1450 rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
1451 &state->session_key_krb5, 0, NULL);
1452 if (rc) {
1453 DEBUG(1, ("cli_session_setup_kerberos: "
1454 "spnego_gen_krb5_negTokenInit failed: %s\n",
1455 error_message(rc)));
1456 state->ads_status = ADS_ERROR_KRB5(rc);
1457 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1458 return tevent_req_post(req, ev);
1461 #if 0
1462 file_save("negTokenTarg.dat", state->negTokenTarg.data,
1463 state->negTokenTarg.length);
1464 #endif
1466 subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
1467 if (tevent_req_nomem(subreq, req)) {
1468 return tevent_req_post(req, ev);
1470 tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
1471 return req;
1474 static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
1476 struct tevent_req *req = tevent_req_callback_data(
1477 subreq, struct tevent_req);
1478 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1479 req, struct cli_session_setup_kerberos_state);
1480 char *inbuf = NULL;
1481 NTSTATUS status;
1483 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
1484 if (!NT_STATUS_IS_OK(status)) {
1485 TALLOC_FREE(subreq);
1486 tevent_req_nterror(req, status);
1487 return;
1490 cli_set_session_key(state->cli, state->session_key_krb5);
1492 if (cli_simple_set_signing(state->cli, state->session_key_krb5,
1493 data_blob_null)
1494 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1495 TALLOC_FREE(subreq);
1496 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1497 return;
1499 TALLOC_FREE(subreq);
1500 tevent_req_done(req);
1503 static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
1505 struct cli_session_setup_kerberos_state *state = tevent_req_data(
1506 req, struct cli_session_setup_kerberos_state);
1507 NTSTATUS status;
1509 if (tevent_req_is_nterror(req, &status)) {
1510 return ADS_ERROR_NT(status);
1512 return state->ads_status;
1515 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
1516 const char *principal)
1518 struct tevent_context *ev;
1519 struct tevent_req *req;
1520 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1522 if (cli_has_async_calls(cli)) {
1523 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1525 ev = tevent_context_init(talloc_tos());
1526 if (ev == NULL) {
1527 goto fail;
1529 req = cli_session_setup_kerberos_send(ev, ev, cli, principal);
1530 if (req == NULL) {
1531 goto fail;
1533 if (!tevent_req_poll(req, ev)) {
1534 status = ADS_ERROR_SYSTEM(errno);
1535 goto fail;
1537 status = cli_session_setup_kerberos_recv(req);
1538 fail:
1539 TALLOC_FREE(ev);
1540 return status;
1542 #endif /* HAVE_KRB5 */
1544 /****************************************************************************
1545 Do a spnego/NTLMSSP encrypted session setup.
1546 ****************************************************************************/
1548 struct cli_session_setup_ntlmssp_state {
1549 struct tevent_context *ev;
1550 struct cli_state *cli;
1551 struct ntlmssp_state *ntlmssp_state;
1552 int turn;
1553 DATA_BLOB blob_out;
1556 static int cli_session_setup_ntlmssp_state_destructor(
1557 struct cli_session_setup_ntlmssp_state *state)
1559 if (state->ntlmssp_state != NULL) {
1560 TALLOC_FREE(state->ntlmssp_state);
1562 return 0;
1565 static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
1567 static struct tevent_req *cli_session_setup_ntlmssp_send(
1568 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
1569 const char *user, const char *pass, const char *domain)
1571 struct tevent_req *req, *subreq;
1572 struct cli_session_setup_ntlmssp_state *state;
1573 NTSTATUS status;
1574 DATA_BLOB blob_out;
1575 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
1577 req = tevent_req_create(mem_ctx, &state,
1578 struct cli_session_setup_ntlmssp_state);
1579 if (req == NULL) {
1580 return NULL;
1582 state->ev = ev;
1583 state->cli = cli;
1584 state->turn = 1;
1586 state->ntlmssp_state = NULL;
1587 talloc_set_destructor(
1588 state, cli_session_setup_ntlmssp_state_destructor);
1590 cli_temp_set_signing(cli);
1592 status = ntlmssp_client_start(state,
1593 lp_netbios_name(),
1594 lp_workgroup(),
1595 lp_client_ntlmv2_auth(),
1596 &state->ntlmssp_state);
1597 if (!NT_STATUS_IS_OK(status)) {
1598 goto fail;
1600 ntlmssp_want_feature(state->ntlmssp_state,
1601 NTLMSSP_FEATURE_SESSION_KEY);
1602 if (cli->use_ccache) {
1603 ntlmssp_want_feature(state->ntlmssp_state,
1604 NTLMSSP_FEATURE_CCACHE);
1606 status = ntlmssp_set_username(state->ntlmssp_state, user);
1607 if (!NT_STATUS_IS_OK(status)) {
1608 goto fail;
1610 status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1611 if (!NT_STATUS_IS_OK(status)) {
1612 goto fail;
1614 status = ntlmssp_set_password(state->ntlmssp_state, pass);
1615 if (!NT_STATUS_IS_OK(status)) {
1616 goto fail;
1618 status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1619 &blob_out);
1620 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1621 goto fail;
1624 state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
1625 data_blob_free(&blob_out);
1627 subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1628 if (tevent_req_nomem(subreq, req)) {
1629 return tevent_req_post(req, ev);
1631 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1632 return req;
1633 fail:
1634 tevent_req_nterror(req, status);
1635 return tevent_req_post(req, ev);
1638 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1640 struct tevent_req *req = tevent_req_callback_data(
1641 subreq, struct tevent_req);
1642 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1643 req, struct cli_session_setup_ntlmssp_state);
1644 DATA_BLOB blob_in, msg_in, blob_out;
1645 char *inbuf = NULL;
1646 bool parse_ret;
1647 NTSTATUS status;
1649 status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1650 &inbuf);
1651 TALLOC_FREE(subreq);
1652 data_blob_free(&state->blob_out);
1654 if (NT_STATUS_IS_OK(status)) {
1655 if (state->cli->server_domain[0] == '\0') {
1656 TALLOC_FREE(state->cli->server_domain);
1657 state->cli->server_domain = talloc_strdup(state->cli,
1658 state->ntlmssp_state->server.netbios_domain);
1659 if (state->cli->server_domain == NULL) {
1660 TALLOC_FREE(subreq);
1661 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1662 return;
1665 cli_set_session_key(
1666 state->cli, state->ntlmssp_state->session_key);
1668 if (cli_simple_set_signing(
1669 state->cli, state->ntlmssp_state->session_key,
1670 data_blob_null)
1671 && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1672 TALLOC_FREE(subreq);
1673 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1674 return;
1676 TALLOC_FREE(subreq);
1677 TALLOC_FREE(state->ntlmssp_state);
1678 tevent_req_done(req);
1679 return;
1681 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1682 tevent_req_nterror(req, status);
1683 return;
1686 if (blob_in.length == 0) {
1687 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1688 return;
1691 if ((state->turn == 1)
1692 && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1693 DATA_BLOB tmp_blob = data_blob_null;
1694 /* the server might give us back two challenges */
1695 parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
1696 &tmp_blob);
1697 data_blob_free(&tmp_blob);
1698 } else {
1699 parse_ret = spnego_parse_auth_response(state, blob_in, status,
1700 OID_NTLMSSP, &msg_in);
1702 state->turn += 1;
1704 if (!parse_ret) {
1705 DEBUG(3,("Failed to parse auth response\n"));
1706 if (NT_STATUS_IS_OK(status)
1707 || NT_STATUS_EQUAL(status,
1708 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1709 tevent_req_nterror(
1710 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1711 return;
1715 status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1717 if (!NT_STATUS_IS_OK(status)
1718 && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1719 TALLOC_FREE(subreq);
1720 TALLOC_FREE(state->ntlmssp_state);
1721 tevent_req_nterror(req, status);
1722 return;
1725 state->blob_out = spnego_gen_auth(state, blob_out);
1726 TALLOC_FREE(subreq);
1727 if (tevent_req_nomem(state->blob_out.data, req)) {
1728 return;
1731 subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1732 state->blob_out);
1733 if (tevent_req_nomem(subreq, req)) {
1734 return;
1736 tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1739 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1741 struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1742 req, struct cli_session_setup_ntlmssp_state);
1743 NTSTATUS status;
1745 if (tevent_req_is_nterror(req, &status)) {
1746 state->cli->vuid = 0;
1747 return status;
1749 return NT_STATUS_OK;
1752 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1753 const char *user,
1754 const char *pass,
1755 const char *domain)
1757 struct tevent_context *ev;
1758 struct tevent_req *req;
1759 NTSTATUS status = NT_STATUS_NO_MEMORY;
1761 if (cli_has_async_calls(cli)) {
1762 return NT_STATUS_INVALID_PARAMETER;
1764 ev = tevent_context_init(talloc_tos());
1765 if (ev == NULL) {
1766 goto fail;
1768 req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1769 if (req == NULL) {
1770 goto fail;
1772 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1773 goto fail;
1775 status = cli_session_setup_ntlmssp_recv(req);
1776 fail:
1777 TALLOC_FREE(ev);
1778 return status;
1781 /****************************************************************************
1782 Do a spnego encrypted session setup.
1784 user_domain: The shortname of the domain the user/machine is a member of.
1785 dest_realm: The realm we're connecting to, if NULL we use our default realm.
1786 ****************************************************************************/
1788 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
1789 const char *pass, const char *user_domain,
1790 const char * dest_realm)
1792 char *principal = NULL;
1793 char *OIDs[ASN1_MAX_OIDS];
1794 int i;
1795 DATA_BLOB blob;
1796 const char *p = NULL;
1797 char *account = NULL;
1798 NTSTATUS status;
1800 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1802 /* the server might not even do spnego */
1803 if (cli->secblob.length <= 16) {
1804 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1805 goto ntlmssp;
1808 #if 0
1809 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1810 #endif
1812 /* there is 16 bytes of GUID before the real spnego packet starts */
1813 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1815 /* The server sent us the first part of the SPNEGO exchange in the
1816 * negprot reply. It is WRONG to depend on the principal sent in the
1817 * negprot reply, but right now we do it. If we don't receive one,
1818 * we try to best guess, then fall back to NTLM. */
1819 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
1820 OIDs[0] == NULL) {
1821 data_blob_free(&blob);
1822 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1824 data_blob_free(&blob);
1826 /* make sure the server understands kerberos */
1827 for (i=0;OIDs[i];i++) {
1828 if (i == 0)
1829 DEBUG(3,("got OID=%s\n", OIDs[i]));
1830 else
1831 DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1832 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1833 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1834 cli->got_kerberos_mechanism = True;
1836 talloc_free(OIDs[i]);
1839 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1841 status = cli_set_username(cli, user);
1842 if (!NT_STATUS_IS_OK(status)) {
1843 TALLOC_FREE(principal);
1844 return ADS_ERROR_NT(status);
1847 #ifdef HAVE_KRB5
1848 /* If password is set we reauthenticate to kerberos server
1849 * and do not store results */
1851 if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1852 ADS_STATUS rc;
1854 if (pass && *pass) {
1855 int ret;
1857 use_in_memory_ccache();
1858 ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1860 if (ret){
1861 TALLOC_FREE(principal);
1862 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1863 if (cli->fallback_after_kerberos)
1864 goto ntlmssp;
1865 return ADS_ERROR_KRB5(ret);
1869 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1871 if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1872 TALLOC_FREE(principal);
1875 if (principal == NULL &&
1876 !is_ipaddress(cli->desthost) &&
1877 !strequal(STAR_SMBSERVER,
1878 cli->desthost)) {
1879 char *realm = NULL;
1880 char *host = NULL;
1881 DEBUG(3,("cli_session_setup_spnego: using target "
1882 "hostname not SPNEGO principal\n"));
1884 host = strchr_m(cli->desthost, '.');
1885 if (dest_realm) {
1886 realm = SMB_STRDUP(dest_realm);
1887 if (!realm) {
1888 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1890 strupper_m(realm);
1891 } else {
1892 if (host) {
1893 /* DNS name. */
1894 realm = kerberos_get_realm_from_hostname(cli->desthost);
1895 } else {
1896 /* NetBIOS name - use our realm. */
1897 realm = kerberos_get_default_realm_from_ccache();
1901 if (realm == NULL || *realm == '\0') {
1902 realm = SMB_STRDUP(lp_realm());
1903 if (!realm) {
1904 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1906 strupper_m(realm);
1907 DEBUG(3,("cli_session_setup_spnego: cannot "
1908 "get realm from dest_realm %s, "
1909 "desthost %s. Using default "
1910 "smb.conf realm %s\n",
1911 dest_realm ? dest_realm : "<null>",
1912 cli->desthost,
1913 realm));
1916 principal = talloc_asprintf(talloc_tos(),
1917 "cifs/%s@%s",
1918 cli->desthost,
1919 realm);
1920 if (!principal) {
1921 SAFE_FREE(realm);
1922 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1924 DEBUG(3,("cli_session_setup_spnego: guessed "
1925 "server principal=%s\n",
1926 principal ? principal : "<null>"));
1928 SAFE_FREE(realm);
1931 if (principal) {
1932 rc = cli_session_setup_kerberos(cli, principal);
1933 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1934 TALLOC_FREE(principal);
1935 return rc;
1939 #endif
1941 TALLOC_FREE(principal);
1943 ntlmssp:
1945 account = talloc_strdup(talloc_tos(), user);
1946 if (!account) {
1947 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1950 /* when falling back to ntlmssp while authenticating with a machine
1951 * account strip off the realm - gd */
1953 if ((p = strchr_m(user, '@')) != NULL) {
1954 account[PTR_DIFF(p,user)] = '\0';
1957 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1960 /****************************************************************************
1961 Send a session setup. The username and workgroup is in UNIX character
1962 format and must be converted to DOS codepage format before sending. If the
1963 password is in plaintext, the same should be done.
1964 ****************************************************************************/
1966 NTSTATUS cli_session_setup(struct cli_state *cli,
1967 const char *user,
1968 const char *pass, int passlen,
1969 const char *ntpass, int ntpasslen,
1970 const char *workgroup)
1972 char *p;
1973 char *user2;
1975 if (user) {
1976 user2 = talloc_strdup(talloc_tos(), user);
1977 } else {
1978 user2 = talloc_strdup(talloc_tos(), "");
1980 if (user2 == NULL) {
1981 return NT_STATUS_NO_MEMORY;
1984 if (!workgroup) {
1985 workgroup = "";
1988 /* allow for workgroups as part of the username */
1989 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1990 (p=strchr_m(user2,*lp_winbind_separator()))) {
1991 *p = 0;
1992 user = p+1;
1993 strupper_m(user2);
1994 workgroup = user2;
1997 if (cli->protocol < PROTOCOL_LANMAN1) {
1998 return NT_STATUS_OK;
2001 /* now work out what sort of session setup we are going to
2002 do. I have split this into separate functions to make the
2003 flow a bit easier to understand (tridge) */
2005 /* if its an older server then we have to use the older request format */
2007 if (cli->protocol < PROTOCOL_NT1) {
2008 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
2009 DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
2010 " or 'client ntlmv2 auth = yes'\n"));
2011 return NT_STATUS_ACCESS_DENIED;
2014 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
2015 !lp_client_plaintext_auth() && (*pass)) {
2016 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2017 " or 'client ntlmv2 auth = yes'\n"));
2018 return NT_STATUS_ACCESS_DENIED;
2021 return cli_session_setup_lanman2(cli, user, pass, passlen,
2022 workgroup);
2025 /* if no user is supplied then we have to do an anonymous connection.
2026 passwords are ignored */
2028 if (!user || !*user)
2029 return cli_session_setup_guest(cli);
2031 /* if the server is share level then send a plaintext null
2032 password at this point. The password is sent in the tree
2033 connect */
2035 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
2036 return cli_session_setup_plain(cli, user, "", workgroup);
2038 /* if the server doesn't support encryption then we have to use
2039 plaintext. The second password is ignored */
2041 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
2042 if (!lp_client_plaintext_auth() && (*pass)) {
2043 DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
2044 " or 'client ntlmv2 auth = yes'\n"));
2045 return NT_STATUS_ACCESS_DENIED;
2047 return cli_session_setup_plain(cli, user, pass, workgroup);
2050 /* if the server supports extended security then use SPNEGO */
2052 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
2053 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
2054 workgroup, NULL);
2055 if (!ADS_ERR_OK(status)) {
2056 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
2057 return ads_ntstatus(status);
2059 } else {
2060 NTSTATUS status;
2062 /* otherwise do a NT1 style session setup */
2063 status = cli_session_setup_nt1(cli, user, pass, passlen,
2064 ntpass, ntpasslen, workgroup);
2065 if (!NT_STATUS_IS_OK(status)) {
2066 DEBUG(3,("cli_session_setup: NT1 session setup "
2067 "failed: %s\n", nt_errstr(status)));
2068 return status;
2072 if (strstr(cli->server_type, "Samba")) {
2073 cli->is_samba = True;
2076 return NT_STATUS_OK;
2079 /****************************************************************************
2080 Send a uloggoff.
2081 *****************************************************************************/
2083 struct cli_ulogoff_state {
2084 struct cli_state *cli;
2085 uint16_t vwv[3];
2088 static void cli_ulogoff_done(struct tevent_req *subreq);
2090 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
2091 struct tevent_context *ev,
2092 struct cli_state *cli)
2094 struct tevent_req *req, *subreq;
2095 struct cli_ulogoff_state *state;
2097 req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
2098 if (req == NULL) {
2099 return NULL;
2101 state->cli = cli;
2103 SCVAL(state->vwv+0, 0, 0xFF);
2104 SCVAL(state->vwv+1, 0, 0);
2105 SSVAL(state->vwv+2, 0, 0);
2107 subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
2108 0, NULL);
2109 if (tevent_req_nomem(subreq, req)) {
2110 return tevent_req_post(req, ev);
2112 tevent_req_set_callback(subreq, cli_ulogoff_done, req);
2113 return req;
2116 static void cli_ulogoff_done(struct tevent_req *subreq)
2118 struct tevent_req *req = tevent_req_callback_data(
2119 subreq, struct tevent_req);
2120 struct cli_ulogoff_state *state = tevent_req_data(
2121 req, struct cli_ulogoff_state);
2122 NTSTATUS status;
2124 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2125 if (!NT_STATUS_IS_OK(status)) {
2126 tevent_req_nterror(req, status);
2127 return;
2129 state->cli->vuid = -1;
2130 tevent_req_done(req);
2133 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
2135 return tevent_req_simple_recv_ntstatus(req);
2138 NTSTATUS cli_ulogoff(struct cli_state *cli)
2140 struct tevent_context *ev;
2141 struct tevent_req *req;
2142 NTSTATUS status = NT_STATUS_NO_MEMORY;
2144 if (cli_has_async_calls(cli)) {
2145 return NT_STATUS_INVALID_PARAMETER;
2147 ev = tevent_context_init(talloc_tos());
2148 if (ev == NULL) {
2149 goto fail;
2151 req = cli_ulogoff_send(ev, ev, cli);
2152 if (req == NULL) {
2153 goto fail;
2155 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2156 goto fail;
2158 status = cli_ulogoff_recv(req);
2159 fail:
2160 TALLOC_FREE(ev);
2161 return status;
2164 /****************************************************************************
2165 Send a tconX.
2166 ****************************************************************************/
2168 struct cli_tcon_andx_state {
2169 struct cli_state *cli;
2170 uint16_t vwv[4];
2171 struct iovec bytes;
2174 static void cli_tcon_andx_done(struct tevent_req *subreq);
2176 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
2177 struct event_context *ev,
2178 struct cli_state *cli,
2179 const char *share, const char *dev,
2180 const char *pass, int passlen,
2181 struct tevent_req **psmbreq)
2183 struct tevent_req *req, *subreq;
2184 struct cli_tcon_andx_state *state;
2185 uint8_t p24[24];
2186 uint16_t *vwv;
2187 char *tmp = NULL;
2188 uint8_t *bytes;
2190 *psmbreq = NULL;
2192 req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
2193 if (req == NULL) {
2194 return NULL;
2196 state->cli = cli;
2197 vwv = state->vwv;
2199 cli->share = talloc_strdup(cli, share);
2200 if (!cli->share) {
2201 return NULL;
2204 /* in user level security don't send a password now */
2205 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
2206 passlen = 1;
2207 pass = "";
2208 } else if (pass == NULL) {
2209 DEBUG(1, ("Server not using user level security and no "
2210 "password supplied.\n"));
2211 goto access_denied;
2214 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
2215 *pass && passlen != 24) {
2216 if (!lp_client_lanman_auth()) {
2217 DEBUG(1, ("Server requested LANMAN password "
2218 "(share-level security) but "
2219 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2220 goto access_denied;
2224 * Non-encrypted passwords - convert to DOS codepage before
2225 * encryption.
2227 SMBencrypt(pass, cli->secblob.data, p24);
2228 passlen = 24;
2229 pass = (const char *)p24;
2230 } else {
2231 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
2232 |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
2233 == 0) {
2234 uint8_t *tmp_pass;
2236 if (!lp_client_plaintext_auth() && (*pass)) {
2237 DEBUG(1, ("Server requested plaintext "
2238 "password but "
2239 "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
2240 goto access_denied;
2244 * Non-encrypted passwords - convert to DOS codepage
2245 * before using.
2247 tmp_pass = talloc_array(talloc_tos(), uint8, 0);
2248 if (tevent_req_nomem(tmp_pass, req)) {
2249 return tevent_req_post(req, ev);
2251 tmp_pass = trans2_bytes_push_str(tmp_pass,
2252 false, /* always DOS */
2253 pass,
2254 passlen,
2255 NULL);
2256 if (tevent_req_nomem(tmp_pass, req)) {
2257 return tevent_req_post(req, ev);
2259 pass = (const char *)tmp_pass;
2260 passlen = talloc_get_size(tmp_pass);
2264 SCVAL(vwv+0, 0, 0xFF);
2265 SCVAL(vwv+0, 1, 0);
2266 SSVAL(vwv+1, 0, 0);
2267 SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
2268 SSVAL(vwv+3, 0, passlen);
2270 if (passlen && pass) {
2271 bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
2272 } else {
2273 bytes = talloc_array(state, uint8_t, 0);
2277 * Add the sharename
2279 tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
2280 cli->desthost, share);
2281 if (tmp == NULL) {
2282 TALLOC_FREE(req);
2283 return NULL;
2285 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
2286 NULL);
2287 TALLOC_FREE(tmp);
2290 * Add the devicetype
2292 tmp = talloc_strdup_upper(talloc_tos(), dev);
2293 if (tmp == NULL) {
2294 TALLOC_FREE(req);
2295 return NULL;
2297 bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
2298 TALLOC_FREE(tmp);
2300 if (bytes == NULL) {
2301 TALLOC_FREE(req);
2302 return NULL;
2305 state->bytes.iov_base = (void *)bytes;
2306 state->bytes.iov_len = talloc_get_size(bytes);
2308 subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
2309 1, &state->bytes);
2310 if (subreq == NULL) {
2311 TALLOC_FREE(req);
2312 return NULL;
2314 tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
2315 *psmbreq = subreq;
2316 return req;
2318 access_denied:
2319 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2320 return tevent_req_post(req, ev);
2323 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
2324 struct event_context *ev,
2325 struct cli_state *cli,
2326 const char *share, const char *dev,
2327 const char *pass, int passlen)
2329 struct tevent_req *req, *subreq;
2330 NTSTATUS status;
2332 req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
2333 &subreq);
2334 if (req == NULL) {
2335 return NULL;
2337 if (subreq == NULL) {
2338 return req;
2340 status = cli_smb_req_send(subreq);
2341 if (!NT_STATUS_IS_OK(status)) {
2342 tevent_req_nterror(req, status);
2343 return tevent_req_post(req, ev);
2345 return req;
2348 static void cli_tcon_andx_done(struct tevent_req *subreq)
2350 struct tevent_req *req = tevent_req_callback_data(
2351 subreq, struct tevent_req);
2352 struct cli_tcon_andx_state *state = tevent_req_data(
2353 req, struct cli_tcon_andx_state);
2354 struct cli_state *cli = state->cli;
2355 uint8_t *in;
2356 char *inbuf;
2357 uint8_t wct;
2358 uint16_t *vwv;
2359 uint32_t num_bytes;
2360 uint8_t *bytes;
2361 NTSTATUS status;
2363 status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
2364 &num_bytes, &bytes);
2365 TALLOC_FREE(subreq);
2366 if (!NT_STATUS_IS_OK(status)) {
2367 tevent_req_nterror(req, status);
2368 return;
2371 inbuf = (char *)in;
2373 if (num_bytes) {
2374 if (clistr_pull_talloc(cli,
2375 inbuf,
2376 SVAL(inbuf, smb_flg2),
2377 &cli->dev,
2378 bytes,
2379 num_bytes,
2380 STR_TERMINATE|STR_ASCII) == -1) {
2381 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2382 return;
2384 } else {
2385 cli->dev = talloc_strdup(cli, "");
2386 if (cli->dev == NULL) {
2387 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2388 return;
2392 if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
2393 /* almost certainly win95 - enable bug fixes */
2394 cli->win95 = True;
2398 * Make sure that we have the optional support 16-bit field. WCT > 2.
2399 * Avoids issues when connecting to Win9x boxes sharing files
2402 cli->dfsroot = false;
2404 if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
2405 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
2408 cli->cnum = SVAL(inbuf,smb_tid);
2409 tevent_req_done(req);
2412 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
2414 return tevent_req_simple_recv_ntstatus(req);
2417 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
2418 const char *dev, const char *pass, int passlen)
2420 TALLOC_CTX *frame = talloc_stackframe();
2421 struct event_context *ev;
2422 struct tevent_req *req;
2423 NTSTATUS status = NT_STATUS_OK;
2425 if (cli_has_async_calls(cli)) {
2427 * Can't use sync call while an async call is in flight
2429 status = NT_STATUS_INVALID_PARAMETER;
2430 goto fail;
2433 ev = event_context_init(frame);
2434 if (ev == NULL) {
2435 status = NT_STATUS_NO_MEMORY;
2436 goto fail;
2439 req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
2440 if (req == NULL) {
2441 status = NT_STATUS_NO_MEMORY;
2442 goto fail;
2445 if (!tevent_req_poll(req, ev)) {
2446 status = map_nt_error_from_unix(errno);
2447 goto fail;
2450 status = cli_tcon_andx_recv(req);
2451 fail:
2452 TALLOC_FREE(frame);
2453 return status;
2456 /****************************************************************************
2457 Send a tree disconnect.
2458 ****************************************************************************/
2460 struct cli_tdis_state {
2461 struct cli_state *cli;
2464 static void cli_tdis_done(struct tevent_req *subreq);
2466 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
2467 struct tevent_context *ev,
2468 struct cli_state *cli)
2470 struct tevent_req *req, *subreq;
2471 struct cli_tdis_state *state;
2473 req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
2474 if (req == NULL) {
2475 return NULL;
2477 state->cli = cli;
2479 subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
2480 if (tevent_req_nomem(subreq, req)) {
2481 return tevent_req_post(req, ev);
2483 tevent_req_set_callback(subreq, cli_tdis_done, req);
2484 return req;
2487 static void cli_tdis_done(struct tevent_req *subreq)
2489 struct tevent_req *req = tevent_req_callback_data(
2490 subreq, struct tevent_req);
2491 struct cli_tdis_state *state = tevent_req_data(
2492 req, struct cli_tdis_state);
2493 NTSTATUS status;
2495 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2496 TALLOC_FREE(subreq);
2497 if (!NT_STATUS_IS_OK(status)) {
2498 tevent_req_nterror(req, status);
2499 return;
2501 state->cli->cnum = -1;
2502 tevent_req_done(req);
2505 NTSTATUS cli_tdis_recv(struct tevent_req *req)
2507 return tevent_req_simple_recv_ntstatus(req);
2510 NTSTATUS cli_tdis(struct cli_state *cli)
2512 struct tevent_context *ev;
2513 struct tevent_req *req;
2514 NTSTATUS status = NT_STATUS_NO_MEMORY;
2516 if (cli_has_async_calls(cli)) {
2517 return NT_STATUS_INVALID_PARAMETER;
2519 ev = tevent_context_init(talloc_tos());
2520 if (ev == NULL) {
2521 goto fail;
2523 req = cli_tdis_send(ev, ev, cli);
2524 if (req == NULL) {
2525 goto fail;
2527 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2528 goto fail;
2530 status = cli_tdis_recv(req);
2531 fail:
2532 TALLOC_FREE(ev);
2533 return status;
2536 /****************************************************************************
2537 Send a negprot command.
2538 ****************************************************************************/
2540 struct cli_negprot_state {
2541 struct cli_state *cli;
2544 static void cli_negprot_done(struct tevent_req *subreq);
2546 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
2547 struct event_context *ev,
2548 struct cli_state *cli)
2550 struct tevent_req *req, *subreq;
2551 struct cli_negprot_state *state;
2552 uint8_t *bytes = NULL;
2553 int numprots;
2554 uint16_t cnum;
2556 req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
2557 if (req == NULL) {
2558 return NULL;
2560 state->cli = cli;
2562 if (cli->protocol < PROTOCOL_NT1)
2563 cli->use_spnego = False;
2565 /* setup the protocol strings */
2566 for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
2567 uint8_t c = 2;
2568 if (prots[numprots].prot > cli->protocol) {
2569 break;
2571 bytes = (uint8_t *)talloc_append_blob(
2572 state, bytes, data_blob_const(&c, sizeof(c)));
2573 if (tevent_req_nomem(bytes, req)) {
2574 return tevent_req_post(req, ev);
2576 bytes = smb_bytes_push_str(bytes, false,
2577 prots[numprots].name,
2578 strlen(prots[numprots].name)+1,
2579 NULL);
2580 if (tevent_req_nomem(bytes, req)) {
2581 return tevent_req_post(req, ev);
2585 cnum = cli->cnum;
2587 cli->cnum = 0;
2588 subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2589 talloc_get_size(bytes), bytes);
2590 cli->cnum = cnum;
2592 if (tevent_req_nomem(subreq, req)) {
2593 return tevent_req_post(req, ev);
2595 tevent_req_set_callback(subreq, cli_negprot_done, req);
2596 return req;
2599 static void cli_negprot_done(struct tevent_req *subreq)
2601 struct tevent_req *req = tevent_req_callback_data(
2602 subreq, struct tevent_req);
2603 struct cli_negprot_state *state = tevent_req_data(
2604 req, struct cli_negprot_state);
2605 struct cli_state *cli = state->cli;
2606 uint8_t wct;
2607 uint16_t *vwv;
2608 uint32_t num_bytes;
2609 uint8_t *bytes;
2610 NTSTATUS status;
2611 uint16_t protnum;
2612 uint8_t *inbuf;
2614 status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2615 &num_bytes, &bytes);
2616 TALLOC_FREE(subreq);
2617 if (!NT_STATUS_IS_OK(status)) {
2618 tevent_req_nterror(req, status);
2619 return;
2622 protnum = SVAL(vwv, 0);
2624 if ((protnum >= ARRAY_SIZE(prots))
2625 || (prots[protnum].prot > cli->protocol)) {
2626 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2627 return;
2630 cli->protocol = prots[protnum].prot;
2632 if ((cli->protocol < PROTOCOL_NT1) &&
2633 client_is_signing_mandatory(cli)) {
2634 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2635 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2636 return;
2639 if (cli->protocol >= PROTOCOL_NT1) {
2640 struct timespec ts;
2641 bool negotiated_smb_signing = false;
2643 /* NT protocol */
2644 cli->sec_mode = CVAL(vwv + 1, 0);
2645 cli->max_mux = SVAL(vwv + 1, 1);
2646 cli->max_xmit = IVAL(vwv + 3, 1);
2647 cli->sesskey = IVAL(vwv + 7, 1);
2648 cli->serverzone = SVALS(vwv + 15, 1);
2649 cli->serverzone *= 60;
2650 /* this time arrives in real GMT */
2651 ts = interpret_long_date(((char *)(vwv+11))+1);
2652 cli->servertime = ts.tv_sec;
2653 cli->secblob = data_blob(bytes, num_bytes);
2654 cli->capabilities = IVAL(vwv + 9, 1);
2655 if (cli->capabilities & CAP_RAW_MODE) {
2656 cli->readbraw_supported = True;
2657 cli->writebraw_supported = True;
2659 /* work out if they sent us a workgroup */
2660 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2661 smb_buflen(inbuf) > 8) {
2662 ssize_t ret;
2663 status = smb_bytes_talloc_string(
2664 cli, (char *)inbuf, &cli->server_domain,
2665 bytes + 8, num_bytes - 8, &ret);
2666 if (tevent_req_nterror(req, status)) {
2667 return;
2672 * As signing is slow we only turn it on if either the client or
2673 * the server require it. JRA.
2676 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2677 /* Fail if server says signing is mandatory and we don't want to support it. */
2678 if (!client_is_signing_allowed(cli)) {
2679 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2680 tevent_req_nterror(req,
2681 NT_STATUS_ACCESS_DENIED);
2682 return;
2684 negotiated_smb_signing = true;
2685 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2686 /* Fail if client says signing is mandatory and the server doesn't support it. */
2687 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2688 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2689 tevent_req_nterror(req,
2690 NT_STATUS_ACCESS_DENIED);
2691 return;
2693 negotiated_smb_signing = true;
2694 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2695 negotiated_smb_signing = true;
2698 if (negotiated_smb_signing) {
2699 cli_set_signing_negotiated(cli);
2702 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2703 cli->use_spnego = False;
2704 cli->sec_mode = SVAL(vwv + 1, 0);
2705 cli->max_xmit = SVAL(vwv + 2, 0);
2706 cli->max_mux = SVAL(vwv + 3, 0);
2707 cli->sesskey = IVAL(vwv + 6, 0);
2708 cli->serverzone = SVALS(vwv + 10, 0);
2709 cli->serverzone *= 60;
2710 /* this time is converted to GMT by make_unix_date */
2711 cli->servertime = make_unix_date(
2712 (char *)(vwv + 8), cli->serverzone);
2713 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2714 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2715 cli->secblob = data_blob(bytes, num_bytes);
2716 } else {
2717 /* the old core protocol */
2718 cli->use_spnego = False;
2719 cli->sec_mode = 0;
2720 cli->serverzone = get_time_zone(time(NULL));
2723 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2725 /* a way to force ascii SMB */
2726 if (getenv("CLI_FORCE_ASCII"))
2727 cli->capabilities &= ~CAP_UNICODE;
2729 tevent_req_done(req);
2732 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2734 return tevent_req_simple_recv_ntstatus(req);
2737 NTSTATUS cli_negprot(struct cli_state *cli)
2739 TALLOC_CTX *frame = talloc_stackframe();
2740 struct event_context *ev;
2741 struct tevent_req *req;
2742 NTSTATUS status = NT_STATUS_OK;
2744 if (cli_has_async_calls(cli)) {
2746 * Can't use sync call while an async call is in flight
2748 status = NT_STATUS_INVALID_PARAMETER;
2749 goto fail;
2752 ev = event_context_init(frame);
2753 if (ev == NULL) {
2754 status = NT_STATUS_NO_MEMORY;
2755 goto fail;
2758 req = cli_negprot_send(frame, ev, cli);
2759 if (req == NULL) {
2760 status = NT_STATUS_NO_MEMORY;
2761 goto fail;
2764 if (!tevent_req_poll(req, ev)) {
2765 status = map_nt_error_from_unix(errno);
2766 goto fail;
2769 status = cli_negprot_recv(req);
2770 fail:
2771 TALLOC_FREE(frame);
2772 return status;
2775 static NTSTATUS cli_connect_sock(const char *host, int name_type,
2776 const struct sockaddr_storage *pss,
2777 const char *myname, uint16_t port,
2778 int sec_timeout, int *pfd, uint16_t *pport)
2780 TALLOC_CTX *frame = talloc_stackframe();
2781 const char *prog;
2782 unsigned int i, num_addrs;
2783 const char **called_names;
2784 const char **calling_names;
2785 int *called_types;
2786 NTSTATUS status;
2787 int fd;
2789 prog = getenv("LIBSMB_PROG");
2790 if (prog != NULL) {
2791 fd = sock_exec(prog);
2792 if (fd == -1) {
2793 return map_nt_error_from_unix(errno);
2795 port = 0;
2796 goto done;
2799 if ((pss == NULL) || is_zero_addr(pss)) {
2800 struct sockaddr_storage *addrs;
2801 status = resolve_name_list(talloc_tos(), host, name_type,
2802 &addrs, &num_addrs);
2803 if (!NT_STATUS_IS_OK(status)) {
2804 goto fail;
2806 pss = addrs;
2807 } else {
2808 num_addrs = 1;
2811 called_names = talloc_array(talloc_tos(), const char *, num_addrs);
2812 if (called_names == NULL) {
2813 status = NT_STATUS_NO_MEMORY;
2814 goto fail;
2816 called_types = talloc_array(talloc_tos(), int, num_addrs);
2817 if (called_types == NULL) {
2818 status = NT_STATUS_NO_MEMORY;
2819 goto fail;
2821 calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
2822 if (calling_names == NULL) {
2823 status = NT_STATUS_NO_MEMORY;
2824 goto fail;
2826 for (i=0; i<num_addrs; i++) {
2827 called_names[i] = host;
2828 called_types[i] = name_type;
2829 calling_names[i] = myname;
2831 status = smbsock_any_connect(pss, called_names, called_types,
2832 calling_names, NULL, num_addrs, port,
2833 sec_timeout, &fd, NULL, &port);
2834 if (!NT_STATUS_IS_OK(status)) {
2835 goto fail;
2837 set_socket_options(fd, lp_socket_options());
2838 done:
2839 *pfd = fd;
2840 *pport = port;
2841 status = NT_STATUS_OK;
2842 fail:
2843 TALLOC_FREE(frame);
2844 return status;
2847 NTSTATUS cli_connect_nb(const char *host, struct sockaddr_storage *pss,
2848 uint16_t port, int name_type, const char *myname,
2849 int signing_state, struct cli_state **pcli)
2851 TALLOC_CTX *frame = talloc_stackframe();
2852 struct cli_state *cli;
2853 NTSTATUS status = NT_STATUS_NO_MEMORY;
2854 int fd = -1;
2855 char *desthost;
2856 char *p;
2857 socklen_t length;
2858 int ret;
2860 desthost = talloc_strdup(talloc_tos(), host);
2861 if (desthost == NULL) {
2862 goto fail;
2865 p = strchr(host, '#');
2866 if (p != NULL) {
2867 name_type = strtol(p+1, NULL, 16);
2868 host = talloc_strndup(talloc_tos(), host, p - host);
2869 if (host == NULL) {
2870 goto fail;
2874 cli = cli_initialise_ex(signing_state);
2875 if (cli == NULL) {
2876 goto fail;
2878 cli->desthost = talloc_move(cli, &desthost);
2880 status = cli_connect_sock(host, name_type, pss, myname, port, 20, &fd,
2881 &port);
2882 if (!NT_STATUS_IS_OK(status)) {
2883 cli_shutdown(cli);
2884 goto fail;
2886 cli->fd = fd;
2888 length = sizeof(cli->src_ss);
2889 ret = getsockname(fd, (struct sockaddr *)(void *)&cli->src_ss,
2890 &length);
2891 if (ret == -1) {
2892 status = map_nt_error_from_unix(errno);
2893 cli_shutdown(cli);
2894 goto fail;
2896 length = sizeof(cli->dest_ss);
2897 ret = getpeername(fd, (struct sockaddr *)(void *)&cli->dest_ss,
2898 &length);
2899 if (ret == -1) {
2900 status = map_nt_error_from_unix(errno);
2901 cli_shutdown(cli);
2902 goto fail;
2905 if (pss != NULL) {
2906 *pss = cli->dest_ss;
2909 *pcli = cli;
2910 status = NT_STATUS_OK;
2911 fail:
2912 TALLOC_FREE(frame);
2913 return status;
2917 establishes a connection to after the negprot.
2918 @param output_cli A fully initialised cli structure, non-null only on success
2919 @param dest_host The netbios name of the remote host
2920 @param dest_ss (optional) The the destination IP, NULL for name based lookup
2921 @param port (optional) The destination port (0 for default)
2923 NTSTATUS cli_start_connection(struct cli_state **output_cli,
2924 const char *my_name,
2925 const char *dest_host,
2926 struct sockaddr_storage *dest_ss, int port,
2927 int signing_state, int flags)
2929 NTSTATUS nt_status;
2930 struct cli_state *cli;
2932 nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
2933 signing_state, &cli);
2934 if (!NT_STATUS_IS_OK(nt_status)) {
2935 DEBUG(10, ("cli_connect_nb failed: %s\n",
2936 nt_errstr(nt_status)));
2937 return nt_status;
2940 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2941 cli->use_spnego = False;
2942 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2943 cli->use_kerberos = True;
2945 if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2946 cli->use_kerberos) {
2947 cli->fallback_after_kerberos = true;
2949 if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
2950 cli->use_ccache = true;
2953 nt_status = cli_negprot(cli);
2954 if (!NT_STATUS_IS_OK(nt_status)) {
2955 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2956 cli_shutdown(cli);
2957 return nt_status;
2960 *output_cli = cli;
2961 return NT_STATUS_OK;
2966 establishes a connection right up to doing tconX, password specified.
2967 @param output_cli A fully initialised cli structure, non-null only on success
2968 @param dest_host The netbios name of the remote host
2969 @param dest_ip (optional) The the destination IP, NULL for name based lookup
2970 @param port (optional) The destination port (0 for default)
2971 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
2972 @param service_type The 'type' of serivice.
2973 @param user Username, unix string
2974 @param domain User's domain
2975 @param password User's password, unencrypted unix string.
2978 NTSTATUS cli_full_connection(struct cli_state **output_cli,
2979 const char *my_name,
2980 const char *dest_host,
2981 struct sockaddr_storage *dest_ss, int port,
2982 const char *service, const char *service_type,
2983 const char *user, const char *domain,
2984 const char *password, int flags,
2985 int signing_state)
2987 NTSTATUS nt_status;
2988 struct cli_state *cli = NULL;
2989 int pw_len = password ? strlen(password)+1 : 0;
2991 *output_cli = NULL;
2993 if (password == NULL) {
2994 password = "";
2997 nt_status = cli_start_connection(&cli, my_name, dest_host,
2998 dest_ss, port, signing_state,
2999 flags);
3001 if (!NT_STATUS_IS_OK(nt_status)) {
3002 return nt_status;
3005 cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
3006 cli->use_level_II_oplocks =
3007 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
3009 nt_status = cli_session_setup(cli, user, password, pw_len, password,
3010 pw_len, domain);
3011 if (!NT_STATUS_IS_OK(nt_status)) {
3013 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
3014 DEBUG(1,("failed session setup with %s\n",
3015 nt_errstr(nt_status)));
3016 cli_shutdown(cli);
3017 return nt_status;
3020 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
3021 if (!NT_STATUS_IS_OK(nt_status)) {
3022 DEBUG(1,("anonymous failed session setup with %s\n",
3023 nt_errstr(nt_status)));
3024 cli_shutdown(cli);
3025 return nt_status;
3029 if (service) {
3030 nt_status = cli_tcon_andx(cli, service, service_type, password,
3031 pw_len);
3032 if (!NT_STATUS_IS_OK(nt_status)) {
3033 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
3034 cli_shutdown(cli);
3035 if (NT_STATUS_IS_OK(nt_status)) {
3036 nt_status = NT_STATUS_UNSUCCESSFUL;
3038 return nt_status;
3042 nt_status = cli_init_creds(cli, user, domain, password);
3043 if (!NT_STATUS_IS_OK(nt_status)) {
3044 cli_shutdown(cli);
3045 return nt_status;
3048 *output_cli = cli;
3049 return NT_STATUS_OK;
3052 /****************************************************************************
3053 Send an old style tcon.
3054 ****************************************************************************/
3055 NTSTATUS cli_raw_tcon(struct cli_state *cli,
3056 const char *service, const char *pass, const char *dev,
3057 uint16 *max_xmit, uint16 *tid)
3059 struct tevent_req *req;
3060 uint16_t *ret_vwv;
3061 uint8_t *bytes;
3062 NTSTATUS status;
3064 if (!lp_client_plaintext_auth() && (*pass)) {
3065 DEBUG(1, ("Server requested plaintext password but 'client "
3066 "plaintext auth' is disabled\n"));
3067 return NT_STATUS_ACCESS_DENIED;
3070 bytes = talloc_array(talloc_tos(), uint8_t, 0);
3071 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3072 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3073 service, strlen(service)+1, NULL);
3074 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3075 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3076 pass, strlen(pass)+1, NULL);
3077 bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
3078 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
3079 dev, strlen(dev)+1, NULL);
3081 status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
3082 talloc_get_size(bytes), bytes, &req,
3083 2, NULL, &ret_vwv, NULL, NULL);
3084 if (!NT_STATUS_IS_OK(status)) {
3085 return status;
3088 *max_xmit = SVAL(ret_vwv + 0, 0);
3089 *tid = SVAL(ret_vwv + 1, 0);
3091 return NT_STATUS_OK;
3094 /* Return a cli_state pointing at the IPC$ share for the given server */
3096 struct cli_state *get_ipc_connect(char *server,
3097 struct sockaddr_storage *server_ss,
3098 const struct user_auth_info *user_info)
3100 struct cli_state *cli;
3101 NTSTATUS nt_status;
3102 uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
3104 if (user_info->use_kerberos) {
3105 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
3108 nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
3109 user_info->username ? user_info->username : "",
3110 lp_workgroup(),
3111 user_info->password ? user_info->password : "",
3112 flags,
3113 Undefined);
3115 if (NT_STATUS_IS_OK(nt_status)) {
3116 return cli;
3117 } else if (is_ipaddress(server)) {
3118 /* windows 9* needs a correct NMB name for connections */
3119 fstring remote_name;
3121 if (name_status_find("*", 0, 0, server_ss, remote_name)) {
3122 cli = get_ipc_connect(remote_name, server_ss, user_info);
3123 if (cli)
3124 return cli;
3127 return NULL;
3131 * Given the IP address of a master browser on the network, return its
3132 * workgroup and connect to it.
3134 * This function is provided to allow additional processing beyond what
3135 * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
3136 * browsers and obtain each master browsers' list of domains (in case the
3137 * first master browser is recently on the network and has not yet
3138 * synchronized with other master browsers and therefore does not yet have the
3139 * entire network browse list)
3142 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
3143 struct sockaddr_storage *mb_ip,
3144 const struct user_auth_info *user_info,
3145 char **pp_workgroup_out)
3147 char addr[INET6_ADDRSTRLEN];
3148 fstring name;
3149 struct cli_state *cli;
3150 struct sockaddr_storage server_ss;
3152 *pp_workgroup_out = NULL;
3154 print_sockaddr(addr, sizeof(addr), mb_ip);
3155 DEBUG(99, ("Looking up name of master browser %s\n",
3156 addr));
3159 * Do a name status query to find out the name of the master browser.
3160 * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
3161 * master browser will not respond to a wildcard query (or, at least,
3162 * an NT4 server acting as the domain master browser will not).
3164 * We might be able to use ONLY the query on MSBROWSE, but that's not
3165 * yet been tested with all Windows versions, so until it is, leave
3166 * the original wildcard query as the first choice and fall back to
3167 * MSBROWSE if the wildcard query fails.
3169 if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
3170 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
3172 DEBUG(99, ("Could not retrieve name status for %s\n",
3173 addr));
3174 return NULL;
3177 if (!find_master_ip(name, &server_ss)) {
3178 DEBUG(99, ("Could not find master ip for %s\n", name));
3179 return NULL;
3182 *pp_workgroup_out = talloc_strdup(ctx, name);
3184 DEBUG(4, ("found master browser %s, %s\n", name, addr));
3186 print_sockaddr(addr, sizeof(addr), &server_ss);
3187 cli = get_ipc_connect(addr, &server_ss, user_info);
3189 return cli;
3193 * Return the IP address and workgroup of a master browser on the network, and
3194 * connect to it.
3197 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
3198 const struct user_auth_info *user_info,
3199 char **pp_workgroup_out)
3201 struct sockaddr_storage *ip_list;
3202 struct cli_state *cli;
3203 int i, count;
3204 NTSTATUS status;
3206 *pp_workgroup_out = NULL;
3208 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
3210 /* Go looking for workgroups by broadcasting on the local network */
3212 status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
3213 &ip_list, &count);
3214 if (!NT_STATUS_IS_OK(status)) {
3215 DEBUG(99, ("No master browsers responded: %s\n",
3216 nt_errstr(status)));
3217 return False;
3220 for (i = 0; i < count; i++) {
3221 char addr[INET6_ADDRSTRLEN];
3222 print_sockaddr(addr, sizeof(addr), &ip_list[i]);
3223 DEBUG(99, ("Found master browser %s\n", addr));
3225 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
3226 user_info, pp_workgroup_out);
3227 if (cli)
3228 return(cli);
3231 return NULL;